Solution Technologies
Управление сайтом без ограничений

Руководство разработчика XS2

Скачать pdf-версию.

Часть 2. Решения на платформе XS2

Глава 14. Применение технологии AJAX в XS2

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

Для реализации подхода AJAX в XS2 удобнее всего воспользоваться уже готовым модулем "ajax", который представляет собой "обертку" весьма популярной библиотки JsHttpRequest Дмитрия Котерова. В общем виде протокол AJAX-сессии выглядит следующим образом:

  1. Возникает некоторое событие на странице сайта, которое ведет к вызову функции Javascript;
  2. Функция Javascript создает объект XS2AJAX, являющийся оберткой JsHttpRequest, назначает функцию, которая будет выполнена после возврата ответа сервера, и отправляет данные на сервер;
  3. На стороне сервера выполняется метод XS2, который возвращает данные клиенту;
  4. На стороне клиента вызывается функция Javascript, которая была назначена в п.2.

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

В Листинге 34 приведен код шаблона с сообщениями и формой, а также с Javascript-функцией, осуществляющей отсылку/прием данных по AJAX-протоколу.

Листинг 34
1.  <html>
2.  <head>
3.  {xs2Fetch mod="ajax" met="init"}
4.  {literal}
5.  <script type="text/javascript">
6.    function submitPost(){
7.      var xsa = new XS2AJAX();
8.      var err = document.getElementById('error');
9.      xsa.onready = function(){
10.       if(xsa.responseJS.error!=''){
11.         document.getElementById('state').innerHTML = ¶
                 xsa.responseJS.error;
12.       }
13.       else{
14.         document.getElementById('posts').innerHTML += ¶
                 xsa.responseText;
15.         document.getElementById('state').innerHTML = ¶
                 "готово";
16.       }
17.       document.getElementById("main").reset();
18.     }
19. 
20.     document.getElementById('state').innerHTML = "идет ¶
                 отправка...";
21.     xsa.send(document.getElementById("main"), ¶
                 '/guestbook/post/add/');
22.   }
23. </script>
24. {/literal}
25. </head>
26. <body>
27.   {xs2GetNodes mod="guestbook" NType="post" var="posts" ¶
                 sort="CDate asc"}
28.   <div id="posts">
29.     {foreach from=$posts item="post"}
30.     <div>
31.      {$post.NName}, {$post.CDate}<br/>
32.      {$post.Text}
33.     </div>
34.     {/foreach}
35.   </div>
36.   <hr/>
37.   Отправить сообщение<br/>
38.   Все поля обязательны для заполнения.<br/>
39.   <form id="main" method="POST" onsubmit="return false">
40.     Ваше имя:<br/><input type="text" name="name" /><br/>
41.     Ваше сообщение:<br/><textarea ¶
                 name="text"></textarea><br/>
42.     <div id="state"></div>
43.     <button onclick="submitPost()">Отправить</button>
44.   </form>
45. </body>
46. </html>

В строке №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 (шаблон).

Листинг 35
1.  <?
2.  xs2Fetch(array('mod'=>'ajax','met'=>'jshttprequest_srv'));
3.  new JsHttpRequest();
4.  
5.  $_RESULT['error'] = '';
6.  
7.  if(!$_POST['name']){
8.     $_RESULT['error'] = 'Вы не заполнили обязательное поле ¶
                 "Имя"';
9.     return;
10. }
11. elseif(!$_POST['text']){
12.    $_RESULT['error'] = 'Вы не заполнили обязательное поле ¶
                 "Сообщение"';
13.    return;
14. }
15. 
16. $id = xs2InsertNode(array(
17.    'mod'=>'guestbook',
18.    'NType'=>'post',
19.    'ParId'=>1,
20.    'NFlag'=>'1',
21.    'NName'=>$_POST['name'],
22.    'Text'=>$_POST['text']
23. ));
24. 
25. $post = xs2GetNode(array('mod'=>'guestbook','NodId'=>$id));
26. 
27. $_HTML->assign("post",$post);
28. ?>

Листинг 36
1.  <div>
2.   {$post.NName}, {$post.CDate}<br/>
3.   {$post.Text}
4.  </div>

Код строк №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-функция, отправляющая информацию о том, какой товар кладется в корзину, на сервер:

Листинг 37
1.  {literal}
2.  <script type="text/javascript">
3.    function addToBasket(uid){
4.      var xsa=new XS2AJAX();
5.  
6.      xsa.onready = function(){
7.         alert('Товар добавлен в корзину.');
8.      }
9.      var a = document.getElementById("amount"+uid).value;
10.     xsa.send({'NodId':uid,'Amount':a}, '/shop/basket/add');
11.   }
12. </script>
13. {/literal}
14. ...
15. {foreach from=$items item="item"}
16.   <strong>{$item.NName}</strong>
17.   <img src="{$item.Image.path}"/>
18.   <div>
19.     {$item.Description}
20.   </div>
21.   <input type="text" id="amount{$item.NodId}"/>
22.   <button onclick="addToBasket({$item.NodId})">
23.     в корзину
24.   </button>
25. {/foreach}
26. ...

Интерес для нас представляют строка №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.

Листинг 38 ::
1.  {literal}
2.  <script type="text/javascript">
3.    function addToBasket(uid){
4.      var xsa=new XS2AJAX();
5.  
6.      xsa.onready = function(){
7.         alert('Ваша фотография отправлена.');
8.      }
9.      var f = document.getElementById("mainForm");
10.     xsa.send(f, '/galleries/photo/add');
11.   }
12. </script>
13. {/literal}
14. ...
15. <form id="mainForm" name="mainForm" ¶
                 enctype="multipart/form-data" ¶
                 method="POST" onsubmit="return false">
16.     Файл с фотографией:
17.     <input type="file" name="Image"/>
18.     <button onclick="sendPhoto()">
19.         отослать
20.     </button>
21. </form>
22. ...

Листинг 39
1.  <?
2.  xs2Fetch(array('mod'=>'ajax','met'=>'jshttprequest_srv'));
3.  new JsHttpRequest();
4.  
5.  xs2InsertNode(array(
6.     'mod'=>'galleries',
7.     'NType'=>'photo',
8.     'ParId'=>1,
9.     'NFlag'=>'1',
10.    'NName'=>'photo',
11.    'Image'=>$_FILES['Image']
12. ));
13. ?>

Одним из достоинств библиотеки JsHttpRequest является то, что она предоставляет разработчику возможность кэшировать частые ajax-запросы. Для этого всего лишь достаточно назначить свойство "caching" объекта XS2AJAX в "true". В этом случае если вызвать функцию send() дважды с одинаковыми параметрами, то второй раз данные вернутся из кэша - запрос даже не пойдет на сервер. Приведем небольшой пример. Листинг 40 содержит кода страницы, на который пользователь может указать станцию метро с помощью двух выпадающих списков. В первом выпадающем списке перечислены линии. Вы выборе определенной линии во второй список динамически подгружаются станции, находящиеся на этой линии. Очевидно, что пользователь может несколько раз менять линию в первом списке, и не имеет смысла повторно запрашивать станции для линии, для которой они уже запрашивались ранее. Для этого достаточно воспользоваться свойством "caching".

Листинг 40
1.  ...
2.  {literal}
3.    var xsa = new XS2AJAX();
4.    xsa.caching = true;
5.    function loadStation(line){
6.      xsa.onready = function(){
7.        if(xsa.responseJs.stations){
8.          var st = xsa.responseJs.stations;
9.          var stl = "<option value=\"0\"> выберите линию ¶
                 </option>";
10.         for(var i=0;i<st.length;i++){
11.           stl += "<option value=\""+st[i].NodId+"\"> ¶
                 "+st[i].NName+" </option>";
12.         }
13.       }
14.     }
15.   }
16. 
17.   xsa.send({'line':line},'/metro/line/get_stations');
18. {/literal}
19. ...
20. <select name="lines" id="lines" ¶
                 onchange="loadStation(this.value)">
21.     {foreach from=$lines item="line"}
22.     <option value="{$line.NodId}">{$line.NName}</option>
23.     {/foreach}
24. </select>
25. 
26. <select name="stations" id="stations">
27.     <option value="0">выберите линию</option>
28. </select>

В заключении этой главы следует отметить, что тот способ организации AJAX, который представлен здесь, не является единственно возможным в XS2. Разработчик может использовать другие библиотеки, самостоятельно подключив их как отдельные методы или модули. Библиотека JsHttpRequest была выбрана как наиболее универсальная и кроссбраузерная.

Введение

Основные характеристики системы XS2
Требование к хостинг-площадке, на которой устанавливается XS2.
Инструкции по установке XS2 на хостинг-площадке.

Часть 1. XS2 шаг за шагом

Модель данных в XS2: модуль, тип, узел, метод.
Как организовать простейшую структуру данных в XS2 и вывести узлы на главной странице сайта.
Множественный выборки узлов и их вывод на странице в цикле.
Создание второстепенной страницы и организация ссылок на нее.
Структура метода в XS2. Что такое процессор и как он взаимодействует в шаблоном внутри одного метода.
Дерево как универсальный способ организации узлов в XS2. Как настраивать вложенность узлов друг в друга.
Ссылки между узлами как основное средство построения альтернативных структур узлов.
Использование функция XS2 API для выполнения редакторских операций в коде методов.
Функция xs2Fetch и ее возможности при организации повторного использования методов.
Подробнее о взаимодействии процессора и шаблона в одном методе: передача данных между процессором и шаблоном.

Часть 2. Решения на платформе XS2

О чем пойдет речь во второй части, для кого она предназначена.
Как производить дополнительные манипуляции с узломпри его вставка, редактировании, удалении, копировании или перемещении.
Постраничный вывод как способ показа больших массивов данных в одном шаблоне.
Как с помощью XS2 быстро сделать сайт с поддержкой множества языковых версий.
Быстрое развертывание удобных пользовательских интерфейсов с технологией AJAX на платформе XS2.
Подробнее о том, как организовать сложные структуры данных в XS2 и производить в них поиск.
В следующих главах, которые будут публиковаться здесь по мере их написания, мы планируем рассказать о:
Copyright ©1998-2008 Солютекс. Все права защищены.
Этот сайт сделан в designLab | Работает на технологии XS2
Условия использования | О защите конфиденциальности