Лабораторная работа: Технология AJAX
Название: Технология AJAX Раздел: Рефераты по информатике, программированию Тип: лабораторная работа |
Кафедра: АСОИиУ Лабораторная работа На тему: AJAX Душанбе, 2009 ВведениеAjax - технология разработки Web-приложений, который использует код на машине клиента для изменения данных на Web-сервере. В результате Web-страницы динамически обновляются без перезагрузки полной страницы, прерывающей обмен данными. С помощью Ajax вы можете создавать более богатые, более динамические пользовательские интерфейсы для Web-приложений, которые приближаются по скорости и гибкости к приложениям, выполняющимся в клиентской части вашего кода. Это два года назад AJAX был в диковинку (да и самого слова AJAX тогда ещё не выдумали). Теперь веб-приложения, страницы которых обновляются "на лету", в порядке вещей. Даже наоборот, без AJAX трудно и представить себе некоторые сервисы. Как работали обычные веб-приложения? Как правило, на событие (клик по ссылке или нажатие на кнопку) браузер реагировал отправкой запроса серверу. Когда с сервера приходил ответ, всё содержимое страницы полностью обновлялось. Одна из проблем состояла в том, что при обновлении содержимого страницы веб-приложение переходит в новое состояние. Из информации о предыдущем состоянии сохраняются только данные, переданные в запросе. Чем более точная информация о прежнем состоянии системы требуется, тем больше данных необходимо пересылать в запросе. Другим недостатком является необходимость пересылать повторяющиеся массивы данных клиенту после каждого события. Например, если пользователь ошибся при заполнении формы, то вместо короткого сообщения об ошибке приходится снова загружать и форму, и всю введённую ранее информации. Современные браузеры, поддерживающие стандарты W3CDOM, позволяют вывести веб-приложение на новый уровень. Схема взаимодействия остается почти такой же. Вот только отправляет запрос и получает ответ с сервера теперь скрипт на стороне клиента, а вместо обновления всей страницы - обновляется только ее часть (вместо обновления могут предприниматься иные действия, например, отправляться следующий запрос). Веб-приложение получается распределенным, и часть логики находится на стороне клиента, а часть - на стороне сервера. Такие приложения и называют термином "AJAXApplications" (аббревиатура расшифровывается как AsynchronousJavascriptAndXmlApplications). Объект XMLHTTPRequestДля асинхронных запросов от клиента к серверу на стороне браузера служит специальный объект под названием XMLHTTPRequest. Перечислим методы и свойства объекта, которые будут использованы далее: XMLHTTPRequest. open("method", "URL", async, "uname", "pswd") - создает запрос к серверу. method - тип запроса, например, GET URL - URL запроса, например http://localhost/file. xml async - если True, то будет использоваться асинхронный запрос, то есть выполнение скрипта продолжится после отправки запроса. В противном случае скрипт будет ожидать ответа от сервера, заморозив UI. uname, pswd - логин и пароль для простой веб-авторизации. XMLHTTPRequest. send("content") - отправляет запрос на сервер. Значением content могут быть данные для POST-запроса или пустая строка. XMLHTTPRequest. onreadystatechange - обработчик событий срабатывающий на каждое изменение состояния объекта. Состояния объекта могут быть следующими: 0 - до того как запрос отправлен (uninitialized) 1 - объект инициализирован (loading) 2 - получен ответ от сервера (loaded) 3 - соединение с сервером активно (interactive) 4 - объект завершил работу (complete) XMLHTTPRequest. responseText - возвращает полученные от сервера данные в виде строки. XMLHTTPRequest. responseXML - если ответ сервера пришел в виде правильного XML, возвращает XMLDOM объект. XMLHTTPRequest. status - возвращает статус HTTP-ответа в виде числа. Например, 404 если запрашиваемая страница не была найдена на сервере. Рассмотрим применение объекта на примере простого AJAX-приложения. Поле SELECT с поискомПредположим у нас есть таблица, в которой порядка миллиона записей. Пользователю необходимо выбрать всего одну запись из таблицы (реализация отношения "один ко многим"). Выбор пользователя является всего лишь одним из этапов заполнения большой веб-формы. Естественно, для того, чтобы пользователь мог выбрать нужную запись из миллиона, нужны какие-то средства поиска этой самой записи. Например, простой текстовый поиск по наименованию. В традиционном веб-приложении для этой цели пришлось бы использовать отдельную страницу и сохранять остальные данные формы в сессии пользователя, либо разбивать процесс заполнения формы на несколько этапов. В AJAX-приложении дополнительная страница не нужна. Выбор записи будет реализован с помощью двух элементов веб-формы. Первый элемент - это текстовое поле, где пользователь вводит ключевое слово. Оно отсылается на сервер, а тот возвращает только те строки из таблицы, которые удовлетворяют условию поиска. Ответ сервера (в виде списка) помещается в поле SELECT, в котором пользователь и сделает окончательный выбор. Таким образом, при отправке всей формы на сервер попадет выбранное в поле SELECT значение в виде ID записи из большой таблицы. В HTML выглядеть это может так: <input type="text" onkeyup="lookup(this. value, 'id_select', 'http://localhost/cgi-bin/xmlhttp. cgi')" /> <select id="id_select" name="id_select"> <option selected="selected" value=""></option> </select> На любое событие KeyUp (отжатие кнопки) в текстовом поле вызывается функция lookup ('текст', 'id-selecta', 'url') function lookup(text, select_id, url) { // Получаем объект XMLHTTPRequest if(! this. http) { this. http = get_http(); this. working = false; } // Запрос if (! this. working && this. http) { varhttp = this. http; // Если в текстовом поле менее трёх // символов - не делаем ничего if (text. length <3) return; // добавляем закодированный текст // в URL запроса url = url + "? text="+encodeURIComponent(text); // создаём запрос this. http. open("GET", url, true); // прикрепляем к запросу функцию-обработчик // событий this. http. onreadystatechange = function() { // 4 - данные готовы для обработки if (http. readyState == 4) { fill(select_id, http. responseText); this. working = false; }else{ // данные в процессе получения, // можно повеселить пользователя // сообщениями // ЖДИТЕ ОТВЕТА } } this. working = true; this. http. send(null); } if(! this. http) { alert('Ошибка при создании XMLHTTP объекта! ') } } Как видно, в начале мы получаем XMLHTTP-объект с помощью функции get_http(). Затем поисковый текст кодируется в стиле URL и формируется GET-запрос к серверу. URL запроса в данном случае будет выглядеть приблизительно так: http://localhost/cgi-bin/xmlhttp. cgi? text=... Скрипт на сервере, получив значение text, делает поиск в таблице и отсылает результат клиенту. В обработчике событий объекта XMLHTTP, когда данные от сервера получены и готовы к использованию, вызывается функция fill('select_id', 'data'), которая заполнит список SELECT полученными данными. Функция get_http() - это кросс-браузерная реализация получения объекта XMLHTTP (в каждом браузере он получается по-своему). Её реализацию с комментариями вы можете легко найти в интернете, это, так сказать, пример из учебника. function get_http() { var xmlhttp; /*@cc_on @if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2. XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft. XMLHTTP"); } catch (E) { xmlhttp = false; } } @else xmlhttp = false; @end @*/ if (! xmlhttp && typeof XMLHttpRequest! = 'undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; } } returnxmlhttp; } Функция fill() получает на вход значение параметра ID списка SELECT, который необходимо заполнить, и сами данные, полученные с сервера. Для простоты предположим, что данные с сервера мы получаем в виде таблицы, поля которой Разделены символом табуляции 't', а строки - символом переноса строки 'n': id1tname1n id2tname2n На основании содержимого этой таблицы мы будем заполнять поле SELECT элементами OPTION. function fill (select_id, data) { // поле SELECT в переменную в виде объекта var select = document. getElementById(select_id); // очищаем SELECT select. options. length = 0; // если данных нет - не делаем больше ничего if(data. length == 0) return; // в массиве arr - строки полученной таблицы var arr = data. split('n'); // для каждой строки for(var i in arr) { // в массиве val - поля полученной таблицы val = arr [i]. split('t'); // добавляем новый объект OPTION к нашему SELECT select. options [select. options. length] = newOption(val [1], val [0], false, false); } } Готово. Теперь для любой веб-формы приложения мы можем реализовать подобный выбор значения из многомиллионного списка, который для пользователя будет выглядеть как считанные нажатия клавиш. В локальной сети выбор происходит практически мгновенно. В случае нестабильного или низкоскоростного соединения с сервером, необходимо также оповещать пользователя о том, что загрузка данных с сервера еще не завершена. Полезно предусмотреть и средства для реакции на обрыв соединения. Суть ее сводится к следующему: осуществлять передачу данных (т.е. общение клиента с сервером) без фактической перезагрузки web-страницы. Есть несколько реализаций этой идеи, данная статья раскажет о моей. При этом я не утверждаю, что ее не было до меня. Если была - я о ней не знал (на момент написания сего). Для начала предлагаю определить, какие плюсы мы получаем, делая AJAX-скрипты. 1. Мы экономим траффик как посетителя, так и свой собственный (у нас ведь платный хостинг и за МБ мы платим:)). 2. Мы экономим время посетителя. 3. Мы облегчаем жизнь серверу - ему не приходится передавать каждый раз кучу "лишнего" HTML-кода. 4. В глазах посетителя мы превращаем свой сайт в системную программу. Он жмет на кнопку и практически тут же видит результат. Из личной практики: К примеру, раньше на WebFashion пользователь, чтобы выйти (очистить cookies), жал на "выход", ждал перезагрузки и, убедившись, что для системы он Гость, уходил с сайта. Теперь, он жмет "выход" и через мгновение видит изменение своего статуса (меняется верхнее навигационное меню). Я думаю, уже не осталось сомнений, что AJAX имеет право на существование на Вашем сайте. Остается только вопрос, как же реализовать идею на практике. Сразу скажу, есть несколько больших и громоздких скриптов, мне они не понравились и я решил написать свой собственный скрипт. Итак, как же динамически осуществить запрос к серверу и главное получить от него вразуметельный ответ? Я надеюсь, все знают о существовании тэга <script>. Если не знаете, дальше можно не читать. Так вот, у него есть замечательный атрибут src. Значение этого атрибута - адрес к JavaScript-файлу, спросите Вы? Не совсем. Это адрес к файлу, который содержит JavaScript-код. Чувствуете разницу? Т. е. этим файлом может быть php-файл с php-кодом, который после обработки сервером выведет некий JavaScript, попутно сохраняя что-то в файлы, создавая cookies, изменяя БД и пр. Фактически программа, создающая новую программу. Перед ознакомлением со следующим абзацем еще раз прочитайте предыдущий, осознайте о чем идет речь, покурите и возвращайтесь. Итак, Вы вернулись, значит мы можем продолжить. На повестке дня еще несколько вопросов, но обо всем по порядку. Нам нужно динамически создавать <script> в документе. Отведем для него специальный блок: <div id="_ajax" style="position: absolute; left: 0; top: 0; visibility: hidden"></div> Стоит заметить, что нам понадобится передавать параметры php-скрипту, а функции URL-кодирования в JavaScript нет. Значит нужно создать нечто вроде таблицы кодирования (выводится элементарным php-скриптом и немного правится руками): Дабы не забивать метр статьи, вкладываю файл. Теперь напишем функцию, которая будет динамически создавать <script>. Функция принимает три параметра: адрес php-файла, массив имен передающихся переменных и массив значений этих переменных. Каждое значение мы будем URL-кодировать. function LoadScript(addr,query,str) { // составление строки запроса for(k = 0; k < str. length; k++) { str2 = ""; // URL-кодируем (что такое chr смотрим во вложенном файле) for(j = 0; j < str [k]. length; j++) str2 += '%' + chr [str [k]. charAt(j)] ; // добавляем к концу запроса "переменная=значение" addr += query [k] +"="+str2; } /* * _ajax - идентификатор div-блока, кто забыл. * Немного пляшем с бубном: * Писать в HTML только <script></script> нельзя - IE ругается, * поэтому добавляем любую строчку, например "MSIE... ". * Также нельзя одной строкой написать "</script>", * разбиваем на две строки. */ _ajax. innerHTML = "MSIE... <script></"+"script>"; /* * даем JavaScript 10 мсек на осознание того, что _ajax изменен * и назначаем атрибут src. */ setTimeout( function() { scr = _ajax. getElementsByTagName("script") [0] ; scr. language = "javascript"; if (scr. setAttribute) scr. setAttribute("src",addr); else scr. src=addr; } , 10); } Теперь, чтобы выполнить запрос index. php? action=view&id=49, нужно вызвать функцию LoadScript() следующим образом: LoadScript("index. php",Array("? action","&id"),Array("view","49")); Для выполнения скрипта без параметров следует передать функции LoadScript() его адрес и два пустых массива. Вы спросите, как выдать некий результат из php-скрипта? В документе, из которого запускаем LoadScript(), создаем блок <divid="_hz"></div> А в php-скрипте пишем echo<<<a _hz. innerHTML="работает!!!"; a; И теперь остается еще один маленький вопросик. Дело в том, что все скрипты, вызывающиеся как <scriptsrc="address"></script> кэшируются браузером. Чтобы этого избежать, каждый php-скрипт начинаем с четырех строк: Header("Expires: Mon, 26 Jul 1997 05: 00: 00 GMT"); Header("Cache-Control: no-cache, must-revalidate"); Header("Pragma: no-cache"); Header("Last-Modified: ". gmdate("D, в M Y H: i: s"). "GMT"); |