- •Введение
- •Несколько слов о книге
- •Глава 1. Каким должен бытъ Web-интерфейс
- •Действия пользователя при работе с приложением
- •Накладные расходы при работе в сети
- •Асинхронное взаимодействие
- •Независимый и переходный образы использования
- •Четыре основных принципа Ajax
- •Браузер имеет дело с приложением, а не с содержимым
- •Сервер доставляет данные, а не содержимое
- •Реальное кодирование требует порядка
- •Применение богатых клиентов Ajax
- •Системы, созданные с использованием Ajax
- •Google Maps
- •Альтернативные технологии
- •Macromedia Flash
- •Java Web Start
- •Резюме
- •Ресурсы
- •Основные элементы Ajax
- •JavaScript изучался не зря
- •Определение внешнего вида с помощью CSS
- •Селекторы CSS
- •Свойства стилей
- •Простой пример использования CSS
- •Обработка DOM с помощью JavaScript
- •Поиск узла DOM
- •Создание узла DOM
- •Добавление стилей к документу
- •Свойство innerHTML
- •Асинхронная загрузка с использованием XML
- •Элементы IFrame
- •Объекты XmlDocument и XMLHttpRequest
- •Использование фуниции обратного вызова для контроля запроса
- •Жизненный цикл процедуры поддержки запроса
- •Отличия Ajax от классических технологий
- •Резюме
- •Ресурсы
- •Порядок из хаоса
- •Образы разработки
- •Реструктуризация и Ajax
- •Во всем надо знать меру
- •Реструктуризация в действии
- •Варианты применения реструктуризации
- •Несоответствие браузеров: образы разработки Fagade и Adapter
- •Управление обработчиками событий: образ разработки Observer
- •Повторное использование обработчиков событий: образ разработки Command
- •Обеспечение единственной ссылки на ресурс: образ разработки Singleton
- •"Модель-представление-контроллер "
- •Серверная программа Ajax, созданная без применения образов разработки
- •Реструктуризация модели
- •Разделение содержимого и представления
- •Библиотеки независимых производителей
- •Библиотеки, обеспечивающие работу с различными браузерами
- •Компоненты и наборы компонентов
- •Элементы, располагаемые на стороне сервера
- •Резюме
- •Ресурсы
- •Применение архитектуры MVC к программам различных уровней
- •Применение архитектуры MVC к объектам, присутствующим в среде браузера
- •Представление в составе Ajax-приложения
- •Отделение логики от представления
- •Отделение представления от логики
- •Контроллер в составе Ajax-приложения
- •Классические JavaScript-обработчики
- •Модель обработки событий W3C
- •Реализация гибкой модели событий в JavaScript
- •Модель в составе Ajax-приложения
- •Использование JavaScript для моделирования предметной области
- •Взаимодействие с сервером
- •Генерация представления на основе модели
- •Отражение объектов JavaScript
- •Обработка массивов и объектов
- •Включение контроллера
- •Резюме
- •Ресурсы
- •Программы, выполняемые на сервере
- •Создание программ на стороне сервера
- •N-уровневые архитектуры
- •Управление моделью предметной области на стороне клиента и на стороне сервера
- •Принципы создания программ на сервере
- •Серверные программы, не соответствующие основным принципам разработки
- •Использование архитектуры Model!
- •Использование архитектуры на базе компонентов
- •Архитектуры, ориентированные на использование Web-служб
- •Частные решения: обмен данными
- •Взаимодействие, затрагивающее только клиентскую программу
- •Пример отображения информации о планетах
- •Взаимодействие, ориентированное на содержимое
- •Взаимодействие, ориентированное на сценарий
- •Передача данных серверу
- •Использование HTML-форм
- •Использование объекта XMLHttpRequest
- •Управление обновлением модели
- •Резюме
- •Ресурсы
- •Создание качественного приложения
- •Отклик программы
- •Надежность
- •Согласованность
- •Простота
- •Как получить результат
- •Предоставление сведений пользователю
- •Поддержка ответов на собственные запросы
- •Обработка обновлений, выполненных другими пользователями
- •Создание системы оповещения
- •Основные принципы оповещения
- •Реализация базовых средств оповещения
- •Отображение пиктограмм в строке состояния
- •Отображение подробных сообщений
- •Формирование готовой системы
- •Предоставление информации в запросах
- •Информация о новизне данных
- •Простой способ выделения данных
- •Выделение данных с использованием библиотеки Scriptaculous
- •Резюме
- •Ресурсы
- •JavaScript и защита браузера
- •Политика "сервера-источника"
- •Особенности выполнения сценариев в Ajax-приложении
- •Проблемы с поддоменами
- •Взаимодействие с удаленным сервером
- •Взаимодействие с Web-службами
- •Защита конфиденциальной информации
- •Вмешательство в процесс передачи данных
- •Организация защищенного НТТР-взаимодействия
- •Передача шифрованных данных в ходе обычного HTTP-взаимодействия
- •Управление доступом к потокам данных Ajax
- •Создание защищенных программ на уровне сервера
- •Ограничение доступа к данным из Web
- •Резюме
- •Ресурсы
- •Что такое производительность
- •Скорость выполнения JavaScript-программ
- •Определение времени выполнения приложения
- •Использование профилировщика Venkman
- •Оптимизация скорости выполнения Ajax-приложения
- •Использование памяти JavaScript-кодом
- •Борьба с утечкой памяти
- •Особенности управления памятью в приложениях Ajax
- •Разработка с учетом производительности
- •Простой пример управления памятью
- •Как уменьшить объем используемой памяти в 150 раз
- •Резюме
- •Ресурсы
- •Сценарий двойной комбинации
- •Недостатки клиентского решения
- •Недостатки клиентского решения
- •Архитектура клиента
- •Разработка взаимодействия клиент/сервер
- •Реализация сервера: VB.NET
- •Написание кода сервера
- •Представление результатов
- •Применение каскадных таблиц стилей
- •Дополнительные вопросы
- •Запросы при выборе нескольких элементов
- •Переход от двойного связного выбора к тройному
- •Реструктуризация
- •Новый и улучшенный объект netContentLoader
- •Создание компонента двойного списка
- •Резюме
- •Глава 10. Опережающий ввод
- •Изучаем опережающий ввод
- •Типичные элементы приложений опережающего ввода
- •Google Suggest
- •Ajax как средство опережающего ввода
- •Структура серверной части сценария: С#
- •Сервер и база данных
- •Тестирование серверного кода
- •Структура клиентской части сценария
- •HTML
- •JavaScript
- •Обращение к серверу
- •Дополнительные возможности
- •Реструктуризация
- •День 1: план разработки компонента TextSuggest
- •День 3: включаем Ajax
- •День 4: обработка событий
- •День 5: пользовательский интерфейс всплывающего окна с предлагаемыми вариантами
- •Итоги
- •Резюме
- •Эволюционирующий портал
- •Классический портал
- •Портал с богатым пользовательским интерфейсом
- •Создание портала с использованием Java
- •Таблица пользователя
- •Серверная часть кода регистрации: Java
- •Структура регистрации (клиентская часть)
- •Реализация окон DHTML
- •База данных окон портала
- •Серверный код окна портала
- •Добавление внешней библиотеки JavaScript
- •Возможность автоматического сохранения
- •Адаптация библиотеки
- •Автоматическая запись информации в базе данных
- •Реструктуризация
- •Определение конструктора
- •Адаптация библиотеки AjaxWindows.js
- •Задание команд портала
- •Выводы
- •Резюме
- •Понимание технологий поиска
- •Классический поиск
- •"Живой" поиск с использованием Ajax и XSLT
- •Возврат результатов клиенту
- •Код клиентской части сценария
- •Настройка клиента
- •Инициализация процесса
- •Код серверной части приложения: РНР
- •Создание XML-документа
- •Создание документа XSLT
- •Объединение документов XSL и XML
- •Совместимость с браузером Microsoft Internet Explorer
- •Совместимость с браузерами Mozilla
- •Последние штрихи
- •Применение каскадных таблиц стилей
- •Улучшение поиска
- •Поддержка браузерами Opera и Safari
- •Использовать ли XSLT
- •Решение проблемы закладок
- •Реструктуризация
- •Объект XSLTHelper
- •Компонент "живого" поиска
- •Выводы
- •Резюме
- •Считывание информации из внешнего мира
- •Поиск XML-лент
- •Изучение структуры RSS
- •Богатый пользовательский интерфейс
- •Чтение лент
- •HTML-структура без таблиц
- •Гибкое CSS-форматироеание
- •Глобальный уровень
- •Предварительная загрузка средствами Ajax
- •Богатый эффект перехода
- •Правила прозрачности, учитывающие индивидуальность браузеров
- •Реализация затухающего перехода
- •Интеграция таймеров JavaScript
- •Дополнительные возможности
- •Введение дополнительных лент
- •Интеграция функций пропуска и паузы
- •Как избежать ограничений проекта
- •Обход системы безопасности браузеров Mozilla
- •Изменение масштаба приложения
- •Реструктуризация
- •Модель приложения
- •Представление приложения
- •Контроллер приложения
- •Выводы
- •Резюме
- •Отладчики
- •Для чего нужен отладчик
- •Средство Safari DOM Inspector для Mac OS X
- •Ресурсы
- •JavaScript — это не Java
- •Формирование объектов
256 Часть III Создание профессиональных Ajax-приложений
*
Заметьте, что мы не используем здесь методы W3C DOM, текст сообщения включается в состав таблицы посредством свойства innerHTML. Это открывает дополнительные возможности по представлению HTML-элементов по сравнению с генерацией обычного текстового узла.
6.4.3. Формирование готовой системы
На данном этапе нами полностью реализована поддержка пиктограмм в строке состояния и отображение текста сообщений. За вывод диалогового окна и строки состояний отвечает высокоуровневый метод render (), код которого показан в листинге 6.6.
Листинг 6.6. Функция msg. render ()
msg.render=function(msgbar){ if (!msgbar){ msgbar='msgbar' ;
}
// О Обеспечить вывод строки состояния msg.msgbarDiv=xGetElementById(msgbar); if (!msg.msgbarDiv){ msg.msgbarDiv=msg.createBar(msgbar);
}
styling.removeAllChildren(msg.msgbarDiv); var lows=new Array();
v a r nveds=new Array О ; var highs=new Array();
// @ Сортировать сообщения в соответствии с приоритетом for (var i in msg.messages){
var message=msg.messages[i]; if (message){
if (message.priority<=msg.PRIORITY__LOW.id) { lows.append (message);
}else if (raessage.priority==msg.PRIORITY_DEFAULT.id){ meds.append(message);
Jelse if (message.priority>=msg.PRIORITY_HIGH.id){ highs.append(message);
}
}
}
// © Воспроизвести низкоприоритетные сообщения for (var i=0;i<lows.length;i++){
lows fi].render(msg.msgbarDiv);
}
// О Воспроизвести сообщения с высоким и средним приоритетом if (meds.length+highs.length>O){ msg.dialog=xGetElementByld(msgbar+"_dialog");
if (!msg.dialog){ msg.dialog=msg.createDialog( msgbar+"_dialog", msg.msgbarDiv, (highs.length>0) );
// 0 Обеспечить отображение диалогового окна
}
Глава 6. Информация для пользователя 257
styling.removeAHChildren(msg.dialog.tbod); for (var i=0;i<highs.length;i++){ highs[i].render(msg.dialog.tbod);
}
for (var i=0;Kmeds.length;i++){ meds[i].render(msg.dialog.tbod);
}
if (highs.length>0){ msg.dialog.ico.src=msg.PRIORITY_HIGH.icon; }else{ msg.dialog.ico.src=msg.PRIORITY_DEFAULT.icon;
}
)
}
// 0 Создать строку состояния msg.createBar=function(id){
var msgbar=document.createElement("div"); msgbar.className='msgbar' ;
msgbar,id=id;
var parentEl=document.body; parentEl.append{msgbar); return msgbar;
}
// в Создать диалоговое окно msg.createDialog=function(id,bar,isModal){
var dialog=document.createElement("div"); dialog.className='dialog' ;
dialog.id=id;
var tbl=document.createElement("table"); dialog.appendChiId(tbl); dialog.tbod=document.createElement("tbody"); tbl.appendChild(dialog.tbod);
var closeB-atton=document. createElement (" div" ); closeButton.dialog=dialog; closeButton.onclick=msg.hideDialog;
var closeTxt=document.createTextNode("x"); closeButton.appendChild(closeTxt); dialog.appendChild(closeButton);
// О Добавить модальный уровень if (isModal){
dialog.modalLayer=document.createElement("div"); dialog.modalLayer.className='modal' ; dialog.modalLayer.appendChild(dialog); document.body.appendChild(dialog.modalLayer); }else{
dialog.clas sName+=' non-modal'; document.body.appendChild(dialog);
}
d i a l o g . i c o = d o c u m e n t . c r e a t e E l e m e n t ( " i m g " ) ; d i a l o g . i c o . c l a s s N a m e = " m s g _ d i a l o g _ i c o n " ;
d i a l o g . i c o . d i a l o g = d i a l o g ;
d i a l o g . i c o . o n c l i c k = m s g - s h o w D i a l o g ; b a r . a p p e n d C h i l d ( d i a l o g . i c o ) ;
r e t u r n d i a l o g ;
}
258 Часть III Создание профессиональных Ajax-приложений
// Скрыть диалоговое окно m s g . h i d e D i a l o g = f u n c t i o n ( e ) {
va r d i a l o g s ( t h i s . d i a l o g ) ? t h i s . d i a l o g : m s g . d i a l o g ; i f ( d i a l o g ) {
if (dialog.modalLayer){ dialog.modalLayer.style.display='none' ;
}else{ dialog.style.display='none' ;
} |
|
|
} |
|
|
} |
|
|
// |
Отобразить диалоговое окно |
|
msg.showDialog=function(e){ |
||
var dialog=(this.dialog) ? this.dialog : msg,dialog; |
||
|
if |
(dialog){ |
|
if |
(dialog.modalLayer){ |
|
dialog.modalLayer.style.display*1block1 ; |
|
|
}else{ |
|
|
dialog.style.display='block'; |
|
} |
|
|
} |
|
|
} |
m |
К функции render () можно обращаться многократно. В процессе работы она проверяет присутствие компонентов пользовательского интерфейса О, © и по мере необходимости создает их, используя функции createDialog © и createBar ©. Для формирования компонентов интерфейса используются стандартные методы обработки элементов DOM. Обработчики событий позволяют отображать и скрывать диалоговое окно.
Для воспроизведения всех сообщений система сначала сортирует их по приоритету и размещает в трех временных массивах @. Затем низкоприоритетные сообщения выводятся в строке состояния ©, а остальные — в диалоговом окне, причем первыми располагаются высокоприоритетные сообщения О.
Для того чтобы реализовать модальное окно, мы помещаем видимые средства поддержки диалога в элемент DIV, занимающий весь экран, и блокирующий все события, связанные с мышью ©. Для модального элемента DIV определен белый фон с прозрачными пикселями. По этому признаку можно отличить модальное окно. Мы не используем установки прозрачности CSS, потому что в этом случае любой вложенный элемент будет также прозрачным. Файл CSS для системы оповещения представлен в листинге 6.7.
Листинг 6.7. Содержимое файла msg. ess
•msg_small_icon{ height: 32px; width: 32px; position:relative; float:left;
}
• ™sg_jiialog_icon { height: 32px; width: 32px;
Глава 6. Информация для пользователя 259
p o s i t i o n : r e l a t i v e ; f l o a t : r i g h t ;
1
• msg _ large _ icon { h e i g h t : 64px;
w i d t h : 64px;
}
.msg_text{
f o n t - f a m i l y : a r i a l ; f o n t - w e i g h t : l i g h t ; f o n t - s i z e : 14pt;
c o l o r : b l u e ;
}
,msgbar{
position:relative; background-color: white; border: solid blue lpx; width: 100%;
height: 38px; padding: 2px;
}
.dialog{
position: absolute; background-color: whiteborder: solid blue lpx; width: 420px;
top: 64px; left: 64px; padding: 4px;
}
.popup{
position; absolute; background-color: white; border: solid blue lpx; padding: 4px;
}
.non-modal{
}
.modal{
position: absolute; top: Opx;
left: Opx; width: 100%; height: 100%;
background-image:url(img/modal_overlay.gif);
260 Часть III. Создание профессиональных Ajax-приложений
Рис. 6.5. Использование CSS-атрибутов f l o a t позволяет размещать пиктограммы в контейнере любой формы.
В данном примере мы задали квадратную строку состояния; пиктограммы автоматически перекомпоновались с учетом выравнивания по левому и правому краю
Следует заметить, что в GSb-классах msg_small_icon и msg_dialog_icon используется стиль float. Класс msg_small_icon применяется для воспроизведения пиктограмм, соответствующих низкоприоритетным сообщениям. Эти пиктограммы располагаются в ряд, начиная с левого края. Для msg__dialog_icon задано выравнивание по правому краю. Базовые средства позволяют отображать строку состояния любой формы и любого размера. Плавающие элементы располагаются в строке состояния в ряд; при заполнении текущего ряда формируется следующий ряд (рис. 6.5).
Теперь, когда мы создали пользовательский интерфейс для объекта Message, надо модифицировать сам объект. Создаваемые сообщения должны иметь возможность включать самих себя в состав пользовательского интерфейса и удаляться по окончании действия. В листинге 6.8 показаны изменения, которые необходимо внести в состав кода, чтобы обеспечить эти возможности.
Листинг 6.8. Модифицированный объект Message
var msg=new Object();
msg.PRIORITY_LOWs= { id: 1, lifetime: 30, icon: "img/msg_lo.png" } ; msg.PRIORITY_DEFAULT={ id:2, lifetime:60, icon:"img/msg_def.png" J; msg.PRIORITY_HIGH= { i d : 3 , lifetime:- l, icon: "img/msg__hi .png" } ; msg.messages=new ArrayO;
msg.dialog=null;
msg.msgBarDiv=null;
msg.suppressRender=false;
msg.Message=function(id,message,priority,lifetime,icon){
this.id=id;
msg.messages[id]=this;
this.message=message;
this.priority={priority) ? priority : msg. PRIORITY__DEFAULT. id; this.lifetime=(lifetime) ? lifetime : this.defaultLifetime(); this.icon={icon) ? icon : this.defaultlcon();
if (this.lifetime>0){ this.fader=setTimeout( "msg.messages['"+this.id+"'].clear()", this.lifetime*1000
);
}
// О Дополнительные параметры if (!msg.suppressRender){ this.attachToBar();
Глава 6. Информация для пользователя 261
}
}
// @ Дополнительные параметры msg.Message.prototype.attachToBar=function(){
if (!msg.msgbarDiv){ msg.render();
}else if (this.priority==msg.PRIORITY_LOW.id){ this.render(msg.msgbarDiv);
lelsei
if (!msg.dialog){ msg.dialog=msg.createDialog( msg.msgbarDiv.id+"_dialog", msg.msgbarDiv, (this.priority==msg.PRIORITY_HIGH.id) );
}
this.render(msg.dialog.tbod);
msg.showDialog();
}
}
msg.Message.prototype.clear=function(){
msg.messages[this.id]=null;
// & Дополнительные параметры if (this.row){ this.row.style.display='none' ; this. row.messageObj'^nullfthis.row^null;
}
i f ( t h i s . i c o T d ) {
t h i s . i c o T d . s t y l e . d i s p l a y s ' n o n e ' ; t h i s . i c o T d . m e s s a g e O b j = n u l l ;
t h i s . i c o T d = n u l l ;
}
_ 1 |
я |
Мы стремимся упростить работы с системой, поэтому при создании сообщения оно автоматически включается в состав пользовательского интерфейса О. Для того чтобы обеспечить воспроизведение нового сообщения, достаточно вызвать конструктор объекта. В зависимости от приоритета сообщения оно будет помещено либо в строку состояния, либо в диалоговое окно ©. Если нежелательно воспроизводить каждое сообщение, например, когда мы добавляем одновременно несколько сообщений, предусмотрен флаг, позволяющий отменить автоматическое отображение. В этих случаях после создания всех необходимых сообщений мы можем вручную вызвать функцию msg.render().
Удаляя сообщения с помощью функции clear(), мы автоматически удаляем соответствующие элементы пользовательского интерфейса ©.
Итак, мы получили комплект базовых средств, упрощающих оповещение пользователей. Мы можем включать оповещение вручную или применять созданную систему в составе других компонентов, предназначенных для по-