Поддержка AJAX в jQuery

В библиотеке jQuery технология AJAX также не оставлена без внимания — здесь предоставляется, пожалуй, самый удобный интерфейс доступа к ней. Реализована поддержка всех подвидов технологии AJAX, а также альтернативный вариант общения браузера с сервером через динамически создаваемый тег <script>. Этот вариант позволяет получать данные не только с того же домена, но и с любого другого при соблюдении некоторых условий. Получить с другого домена можно код JavaScript, а также объект в формате JSONP.

При отправке запроса на сервер добавляется заголовок x-requested-with со значением "XMLHttpRequest".

x-requested-with: XMLHttpRequest

Благодаря этому заголовку на сервере можно определить, откуда поступил запрос. Узнать, что запрос сделан с помощью AJAX, можно так.

if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])
   && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
   // Запрос выполнен с помощью AJAX
}

Метод load()

Метод load() позволяет загрузить данные с сервера в определенный элемент коллекции jQuery. После вставки данных объектная модель документа будет обновлена. Формат метода:

load(<URL>[<Селектор>][, <Данные>][, <Функция обратного вызова>])

Загрузить данные можно только с того же домена. Если указан только первый параметр, то запрос будет сделан методом GET.

$("#div1").load("/ajax.php?id=1");

Получить отправленные данные на сервере можно с помощью глобального массива $_GET.

if (isset($_GET['id'])) $id = $_GET['id'];

В необязательном параметре <Селектор> можно указать селектор, который ограничит набор вставляемых данных. Например, при таком содержимом файла ajax.php:

<?php
header('Content-Type: text/html; charset=utf-8');
?>
<span id="span1">Данные 1</span>
<span id="span2">Данные 2</span>

выражение

$("#div1").load("/ajax.php");

загрузит в элемент с идентификатором div1 следующие данные:

<span id="span1">Данные 1</span>
<span id="span2">Данные 2</span>

Если указать выражение

$("#div1").load("/ajax.php #span2");

то вставляемые данные будут ограничены элементом с идентификатором span2 и мы получим следующие данные:

<span id="span2">Данные 2</span>

Параметр <Данные> позволяет передать несколько параметров. Для этого параметры и значения должны быть указаны следующим образом.

{
   Параметр1: "Значение1",
   Параметр2: "Значение2",
   ...
   ПараметрN: "ЗначениеN"
}

Если параметр <Данные> указан, то данные передаются методом POST. В случае если параметры или значения содержат запрещенные символы, то они будут автоматически перекодированы с помощью метода encodeURIComponent().

$("#div1").load("/ajax.php", { txt: "Текст" });

Получить отправленные данные на сервере можно с помощью глобального массива $_POST.

if (isset($_POST['txt'])) $txt = $_POST['txt'];

В качестве параметра <Функция обратного вызова> указывается ссылка на функцию следующего формата.

function <Название функции>(<Загруженные данные>[, <Статус>[,
                            <Объект XMLHttpRequest>]]) {
   // ...
}

Функция будет вызвана после окончания загрузки, независимо от ее результата. Внутри функции доступна ссылка (this) на текущий DOM-элемент. Если в первом параметре указать переменную, то через нее будут доступны данные, которые загружены с сервера. Через параметр <Статус> доступен статус запроса. Возвращаются следующие значения:

Обработать ошибку загрузки можно, например, так.

$("#div1").load("/ajax.php", { txt: "Текст" },
   function(data, status) {
      if (status == 'error') {
         $(this).html("Ошибка при загрузке");
      }
   });

Через параметр <Объект XMLHttpRequest> доступна ссылка на объект XMLHttpRequest. Обработать ошибку загрузки с помощью этого параметра можно, например, так.

$("#div1").load("/ajax2.php", { txt: "Текст" },
   function(data, status, XMLHttpRequest) {
      if (XMLHttpRequest.status != 200) {
         $(this).html("Ошибка при загрузке");
      }
   });

В качестве примера использования метода load() рассмотрим вывод каталога фильмов. Изначально из базы данных MySQL выводятся только названия фильмов. После щелчка на ссылке Показать с помощью технологии AJAX с сервера будет загружено полное описание фильма и отображено в элементе DIV. Изначально элемент является скрытым. После загрузки описаний мы отображаем этот элемент и изменяем текст ссылки на Скрыть. Если щелкнуть мышью на этой ссылке, то описание будет скрыто, а текст ссылки изменится на Показать. Повторный щелчок на ссылке Показать приводит к отображению описания без повторной загрузки. SQL-запрос для создания таблицы представлен в листинге 11.1. Содержимое файла index.php (основной файл) представлено в листинге 11.2, а текст файла ajax.php (для вывода полного описания фильма) содержится в листинге 11.3.

Листинг 11.1. SQL-запрос для создания таблицы

CREATE TABLE `films` (
   `id` int(11) auto_increment,
   `name` varchar(255) character set `utf8` collate `utf8_general_ci`,
   `descr` text character set `utf8` collate `utf8_general_ci`,
   PRIMARY KEY (`id`)
) engine=MYISAM character set `utf8` collate `utf8_general_ci`;
INSERT INTO `films` (`id`, `name`, `descr`) VALUES
(1, 'Фильм 1', 'Описание фильма 1'),
(2, 'Фильм 2', 'Описание фильма 2'),
(3, 'Фильм 3', 'Описание фильма 3');

Листинг 11.2. Содержимое файла index.php

<?php
// Запрещаем кеширование
header('Expires: Sun, 27 May 2007 01:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
// Указываем кодировку
header('Content-Type: text/html; charset=utf-8');
// Подключаемся к базе
$db = mysql_connect('localhost', 'root', '123456')
      or die('Не удалось установить подключение');
mysql_select_db('test') or die('Такой базы данных нет');
mysql_query('SET NAMES `utf8`'); // Кодировка соединения
?>
<!doctype html>
<html>
<head>
<title>Метод load()</title>
<meta charset="utf-8">
<script src="js/jquery.js"></script>
<script>
function f_show(id, elem) {
   var div = $("#div" + id);
   var link = $(elem);
   if (div.is(":hidden")) {
      if (div.text() == "") {
         div.load("/ajax.php", { "id": id },
         function(responseText, textStatus) {
            if (textStatus == 'error') {
               div.html("Ошибка при загрузке");
            }
            div.slideDown(300);
            link.html("Скрыть");
         });
      }
      else {
         div.slideDown(300);
         link.html("Скрыть");
      }
   }
   else {
      div.slideUp(300);
      link.html("Показать");
   }
}
</script>
</head>
<body>
<?php
$query = 'SELECT `id`, `name` FROM `films` ORDER BY `name`';
if ($res = mysql_query($query)) {
   while ($row = mysql_fetch_row($res)) {
      echo '<a href="#" onclick="f_show(' . $row[0] . ', this); ';
      echo 'return false;">Показать</a> <b>';
      echo htmlspecialchars($row[1], ENT_COMPAT, 'UTF-8');
      echo "</b><br>\n";
      echo '<div id="div' . $row[0] . '" style="display:none;">';
      echo "</div>\n";
   }
}
mysql_close($db);
?>
</body>
</html>

Листинг 11.3. Содержимое файла ajax.php

<?php
// Указываем кодировку
header('Content-Type: text/html; charset=utf-8');
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
   exit('Данные отправлены не через AJAX');
}
if (isset($_POST['id'])) $id = (int)$_POST['id'];
else $id = 0;
if ($id === 0) exit('Параметр id содержит ошибку');
// Подключаемся к базе
$db = mysql_connect('localhost', 'root', '123456')
      or die('Не удалось установить подключение');
mysql_select_db('test') or die('Такой базы данных нет');
mysql_query('SET NAMES `utf8`'); // Кодировка соединения
$query = 'SELECT `descr` FROM `films` WHERE `id`=' . $id;
if ($res = mysql_query($query)) {
   if (mysql_num_rows($res) != 0) {
      $row = mysql_fetch_row($res);
      echo $row[0]; // Выводим описание
   }
   else {
      echo 'Фильм не найден';
   }
}
else {
   echo 'Ошибка при выполнении запроса';
}
mysql_close($db);
?>
Предыдущая статья Все статьи Следующая статья