Vasya Tapkin: It's Super Site. George Tailor: It's Very Bad Site. Mary Tompkins: I know nothing about this site.
« Введение в технологию ajax. Часть 1 | Введение в технологию ajax. Часть 3 » |
Введение в технологию ajax. Часть 2
Я продолжаю серию статей посвященных технологии ajax. В прошлый раз я рассказал об истории развития ajax, о том, как поддержка методов “подзагрузки” информации в страницу проделала путь от специфической технологии, поддерживаемой только internet explorer, до общепризнанного стандарта в web. Я рассказал об “старых” методиках – применявшихся до того как поддержка ajax добавилась в opera9 и firefox. Я упомянул о существовании библиотеки Д. Котерова и ее подходе к реализации ajax. Сегодня я расскажу вам о библиотеках иного плана. Их цель не обеспечить “просто отправку и загрузку данных” а, именно, обеспечить высокоуровневый слой-посредник между javascript-кодом, который исполняется в вашем браузере, и php-кодом работающем на веб-сервере. Причем, и это важно, такая коммуникация должна быть “прозрачной” или незаметной – т.е. обоим сторонам будет казаться что вызываемые ими функции находятся “вот здесь рядом”, а не за тысячи километров.В прошлый раз я закончил на том, что показал, как именно можно выполнить ajax вызов и загрузить в страницу некоторый код xml. Затем данный код анализировался, и его содержимое применялось для изменения внешнего вида страницы. Я опустил вопрос о том, откуда взялся этот самый xml, кто его сформировал. Интуитивно нам все ясно, что код должен был быть сгенерирован некоторым php-скриптом посредством множества вызовов функций print ‘еще кусочек xml’. Например, так:
<?php
header ('Content-Type: text/xml');
// важно не забыть указать тип возвращаемой информации
print ('<?xml version="1.0" encoding="windows-1251"?>' . "\n");
print ('<result><color>red</color><message>Запрос выполнен успешно</message></result>' . "\n");
?>
А теперь пример использования json-функций:
<?php
// исходная информация для последующего кодирования -
// обратите внимание,что мы используем сложные типы данных:
// ассоциативный массив, содержащий вложенный массив объетов (payments)
$x = array (
'fio' => 'bill makkenzi',
'birthdate' => '2000.1.1',
'payments' => array (
array ('dateof' => '2001.1.1', 'balance' => 3000 , 'currency' => 'EUR'),
array ('dateof' => '2002.1.1', 'balance' => 5700 , 'currency' => 'USD'),
array ('dateof' => '2003.7.1', 'balance' => -600 , 'currency' => 'EUR')
)
);
print '<h1>Сначала JSON из PHP-объекта</h1>';
print json_encode ($x);// создаем строку с json-нотацией
print '<h1>А теперь PHP из JSON-строки</h1>';
print '<pre>';// выполняем раскодирование json-строки в переменную php
print_r (json_decode (json_encode ($x)));
print '</pre>'; ?>
А для разбора json-строки в коде javascript достаточно сделать вызов функции eval (функция вычисляет переданный ей аргумент – строку с json нотацией). Последнее - закодировать данные из javascript в json-строку текста для последующей отправки серверу - и цикл замкнется. Давайте разберем это на примере библиотеки jquery, я писал о ней в прошлых сериях, хотя большей частью сосредоточился на том, какие плюсы jquery дает для работы с деревьями DOM, с событиями элементов. Теперь осталось рассмотреть предпоследнюю главную возможность jquery – поддержку ajax. Возможно, я сделаю в последующем еще одну статью, которая будет посвящена анимации и спецэффектам в javascript с помощью jquery и других библиотечек, но об этом после. Задача будет проста – javascript-код делает вызов некоторого файла php, который читает размещенный на сервере файл, каждая строка которого, например, - имя пользователя оставившего сообщение и собственно, текст сообщения в гостевой книге сайта, разделенные символом “:”. Данные кодируются в json-формат, затем отправляются в браузер, где строится html-таблица с перечнем этих сообщений. Сначала пример файла с данными (baza.txt):
<?php
$plaindata = file ('baza.txt');
// прочитали файл с сообщениями
$result = array ();
// входная переменная управляющая работой скрипта - количество сообщений которые нужно вернуть
$page_size = $_REQUEST ['page_size'];
for ($i = 0; $i < min($page_size, count($plaindata)); $i++){
// в цикле накапливаем пары (кто, сообщение) в массиве
list ($user, $msg) = explode (':', $plaindata [$i]);
$result [] = array ('user'=>$user, 'msg' => $msg);
}
// здесь формируем окончательный массив с данными, отправляем его в кодированной форме браузеру
print json_encode (array ('filesize' => filesize ('baza.txt'), 'messages' => $result));
?>
Ключ | Примечание |
async | Булева переменная, кодирует признак того, будет ли сделан удаленный вызов как синхронный или асинхронный. Если вызов синхронный то на момент выполнения запроса браузер будет заблокирован. |
beforeSend | Функция, которая вызывается перед отправкой запроса, ее назначение выполнить окончательную до-настройку объекта XMLHttpRequest находящегося внутри jquery. |
complete | Функция вызывается после завершения вызова, когда данные были возвращены, и не зависимо от того успешно, или нет произошел ajax-вызов. |
contentType | Сообщение серверу, что текстовые данные кодируются следующим образом. |
data | Собственно данные, которые отправляются серверу, это может быть как строка текста, так и массив, объект или их комбинация. |
dataType | Очень важный параметр, управляет тем, в каком формате данные будут возвращены сервером. Возможны следующие значения: xml, html, script, json. |
error | Функция вызываемая в том случае если удаленный вызов был неуспешен. |
processData | Возможность отключить кодирование данных перед отправкой. Очень специфическая функция – лучше не трогайте. |
success | Функция вызываемая, когда запрос был успешно завершен. |
timeout | Переменная кодирующая интервал времени в течении которого мы ждем завершения удаленного вызова. Задается в миллисекундах. |
type | Тип запроса: GET или POST. Остальные методы: HEAD, PUT – не поддерживаются. |
url | Самое главное – адрес страницы php, которую следует запустить. |
<html>
<head>
<script type="text/javascript" language="javascript" src="jquery.js"> </script>
<script>
function sender (){
$.ajax({
type: "POST", url: "bazareader.php", dataType : 'json',
data: {
page_size: $('#page_size').attr('value')
},
success: function(msg){
var oRow = null;
var oCell = null;
alert( "File Length: " + msg.filesize );
var t = document.createElement ('table');
// создаем первую строку таблицы с заголовками - названиями столбцов
oRow = t.insertRow(0);
// создаем ячейку строки
oCell = oRow.insertCell(0);
// и указываем содержимое ячейки
oCell.innerHTML = 'User';
oCell = oRow.insertCell(1);
oCell.innerHTML = 'Message';
// организуем цикл по массиву сообщений
for (var i = 0; i < msg.messages.length; i++){
// создаем очередную строку
oRow = t.insertRow(i + 1);
// в нее помещаем две ячейки - для имени пользвователя
oCell = oRow.insertCell(0);
oCell.innerHTML = msg.messages[i].user;
// и для текста сообщения
oCell = oRow.insertCell(1);
oCell.innerHTML = msg.messages[i].msg;
}//for
document.getElementById('dv_Result').appendChild (t);
}
}
);
}// конец ajax вызова
</script>
</head>
<body>
<div id="dv_Result" style="">
Result ...
</div>
<br />
Page Size: <input type="text" id="page_size" value="10" />
<br />
<input type="button" onclick="sender ()" value="click me !"/>
</body>
</html>
Естественно, что в качестве источника данных может выступать и произвольный скрипт, например, далее я выполняю загрузку с сайта tut.by новостей в формате rss. Данный формат основан на xml (следовательно, все, что мне нужно - это при вызове ajax указать значение свойства dataType как “xml”) и выглядит примерно так:
<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0">
<channel>
<title>Новости TUT.BY Главные новости</title>
<link>http://news.tut.by/</link>
<description>Новости TUT.BY</description>
<item>
<title>Заголовок новости</title>
<link>http://news.tut.by/94435.html</link>
<description>Краткое описание новости</description><pubDate>Mon, 17 Sep 2007 08:40:00 +0300</pubDate>
<guid>http://news.tut.by/94435.html</guid>
</item>
</channel>
</rss>
Теперь пример когда javascript, который загружает данную ленту новостей rss и выполняет ее разбор, затем идет конструирование таблицы, каждая строка которой – новость. Еще момент: если мы делаем ajax вызов к содержимому расположенному не в нашем домене, например ваш скрипт размещен на сайте abc.by, а вызов идет к ленте на tut.by, то мы столкнемся с политикой безопасности регламентирующей кроссдоменные вызовы. Так для internet explorer код, который я приведу далее при попытке открытия удаленного адреса приведет к появлению на экране диалогового окна, где мы должны подтвердить что действительно согласны выполнить загрузку данных из другого домена. Этот параметр можно изменить в окне настроек, как показано на рис. 4. Для firefox, opera все гораздо хуже – специальных параметров настроек для управления этим не предусмотрено. В любом случае, можно воспользоваться стандартной методикой обмана: создается файл-посредник. Именно он вызывается из javascript, и в свою очередь выполняет чтение ленты rss с другого сайта (в php ограничения на crossdomain-вызовы помягче). Вот пример такого файла посредника:
<?php
// важно правильно указать тип заголовков: что именно мы возвращаем
header('Content-Type: application/rss+xml');
$f = fopen ('http://news.tut.by/rss/index.rss', 'r') or die ('cannot open file');
while (!feof($f)) {
print fread($f, 8192);
}
fclose($f);
?>
function sender (){
$.ajax({
type: "POST",
url: "fromby.php",
success: function(msg){
var title = msg.getElementsByTagName ('title') [0];
title = title.firstChild.nodeValue;
alert ('Загружена новостная лента: ' + title);
// получаем список всех новостей в ленте
var items = msg.getElementsByTagName ('item');
var t = document.createElement ('table');
oRow = t.insertRow(0);
// создаем заголовки таблицы
oCell = oRow.insertCell(0).innerHTML= 'Заголовок';
oCell = oRow.insertCell(1).innerHTML= 'Новость';
oCell = oRow.insertCell(2).innerHTML= 'Ссылка';
for (var i = 0; i < items.length; i++){
var rss_item = items[i];
// извлекаем из документа xml набор тегов
var i_title = rss_item.getElementsByTagName ('title')[0].firstChild.nodeValue;
var i_link = rss_item.getElementsByTagName ('link')[0].firstChild.nodeValue;
var i_description = rss_item.getElementsByTagName ('description')[0].firstChild.nodeValue;
oRow = t.insertRow(i+1);
// создаем заголовки таблицы
oCell = oRow.insertCell(0).innerHTML= i_title;
oCell = oRow.insertCell(1).innerHTML= i_description;
oCell = oRow.insertCell(2).innerHTML= i_link;
}
document.getElementById('dv_Result').appendChild (t);
}
}
);
}// конец ajax вызова
« Введение в технологию ajax. Часть 1 | Введение в технологию ajax. Часть 3 » |