Хороший AJAX
Большинство веб-разработчиков ограничивают себя в использовании аякса, потому что он, как известно, обладает некоторыми распространенными недостатками:
- Неиндексируемость динамически загружаемого содержимого поисковиками;
- Невозможность работать с URL (к примеру, добавлять в закладки динамически загруженный материал);
- Динамически создаваемые страницы не регистрируются в истории браузера, поэтому невозможно использовать клавиши «назад» и «вперед»;
Но, на другой стороне весов имеются неопровержимые преимущества AJAX:
- Экономия трафика;
- Уменьшение нагрузки на сервер;
- Ускоренная работа веб-приложения (это результат первых двух пунктов).
В этой статье мы расскажем, как преодолеть минусы и полноценно пользоваться плюсами AJAX.
Идеи
- Все страницы сайта получаем через AJAX, т. е. обновляем только заголовок и содержимое страницы. Это увеличивает скорость работы сайта и снижает трафик между сервером и браузером.
- У каждой «аяксовой» страницы свой адрес. Например, вы кидаете другу ссылку в аське на такую страницу и он видит именно то, что нужно. Или человек приходит по ссылке на какую-то страницу (скажем, из поисковика) и тоже видит нужную страницу.
- Понятная навигация — страницы сайта не ссылаются сами на себя. В нашем случаем мы будем просто выделять ссылки на текущую страницу.
- Рабочие кнопки «назад» и «вперед». Чтобы пользователь работал с нашим сайтом в привычной ему форме.
- Работа сайта без Javascript. Содержимое сайта будет индексироваться поисковиками и приверженцы текстовых браузеров тоже не останутся в обиде.
Серверная часть
Для начала нам нужен . Кроме того, у нас должна быть возможность получать одну и ту же страницу в форматах HTML (полный код страницы) и XML (только заголовок и содержимое страницы). При этом будет удобно, если html и xml версии будут различаться только одним параметром в адресе. Например, так:
- HTML версия страницы — /page1/page 1-1.html;
- XML версия — /page1/page 1-1.html?ajax=yes.
Мы сделали это на PHP, вы же можете выбрать любой другой серверный язык программирования.
Клиентская часть
Для простоты работы возьмем библиотеку (с ее помощью будем реализовывать AJAX). Для работы с историей браузера понадобиться библиотека .
Для начала нам нужно переписать адреса у ссылок и на событие click привязать выполнение AJAX-запроса, отметку ссылок с тем же адресом, что и у текущей, и добавление этого клика в историю посещений. Обратите внимание, что мы не будем переписывать следующие типы ссылок:
- внешние ссылки, т. е. ссылки на страницы других сайтов;
- ссылки на картинки, архивы и прочие файлы (расширения таких файлов указываем в переменной forbiddenTypes);
- ссылки с заранее указанным классом (forbiddenClass) — если внутри сайта есть страницы, которые необходимо грузить целиком.
function setupNewLinks(obj) { var links = obj.getElementsByTagName("a"); // все ссылки внутри объекта obj // перебираем ссылки for (i = 0; i < links.length; i ++) { // проверяем, можно ли переписывать адрес текущей ссылки //(проверка по имени класса, расширению и "внешности" ссылки// если можно, то переписываем tmp = links[i].href; tmp = tmp.replace("http://"+site, ""); indexOfDot = 0; if(tmp.lastIndexOf(".") > 0) indexOfDot = tmp.lastIndexOf("."); if(forbiddenTypes.match(tmp.substring(indexOfDot)) == null && tmp.substring(0, 7) != "http://" && links[i].className != forbiddenClass) { // прописываем, что происходит при клике на ссылку $(links[i]).bind("click", function() { markLinksWithHref(this.href); historyVar.getNewHistoryState(this.href.replace("http://"+site+"/#", "")); this.className = "curPage"; }); // заменяем адрес links[i].href = "#" + tmp; } } }
Параметром функции указываем объект страницы, внутри которого надо искать ссылки.Вначале указываем весь документ (setupNewLinks (document)), при каждом обновлении контента — только этот контент (setupNewLinks (document.getElementById (’’content’’))).
Сейчас при клике на ссылку ее класс меняется на curPage. Но нам нужно отметить все такие ссылки внутри страницы. Для этого используем вот такую функцию. Ее аргумент — адрес текущей ссылки.
// с помощью этой функции мы отмечаем все ссылки // с одинаковым значением href function markLinksWithHref(linkHref) { var links = document.getElementsByTagName("a"); if(navigator.appName == 'Microsoft Internet Explorer') linkHref = linkHref.replace("http://"+site+"/", ""); for (i = 0; i < links.length; i ++) { if(links[i].href == linkHref || links[i].href == linkHref+"/") links[i].className = "curPage"; else links[i].className = ""; } }
Мы получили данные в формате XML и теперь нам нужно их распарсить и заменить заголовок и содержание текущей страницы. Аргументом функции будет полученный XML.
function parseGetData(data) { //получаем заголовок и содержание страницы из XML title = data.getElementsByTagName('title'); cnt = data.getElementsByTagName('content'); //вставляем это в нашу страницу $('#content').html(cnt[0].firstChild.nodeValue); document.title = title[0].firstChild.nodeValue; // обновляем ссылки внутри страницы setupNewLinks(document.getElementById('content')); markLinksWithHref(window.location.href); }
Итак,мы реализовали пункты 1 и 3. Сделаем пункт 2. При каждой загрузке страницы (или клике на кнопки «назад» или «вперед») мы будем проверять адрес и показывать пользователю нужную ему страницу. Заметим, что проверка при первой загрузке и переходе из истории немного отличаются.
function checkAnchorOnload() { // определяем полный путь и якорь страницы var urlPathName = location.pathname; var urlAnchor = location.hash; // проверяем адрес, если пользователь первый раз //вошел на сайт. Если в адресе есть якорь, то // подгружаем страницу if(start == 'yes') { if(urlPathName != "/") { location.href = "http://"+site+"/#"+urlPathName; } else if(urlAnchor != "" && urlAnchor.indexOf("#/") != -1) { getDataAjax(urlAnchor.replace("#", "")); } } // примерно такая же проверка, но только при нажатии // "назад" или "вперед" в браузере else if(start == '') { if(urlPathName == "/") { if(urlAnchor == "" || (urlAnchor == "#" && navigator.appName == 'Microsoft Internet Explorer')) { getDataAjax("http://"+site+"/"); } else if(urlAnchor.indexOf("#/") != -1) { getDataAjax(urlAnchor.replace("#/", "")); } } } }
Рассмотрим функцию, которая будет «слушать» изменение истории и реагировать на нажатия кнопок «назад» и «вперед».
function historyHandler() { var stateVar = "nothin'", displayDiv = document.getElementById("content"); this.getNewHistoryState = function(currentState) { var newVal = currentState; unFocus.History.addHistory(newVal); }; this.historyListener = function(historyHash) { stateVar = historyHash; // при каждом изменении истории мы будем // выдавать соответствующий контент checkAnchorOnload(); }; unFocus.History.addEventListener('historyChange', this.historyListener); this.historyListener(unFocus.History.getCurrent()); }; var historyVar;
Мы написали все необходимые функции, осталось только «привязать» их к странице.
function init() { setupNewLinks(document); // переписываем адреса ссылок historyVar = new historyHandler(); // запоминаем историю start = ''; }
Лучше всего вызывать эту функцию либо при загрузке DOM, либо в конце самого документа.
В итоге получился .
Оригинал статьи на . Взято с .
