
Ajax в действии
.pdfГлава 11. Улучшенный Web-портал Ajax 451
Листинг 11.5. Правила CSS регистрационной формы
<style type="text/css">
<! — О Элементы html и body —>
h t m l , |
body{ m a r g i n : Opx; padding:Орх; |
||
|
|
height:100%; |
} |
< ! — © Определить стиль элемента заголовка --> |
|||
#header{ |
b a c k g r o u n d - c o l o r : |
#C0C0C0; |
|
|
h e i g h t : |
ЮОрх; |
|
|
b o r d e r - b o t t o m : lpx |
s o l i d b l a c k ; |
|
|
f o n t - w e i g h t : b o l d ; J |
|
< ! — © Разместить элемент span регистрационной формы —> #login { t e x t - a l i g n : r i g h t ; f l o a t : r i g h t ;
m a r g i n - t o p : 1 5 p x ;
m a r g i n - r i g h t : 1 5 p x ; )
< ! - - О Отформатировать текст заголовка -->
#sloganText{ f o n t - s i z e : 25px; |
|
m a r g i n - l e f t : |
15px; |
l i n e - h e i g h t : |
ЮОрх; } |
< / s t y l e > |
|
Вначале мы удаляем все поля или заполнения из тела О документа. Высоту (свойство height) мы задаем равной 100%. Важно отметить, что нам необходимо задать данные свойства в дескрипторах HTML И body, поскольку различные браузеры получают данную информацию из одного из указанных дескрипторов.
Разрабатывая стилевое оформление заголовка ©, мы можем задать цвет фона элемента div. Кроме того, можно установить высоту и добавить границу кнопки, чтобы отделить заголовок от содержимого. Помимо этого, можно изменить свойства шрифтов, которые мы посчитаем нужными.
Мы принимаем регистрационную информацию © и перемещаем ее в правую сторону экрана. Для этого используется свойство float со значением right. Для выравнивания текстовых блоков применяется свойство textalign, поэтому содержимое элемента span также выравнивается по правому полю. Благодаря этому текстовые окна выглядят более унифицировано. В противном случае они не были бы выровнены правильно, поскольку имя строки короче, чем пароль. Кроме того, для выравнивания положения регистрационной информации можно добавить поля, чтобы правый край соответствующего окна не примыкал непосредственно к границе элемента div заголовка.
В заключение необходимо определить стиль текста заголовка О. Задавая высоту строки (свойство lineheight) равной высоте элемента div, мы позволяем центрировать текст заголовка вертикально. Кроме того, свойства шрифта задаются так, чтобы текст был заметен. Далее мы добавили поле, поэтому первая буква в слове Ajax не выровнена по краю заголовка. После применения правил CSS к заголовку можно записать документ и посмотреть, как таблицы CSS изменили его внешний вид (рис 11.8).


Рис. 11.9. Сообщение об ошибке, вызванное предоставлением неверных сведений
Прежде чем отправлять информацию на сервер, необходимо отобразить для пользователя сообщение о том, что щелчок на кнопке позволяет ему войти в систему. Благодаря этому пользователь не будет повторно щелкать на кнопке, думая, что ничего не происходит.
Итак, мы получаем поля имени пользователя и пароля и помещаем их в строку, отправляемую на сервер. Значения отправляются на сервер с помощью объекта ContentLoader, принимающего в качестве параметров URL, функцию, вызываемую при удачном завершении действия, функцию, вызываемую в случае ошибки, действие формы POST, а также строку, содержащую отправляемые параметры. Рассмотрим подробнее функцию, вызываемую при успешном возврате данных с сервера и обрабатывающую эти данные: CreateScript{).
function CreateScript() {
strText - this.req.responseText; eval(strText);
}
При создании серверной части сценария мы возвращали текстовые строки, содержащие выражения JavaScript в свойстве responseText возвращаемого объекта. Чтобы эффективно использовать выражения JavaScript, их необходимо обработать с помощью метода eval (), точно определяющего, что содержит строка, и выполняющего указанные в ней действия. В данном случае строка либо будет содержать сообщение об ошибке, сгенерированное при сбое LoginFilter, либо код создания окна, если фильтр пропускает данные к SelectServlet (листинг 11.8).
Из чего состоит строка? В данном приложении мы не собираемся возвращать в ответ на запрос XML-документ, как мы поступали во многих других примерах. Вместо этого мы вернем структурированные выражения JavaScript, которые смогут использовать метод eval(). Используя термины, сформулированные в главе 5, можно сказать, что наше решение ориентировано скорее на сценарий, чем на данные. Как и ранее, мы приняли данный подход только ради разнообразия. В качестве среды передачи при разработке кода портала можно использовать XML или JSON.
Теперь можно сохранить портал и запустить его, чтобы посмотреть, как работает процедура регистрации. Как видно на рис. 11.9, в поля были введены неверное имя пользователя и пароль.
Ниже кнопки "login" на рис. 11.9 отображено сообщение об ошибке, информирующее пользователя, что предоставленные им данные неверны.

Если, с другой стороны, регистрация прошла успешно, запрос перенаправляется на основную страницу портала. В этом случае следующим шагом является создание окон. Чтобы получить намеченный богатый пользовательский интерфейс, нам придется разработать довольно много кода DHTML, но на самом деле эта тяжелая работа уже выполнена, поскольку мы используем готовую DHTML-библиотеку JavaScript.
11.4. Реализация окон DHTML
Наш портал Ajax имеет богатый пользовательский интерфейс, позволяющий пользователю динамически размещать окна. Кроме того, пользователь может устанавливать размер окна (желательную ширину и высоту). При изменении указанных настроек мы можем с помощью Ajax реализовать взаимодействие с сервером и записать новые значения в собственной базе данных (причем пользователь даже не будет знать об этом). Чтобы разрешить подобное поведение, требуется разработать таблицу базы данных, в которой будут храниться свойства окна — высота, ширина и положение. Код серверной части сценария должен получать данные значения и соответствующим образом обновлять величины в базе данных. Написание DHTML-кода, совместимого с основными браузерами, может оказаться сложным, поэтому для реализации перетаскивания и изменения размеров окна мы используем сценарий библиотеки DHTML. Данная библиотека, JSWindow. js, представляет собой внешний файл JavaScript, содержащий код всех требуемых нам функций . (Эту библиотеку можно найти на Web-сайте данной книги.) Чтобы активизировать инфраструктуру Ajax, нам потребуется лишь незначительно изменить код данной библиотеки.
11.4.1. База данных окон портала
Нам нужна таблица базы данных, способная содержать свойства нескольких окон DHTML для каждого пользователя. Каждый пользователь может иметь несколько строк в данной таблице — по одной на каждое окно портала. Таблица применяется для извлечения последнего запомненного положения и размера окна при первом входе пользователя в систему. Когда пользователь что-то меняет, значения обновляются, чтобы при следующем посещении окна располагаться точно так же. Для создания таблицы portal_windows используется следующий SQL-код:
create table portal_windows(
id int primary key not null, user_id int not null, xPos int not null, yPos int not null,
width int not null, height int not null,
url varchar(255) not null, title varchar(255) not null
);


Рис. 11.11. Данные, введенные для пользователя с идентификатором 1
нужно отображать на экране. В связи с этим мы определяем объект PortalWindow, представляющий строку информации в базе данных, как показано в листинге 11.7.
Листинг 11.7. PortalWindow.java public class PortalWindow { private int id=-l;
private User user=null; private int xPos=0; private int yPos=0; private int width=0; private int height=0; private String url=null; private String title=null;
public PortalWindow(
int id. User user, int xPos, int yPos, int width,int height,
String url, String title
) {
this.id = id; this.user = user; this.xPos = xPos; this.yPos = yPos; this.width = width; this.height = height; this.url = url; this.title = title;
}
public int getHeight() {return height;}
public void setHeight(int height) {this.height » height;} public int getld() {return id;}
public void setld(int id) {this.id = id;} public String getTitle() {return title;}
public void setTitle(String title) {this.title = title;} public String getUrl() {return url;}
public void setUrlfString url) {this.url = url;} public User getUser() {return user;}
public void setUser(User user) {this.user = user;} public int getWidth() {return width;}
public void setWidth(int width) {this.width • width;} public int getXPos() {return xPos;}

public void setXPos(int pos) {xPos = pos;J public int getYPos() {return yPos;}
public void setYPos(int pos) {yPos = pos;}
}
Как и прежде, объект представляет собой достаточно прямолинейное отображение структуры базы данных. В реальной задаче мы, возможно, использовали бы для облечения жизни ORM-систему, например Hibernate или iBATIS, но сейчас нам требуется, чтобы все было довольно простым и платформенно-независимым. Обратите внимание на то, что мы предоставляем для этого объекта как методы установки, так и методы получения, поскольку нам нужно, чтобы объекты обновлялись динамически в ответ на события на стороне клиента. Запрошенный при регистрации URL, portalLogin,servlet, отображается в сервлет, извлекающий все окна портала для этого пользователя и возвращающий в ответ указания JavaScript. Основной сервлет показан в листинге 11.8.
Листинг11.8.СервлетSelectServlet.Java
public class SelectServlet extends HttpServlet { protected void doPost(
HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException { HttpSession session=request.getSession(); User user={User)
// О Проверить сеанс (session.getAttributef"user"));
StringBuffer jsBuf=new StringBuffer(); if (user==null){
jsBuf.append(JSUtil.logout()) ; }else{
List windows=DBUtil // 0 Определить объект
.getPortalWindows(user); // в Использовать объект JSUtil
j sBuf.append(JSUtil.initUI() );
for (Iterator iter=windows.iterator();iter.hasNext();) PortalWindow window=(PortalWindow)(iter.next()); session.setAttribute("window_"+window.getld(),window) jsBuf.append
// О Объявить окно портала
(JSUtil.initWindow(window));
}
J
Writer writer=response.getWriter(); // 0 Записать в выходной поток.
writer.write(j sBuf.toString()); writer.flush();
> } |
. |
J |
||
|
|
|
|
|

Глава 11. Улучшенный Web-портал Ajax 459
Итак, мы формируем выражение SQL О, последовательно проходим по сгенерированному этим выражением набору результатов © и во всех случаях добавляем к нашему списку объект PortalWindow ©.
Далее мы используем вспомогательный объект JSUtil, генерируем код инициализации и объявляем объекты окна на JavaScript. Соответствующие методы по сути представляют собой упражнения по конкатенации строк, поэтому мы не будем приводить здесь класс целиком. Принцип его действия демонстрируется в приведенном ниже коде.
public static String initwindow(PortalWindow window) { StringBuEfer jsBuf=new StringBuffer{)
.append("CreateWindow{new NewWin('")
.append(window.getId())
.append("',")
,append(window.getXPos())
.append(",")
.append(window.getYPos())
.append(",")
.append(window.getWidth())
.append(",")
.append(window.getHeight())
.append(",'")
.append(window.getUrK))
.append("','")
.append(window.getTitle{))
. a p p e n d ^ " ) ) ; (BBSS)n11); return j s B u f . t o S t r i n g ( ) ;
}
Метод initwindow () генерирует код JavaScript для инициализации одного окна портала. Код JavaScript успешного запроса может выглядеть приблизительно так, как показано ниже: для всех окон последовательно вызывается функция initwindow () (для улучшения читаемости код был соответствующим образом отформатирован):
document.getElementByld('login' )
.innerHTML='Welcome back!' document.getElementByld('defaultConten')
.style.display=tquotenonetquote;
CreateWindow( new NewWin(
tquoteltquote,612,115,615,260,
tquotehttp://www.j avaranch.comtquote,tquoteJavaRanchtquote
)
);
CreateWindow( new NewWin(
tquote2tquote,10,115,583,260,
tquotehttp://www.google.comtquote,tquoteGoogletquote
)
>;
CreateWindow(
new NewWin(
460 Часть IV. Ajaxв примерах
tquote3tquote,10,387,1220,300, tquotehttp://radio.j avaranch.com/pascarellotquote, tquoteAjax Blog!tquote
)
>;
Поскольку мы уже вошли в систему, текстовое окно регистрации и кнопку "Отправить" можно убирать; вместо них отображается приветственное сообщение. Чтобы разместить это сообщение, необходимо будет скрыть содержимое, по умолчанию располагающееся на экране. Для этого свойство display элемента DOM defaultContent устанавливается равным попе, поэтому оно убирается из поля зрения пользователя.
Обрабатывающий окно оператор JavaScript состоит из двух частей. Первая часть представляет собой вызов функции CreateWindow(), являющейся частью добавленной нами библиотеки JavaScript. В вызове функции мы вызовем новый конструктор объекта. Конструктор создает класс окна, облегчающий обращение к свойствам окна. Функция JavaScript, создающая класс окна, должна получить параметры OKHaid, width, height, xPos, yPos, url и t i t l e . Когда сервлет возвратит эту строку клиенту, метод JavaScript eval () выполнит ее.
Как правило, мы придерживаемся договоренностей относительно генерации кода, дающих простой, повторяемый код, вызывающий функции нашей библиотеки JavaScript. Код инициализации можно поместить в один вызов, привязав его к клиенту, но реализовать данную возможность мы предоставляем читателю в качестве самостоятельного упражнения.
Использованная нами библиотека JavaScript создает плавающие окна JavaScript. Давайте посмотрим, как сделать эти функции создания окон доступными на стороне клиента.
11.4.3. Добавление внешней библиотеки JavaScript
Как отмечалось ранее, мы используем библиотеку DHTML, которую можно загрузить с Web-сайта www.manning.com. Файл JSWindow. js содержит все методы DOM JavaScript, необходимые для создания элементов окон. Кроме того, библиотека применяет обработчики событий к объектам окон, так что мы можем использовать возможности перетаскивания. Готовые библиотеки кода удобны тем, что позволяют сокращать время разработки и обычно работают во всех браузерах.
Первым делом требуется переименовать файл, чтобы мы могли модифицировать его. Запишем файл JavaScript под именем A j axWindow. j s в рабочей папке.
Чтобы использовать функции, содержащиеся в AjaxWindow. js, необходимо сослаться на внешний файл JavaScript посредством дескриптора script. В дескрипторе JavaScript element мы используем атрибут src. Элемент script, связывающийся с требуемым файлом . js, необходимо включить в заголовок нашей HTML-страницы.
<script type="text/javascript" src="AjaxWindow.js"X/script>