AJAX

Представляю Вам третью статью из серии jQuery для начинающих. В этот раз я постараюсь рассказать о реализации AJAX запросов...
Что такое AJAX я думаю рассказывать не стоит, ибо с приходом веб-два-нуля большинство пользователей уже воротят носом от перезагрузок страниц целиком, а с появлением jQuery реализация упростилась в разы...
Примечание: Во всех примерах используется сокращенный вариант вызова jQuery методов, используя функцию $(знак доллара)

jQuery(..).load

Начнем с самого простого — загрузка HTML кода в необходимый нам DOM элемент на странице. Для этой цели нам подойдет метод load. Данный метод может принимать следующие параметры:
  1. url запрашиваемой страницы
  2. передаваемые данные (необязательный параметр)
  3. функция которой будет скормлен результат (необязательный параметр)
Приведу пример JavaScript кода:
// по окончанию загрузки страницы
$(document).ready(function(){
// вешаем на клик по элементу с id = example-1
$('#example-1').click(function(){
// загрузку HTML кода из файла example.html
$(this).load('ajax/example.html');
})
});
Пример подгружаемых данных (содержимое файла example.html):
Example<br/>
Data Loaded By AJAX<br/>
Bye-Bye

jQuery.ajax

Это самый основной метод, а все последующие методы лишь обертки для метода jQuery.ajax. У данного метода лишь один входной параметр — объект включающий в себя все настройки (выделены параметры которые стоит запомнить):
  • async — асинхронность запроса, по умолчанию true
  • cache — вкл/выкл кэширование данных браузером, по умолчанию true
  • contentType — по умолчанию «application/x-www-form-urlencoded»
  • data— передаваемые данные — строка иль объект
  • dataFilter — фильтр для входных данных
  • dataType— тип данных возвращаемых в callback функцию (xml, html, script, json, text, _default)
  • global — тригер — отвечает за использование глобальных AJAX Event'ов, по умолчанию true
  • ifModified — тригер — проверяет были ли изменения в ответе сервера, дабы не слать еще запрос, по умолчанию false
  • jsonp — переустановить имя callback функции для работы с JSONP (по умолчанию генерируется на лету)
  • processData — по умолчанию отправляемые данный заворачиваются в объект, и отправляются как «application/x-www-form-urlencoded», если надо иначе — отключаем
  • scriptCharset — кодировочка — актуально для JSONP и подгрузки JavaScript'ов
  • timeout — время таймаут в миллисекундах
  • type— GET либо POST
  • url— url запрашиваемой страницы
Локальные AJAX Event'ы:
  • beforeSend — срабатывает перед отправкой запроса
  • error — если произошла ошибка
  • success — если ошибок не возникло
  • complete — срабатывает по окончанию запроса
Для организации HTTP авторизации (О_о):
  • username — логин
  • password — пароль
Пример javaScript'а:
$.ajax({
url: '/ajax/example.html', // указываем URL и
dataType : "json", // тип загружаемых данных
success: function (data, textStatus) { // вешаем свой обработчик на функцию success
$.each(data, function(i, val) { // обрабатываем полученные данные
/* ... */
});
}
});

jQuery.get

Загружает страницу, используя для передачи данных GET запрос. Может принимать следующие параметры:
  1. url запрашиваемой страницы
  2. передаваемые данные (необязательный параметр)
  3. callback функция, которой будет скормлен результат (необязательный параметр)
  4. тип данных возвращаемых в callback функцию (xml, html, script, json, text, _default)

jQuery.post

Данный метод аналогичен предыдущему, лишь передаваемые данные уйдут на сервер посредством POST'а. Может принимать следующие параметры:
  1. url запрашиваемой страницы
  2. передаваемые данные (необязательный параметр)
  3. callback функция, которой будет скормлен результат (необязательный параметр)
  4. тип данных возвращаемых в callback функцию (xml, html, script, json, text, _default)
JavaScript:
$(document).ready(function(){ // по завершению загрузки страницы
$('#example-3').click(function(){ // вешаем на клик по элементу с id = example-3
$.post('ajax/example.xml', {}, function(xml){ // загрузку XML из файла example.xml
$('#example-3').html('');
$(xml).find('note').each(function(){ // заполняем DOM элемент данными из XML
$('#example-3').append('To: ' + $(this).find('to').text() + '<br/>')
.append('From: ' + $(this).find('from').text() + '<br/>')
.append('<b>' + $(this).find('heading').text() + '</b><br/>')
.append( $(this).find('body').text() + '<br/>');
});
}, 'xml'); // указываем явно тип данных
})
});
Файл example.xml:
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

jQuery.getJSON

Загружает данные в формате JSON (удобней и быстрее нежели XML). Может принимать следующие параметры:
  1. url запрашиваемой страницы
  2. передаваемые данные (необязательный параметр)
  3. callback функция, которой будет скормлен результат (необязательный параметр)
JavaScript:
$(document).ready(function(){ // по завершению загрузки страницы
$('#example-4').click(function(){ // вешаем на клик по элементу с id = example-4
$.getJSON('ajax/example.json', {}, function(json){ // загрузку JSON данных из файла example.json
$('#example-4').html('');
// заполняем DOM элемент данными из JSON объекта
$('#example-4').append('To: ' + json.note.to + '<br/>')
.append('From: ' + json.note.from + '<br/>')
.append('<b>' + json.note.heading + '</b><br/>')
.append( json.note.body + '<br/>');
});
})
});
Файл example.json:
{
note:{
to:'Tove',
from:'Jani',
heading:'Reminder',
body:'Don\'t forget me this weekend!'
}
}

jQuery.getScript

данная функция загружает и выполняет локальный JavaScript. Может принимать следующие параметры:
  1. url запрашиваемого скрипта
  2. callback функция, которой будет скормлен результат (необязательный параметр)
JavaScript:
$(document).ready(function(){ // по завершению загрузки страницы
$('#example-5').click(function(){ // вешаем на клик по элементу с id = example-5
$.getScript('ajax/example.js', function(){ // загрузку JavaScript'а из файла example.js
testAjax(); // выполняем загруженный JavaScript
});
})
});
Файл example.js:
function testAjax() {
$('#example-5').html('Test completed'); // изменяем элемент с id = example-5
}

Отправка Формы

Для отправки формы посредством jQuery можно использовать любой из перечисленных способов, а вот для удобства «сбора» данных из формы лучше использовать плагин jQuery Form

Примеры использования JSONP

Отдельно стоит отметить использование JSONP— ибо это один из способов осуществления кросс-доменной загрузки данных. Если немного утрировать — то это подключение удаленного JavaScript'a, содержащего необходимую нам информациию в формате JSON, а так же вызов нашей локальной функции, имя которой мы указываем при обращении к удаленному серверу (обычно это параметр callback). Чуть более наглядно это можно продемонстрировать следующая диаграмма (кликабельно):
При работе с jQuery имя callback функции генерируется автоматически для каждого обращения к удаленному серверу, для этого достаточно использовать GET запрос ввида:
http://api.domain.com/?type=jsonp&query=test&callback=?
Вместо последнего знака вопроса (?) будет подставлено имя callback функции. Если же Вы не хотите использовать данный способ, то Вам необходимо будет явно указать имя callback функции, используя опцию jsonp при вызове метода jQuery.ajax().

События

Для удобства разработки, на AJAX запросах висит несколько event'ов, их можно задавать для каждого AJAX запроса в отдельности, либо глобально. На все event'ы можно повесить свою функцию.
Пример для отображения элемента с id=«loading» во время выполнения любого AJAX запроса:
$("#loading").bind("ajaxSend", function(){
$(this).show(); // показываем элемент
}).bind("ajaxComplete", function(){
$(this).hide(); // скрываем элемент
});
Для локальных событий — вносим изменения в опции метода ajax():
$.ajax({
beforeSend: function(){
// Handle the beforeSend event
},
complete: function(){
// Handle the complete event
}
// ...
});
Для большей наглядности, приведу следующую диаграмму (кликабельно):
Ну и собственно список всех event'ов:
  • ajaxStart— Данный метод вызывается в случае когда побежал AJAX запрос, и при этом других запросов нету
  • beforeSend— Срабатывает до отправки запроса, позволяет редактировать XMLHttpRequest. Локальное событие
  • ajaxSend— Срабатывает до отправки запроса, аналогично beforeSend
  • success— Срабатывает по возвращению ответа, когда нет ошибок ни сервера, ни вернувшихся данных. Локальное событие
  • ajaxSuccess— Срабатывает по возвращению ответа, аналогично success
  • error— Срабатывает в случае ошибки. Локальное событие
  • ajaxError— Срабатывает в случае ошибки
  • complete— Срабатывает по завершению текущего AJAX запроса (с ошибкои или без — срабатывает всегда).Локальное событие
  • ajaxComplete— Глобальное событие, аналогичное complete
  • ajaxStop— Данный метод вызывается в случае когда больше нету активных запросов

Применение ajax + php

Для того, чтобы понять, нужен ли нам вообще ajax с php, давайте разберемся для чего он может быть полезен. Применение ajax+ php может быть разнообразным, единственное, то что, нельзя конструировать элементы страницы с помощью данной технологии, которые несут в себе релевантность для поисковых систем. Потому что ajax подгружает элементы страницы после ее загрузки при вызове js событий, но как нам известно, поисковые системы не умеют читать javascript кода, поэтому нужно тщательно выбирать где нужно, а где не нужно применять ajax с php.

Где можно применить ajax + php?

  1. Добавление нового комментария
  2. Голосование
  3. Авторизация на сайте
  4. Организация поиска на сайте (автозавершение)
  5. Пошаговая регистрация пользователя на сайте
  6. Подписка на e-mail
  7. Просмотр фотографий

И другие…

Как видите вариантов применения ajax + php масса. То есть, можно применить там, где перезагрузка страницы будет не уместной, где нужно просто обменяться данными с сервером.

Где не стоит применять ajax + php

Мое мнение объективное, может вы думаете иначе, но полагаясь на мой опыт скажу что ajax + php не стоит применять:

  1. Для реализации меню
  2. Реализации вкладок на странице (Например: когда в интернет магазине на странице товара вы видите обзор, информация, комментарии, фото, видео … не нужно делать загрузку данных при переключении данных вкладок.)

И другие негативные примеры, которые могут навредить лучшему ранжированию вашей страницы.

Взаимодействие ajax с php

По сути, технология ajax не может существовать без php скриптов, так как ajax, только отправляет данные на сервер и принимает обратный ответ, при этом не перезагружая страницы. Поэтому правильнее задать вопрос, как связать работу ajax и php. Но об этом мы поговорим в следующем пункте статьи (ajax php пример), а сейчас разберемся с спецификой работы ajax.

Для отправки данных на сервер, нужно создать объект XMLHTTPRequest. С помощью него открыть url (php скрипт), послать на него данные (POST или GET метод), получить ответ, и средствами знаний языка js вывести полученный ответ сервера на монитор (ответом может быть любой фрагмент или элемент страницы сайта).

Для прояснения посмотрите ниже предоставленную схему иллюстрирующую взаимодействие ajax с php.

ajax php взаимодействие

Ajax + php пример

Для примера взаимодействия ajax с php, создадим два файла:

1.       ajax_page.html

2.       get_ajax.php

Сначала рассмотрим пользовательскую сторону приложения, то есть ajax_page.html:


<html>
<head>
<title>Ajax + PHP: пример | sitear.ru</title>
<script Language="JavaScript">
function XmlHttp()
{
var xmlhttp;
try{xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");}
catch(e)
{
 try {xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");} 
 catch (E) {xmlhttp = false;}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined')
{
 xmlhttp = new XMLHttpRequest();
}
  return xmlhttp;
}
 
function ajax(param)
{
                if (window.XMLHttpRequest) req = new XmlHttp();
                method=(!param.method ? "POST" : param.method.toUpperCase());
 
                if(method=="GET")
                {
                               send=null;
                               param.url=param.url+"&ajax=true";
                }
                else
                {
                               send="";
                               for (var i in param.data) send+= i+"="+param.data[i]+"&";
                               send=send+"ajax=true";
                }
 
                req.open(method, param.url, true);
                if(param.statbox)document.getElementById(param.statbox).innerHTML = '<img src="images/wait.gif">';
                req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                req.send(send);
                req.onreadystatechange = function()
                {
                               if (req.readyState == 4 && req.status == 200) //если ответ положительный
                               {
                                               if(param.success)param.success(req.responseText);
                               }
                }
}
</script>
</head>
<body>
<div id="status">
Здесь будем принимать отчеты о работе ajax приложения и ответ сервера.
</div>
                <form action="get_ajax.php">
                <p><b>Поле ввода 1</b></p>
                <p><textarea id="area_1" name="area_1" style="height:50px; width:500px;">Введите свой текст. Например: Я люблю sitear.ru!</textarea></p>
                <p><b>Поле ввода 2</b></p>
                <p><textarea id="area_2" name="area_1" style="height:100px; width:500px;">Произвольный текст... Я тащусь от этой статьи, и хочу подписаться на RSS, что-бы читать такие статьи почаще!!!</textarea></p>
                <input type='button' value='TEST AJAX' onclick='
                               ajax({
                                                               url:"get_ajax.php",
                                                               statbox:"status",
                                                               method:"POST",
                                                               data:
                                                               {
                                                                              first_area:document.getElementById("area_1").value,
                                                                              second_area:document.getElementById("area_2").value
                                                              },
                                                               success:function(data){document.getElementById("status").innerHTML=data;}
                                               })'
                >
                </form>
</body>
</html>

ajax_page.html:

Пример странички ajax_page.html

Разберем javascript сторону данного примера:

XmlHttp() – функция которая создает объект XMLHttpRequest(), она написана максимально компактно и кроссбраузерно.

ajax(param) – наш обработчик при вызове событий (onclick), принимает в массиве paramнеобходимые данные:

url – куда отсылать данные, причем он может быть в таком виде page.php?parameter=value, то есть информация может передаваться по методу GET.

statbox – ид html блока который будет принимать результаты работы ajax + php приложения.

method – метод отправки данных, может быть POST или GET. В нашем примере мы используем POST метод, но в то же время через url можно передавать информацию GET методом.

data – массив передаваемых данных. В нашем примере, данные автоматически берутся из поля 1 и 2, хотя можно просто писать data: {name: "value"}.

success – имя функции или сама функция, которая будет обрабатывать полученные данные (текст).

Вызов функции ajax как вы видите сделан событием onclick=ajax().

Теперь разберем серверную сторону ajax + php приложения, то есть файл get_ajax.php:


<?php 
header("Content-type: text/plain; charset=windows-1251");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
sleep(2);
echo "Ура получилось! Спасибо sitear.ru!<br>";
while(list ($key, $val) = each ($_POST))
{
                $val = iconv("UTF-8","CP1251", $_POST[$key]);
                echo "<b>".$key.":</b> "."<pre>".stripslashes($val)."</pre>";
}
?>

Здесь все гораздо проще. Сначала устанавливаем кодировку выходящих данных, с помощью header. Устанавливаем запрет на кеширование данных. sleep(2) – приостанавливает работу скрипта на 2 секунды, это для того, что бы увидеть анимацию ожидания wait.gif. Выводим полученные данные, при этом читая все элементы массива $_POST и преобразуя их в нужную кодировку (для кириллицы).

Для запуска нашего ajax php приложения загружаем в браузер страничку ajax_page.html

Вот что у меня получилось при нажатии кнопки TEST AJAX :

Ожидание ответа php с сервера

Это ответ, полученный от файла get_ajax.php:

Ответ ajax php приложения

УДАЛЕНИЕ И ДОБАВЛЕНИЕ ТОВАРОВ В КРАТКОЙ КОРЗИНЕ

Открываем типовые динамические страницы интернет магазина, далее "Интернет-магазин корзина" и "Настройки страницы"
Находим:
// Добавление товара в корзину
if (Core_Array::getRequest('add')) ...
И выше добавляем:
// Ajax Обновление товара в корзине
if (Core_Array::getRequest('updateCart')) {
    $shop_item_id = intval(Core_Array::getRequest('updateCart'));    
    $count = intval(Core_Array::getRequest('count'));    
    if (($shop_item_id) && ($count)) {    
        $oShop_Cart_Controller = Shop_Cart_Controller::instance();
        $oShop_Cart_Controller
        ->checkStock($bCheckStock)
        ->shop_item_id($shop_item_id)
        ->quantity($count)
        ->update();
    }
}
// Ajax Удаляение товара из корзины
if (Core_Array::getRequest('deleteCart')) {
    $shop_item_id = intval(Core_Array::getRequest('deleteCart'));
    if ($shop_item_id) {
        $oShop_Cart_Controller = Shop_Cart_Controller::instance();
        $oShop_Cart_Controller
        ->shop_item_id($shop_item_id)
        ->delete();
    }
}
Находим:
// Ajax
if (Core_Array::getRequest('_', FALSE) && (Core_Array::getRequest('add') || Core_Array::getRequest('loadCart')))
И заменяем на:
// Ajax
if (Core_Array::getRequest('_', FALSE) && (Core_Array::getRequest('add') || Core_Array::getRequest('loadCart') || Core_Array::getRequest('updateCart') || Core_Array::getRequest('deleteCart')))
Изменения в JS:
Открываем скрипт магазина /templates/template_НОМЕР/script.js 
Находим:
// Функции без создания коллекции
$.extend({
...
И добалвяем в них 3 функции:
updateCart: function(path, shop_item_id, count){
    $.clientRequest({
        path: path + '?updateCart=' + shop_item_id + '&count=' + count,
        callBack: $.updelCallback,
        context: $('.little-cart')
    });
    return false;
    },
deleteCart: function(path, shop_item_id){
    $.clientRequest({
        path: path + '?deleteCart=' + shop_item_id,
        callBack: $.updelCallback,
        context: $('.little-cart')
    });
    return false;
},
updelCallback: function(data, status, jqXHR){
    $.loadingScreen('hide');
    $(this).html(data);
}
Изменения в XSL-шаблоне:
В XSL-шаблон добавляем для товара:
<xsl:variable name="kol" select="../quantity" />
<xsl:variable name="cena" select="format-number(price, '#####0,##', 'my')" />                                
Стоимость: <xsl:value-of select="$cena * $kol"/>    
<br />
Кол-во: <xsl:value-of select="$kol"/>
<br />
<a href="#" onclick="return $.updateCart('{/shop/url}cart/', {@id}, {$kol}+1)">Добавить</a>
<br />
<a href="#" onclick="return $.updateCart('{/shop/url}cart/', {@id}, {$kol}-1)">Убавить</a>
<br />
<a href="#" onclick="return $.deleteCart('{/shop/url}cart/', {@id})">Удалить</a>
Для вывода общей суммы покупок можно добавить:
<p>Сумма: <xsl:value-of select="total_amount"/><xsl:text> </xsl:text><xsl:value-of select="shop_currency/name"/></p>
Получаем 
Добавить, Убавить и Удалить лучше всего доработать и заменить на иконки