Библиотека JavaScript History API: Назад в будущее.

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

Великий и могучий Интернет прочно вошел в нашу жизнь и развивается не только высокими темпами, но и часто неисповедимыми путями. Именно поэтому многие блестящие новаторские решения вынужденно дожидаются лучших времен, т.к. не могут в полной мере функционировать в неспокойном океане сети, где браузеры, воюя за превосходство либо устанавливают свои правила, либо игнорируют чужие. Не обошла такая участь и замечательную API истории HTML5. Речь в этой статье пойдет о миниатюрной и простой библиотеке History, российского программиста Дмитрия Пахтинова, которая позволяет пользоваться всеми замечательными способностями History API без опасения быть отвергнутым старыми и/или капризными браузерами.

Кратко напомню, что History API это небольшой набор методов JavaScript объекта window.history, которые позволяет управлять историей браузера, например записывать в историю требуемые адреса - history.pushState(), реагировать на события нажатия кнопок браузера "Вперед" и "Назад" - событие popstate, переписывать текущее состояние - history.replaceState() и т.д. Весь этот простой набор, однако позволяет разработчику создавать ультрасовременные динамические сайты, на которых подгрузка контента происходит без перезагрузки страницы, но при этом по доброй старой традиции меняется запись в адресной строке, заполняется история и поддерживается полноценная навигация по пройденным, а на самом деле - динамически подгруженным страницам.

Такая структура очень удобна и современна, наиболее популярные сайты (читай социальные сети, и даже не будем показывать пальцем, какие) успешно взяли ее на вооружение. Страница не мелькает и не дергается при загрузке новой информации, как это обычно происходит при перезагрузке, продолжает работать запущенный медиа-плеер, или иной процесс на странице. Повторяю, это достигается отменой перезагрузки страницы при переходе по ссылкам, и манипуляцией адресной строкой и историей из JavaScript. И все бы было чудесно, но беде случилась все та же - не поддержка History API старыми браузерами. В результате, разработчикам приходилось использовать громоздкие решения сторонних библиотек и прочие костыли. Но теперь, я с удовольствием сообщаю, что проблеме пришел конец в лице программиста devote и его библиотеки history.js.

Библиотека history.js по сути просто позволяет полноценно пользоваться способностями History API без опаски быть "непонятым" старыми браузерами и их пользователями. Так что если вы уважающий себя разработчик и желаете писать сайты по последнему слову техники, то можете смело за это браться. Библиотека history.js тестирована на таких старых браузерах как Opera 9+, FireFox3+, Internet Explorer 7+. Основные преимущества библиотеки в том, что она миниатюрна и полностью адаптивна. History.js использует стандартные методы History API, и при необходимости даже может быть легко удалена из сайта безо всякого нарушения его функциональности.

Библиотека history.js очень проста в применении.
Скачать ее последнюю версию можно по адресу http://code.spb-piksel.ru/?history.latest.zip.
Кроме того, по адресу http://history.spb-piksel.ru/ можно наглядно изучить на примере демо сайта как работает history.js.
Общее хранилище разработок автора можно найти тут https://github.com/devote.
Здесь я кратко опишу лишь основные моменты библиотеки history.js...

Подключение библиотеки может сопровождаться внесением трех параметров:

  • basepath - базовый путь к сайту, по умолчанию имеет значение корня "/".
  • redirect - преобразование ссылок, по умолчанию true(включено).
  • type - строка начала якоря, по умолчанию ничего не подставляет

Первый параметр необходим, если сайт помещен не в корневую директорию домена, а в одну из внутренних папок, тогда часть пути указанная в basepath будет дописываться в начало всех ссылок, обеспечивая корректные переходы Вторые два параметра служат для придания эстетической красоты ссылкам: redirect - убирает из ссылок символ якоря #, который необходим для совместимости со старыми браузерами. Дело в том, что в старых браузерах невозможно поменять ссылку в адресной строке не перезагрузив при этом страницу, и чтобы обойти это досадное свойство стали использовать метод якоря, который по спецификации ссылается на некое место текущей страницы, и не допускает обновления. А вот новые браузеры, знающие, что такое history.pushState(), не нуждаются в этом костыле, и параметр redirect умеет "очищать" ссылку для них, но добавлять символ # в адрес тем, кому history.pushState() не ведом. type - также служит для причесывания вида ссылок в строке, например чтобы якорь начинался со знака слеш.

Параметры basepath, redirect и type можно комбинировать при вызове:

	history-1.2.6.min.js?type=/&redirect=false&basepath=/pathtosite/ 
//	порядок опций не имеет значение.

Далее, я не стану вдаваться в подробности динамической загрузки контента, т.к. методы AJAX выходят далеко за рамки данной статьи. Основная идея состоит в том, чтобы при клике по ссылке, отменить перезагрузку ( return false), подгрузить нужный контент (ajax) и записать путь в историю ( pushState ). Но прежде всего, нужно повесить обработчик на событие popstate, реагирующее на нажатие кнопок браузера "Вперед" и "Назад". Так разработчик описывает эту процедуру:

Использование события popstate на чистом JS:

    window[ window.addEventListener ? 'addEventListener' : 'attachEvent' ]
	( 'popstate', function( event ) {

        // получение location из объекта event
        var loc = event.location || document.location;

        alert( "return to: " + loc );

    }, false);

Или использование события popstate в связке jQuery:

	$( window ).bind( 'popstate', function( event ) {

		// jQuery оригинальное событие хранит в свойстве originalEvent
		var loc = event.location || ( event.originalEvent && event.originalEvent.location )
		|| document.location;

        alert( "return to: " + loc );
	});

Обратите внимание, здесь используется event.location именно для поддержки старых браузеров. Далее иллюстрацией работы послужит сам файл http://history.spb-piksel.ru/js/main.php с демо сайта. Основные моменты: повесим на клик по ссылкам нужный обработчик, используя например jQuery:

$("#main_content a.ajax").click( actionAnchors );

Опишем функцию:

function actionAnchors( e ) {

		// подгружаем нужный контент
		this.href && loadContent( this.href, true );

		return false;
	}

и далее создадим функцию динамической загрузки, где помимо загрузки контента, в зависимости от параметра push записываем историю:

function loadContent( url, push ) {
	// вызываем ajax, подгружаем контент...
	...
	// 
	if ( push ) {
	// записываем историю и заменяем ссылку в браузере
	history.pushState( null, null, url );
	}
}

И конечно, не забываем про наш собственный обработчик popstate, который будет вызывать loadContent без параметра push, т.е. в историю ничего не вносить:

$( window ).bind( 'popstate', function( e ){
	var loc = e.location || 
	( e.originalEvent && e.originalEvent.location )|| document.location;

	// подгружаем нужный контент
	loadContent( loc.href );
});

На этом статья заканчивается, а написание сайтов продолжается.
Как любит говаривать автор библиотеки History.js : "Пользуйтесь на здоровье!".

Hosted by uCoz