
Ajax в действии
.pdf562 Часть IV. Ajax в примерах
новлении пользовательского интерфейса содержимое должно помещаться на слой 0. Значение 1 приводит к вставке данных на слой 1.
Подведем итог. У нас есть методы, с помощью которых реализуется переход вперед/назад по набору статей, и мы можем их использовать для создания методов слайд-шоу. Рассмотрим их В листинге 13.34 показаны метод startSlideShow, который, как вы помните, вызывался из метода s t a r t ( ) , и дополняющий его метод nextSlide ().
ЛистинМ3.34. Методы навигации по слайд-шоу
startSlideShow: function(resume) {
var delay = resume ? 1 : this.options.slideTransitionDelay; this.transitionTimer = setTimeout{this.nextSlide.bind(this),
delay);
К |
|
|
nextSlide: function{) { |
||
|
if ( this.hasNextO |
) |
|
this.next(); |
|
|
else |
|
|
this.loadRSSFeed(0, true); |
|
|
this.transitionTimer = setTimeout{ |
|
|
|
this.nextSlide.bind(this), |
), |
|
this.options.slideTransitionDelay ) ; |
|
ш |
Приведенный метод startSlideShow вызывает nextSlide после заданной задержки. В зависимости от того, возобновляем ли мы слайд-шоу после паузы или нет, задержка равна либо slideTransitionDelay, либо одной миллисекунде (практически мгновенно). Таким же простым является и метод nextSlide, вызывающий метод next() при наличии следующего слайда. Если текущий слайд является последним в данной ленте, вызывается loadRSSFeed(0,true) и мы переходим на начало ленты. После этого просто устанавливается таймер и процесс повторяется. Все очень легко!
Мы уже говорили, что слайд-шоу можно приостановить с помощью кнопки паузы, однако соответствующий метод еще не был реализован. Восполним этот пробел и создадим метод, показанный в листинге 13.35.
riv*i к i n i i O . O J . i v ( С 1чЛЦ u a U o c
"•явчвИнЯиИИН^ВДИв^вРИ^1 *i "•• -•;••••••'. • •Щ^шШЯШЩшШШШШЯШЯШЩШЯ^Ш^ШВЯШШЯШЩШШШШШШшШШШШШШШШШШШШШШШШШШ
pause: function() { if ( this.paused )
this.startSlideShow(true); else
clearTimeout( this.transitionTimer ); this.paused = !this.paused;
- ± |
- |
Метод pause переключает состояние паузы нашего слайд-шоу. Текущее состояние отслеживается с помощью булева атрибута this.paused. Если слайд-шоу уже приостановлено, метод pause вызывает функцию s t a r t - SlideShow, в качестве значения свойства resume передавая значение true;

564 Часть IV. Ajax в примерах
Таблица 13.5. Параметры Effect . FadeTo
Параметр |
Описание |
t h i s . getLayer ( l a y e r ) |
Затухающий элемент DOM |
п |
Степень прозрачности (значение между 0 и 1) |
t h i s . o p t i o n s . f adeDuration |
Время затухания |
12 |
Число промежуточных этапов |
{complete: onComplete} |
Обратный вызов, запускаемый после завершения |
близкое к 1 (но не точно 1), похоже, немного уменьшает мерцание изображения, поэтому вместо 1 мы будем использовать величину 0,9999. Чтобы указать, какой слой должен затухать, мы передаем функции номер слоя (0 или 1). Наконец, последний аргумент — это функция, обеспечивающая перехват обратного вызова сразу после завершения перехода. Реализация метода fadeTo() показана в листинге 13.38.
fadeTo: function( n, layer, onComplete ) { new Effect.FadeTo( this.getLayer(layer),
n,
this.options.fadeDuration,
12,
{complete: onComplete J |
); |
|
Ь |
|
л |
Из-за внезапного приступа лени или в качестве продуманного методологического приема мы решили не изобретать заново эффект перехода. Вместо этого мы используем метод Effect. FadeTo из библиотеки Rico, который и выполнит всю работу. Параметры Effect.FadeTo приведены в табл. 3.5.
Чтобы получить элемент div, соответствующий затухающему слою содержимого, мы использовали вспомогательный метод getLayerO, показанный в листинге 13.39.
Листинг 13.39. Метод aetLaverO _ | Ц ^ Н ^ ^ ^ ^ Д | Н ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ И в getLayer: function(n) {
var contentArea - $(this.id+'_content');
var children = contentArea.childNodes; var j = 0; for ( var i = 0 ; i < children.length ; i++ } {
if ( children[i].tagName && children[i].tagName.toLowerCase() == 'div' ) { if ( j -~ n ) return children[i];
}
}
return null;
Глава 13. Создание приложений Ajax, не использующих сервер 565
Данный метод находит область содержимого, предполагая, что ее идентификатор построен как идентификатор приложения с дописанным в конец значением _content. Найдя элемент содержимого, метод прослеживает его потомков и находит n-й дочерний элемент div.
Все, закончили и с переходами. Теперь рассмотрим тему загрузки RSSлент посредством магии Ajax.
Загрузка RSS-лент с помощью Ajax
Мы уделили довольно много внимания темам создания компонента и обеспечения богатой семантики слайд-шоу, а также необычных технологий DHTML для переходов между слайдами. Однако если все это не создано на основе инфраструктуры Ajax, гордиться совершенно нечем. Все дело в том, что идеальный пользовательский интерфейс может обеспечить только Ajax со своей масштабируемостью и индивидуальным извлечением данных плюс сложный DHTML со своими богатыми возможностями и эффектами. Говорить об этом можно долго, так что лучше все лее рассмотрим требуемую инфраструктуру Ajax, начав с метода, приведенного в листинге 13.40 и выполняющего загрузку RSS-ленты в память.
loadRSSFeed: function{feedlndex, |
forward) { |
|||
|
|
thxs.feedlndex = feedlndex; |
|
|
|
|
this.iteralndex = forward ? 0 |
: |
"last"; |
|
new net.ContentLoader(this, |
|
|
|
|
|
this.options.rssFeeds[feedlndex], |
||
|
|
"GET", |
[] |
).sendRequest(); |
) , |
|
|
я |
Данный метод с помощью давно знакомого объекта net.ContentLoader формирует запрос Ajax, передавая в качестве параметра URL RSS-ленты, заданный в массиве this.options.rssFeeds. Параметр forward представляет собой булеву величину, указывающую, что мы загружаем (или не загружаем) новое содержимое вследствие перехода на следующую статью. Далее, согласно этой информации, обновляется свойство itemlndex. Обратите внимание на то, что, если мы переходим назад, itemlndex получает значение, равное last, а не целочисленной величине. Такое решение объясняется тем, что свойство itemlndex должно указывать индекс последней статьи предыдущей RSS-ленты. Единственная проблема заключается в том, что мы не знаем, сколько статей в ленте, поскольку она еще не загружена.
Напомним, что согласно неявному контракту с net.ContentLoader нам требуются методы ajaxUpdate и handleError. Разберем вначале метод aj axUpdate, показанный в листинге 13.41, и посмотрим, как с помощью данной реализации разрешить нашу дилемму индексирования.
566 Часть IV. Ajax в примерах
Листинг 13.41. Метод *1а^Аз^ШШШШЯИШШШШШШШШ
aj axUpdate: function(request) { if ( window.netscape Sfi
window.netscape.security.PrivilegeManager.enablePrivilege)
netscape.security.PrivilegeManager.enablePrivilege( 'UniversalBrowserRead') ;
this.currentFeed = RSSFeed.parseXML(request.responseXML.documentElement);
if ( this-itemlndex == "last" )
this.itemlndex = this.currentFeed.items.length - 1; this.updateView();
__L |
|
ш |
Метод ajaxUpdate начинает с проверки того, что он работает в среде, предлагающей PrivilegeManager. Если да, тогда он затребует привилегию UniversalBrowserRead. Как отмечалось выше, это сделано для того, чтобы наше приложение могло запускаться локально в браузерах Mozilla.
В приведенном коде this.currentFeed — это экземпляр объекта модели RSSFeed, определенный в разделе "Модель". Он соответствует одной ленте RSSFeed, загруженной в память после отклика Ajax. Если значение this.itemlndex равно l a s t (такое значение устанавливается методом loadRSSFeed при возврате к предыдущей статье), свойство itemlndex обновляется в соответствии с реальным числом статей в новой загруженной ленте RSSFeed. Наконец, в ответ на вызов updateView() обновляется пользовательский интерфейс.
Не забывайте, что нам еще нужно определить метод handleError (не только потому, что это подразумевает контракт с net.ContentLoader, но и потому, что нам действительно нужно какое-то средство обработки ошибок). Если ленту RSS загрузить не удается, мы предоставляем сообщение, показанное в реализации handleError. Разумеется, возможны (и желательны) более сложные реализации.
handleError: function(request) {
this.getLayer(this.visibleLayer).innerHTML = this.options.errorHTML;
Ь
Итак, мы реализовали все необходимые возможности Ajax в приложении RSSReader, остался последний штрих — написать пару методов, обновляющих пользовательских интерфейс.
Обработка пользовательского интерфейса
Напомним, что классы модели и представления мы создавали так, чтобы облегчить себе реструктуризацию кода приложения. Теперь, переходя к контроллеру, отвечающему за обновление пользовательского интерфейса, мы можем считать, что сделана почти все работа. Это действительно так. Рассмотрим, например, метод updateView () (листинг 13.42), на который мы неоднократно ссылались в ходе предыдущей работы.
Глава 13. Создание приложений Ajax, не использующих сервер 567
ЛИСТИНГ 13.42. Метод updateViewf)
updateView: function() {
var rssItemView • new RSSItemView( this.currentFeed.items[this.itemlndex], this.feedlndex,
this.itemlndex, this.options.rssFeeds.length )j
this.getLayer(this.visibleLayer).innerHTML = rssItemView; this.fadeln( this.visibleLayer, this.bringVisibleLayerToTop.bind(this) );
— ± |
. |
Как видите, метод updateview() делегирует всю тяжелую работу классу представления, вызывая экземпляр этого класса и используя его как значение свойства innerHTML видимого слоя (в конечном счете это приводит к постепенному проявлению данного слоя). Три строчки кода. Совсем немного. Обратите внимание на то, что как только слой попадает в поле зрения, мы вызываем метод завершения работы bringVisibleLayerToTop. Этот метод обновляет стилевое свойство слоя z Index, вследствие чего данный слой становится выше другого, постепенно его затеняя. Реализация функции bringVisibleLayerToTop () выглядит следующим образом:
bringVisibleLayerToTop: function() {
this.getLayer(this.visibleLayer).style.zlndex = 10; this.getLayer((this.visibleLayer+1)%2).style.zlndex = 5;
}
Вот и все, что можно сделать с точки зрения работы с пользовательским интерфейсом. Разделяя обязанности между классами модели, представления и контроллера, мы смогли получить простую управляемую архитектуру.
13.7.4. Выводы
Реструктуризация заключается в таком изменении кода, чтобы мы получили MVC-представление нашего приложения для чтения RSS-лент. Мы создали класс модели RSSFeed, инкапсулирующий концепцию RSS-ленты, кроме того, создали класс RSSItem. Для инкапсуляции концепции представления элемента RSSItem в контексте родительского элемента RSSFeed был создан класс представления RSSItemView. Наконец, мы связали классы модели и представления с помощью класса контроллера RSSReader, объединяющего управление событиями и реализацию слайд-шоу с эффектами перехода.
13.8. Резюме |
|
_ |
В данной главе инфраструктура Ajax позволила получать информацию непосредственно с рабочего стола, не требуя коммерческого клиентского приложения, экономя наши деньги и позволяя настраивать решение согласно насущным потребностям. Нам удалось загрузить несколько XML-файлов и получить при этом только ту информацию, которая нас интересует. Мы разра-
>68 Часть IV. Ajax в примерах
ютали HTML-каркас приложения и применили правила CSS, что позволило сегко настраивать внешний вид программы. Используя DHTML, мы смогли >азработать богатый пользовательский интерфейс, позволяющий пользоватеим пропускать сообщения, приостанавливать их поток, а также добавлять ю мере необходимости новые ленты. Все это стало возможным благодаря инфраструктуре Ajax, разрешившей получать RSS-ленты с Web-сайтов. Измешв несколько операторов, мы можем легко настроить приложения на чтение побой XML-ленты. Кроме того, можно разрабатывать собственные форматы •CML для отображения новостей, рекламы и всего остального, что обычно разлетается на Web-сайтах. Наконец, мы провели реструктуризацию сценария ;огласно архитектуре "модель-представление-контроллер" (MVC), повысив штаемость и удобство эксплуатации кода.
Часть V
Приложения


572 Часть V. Приложения
Работать с технологией Ajax очень просто. Для выполнения всей работы вам потребуется лишь небольшой набор инструментов. Вообще, сложные приложения Ajax можно создавать, используя только Web-браузер, текстовый редактор и имея доступ к Web-серверу (который располагается либо на вашем компьютере, либо на каком-то Web-сайте, к которому вы имеет доступ). Тем не менее хороший набор инструментов очень важен для программиста, поэтому в настоящее время существует несколько таких довольно сложных наборов.
В настоящее время специализированных интегрированных сред разработки (Integrated Development Environment — IDE) Ajax не существует, хотя со временем они, скорее всего, появятся. Однако есть несколько инструментов разработки, предлагающих поддержку некоторых составляющих процесса разработки Ajax-продукта. В данном приложении представлен обзор доступных типов инструментов и рассказывается, как с их помощью разумнее и быстрее организовать свою работу.
АЛ. Правильный набор инструментов
Правильно подобранные инструменты разработки могут оказаться бесценными с точки зрения ускорения повторяющихся или сложных процессов и оказать огромнейшее влияние на производительность разработчика. "Неправильные" инструменты могут отвлекать внимание от необходимой работы, ограничивать возможности и вынуждать разработчика использовать только определенные процессы или совмещать в действительности несовместимые вещи. Различные разработчики предпочитают разные инструменты, которые, к тому же могут быть более или менее удачными для различных типов проектов. Иногда разработчику стоит потратить немного своего времени и выбрать набор инструментов, лучше всего подходящий для поставленной задачи. Пожалуй, лучше всего данную мысль сформулировал Авраам Линкольн:
"Если мне дадут шесть часов на то, чтобы срубить дерево, первые четыре из них я потрачу на затачивание топора".
Если вы будете поступать по такому же принципу, отдача может быть огромной. Разумеется, важно соблюдать и разумное соотношение между отладкой инструментов и их использованием, особенно если речь идет о нестандартной промежуточной ситуации, например, как в случае с существующими инструментами Ajax.
А.1.1. Получение совместимых инструментов
В настоящее время доступно множество инструментов в виде бесплатных пакетов, проектов с открытым исходным кодом и коммерческих продуктов. Мощных специализированных инструментов, предназначенных исключительно для Ajax, пока что не существует, однако имеются средства разработки Web-приложений, многие из которых поддерживают JavaScript, HTML и CSS.