Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax_v_deystvii.pdf
Скачиваний:
38
Добавлен:
05.03.2016
Размер:
5.83 Mб
Скачать

Пожалуй, это все, на что можно надеяться при адаптации библиотеки. Перейдем теперь к API портала. Изучая метод handleMouseUp (), можно догадаться об одной из трех команд портала, которые должен иметь компонент портала. При отпускании кнопки мыши вызывается метод saveWindowProp- e r t i e s t ) , записывающий состояние и положение текущего окна. Ниже мы подробно рассмотрим детали этого процесса, а также разберем другие API команд портала.

11.6.3. Задание команд портала

Как обсуждалось выше, наш компонент портала, в первую очередь, является отправителем команд. Отправляемые команды представляют собой запросы Ajax к серверной системе управления порталом. Понятие команд и формальную структуру Command в Ajax мы уже рассматривали в главах 3 и 5. Теперь мы изучим другую возможность использовать данные знания.

Итак, мы организовали в портале поддержку таких команд: регистрация, загрузка и запись настроек. Еще мы собираемся ввести возможность добавления и удаления окон, о которой мы уже упоминали, хотя и не показывали ее полную реализацию. Перечисленные возможности можно представлять как методы нашего портала. Однако, прежде чем мы начнем рассмотрение кода, выполним подготовительную работу, которая поможет нам в локализации изменений. Прежде всего, мы имеем в виду имена самих команд. Давайте определим символы для всех имен команд, чтобы их можно было использовать в любой части компонента. Рассмотрим следующий набор символов:

Portal.LOGIN_ACTION » "login"; Portal.LOAD__SETTINGS_ACTION - "PageLoad"; Portal.SAVE_SETTINGS_ACTION = "UpdateDragWindow"; Portal.ADD_WINDOW_ACTION - "AddWindow"; Portal.DELETE_WINDOW_ACTION - "DeleteWindow";

Хотя используемый язык и не поддерживает напрямую константы, предположим, что, используя договоренность о прописных буквах, можно считать указанные значения постоянными. Мы можем просто провести данные строковые литералы через наш код, но данный подход слишком неаккуратен. При подобном использовании констант наши "магические" строки будут располагаться в одном месте. Если контракт сервера изменится, мы сможем к этому приспособиться. Представим, например, каким образом может измениться контракт сервера (табл. 11.1).

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

myPortal.issuePortalCommand( Portal.SAVE_SETTINGS_ACTION, "settingl=" + settinglValue, "setting2=" + setting2Value, . . . )-"

В данном сценарии мы рассматриваем метод issuePortalCommand(), принимающий в качестве первого аргумента имя команды (например, одну из

Таблица 11.1. Изменения открытого контракта

Изменение контракта сервера

Требуемое действие

Переименована команда (например,

Заменить правую часть оператора присваивания

PageLoad заменена глагольной

константы LOAD_SETTINGS_ACTION новым

формой LoadPage)

значением. Остальная часть кода не меняется

Сервер больше не поддерживает

Удалить контракт и выполнить глобальный поиск

команду

всех упоминаний команды. В каждом случае

 

произвести необходимую модификацию кода

Сервер поддерживает новую команду

Добавить константу для этой команды

 

и использовать ее имя в коде

наших констант) и переменное число аргументов, соответствующих параметрам, которые ожидает/требует команда. Как и следовало ожидать, параметры имеют точно такую же форму, которая требуется методом sendRequest() объекта net.ContentLoader. Определенный нами метод issuePortalCommand() можно реализовать следующим образом:

issuePortalCommand: function{ commandName ) {

/ / О Получить параметр действия

v a r a c t i o n P a r a m - t h i s . o p t i o n s [ t q u o t e a c t i o n p a r a m t q u o t e ] ; // © Получить суффикс URL

v a r u r l S u f f i x = t h i s . o p t i o n s [ t q u o t e u r l S u f f i x t q u o t e J ; i f ( ' u r l S u f f i x ) u r l S u f f i x = " " ;

v a r u r l = t h i s . b a s e U r l ; var callParms •" [];

if (actionParam){ callParms.push(

//© Применить параметр действия actionParam + "=" + commandName ); }else{

//О Применить суффикс URL

url += "/" + commandName + urlSuffix; } for ( var i = 1 ; i < arguments.length ; i++ )

callParms.push( argumentsfi] ); var ajaxHelper = new

// 0 Создать объект ContentLoader net.ContentLoader( this, url, "POST", [] );

ajaxHelper.sendRequest // 0 Отправить запрос

,apply( ajaxHelper, callParms );

),

Данный метод создает URL, основываясь на конфигурационных опциях, обсуждавшихся в разделе 11.6.1, Если мы установили значение actionParam О, оно будет добавлено к параметрам с помощью POST, передаваемым на сервер ©. Если нет, мы добавим команду к пути URL О, присоединяя суффикс URL, если он указан в опциях ©. Первый аргумент функции — имя команды. Все остальные аргументы рассматриваются как параметры запроса. Затем сформированный URL передается объекту ContentLoader ©, и, как показано в предыдущем примере, отправляется запрос со всеми предоставленными

параметрами ©. Благодаря данному методу все API команд нашего портала будут очень лаконичными . Еще один "бонус" подобного общего метода заключается в том, что мы можем поддерживать новые команды, появляющиеся на сервере, не меняя код клиентской части приложения. А теперь рассмотрим команды, которые мы уже знаем.

регистрация

Напомним, что обработчик событий onclick нашей кнопки регистрации инициирует вызов метода login () страницы, который в свою очередь вызывает указанный выше метод. Функция login (по крайней мере, с точки зрения сервера) представляет собой команду, которую сервер должен обработать, проверив предоставленную пользователем регистрационную информацию, а затем (если эта информация верна) ответив так же, как команда load-page. Учитывая сказанное, рассмотрим реализацию функции login (), показанную в листинге 11.15.

login: function(userName, password) { this.userName = userName; this.password - password;

if ( this.options.messageSpanld ) document.getElementById(

this.options.messageSpanld).innerHTML = "Verifying Credentials";

 

this.issuePortalCommand( Portal.LOGIN_ACTION,

 

 

},

"user=" + this.userName, "pass=" + this.password

);

 

 

 

m

Данный метод помещает сообщение "Verifying Credentials" в элемент span, определяемый настраиваемой опцией t h i s . options .messageSpanld. Затем он отправляет команду login внутреннему коду портала, передавая регистрационную информацию, полученную методом в виде параметров запроса. Всю сложную работу выполняет метод issuePortalCommand{).

Загрузка настроек

Напомним, что функция createPortai () нашей страницы вызывает указанный выше метод для загрузки исходной конфигурации окон портала. Для загрузки настроек страницы применяется метод, который даже проще рассмотренного выше метода регистрации. Это просто удобная интерфейсная оболочка вокруг команды issuePortalCommand{). В качестве единственного своего параметра, используемого сервером для загрузки нужных настроек окон, она передает имя пользователя.

loadPage: function(action) {

this.issuePortalCommand( Portal.LOAD_SETTINGS_ACTION, "user=" + this.userName, "pass=" + this.password ); },

476 Часть IV. Ajax в примерах

Запись настроек

Метод записи настроек также достаточно прост. Напомним, что данный метод вызывается адаптированной библиотекой AjaxWindows.js при наступлении события mouseup и производит запись всех операций перемещения и изменения размеров.

saveWindowProperties: function(id) {

this.issuePortalCommand( 'portal.SAVE_SETTINGS_ACTION, "ref=" + id, "x=" + parselnt(elemWin.style.left), "y=" + parselnt(elemWin.style.top),

»w=" + parselnt(elemWin.style.width),

"h=" + parselnt(elemWin.style.height) ); elemWin = null; },

Добавление и удаление окон

Хотя мы не полностью разработали концепцию добавления и удаления окон (по крайней мере, с точки зрения пользовательского интерфейса, удобного для инициации этих действий), мы можем определить командные методы API, поддерживающие указанные операции.

addWindow: f u n c t i o n ( t i t l e ,

u r l , х,

у,

w,

h)

{

 

 

 

t h i s . issuePortalCommand (

P o r t a l .ADD__WINDOW_ACTION,

" t i t l e - "

+

t i t l e ,

" u r l - "

+

u r l ,

"x="

+ x,

" y = " + y, " w = " + w, " h = " + h ) ; },

 

deleteWindow: f u n c t i o n ( i d )

{

 

 

 

 

 

 

 

 

v a r d o D e l e t e •

 

 

 

 

 

 

 

 

 

 

c o n f i r m ( " A r e you

s u r e

you

want

to

d e l e t e

t h i s

window?");

i f ( d o D e l e t e ) t h i s . i s s u e P o r t a l C o m m a n d (

 

 

 

 

Portal.DELETE_WINDOW_ACTION,

" r e f = " +

id

);

},

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

11.6.4. Обработке средствами Ajax

Как уже отмечалось, в данном примере мы используем технологию Ajax для обработки ответов. В частности здесь реализуется взаимодействие, ориентированное на сценарии. Описанная технология основана на том, что ожидаемый ответ сервера представляет собой приемлемый код JavaScript. При таком подходе очень желательно, чтобы клиенту для понимания ответа не требовалось выполнять какую-либо сортировку или синтаксический анализ. Ответ вычисляется с помощью метода JavaScript eval (), и в дальнейшем с клиента снимается вся ответственность. Недостаток данного подхода состоит Б ТОМ, что вся ответственность возлагается на сервер, который отвечает за понимание клиентской объектной модели и генерирует синтаксически верный ответ, согласующийся с требованиями языка (JavaScript). Второй недостаток описанного подхода частично устраняется с помощью использования для определения откликов популярной разновидности рассматриваемой технологии — JSON. Существуют определенные серверные библиотеки, помогающие гене-

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]