Если попытаться в нескольких словах описать суть технологии AJAX, то получится примерно следующее: AJAX - это технология, позволяющая отправлять данные на сервер и получать ответ от него без перезагрузки страницы в браузере. Мы намерено не будем вдаваться в тонкости значения термина, поскольку будучи привлекательным маркетинговым концептом, AJAX оброс множеством споров и легенд. Для нас важно лишь, что под этим термином понимается любой способ обмена данными с сервером без перезагрузки страницы.
Для реализации подхода AJAX в XS2 удобнее всего воспользоваться уже готовым модулем "ajax", который представляет собой "обертку" весьма популярной библиотки JsHttpRequest Дмитрия Котерова. В общем виде протокол AJAX-сессии выглядит следующим образом:
Возникает некоторое событие на странице сайта, которое ведет к вызову функции Javascript;
Функция Javascript создает объект XS2AJAX, являющийся оберткой JsHttpRequest, назначает функцию, которая будет выполнена после возврата ответа сервера, и отправляет данные на сервер;
На стороне сервера выполняется метод XS2, который возвращает данные клиенту;
На стороне клиента вызывается функция Javascript, которая была назначена в п.2.
Рассмотрим реализацию этого протокола на конкретном примере. Нашей учебной задачей будет организация отправки сообщения в гостевую книгу без перезагрузки страницы. Как и в классической гостевой книге, посетитель видит на странице ленту сообщений форму для отправки. Однако после заполнения формы и нажатия на кнопку "Отправить" страница не перезагружается, а новое сообщение сразу же добавляется в ленту.
В Листинге 34 приведен код шаблона с сообщениями и формой, а также с Javascript-функцией, осуществляющей отсылку/прием данных по AJAX-протоколу.
В строке №3 мы вызываем метод "/ajax/init/", после чего в Javascript нам будет доступен объект XS2AJAX. Далее следует реализация метода отправки "submitPost()", который вызывается при нажатии на кнопку "Отправить" в форме. В строке №7 создается объект XS2AJAX, который является оберткой объекта JsHttpRequest. Кстати, экземпляр JsHttpRequest доступен через свойство "jshttprequest" объекта XS2AJAX. Однако в нашем методе мы используем методы и свойства объекта XS2AJAX, которые упрощены по сравнению с методами и свойствами JsHttpRequest.
В строке №9 мы назначаем в свойство "onready" функцию, которая выполнится после прихода данных с сервера, а в строке №21 производим отправку формы методу "/guestbook/post/add/".
Далее управление передается серверу. Код метода "/guestbook/post/add/" приведен в Листинге 35 (процессор) и Листинге 36 (шаблон).
Код строк №2 и №3 Листинга 35 обеспечивает возврат данных из метода в нужном формате. Стоит обратить внимание, что этот код нельзя выносить в методы, которые вызываются с помощью команды "xs2Fetch". После вызовов строк №2,3 мы можем использовать глобальный массив $_RESULT для возврата данных обратно клиенту. Все, что мы назначим в нашем процессоре в этот массив, будет доступну в Javascript-коде через свойство "responseJS" объекта XS2AJAX.
Обратите внимание, что данные формы доступны в процессоре через предопределенный в PHP массив $_POST, то есть так, как будто форма была отправлена обычным методом "POST".
Метод "/guestbook/post/add/" имеет шаблон (Листинг 36), то есть производит прямой вывод в браузер. Библиотека "JsHttpRequest" устроено таким образом, что весь прямой вывод в браузер "перехватывается" и становится доступным в Javascript-коде через свойство "responseText" объекта XS2AJAX. Это очень удобно для передачи html-кода, который на клиентской стороне вставляется в страницу. В нашем случае мы передаем обратно клиенту только что вставленное сообщение с html-оформлением.
После того, как метод на стороне сервера отработал, управление снова передается клиентской части в Javascript. В строке №10 Листинга 34 мы проверяем, не произошла ли ошибка, и если таковая имела место, выводим ее в элемент с идентификатором "state". Если ошибки не было, мы добавляем к уже имеющимся на странице сообщениям новое и выводим сообщение "готово". В строке №17 мы производим очистку формы.
В нашем примере мы отправляли через AJAX целиком целую форму, оформленную в html-коде тэгом FORM. Однако в некоторых случаях разработчик сталкивается с необходимостью отправки на сервер произвольных данных, полученных не из формы на странице, а из других источников. Библиотека JsHttpRequest позволяет это сделать. При этом данные будут доступны на стороне сервера все через тот же массив $_POST, то есть так, будто они были отправлены через форму.
Для примера рассмотрим хрестоматийную задачу организации действия "положить в корзину" на странице со списком товаров в интернет-магазине. В Листинге 37 представлен цикл вывода товаров на странице и Javascript-функция, отправляющая информацию о том, какой товар кладется в корзину, на сервер:
Интерес для нас представляют строка №9. Вместо объекта "FORM" мы указываем в первом параметре функции "send()" объект Javascript, содержащий в качестве полей данные, отправляющиеся на сервере. В нашем примере этот объект состоит из двух полей: "NodId" и "Amount". На сервере оба поля будут доступны как элементы массива $_POST: $_POST['NodId'] и $_POST['Amount'].
Еще одной из частых задач при работе с AJAX является отправка на сервер файла. Единственным способ отправки файла с локальной машины на сервер через браузер - это использование элемента "INPUT" типа "file" (естественно, мы исключаем такие решения, как Flash или Java-апплет). При отправке файла через AJAX точно также используется INPUT типа "file". На сервере отправленные браузером файлы доступны через предопределенный массив PHP $_FILES, а это значит, что работа с ними производится абсолютно так же, как при обычной отправке файла методом POST. Листинги 38 и 39 представляются соответственно клиентскую и серверную части, отвечающие за отправку файла фотографии через AJAX.
Одним из достоинств библиотеки JsHttpRequest является то, что она предоставляет разработчику возможность кэшировать частые ajax-запросы. Для этого всего лишь достаточно назначить свойство "caching" объекта XS2AJAX в "true". В этом случае если вызвать функцию send() дважды с одинаковыми параметрами, то второй раз данные вернутся из кэша - запрос даже не пойдет на сервер. Приведем небольшой пример. Листинг 40 содержит кода страницы, на который пользователь может указать станцию метро с помощью двух выпадающих списков. В первом выпадающем списке перечислены линии. Вы выборе определенной линии во второй список динамически подгружаются станции, находящиеся на этой линии. Очевидно, что пользователь может несколько раз менять линию в первом списке, и не имеет смысла повторно запрашивать станции для линии, для которой они уже запрашивались ранее. Для этого достаточно воспользоваться свойством "caching".
В заключении этой главы следует отметить, что тот способ организации AJAX, который представлен здесь, не является единственно возможным в XS2. Разработчик может использовать другие библиотеки, самостоятельно подключив их как отдельные методы или модули. Библиотека JsHttpRequest была выбрана как наиболее универсальная и кроссбраузерная.