Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
107
Добавлен:
02.05.2014
Размер:
6.34 Mб
Скачать

Глава 3. Управление кодом Ajax 135

возможности языка формируют специфический стиль программирования. Несмотря на то что сам код Prototype сложен для восприятия, так как он далек от стиля Java/C#, пользоваться самой библиотекой и другими библиотеками, созданными на ее основе, очень просто. Prototype молено рассматривать как библиотеку для разработчиков библиотек. При работе над Ajax-приложениями целесообразнее использовать библиотеки, созданные на основе Prototype, чем сами базовые средства. Некоторые из этих библиотек мы рассмотрим в следующем разделе. Здесь же ограничимся кратким обсуждением основных средств Prototype. Это нужно для того, чтобы понять стиль кодирования и лучше разобраться в продуктах Scriptaculous, Rico и Ruby on Rails.

Prototype обеспечивает "расширение" одного объекта другим путем копирования всех свойств и методов родительского объекта в дочерний объект. Эту особенность лучше рассмотреть на конкретном примере. Предположим, что мы определили родительский класс Vehicle.

function Vehicle(numWheels,maxSpeed){ this.numWheels=numWheels; this.maxSpeed=maxSpeed;

}

Мы хотим создать конкретный экземпляр этого класса, представляющий пассажирский поезд. В дочернем классе также нужны средства, представляющие число вагонов и механизм для изменения этого значения. Пользуясь обычными средствами JavaScript, мы можем написать следующий код:

var passTrain=new Vehicle(24,100); passTrain.carriageCount=12; passTrain.addCarriage=function(){

this.carriageCount++;

}

passTrain.removeCarriage=function(){

this.carriageCount—;

}

Итак, мы реализовали функциональные возможности, необходимые для объекта passTrain. Анализируя код с точки зрения специалиста по проектированию программ, можно сказать, что в нем практически ничего не сделано для формирования привычного всем объекта. Prototype может помочь в решении подобных задач, определяя функции и расширяя с их помощью базовый объект. Определим расширенные возможности и оформим их в виде объекта.

function CarriagePuller(carriageCount){ this.carriageCount=carriageCount; this.addCarriage=function(){ this.carriageCount++;

)

this.removeCarriage=function(){

this.carriageCount—;

}

}

136 Часть I. Новый взгляд на Web-приложение

Затем объединим созданные средства с базовым объектом, обеспечив требуемое поведение.

var parent=new Vehicle(24,100) ;

var extension=new CarriagePuller(12);

var passTrain=Object.extend(parent,extension);

Заметьте, что родительский объект и объект расширения были определены независимо друг от друга, а лишь затем мы объединили их. Отношение "родительский-дочерний" имеет место между экземплярами, а не между классами Vehicle и CarriagePuller. Несмотря на то что данное решение не соответствует строго объектному подходу, весь код для конкретного действия, в нашем случае это движение вагонов, содержится в одном месте, а это упрощает его повторное использование. Если для небольших примеров подобные приемы могут показаться излишними, то для масштабных приложений они оказываются очень полезными.

Библиотека Prototype также предоставляет средства поддержки Ajax — объект, позволяющий извлекать объект XMLHttpRequest при работе на различных браузерах. Тип Ajax.Request используется для передачи запросов серверу посредством объекта XMLHttpRequest.

var req=new Ajax.Request('myData.xml');

В конструкторе используется стиль программирования, который часто встречается в библиотеках на базе Prototype. В качестве необязательного параметра указывается ассоциативный массив, позволяющий при необходимости задавать различные установки. Для каждой из них предусмотрено значение по умолчанию, поэтому указывать надо только те параметры, которые необходимо изменить. В конструкторе Ajax.Request посредством ассоциативного массива можно указать передаваемые данные, параметры запроса, HTTPметод и функцию обратного вызова. Пример вызова Ajax.Request, в результате которого переопределяются некоторые установки, приведен ниже.

var req=new Ajax.Request( 'myData.xml1,

{method: 'get1 ,

parameters: { name:'dave',likes:'chocolate,rhubarb' }, onLoaded: function(){ alert('loaded!'); }, onComplete: function(){

alert (' done! \n\n' +req. transport. responseText) ;

}

}

);

Здесь посредством массива задаются четыре параметра. Поскольку в библиотеке Prototype по умолчанию используется метод post, то метод get приходится указывать явно. При использовании метода get строка параметров присоединяется к URL в первой строке запроса. Если бы мы использовали метод post, параметры помещались бы в тело запроса. Обработчики onLoaded и onComplete представляют собой функции обратного вызова, которые получают управление тогда, когда свойство readyState объекта XMLHttpRequest изменяется. Переменная req. transport в функции onComplete содержит ссылку на объект XMLHttpRequest.

Глава 3. Управление кодом Ajax

137

На основе Ajax.Request определен тип Ajax.updater, который загружает фрагменты сценария, сгенерированные сервером, и выполняет их. Такой подход соответствует шаблону, ориентированному на сценарий. Мы подробно опишем его в главе 5.

На этом мы завершаем краткий обзор библиотек, предназначенных для работы с различными браузерами. Набор библиотек, описанных здесь, далеко не полон, а библиотеки, приведенные в качестве примера, выбраны почти случайным образом. Как уже было сказано ранее, разработки в этой области ведутся достаточно интенсивно, и в ближайшее время можно ожидать появления новых продуктов. В следующем разделе мы рассмотрим ряд компонентов, созданных на базе библиотек, рассмотренных ранее, и других библиотек.

3.5.2. Компоненты и наборы компонентов

Рассмотренные нами библиотеки обеспечивают поддержку различных браузеров на достаточно низком уровне. В частности, они позволяют работать с элементами DOM и загружать ресурсы с сервера. Данные инструменты существенно упрощают создание пользовательских интерфейсов и логики приложений, но, несмотря на это, объем работы остается гораздо большим, по сравнению тем, который требуется при использовании Swing, MFC или Qt.

По этой причине начали появляться компоненты и их наборы, ориентированные на работу с Ajax. В данном разделе мы рассмотрим некоторые из них. Как и прежде, мы ставим перед собой задачу не детально изучить, а лишь сформировать общее представление об этих компонентах.

Scriptaculous

Библиотека компонентов Scriptaculous создана на базе библиотеки Prototype, которую мы рассматривали в предыдущем разделе. На сегодняшний день Scriptaculous предоставляет лишь два набора функций, однако работа над данной библиотекой продолжается и разработчики планируют реализовать дополнительные возможности.

Библиотека Effects определяет визуальные анимационные эффекты, которые молено применить к элементам DOM для изменения их размеров, расположения и прозрачности. Элементы в составе Effects можно легко объединять друг с другом, реализуя вторичные эффекты. Например, вызов Puff () приводит к тому, что размеры элемента увеличатся, в то же время он станет более прозрачным и наконец исчезнет с экрана. Еще одна базовая функция, ParalleK), позволяет одновременно применить несколько эффектов. Библиотека Effects хорошо подходит для тех случаев, когда надо быстро реализовать визуальную обратную связь с пользователем. Пример ее применения будет приведен в главе 6.

Для применения эффекта обычно достаточно вызвать конструктор и передать ему в качестве параметра целевой элемент DOM либо его идентификатор, например:

new Effect.SlideDown(myDOMElement);

138Часть I. Новый взгляд на Web-приложение

Воснове эффектов, реализованных в данной библиотеке, лежит принцип перемещения объектов с учетом временных параметров и событий. Разработчику предоставляется возможность использовать линейное и синусоидальное перемещение, а также качание и пульсацию. Для создания эффектов, определяемых пользователем, достаточно объединить основные эффекты и задать соответствующие параметры. Подробное их обсуждение выходит за рамки нашего краткого обзора. Пример применения эффектов Scriptaculous будет приведен в главе 6 при разработке системы оповещения.

Набор Scriptaculous также содержит библиотеку, обеспечивающую перетаскивание объектов с помощью мыши. Эту возможность предоставляет класс Sortable. Он получает родительский элемент DOM и обеспечивает перетаскивание всех дочерних элементов. Параметры, передаваемые конструктору, позволяют задать обработчики обратного вызова, получающие управление при движении или опускании объекта, типы дочерних элементов и список целевых объектов (т.е. элементов, которые могут принять перетаскиваемый объект в том случае, если пользователь отпустит кнопку мыши в тот момент, когда курсор находится над одним из них). В качестве параметров могут быть также указаны объекты Effect. Их действие проявляется при нажатии кнопки мыши, в процессе движения курсора либо при отпускании кнопки мыши.

Rico

Подобно Scriptaculous, средства Rico созданы на базе библиотеки Prototype и также предоставляют настраиваемые эффекты и возможность перетаскивания объектов. Кроме того, средствами Rico поддерживается объект Behavior — фрагмент кода, применяемый к поддереву DOM для реализации интерактивных функций. Примером применения Behavior может служить компонент Accordion, который помещает набор элементов DOM в заданную область и расширяет их по одному. (Компонент такого типа обычно называют полосой outlook (outlook bar), поскольку он получил популярность благодаря использованию в Microsoft Outlook.)

Создадим простой компонент Rico Accordion. Нам потребуется родительский элемент DOM; каждый элемент, дочерний по отношению к нему, становится отдельной панелью в составе области. Для каждой панели мы определяем элемент div, содержащий еще два элемента div, которые задают заголовок и тело панели.

<div id='myAccordion'> <div>

<div>Dictionary Definition</div> <div>

<ul>

<li><b>n.</b>A p o r t a b l e

wind

i n s t r u m e n t w i t h a

s m a l l

keyboard and

f r e e

m e t a l

r e e d s

t h a t sound

when

a i r i s

f o r c e d p a s t

them

b y p l e a t e d

b e l l o w s

o p e r a t e d b y t h e

p l a y e r . < / l i >

 

 

 

 

 

 

 

 

<li><b>adj . </b>Having f o l d s

o r

bends

l i k e

t h e

b e l l o w s

o f a n a c c o r d i o n : a c c o r d i o n p l e a t s ; a c c o r d i o n b l i n d s . < / l i >

Глава 3. Управление кодом Ajax 139

</ul>

</div>

</div>

<div>

<div>A picture</div> <div>

<img src='monkey-accordion.jpg'X/img> </div>

</div>

</div>

Первая панель предоставляет статью словаря, определяющую слово accordion (аккордеон), а вторая панель содержит изображение обезьяны, играющей на аккордеоне (рис. 3.9). При воспроизведении без применения специальных средств эти два элемента размещаются один над другим. Однако мы присвоили элементу div верхнего уровня идентификатор и можем передать его объекту Accordion, код которого приведен ниже.

var outer=$('myAccordion') ; outer.style.width='320px'; new Rico.Accordion{

outer,

{ panelHeight:400, expandedBg:'#909090', collapsedBg:'#404040',

}

);

Первая строка выглядит несколько необычно. Символ $ допустим в имени переменной и, использованный так, как показано выше, ссылается на функцию в базовой библиотеке Prototype. Функция $ () выполняет преобразование узлов DOM подобно тому, как это делает функция библиотеки х xGetElementByld(), рассмотренной в предыдущем разделе. Мы передаем конструктору объекта Accordion ссылку на преобразованный элемент DOM, а также массив параметров (подобный подход часто применяется в библиотеках, созданных на базе Prototype). В данном случае параметры лишь задают стили для визуальных элементов компонента Accordion. При необходимости можно также указать функцию обратного вызова, которая получит управление при открытии или закрытии панели. На рис. 3.9 показан эффект, полученный в результате применения объекта Accordion к элементам DOM. Объект Behavior предоставляет средства для создания" на базе популярных элементов разметки компонентов, пригодных для повторного использования, и обеспечивает разделение содержимого и интерактивного поведения. Разговор о принципах разработки пользовательского интерфейса средствами JavaScript мы продолжим в главе 4.

Внимание заслуживает также средство Rico, обеспечивающее поддержку запросов к серверу в стиле Ajax. Эти запросы реализуются посредством глобального объекта AjaxEngine. Возможности объекта AjaxEngine не ограничиваются использованием XMLHttpRequest в различных браузерах. Он определяет ответ в формате XML, состоящий из набора элементов response. Процессор Rico автоматически декодирует их и обеспечивает поддержку двух

140 Часть I. Новый взгляд на Web-приложение

Рис. 3.9. Средства B e h a v i o r в составе Rico позволяют оформлять обычные узлы DOM в виде интерактивных компонентов. Для того чтобы сделать это, достаточно передать ссылку на узел верхнего уровня конструктору объекта B e h a v i o r . В данном случае объект A c c o r d i o n применен к набору элементов d i v (его внешний вид, полученный без использования A c c o r d i o n , показан слева). В результате формируется интерактивный компонент (он представлен справа), в котором по щелчку мыши открываются и закрываются отдельные панели

типов ответа. Один из этих типов предполагает непосредственное обновление элементов D0M, а второй — замену объектов JavaScript. Аналогичный механизм будет более подробно рассмотрен в разделе 5.5.3 при обсуждении взаимодействия клиента и сервера. Теперь перейдем к рассмотрению базовых средств, которые воздействуют на работу как клиента, так и сервера.

3.5.3. Элементы, располагаемые на стороне сервера

Средства, которые мы рассматривали до сих пор, выполняются исключительно в среде браузера и могут обсуживаться любым Web-сервером как обычные JavaScript-файлы. Сейчас мы рассмотрим программные компоненты, которые располагаются на стороне сервера и динамически генерируют JavaScript-код или элементы разметки HTML.

Эти компоненты гораздо сложнее рассмотренных ранее. Данные средства мы также не будем обсуждать подробно, а ограничимся лишь кратким рассмотрением их возможностей. К программным средствам, располагаемым на стороне сервера, мы вернемся в главе 5.

DWR, JSON-RPC и SAJAX

Начнем наш разговор о программных средствах, выполняющихся на стороне сервера, с обсуждения трех продуктов. Мы рассматриваем их совместно, поскольку в них, несмотря на различие языков, применяется один и тот же подход. SAJAX работает с разными языками, которые используются для создания программ, выполняющихся на стороне сервера, а именно: РНР,

Глава 3. Управление кодом Ajax 141

python, Perl и Ruby. DWR (Direct Web Remoting) базируется на языке Java и вместо отдельных функций предоставляет методы объектов. JSON-RPC (JavaScript Object Notation-based Remote Procedure Calls) поддерживает работу с JavaScript для сервера, Python, Ruby, Perl и Java.

Все три продукта позволяют создавать на стороне сервера объекты, методы которых непосредственно доступны для запросов Ajax. В процессе работы Ajax-приложений часто используются функции, выполняющиеся на сервере и возвращающие результаты вычислений. Необходимость в подобных функциях возникает по разным причинам, например, с их помощью можно обрабатывать данные, полученные из базы. Рассматриваемые здесь средства обеспечивают доступ к таким функциям или методам из программ, выполняющихся в среде браузера, в частности, предоставляют клиентскому коду программные средства, реализующие модель.

Рассмотрим пример использования SAJAX для работы с РНР-функциями, определенными на сервере. В данном случае функция, выбранная в качестве примера, лишь возвращает строку текста.

<?php

function sayHello(name){

return("Hello! {$name} Ajax in Action!!!!"); ?>

Для того чтобы представить эту функцию JavaScript-программе на клиентском уровне, нам надо импортировать в PHP-программу процессор SAJAX и вызвать функцию sajax_export.

<?php

require('Saj ax.php') ; sajax_init() ; sajax_export("sayHello") ; ?>

После создания динамической Web-страницы мы используем SAJAX для генерации JavaScript-оболочки экспортируемых функций. Сгенерированный код создает функцию JavaScript, заголовок которой идентичен функции на стороне сервера.

<script type='text/javascript'> <?

sajax_show_javascript(); ?>

alert(sayHello("Dave"));

</script>

При вызове функции sayHello ("Dave") в среде браузера сгенерированный JavaScript-код формирует Ajax-запрос серверу, функция выполняется на стороне сервера и результаты возвращаются в составе HTTP-ответа. При разборе ответа извлекается возвращаемое значение и передается JavaScriptпрограмме. Разработчику не приходится непосредственно применять технологии Ajax; все необходимые действия скрыты от него и выполняются библиотеками SAJAX.

142 Часть I. Новый взгляд на Web-приложение

Все три рассматриваемых здесь продукта осуществляют низкоуровневое отображение функций на стороне сервера в клиентские вызовы Ajax. Они автоматизируют рутинные операции, требующие много времени и усилий, но при их использовании возникает опасность доступа к серверной логике из Интернета. Этот вопрос мы подробнее рассмотрим в главе 5.

Остальные средства, рассматриваемые в этом разделе, действуют более сложным образом — они генерируют уровни пользовательского интерфейса для моделей, объявленных на сервере. Несмотря на использование технологий Ajax, они следуют своим собственным программным моделям. В результате работа с этими продуктами несколько отличается от написания универсальных Ajax-приложений.

Backbase

Backbase Presentation Server предоставляет обширный набор компонентов, связываемых в процессе работы с XML-дескрипторами. Они включаются в HTML-документы, сгенерированные сервером. Общий принцип работы аналогичен работе компонентов Rico Behavior, за исключением того, что вместо HTML-дескрипторов Backbase использует для обозначения компонентов пользовательского интерфейса произвольно задаваемый набор XHTMLэлементов.

Backbase предоставляет реализацию серверных компонентов для Java и

.NET и распространяется на коммерческой основе.

Echo2

Продукт NextApp Echo2 представляет собой процессор на базе Java, который генерирует богатые компоненты пользовательского интерфейса, объявленные на сервере. При загрузке в браузер компоненты работают автономно; взаимодействие с пользователями обеспечивает сценарий JavaScript. При необходимости они обращаются к серверу, используя очередь запросов, подобную той, которая применяется Riсо.

Echo2 считается решением на базе Ajax. Для работы с ним не требуется знание HTML, JavaScript или CSS, если, конечно, пользователь не собирается расширять набор доступных компонентов. В большинстве случаев разработка клиентских приложений осуществляется с использованием только средств Java. Исходные коды Echo2 открыты. Допускается применение данного продукта в коммерческих целях.

Ruby on Rails

Ruby on Rails представляет собой набор средств для разработки приложений, написанных на языке программирования Ruby. В рамках данного продукта объединены решения для отображения серверных объектов в базу данных и представления содержимого с помощью шаблонов. В основном он соответствует архитектуре "модель-представление-контроллер" для сервера, которая была описана в разделе 3.4. Ruby on Rails обеспечивает быструю разработку как простых Web-узлов, так и средней сложности. Генерация ко-

Глава 3. Управление кодом Ajax 143

пов общего назначения осуществляется автоматически. Количество установок, необходимых для получения работающего приложения, также сведено к минимуму.

Последние версии Rails обеспечивают поддержку Ajax посредством библиотеки Prototype. Prototype и Rails естественным образом сочетаются друг с другом, поскольку JavaScript-код для Prototype сгенерирован из программ Ruby и стили программирования совпадают. Как и в случае с Echo2, Rails не требует знания Ajax-технологий, в частности JavaScript, однако разработчик, знакомый с этим языком, может расширить средства поддержки Ajax.

На этом мы заканчиваем обзор продуктов независимых производителей для Ajax. Как уже было сказано ранее, работа над большинством рассмотренных здесь средств продолжается.

Разработчики многих библиотек придерживаются собственного стиля программирования, поэтому при написании примеров для данной книги мы старались передать характерные черты технологий Ajax и в то же время избежать глубокого изучения конкретных продуктов. Некоторые из рассмотренных здесь средств будут встречаться и далее в книге.

3.6. Резюме

В данной главе реструктуризация рассматривалась как средство для повышения качества кода и обеспечения дополнительной степени гибкости программ. Мы начали с того, что использовали реструктуризацию для упрощения доступа к объекту XMLHttpRequest. Был рассмотрен ряд образов разработки, которые можно применять при работе с Ajax для решения проблем, типичных для различных задач программирования. Образы разработки представляют собой полуформальные средства представления знаний разработчиков, которые решали задачи определенных типов. Они могут быть использованы при реструктуризации, преследующей определенные цели.

Образы Facade и Adapter предоставляют удобные способы устранения различий между разными реализациями. В Ajax-приложениях эти образы могут быть использованы для создания дополнительного уровня кода, скрывающего различия браузеров. Следует заметить, что несоответствие браузеров является.постоянным источником проблем при работе с JavaScript.

Observer — это гибкий образ для работы с системами, управляемыми событиями. Мы вернемся к его использованию в главе 4 при рассмотрении уровней пользовательского интерфейса приложения. Будучи использованным совместно с Command, предоставляющим удобный способ инкапсуляции действий пользователя, Observer может быть применен для поддержки ввода данных и отмены выполненных действий. Как вы увидите в главе 5, образ разработки Command также находит применение в организации взаимодействия клиента и сервера.

Образ разработки Singleton обеспечивает доступ к конкретным ресурсам. В Ajax этот образ часто применяется для управления обменом по сети. Данный вопрос также будет обсуждаться в главе 5.

144Часть I. Новый взгляд на Web-приложение

Вэтой главе мы подробно обсудили архитектуру "модель-представление- контроллер", хорошо зарекомендовавшую себя в различных областях (в том числе и при создании программ для работы в Интернете). В частности, данную архитектуру удобно использовать для создания Web-приложений. Мы говорили о том, каким образом MVC способствует повышению степени гибкости программ, выполняемых на стороне сервера, в том числе обсудили важность уровня абстрактных данных и шаблонов.

Пример программного обеспечения интерактивного магазина продемонстрировал совместное применение образов разработки и реструктуризации. С первого раза трудно создать совершенный код, поэтому реструктуризация является сложным, но необходимым этапом работы, призванным обеспечить преимущества образов разработки для конкретной программы. Конечный результат существенно отличался от программы, полученной на первом этапе разработки.

И наконец, мы рассмотрели библиотеки и компоненты независимых производителей. Они также могут быть применены для упорядочения кода, создаваемого в рамках Ajax-проектов. В настоящее время доступны средства, которые могут быть использованы при решении различных задач: от формирования оболочек, скрывающих различия между браузерами, до программных решений, включающих создание клиентского и серверного кода. Кроме того, в главе описано несколько наиболее популярных продуктов, и к некоторым из них мы еще вернемся в этой книге.

В следующих двух главах мы применим полученные знания о реструктуризации и образах разработки при создании клиентских программ Ajax и систем, предполагающих взаимодействие клиента и сервера. Эти примеры подскажут вам способы решения задач, с которыми вы наверняка столкнетесь при разработке сложных Web-приложений.

3.7. Ресурсы

Мартин Фаулер (Martin Fowler), а также его соавторы Кент Бек (Kent Beck), Джон Брант (John Brant), Вильям Опдайк (William Opdyke) и Дон Роберте (Don Roberts) написали хорошее руководство по реструктуризации: Refactoring: Improving the Design of Existing Code (Addison-Wesley Professional, 1999).

Эрик Гамма (Erich Gamma), Ричард Хелм (Richard Helm), Ральф Джонсон (Ralph Johnson) и Джон Влиссидс (John Vlissides), известные как "команда четырех", написали книгу Design Patterns (Addison-Wesley Professional, 1995), которую высоко оценили многие разработчики программного обеспечения.

Впоследствии Эрик Гамма занялся архитектурой интегрированной среды разработки Eclipse (подробнее о ней речь пойдет в приложении А). С текстом интервью, в котором обсуждались Eclipse и образы разработки, можно ознакомиться по адресу http://www.artima.com/lejava/articles/gammadp.html.

Майкл Мехемофф (Michael Mahomoff) поддерживает Web-узел, посвященный образам разработки для Ajax (http://www.ajaxpatterns.org).