В покере есть такая начальная комбинация карт — туз и валет. Ее называют «AJAX». Если она выпадает при раздаче, то шансы на выигрыш очень велики. Существует одноименная компьютерная технология, которая обещает стать козырной картой в колоде любого сайта.

 

Теория

Вначале — пара слов про технологии, которые мы будем использовать в статье. Чтобы писать полноценные веб-приложения на Аяксе, надо на приличном уровне знать и уметь применять:

  • язык разметки гипертекста HTML, а лучше XHTML;
  • каскадные таблицы стилей CSS;
  • объектную модель DOM;
  • язык программирования на стороне клиента, обычно
    JavaScript;
  • объект XMLHttpRequest для обмена данными с сервером;
  • XML для формирования данных, либо другой формат, например
    JSON.

Если в вышеперечисленном списке встретились незнакомые слова, то не стоит отчаиваться — я поясню их, когда это понадобится.

 

Общая схема работы

Пользователь заходит на страничку, сделанную при помощи Аякса, и производит некое действие, например, кликает мышкой по ссылке. Обработчик этого события посылает запрос на сервер. Он получает информацию и посылает ответ, который обрабатывает соответствующая функция на стороне клиента. Эта функция формирует готовый HTML и показывает его пользователю. Чтобы представить этот процесс, можно взглянуть на схему.


Общая схема работы веб-страницы на AJAX

XMLHttpRequest

Для того чтобы написать наше первое приложение – интерактивную страничку на AJAX, нам надо научиться пользоваться объектом XMLHttpRequest. Что может быть проще, чем создать объект нужного класса? Но вспомним главную беду веб-программистов: у всех пользователей разные браузеры. Microsoft Internet Explorer поддерживает XMLHttpRequest в виде ActiveX-объекта Microsoft.XMLHTTP, остальные же браузеры считают его нативным, и проблем возникнуть не должно. Теперь алгоритм создания объекта XMLHttpRequest прояснен. Сначала определяем браузер, потом создаем объект нужным нам образом:

function createHttpRequest() {
var httpRequest;
var browser = navigator.appName;

if (browser == "Microsoft Internet Explorer") {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
} else {
httpRequest = new XMLHttpRequest();
}

return httpRequest;
}

Что умеет делать этот объект? Самой главной функциональностью для нас будет возможность отправлять запросы на сервер и обрабатывать ответы в асинхронном режиме. Нам придется использовать метод установки параметров соединения open и метод отправки запроса send. Также мы задействуем свойство onreadystatechange для установки обработчика получения ответа на запрос. Полный список свойств и методов XMLHttpRequest можно посмотреть в таблицах «Методы класса XMLHttpRequest» и «Свойства класса XMLHttpRequest».

Методы класса XMLHttpRequest

abort()

отменяет текущий запрос;

getAllResponseHeaders()

возвращает полный список
HTTP-заголовков в виде строки;

getResponseHeader( headerName )

возвращает значение
указанного заголовка;

open( method, URL, async, userName, password )

определяет метод, URL и
другие опциональные параметры запроса;
параметр async определяет, происходит ли
работа в асинхронном режиме;

send( content )

отправляет запрос на
сервер;

setRequestHeader( label, value )

добавляет HTTP-заголовок к
запросу.

Свойства класса XMLHttpRequest


onreadystatechange

обработчик события, которое происходит при каждой смене состояния объекта;


readyState

возвращает текущее состояние объекта (0 — неинициализирован, 1 — открыт, 2 – отправка данных, 3 – получение данных и 4 – данные загружены);


responseText

текст ответа на запрос;


responseXML

текст ответа на запрос в виде
XML, который затем может быть распарсен посредством
DOM;


status

возвращает HTTP-статус в виде числа (404 – «Not Found», 200 – «OK» и т.д.)


statusText

возвращает статус в виде строки («Not Found», «OK» и т.д.)

Теперь, я думаю, ты достаточно осведомлен и готов писать метод отправки запроса. В качестве параметров мы будем передавать ему адрес, на который идет запрос (я назвал этот параметр «file», так как использовал относительные адреса), идентификатор HTML-элемента — _resultId, в котором будем отображать результат, и обработчик ответа на данный запрос — getRequestProc. Реализация проста, как арбуз: определяем параметры соединения, устанавливаем обработчик и посылаем запрос с пустым телом на сервер.

function sendRequest(file, _resultId, getRequestProc) {
resultId = _resultId;
document.getElementById(resultId).innerHTML = 'Подождите, идет загрузка...';
httpRequest.open('get', file);
httpRequest.onreadystatechange = getRequestProc;
httpRequest.send(null);
}

Осталось написать обработчик ответа, и наш мини-Аякс-движок готов. Здесь тоже все просто. Проверяем, полностью ли передан ответ на запрос, и выводим полученный ответ в элемент с идентификатором _resultId, который мы так предусмотрительно сохранили:


function getRequest() {
if (httpRequest.readyState == 4) {
document.getElementById(resultId).innerHTML = httpRequest.responseText;
}
}

Теперь добавим переменных и упакуем все в один файл
ajax.js:

var httpRequest = createHttpRequest();
var resultId = '';

Скажи миру: «Привет»

Раз библиотека готова, можно попробовать ее использовать. Вначале скажем миру «Привет», а затем модернизируем приложение для работы с динамическими табами (вкладками).

<html>
<head>
<title>Привет, мир AJAX'a</title>
<script language="JavaScript" src="https://xakep.ru/wp-content/uploads/post/35903/ajax.js" type="text/javascript"></script>
</head>

<body>

<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('hello.txt', 'result', getRequest);">Кликни по мне, чтобы отправить запрос</a>.
<p id="result">Здесь будет результат запроса</p>

</body>
</html>

Посмотрим, что мы с тобой наколдовали. У нас есть линк, при щелчке на который на сервер отправляется запрос к файлу hello.txt. Поскольку txt-файл не является скриптом, сервер просто передаст его содержимое, которое мы и выведем для пользователя. Как видишь, программирование на стороне сервера пока даже не применялось, но и из такой простоты можно выжать интересные вещи. Например, сделать страницу с несколькими вкладками:

<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('1.html', 'result', getRequest);">Вкладка №1</a>
<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('2. html', 'result', getRequest);">Вкладка №2</a>
<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('3. html', 'result', getRequest);">Вкладка №3</a>
<hr>
<p id="result"></p>

Как видишь, ссылок теперь 3, и загружают они разные HTML-файлы. В результате получилась страничка с динамически изменяемым содержанием.

Серверная часть

Набаловавшись вдоволь с обычными страничками, посмотрим, что можно сделать с помощью скриптов на стороне сервера. Писать буду на самом распространенном у нас языке для веба – PHP. Сначала повторим наш успех и скажем «Привет». Действия полностью аналогичны предыдущим, но только запрос адресуется на скрипт:


<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('hello.php', 'result', getRequest);">Кликни по мне, чтобы отправить запрос</a>.
<p id="result">Здесь будет результат запроса</p>

А PHP-файл должен просто что-то выводить:

<?php echo "Этот пример реализован связкой AJAX + PHP!" ?>

Сверхдинамичный поиск

Теперь мы вооружились до зубов и можем написать настоящее AJAX-приложение. В качестве не очень сложного примера я предложу «сверхдинамичный поиск», который был подсмотрен мной в одном из фреймворков на Python. Идея такая: имеется форма поиска, пользователь вводит в ней букву за буквой искомое слова, и после каждого нажатия на клавишу формируются результаты. Попробую проиллюстрировать. Пользователь вводит букву «Х» — на экране автоматически выводятся ссылки на все статьи, в которых эта буква встречается. Затем он вводит «а», и поиск ведется уже по сочетанию «Ха». И так далее. Реализацию начнем с HTML-видами нашего проекта:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Привет, мир AJAX'a</title>
<script language="JavaScript" src="https://xakep.ru/wp-content/uploads/post/35903/ajax.js" type="text/javascript"></script>

<script language="JavaScript" type="text/javascript">

function sendSearchRequest() {
sendRequest('search.php?q=' + document.getElementById('searchQuery').value, 'result', getRequest);
}

</script>

</head>

<body>
Введите текст для поиска:
<input id="searchQuery" type="text" size="30" maxlength="30" onKeyUp="javascript: sendSearchRequest();">
<hr />
<p id="result">Здесь будет результат запроса</p>

</body>
</html>

В этом случае мы не только подключили файл ajax.js, но и написали дополнительный скрипт, который будет срабатывать при нажатии на кнопку в поле ввода. Его работа будет очень простой — он будет передавать строку для поиска, которая берется из поля ввода, в виде параметра для скрипта PHP. Теперь очередь PHP’шного скрипта. Для простоты я завел массив $pages, который у меня представляет собой содержимое страниц сайта. Он обычно загружается из базы данных, либо поиск производится средствами БД, что, конечно, правильнее, так как скорость на порядок выше.

После того как в $pages помещено содержимое страниц, необходимо получить значение параметра q из запроса, переданного клиентским скриптом, и если запрос не пустой, пробежаться по массиву $pages и вывести содержимое страниц, которые содержат строку для поиска.


<?php
// Массив с содержимым страниц сайта
$pages = array(…);

$query = $_GET['q'];

$result = '';

if (!empty($query))
{
foreach ($pages as $page)
if (strstr($page, $query))
$result .= "<li>" . str_replace($query, "<strong>$query</strong>", $page) . "</li>";

if (!empty($result))
echo "<ol>$result</ol>";
else
echo "По запросу \"$query\" ничего найдено!";
}
else
echo "Введите запрос для поиска";
?>


Поиск на Аяксе в действии

 

А где же XML?

Хочу XML! Почему мы текст какой-то передаем, обещали же XML? Вообще, если посмотреть на название объекта XMLHttpRequest, то может показаться, что он создан только для передачи XML-данных. На буржуйских форумах и блогах, однако, часто выражается мнение, что это просто дань моде и можно использовать другие форматы — от чистого текста и HTML до текста на JavaScript. Но есть один существенный факт: при передаче данных в виде XML, они занимают меньше места и быстрее грузятся.

Разберем такой пример. Есть XML-файл (возможно генерящийся скриптом), который содержит название и адрес некого банка :).

<?xml version="1.0" encoding="UTF-8"
standalone="yes"?>
<bank>
<bank_name>Банк Васи Пупкина</bank_name>
<bank_address>ул. Ленинградская, 57</bank_address>
</bank>

Его надо получить, распарсить и вывести информацию в отформатированном виде. Сделать это очень просто с помощью объектов, встроенных в
JavaScript:


function getXmlRequest() {
if (httpRequest.readyState == 4) {
var xmlDocument = httpRequest.responseXML;
var bankName = xmlDocument.getElementsByTagName('bank_name').item(0).firstChild.data;
var bankAddress = xmlDocument.getElementsByTagName('bank_address').item(0).firstChild.data;

document.getElementById(resultId).innerHTML = '<strong>Название банка: </strong>' + bankName + '<br />'
+ '<strong>Адрес банка: </strong>' + bankAddress;
}
}

Если ты заметил, здесь, в основном, используются свойства и методы объекта responseXML, который представляет собой ответ сервера на запрос в виде XML. C ним довольно удобно работать, так как все необходимые функции встроены. Сама же ссылка будет выглядеть так:


<a href="https://xakep.ru/wp-content/uploads/post/35903/#" onclick="javascript:sendRequest('1.xml', 'result', getXmlRequest);">Кликни по мне, чтобы отправить запрос</a>.

Важно отметить, что в качестве параметра передается функция getXmlRequest, которую мы написали.

 

Ссылки:


www.dhtmlgoodies.com
— библиотека готовых скриптов AJAX и DHTML.
www.w3.org/TR/XMLHttpRequest — черновой вариант стандарта объекта
XMLHttpRequest.
ru.wikipedia.org/wiki/Ajax — статья про Аякс в Википедии. Очень рекомендую также посмотреть английский вариант.
code.google.com/webtoolkit — библиотека для AJAX-приложений от Google.
www.modernmethod.com/sajax — популярная AJAX-библиотека для PHP.

www.xajaxproject.org
— еще одна библиотека для связки AJAX и PHP.
prototype.conio.net — фреймворк для разработки JavaScript-приложений.
ajax.asp.net — реализация принципов AJAX от Microsoft.
dojotoolkit.org — одна из лучших AJAX-библиотек, которая содержит действительно большой функционал.

 

Недостатки Аякса

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

Поисковая оптимизация

По моему мнению, главной проблемой страниц на Аяксе является их «невкусность» для поисковиков, поэтому такие страницы очень плохо ими «съедаются», ведь поисковик не умеет переходить по ссылкам JavaScript. Огромное количество пользователей могут пройти мимо твоего сайта, даже если на нем есть требуемый контент. Следовательно, его нужно сделать доступным другим способом, хотя бы самым банальным – смастерить страничку «Карта сайта» с полным списком страниц.


Кроссбраузерность

У пользователей есть плохое качество — они пользуются разными браузерами. Казалось бы, нет проблем – пиши код на HTML, CSS и JavaScript, который соответствует стандартам, и все. Но не тут-то было — разные браузеры поддерживают стандарты неодинаково. Что ж, ставим себе несколько самых популярных браузеров (причем необходимо поставить еще и их разнообразные версии) и тестируем наши веб-странички.


Пользователи без AJAX

Ты будешь смеяться, но есть странные типы (я, например), у которых JavaScript работает только для определенных сайтов, а для других отключен, или у которых нестандартный браузер, не знающий про AJAX. Как же им быть? Обязательно сделай альтернативную HTML-версию страницы, бери пример с
gmail.com!

Кнопка «Назад»

По данным исследователей, кнопка браузера «Назад» является вторым по популярности средством навигации после перехода по ссылке. То есть пользователь всегда рассчитывает на возможность вернуться на одну страницу назад. Веб-странички, которые созданы с использованием Аякса, такую возможность не поддерживают, потому что их содержание создается «на лету». Чтобы как-то это исправить, можно запрограммировать соответствующую логику на JavaScript и сделать ссылку «Назад», щелчок на которую позволит пользователю перейти на предыдущую страницу. Второй вариант, более универсальный и чаще всего легче реализуемый, – использовать невидимый IFRAME, который будет накапливать историю переходов.


Избранное

Твоя страничка на Аяксе настолько понравилась посетителю сайта, что он решил кинуть ее в «Избранное» (или в «Закладки», если посетитель — лисовод). Но у него ничего не получится, так как у группы страничек на Аяксе всегда адрес первой из них. Справиться с проблемой опять же можно двумя способами: программингом и хаком. Программерское решение заключается в том, чтобы каждая сгенерированная страница имела свой адрес и ссылку «Добавить в Избранное», которая будет реализовывать нужную логику. Второй способ — использовать ссылку на подраздел, который идет в адресе страницы после знака диеза «#». Дело в том, что с помощью JavaScript эту часть адреса можно изменять. Таким образом, этот хак может частично решить и проблему кнопки «Назад».

Неопределенное время ответа

Время ответа сервера на запрос не определено — может пройти несколько секунд, а может — несколько минут. И пользователь начинает сильно нервничать, грызть ногти и наконец закрывает страничку — ведь браузер никак не отображает, что там что-то происходит :). Чтобы не доводить пользователя до невроза, нужно вставить на страничку хотя бы надпись «Идет загрузка», а лучше — анимированное графическое изображение, которое будет показывать, что она жива.

 

Это еще не конец

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



Полную версию статьи ты можешь
прочитать в декабрьском
номере
"Хакера"

Оставить мнение

Check Also

Твой тайный туннель. Детальный гайд по настройке OpenVPN и stunnel для создания защищенного канала

У тебя могут быть самые разные мотивы, чтобы пользоваться VPN: недоверенные сети, разного …