Настройка Wi-Fi

Используем HTML5 History API. Управление историей просмотров

Используем HTML5 History API. Управление историей просмотров

До появления HTML5 единственное, что мы не могли контролировать и управлять (без перезагрузки контента или хаков с location.hash) - это история одного таба. С появлением HTML5 history API все изменилось - теперь мы можем гулять по истории (раньше тоже могли), добавлять элементы в историю, реагировать на переходы по истории и другие полезности. В этой статье мы рассмотрим HTML5 History API и напишем простой пример, иллюстрирующий его возможности.

Основные понятия и синтаксис History API опирается на один DOM интерфейс - объект History. Каждый таб имеет уникальный объект History, который находится в window.history . History имеет несколько методов, событий и свойств, которыми мы можем управлять из JavaScript. Каждая страница таба(Document object) представляет собой объект коллекции History. Каждый элемент истории состоит из URL и/или объекта состояния (state object), может иметь заголовок (title), Document object, данные форм, позиция скролла и другую информацию, связанную со страницей.

Основные методы объекта History:

  • window.history.length: Количество записей в текущей сессии истории
  • window.history.state: Возвращает текущий объект истории
  • window.history.go(n) : Метод, позволяющий гулять по истории. В качестве аргумента передается смещение, относительно текущей позиции. Если передан 0, то будет обновлена текущая страница. Если индекс выходит за пределы истории, то ничего не произойдет.
  • window.history.back() : Метод, идентичный вызову go(-1)
  • window.history.forward() : Метод, идентичный вызову go(1)
  • window.history.pushState(data, title [, url]) : Добавляет элемент истории.
  • window.history.replaceState(data, title [, url]) : Обновляет текущий элемент истории
  • Для перехода на 2 шага назад по истории можно использовать:
    history.go(-2)
    Для добавления элементов истории мы можем использовать history.pushState:
    history.pushState({foo: "bar"}, "Title", "/baz.html")
    Для изменения записи истории мы можем использовать history.replaceState:
    history.replaceState({foo: "bat"}, "New Title") Живой пример Теперь мы знаем основы, давайте посмотрим на живой пример. Мы будем делать веб файловый менеджер, который позволит вам найти URI выбранного изображения(). Файловый менеджер использует простую файловую структуру, написанную на JavaScript. Когда вы выбираете файл или папку картинка динамически обновляется.

    Мы используем data-* атрибуты для хранения заголовка каждой картинки и используем свойство dataset для получения этого свойства:

  • crab2.png

  • Чтобы все работало быстро мы подгружаем все картинки и обновляем атрибут src динамически. Это ускорение создает одну проблему - оно ломает кнопку назад, поэтому вы не можете переходить по картинками вперед или назад.

    HTML5 history приходит на помощь! Каждый раз когда мы выбираем файл создается новая запись истории и location документа обновляется (оно содержит уникальный URL картинки). Это означает, что мы можем использовать кнопку назад для обхода наших изображений, в то время как в строке адреса у нас будет прямая ссылка на картинку, которую мы можем сохранить в закладки или отправить кому-либо.

    Код У нас есть 2 дива. Один содержит структуру папок, другой содержит текущую картинку. Все приложение управляется с помощью JavaScript. В будут освещены только самые важные моменты. Исходный код примера очень короткий (порядка 80 строк) посмотрите его после прочтения всей статьи.

    Метод bindEvents навешивает обработчики для события popstate , который вызывается, когда пользователь переходит по истории и позволяет приложению обновлять свое состояние.
    window.addEventListener("popstate", function(e){ self.loadImage(e.state.path, e.state.note); }, false);
    Объект event , который передается в обработчик события popstate имеет свойство state - это данные, которые мы передали в качестве первого аргумента pushState или replaceState .

    Мы навешиваем обработчик на событие click на див, который представляет нашу файловую структуру. Используя делегацию событий, мы открываем или закрываем папку или загружаем картинку (с добавлением записи в историю). Мы смотрим на className родительского элемента для того, чтобы понять на какой из элементов мы нажали:
    - Если это папка мы открываем или закрываем её
    - Если это картина, то мы показываем её и добавляем элемент истории

    Dir.addEventListener("click", function(e){ e.preventDefault(); var f = e.target; // Это папка if (f.parentNode.classList.contains("folder")) { // Открываем или закрываем папку self.toggleFolders(f); } // Это картинка else if (f.parentNode.classList.contains("photo")){ note = f.dataset ? f.dataset.note: f.getAttribute("data-note"); // отрисовываем картинку self.loadImage(f.textContent, note); // добавляем элемент истории history.pushState({note: note, path:f.textContent}, "", f.textContent); } }, false);
    Метод, который изменяет содержимое картинки и обновляет её подпись очень прост:
    loadImage: function(path, note){ img.src = path; h2.textContent = note; }
    Мы получили простое приложение , демонстрирующее возможности обновленного интерфейса объекта History . Мы используем pushState для добавления элемента истории и событие popstate для обновления содержимого страницы. Кроме этого при клике на картинку мы получаем в адресной строке её действительный адрес, который мы можем сохранить или отправить кому-нибудь.

    Когда можно будет использовать? Firefox 4+
    Safari 5+
    Chrome 10+
    Opera 11.5+
    iOS Safari 4.2+
    Android 2.2+
    IE ???
    Список браузеров , поддерживающих history API

    History API представляет собой одно из интересных новшеств HTML 5. Благодаря ему появляется возможность навигации по истории одного таба браузера без перезагрузки страницы, при этом браузер корректно отрабатывает функции "назад" и "вперед".

    Это дает замечательные возможности при использовании History API совместно с Ajax. Теперь нет необходимости использовать традиционную конструкцию #!, можно просто заменить URL целиком. Благодаря этому мы получаем следующие преимущества:

      ­
    • в URL теперь отображается реальный адрес страницы, пользователи могут спокойно копировать ссылку на страницу из адресной строки браузера и распространять ее;
    • ­
    • отказ от конструкции #! при использовании Ajax позволяет не беспокоиться о потерянных для индексации поисковыми системами ссылках;
    • ­
    • ссылки просто становятся чище и красивее.

    В этой статье мы кратко рассмотрим HTML5 History API и создадим простой пример с использованием плагина History.js для популярного Javascript ­фреймворка jQuery. В качестве примера реализуем постраничную Ajax­навигацию на странице листинга продуктов Magento.

    Обзор HTML5 History API

    За работу с историей отвечает объект History. Мы можем получить этот объект для текущего таба через read­only ссылку window.history.

    Основные методы и свойства объекта History:

    window.history.state

    Возвращает текущий объект истории. С помощью этого объекта можно получить данные, которые передаются методами pushState и replaceState путем доступа к свойствам этого объекта.

    window.history.length

    Свойство lenght показывает количество записей в истории.

    window.history.go(n)

    Переход к определенной позиции в истории, в качестве аргумента передается смещение относительно текущий позиции. Этот метод существовал до появления HTML5.

    window.history.back()

    Переход к предыдущему элементу в истории, идентично вызову go(- ­1).

    window.history.forward()

    Переход к следующему элементу в истории, идентичный вызову go(1).

    Методы window.history.back() и window.history.forward() также существовали до HTML5.

    window.history.pushState(data, title [, url])

    Добавляет новый элемент в историю. Метод принимает три параметра:

  • Данные состояния истории. Эти данные можно получить затем в обработчике события popstate. Если дополнительные данные не требуются можно передавать null;
  • Заголовок страницы, который отобразится в окне браузер, так же можно передавать null;
  • URL, который должен отображаться в адресной строке.
  • History.pushState({param: "Value"}, "", "myurl.html");

    Если текущий URL был http://yoursite.com/path/to/page.html, то он будет заменен на http://yoursite.com/path/to/myurl.html, как если бы мы перешли по ссылке обычным способом.

    URL, передаваемый третьим параметром, может быть как относительным так и абсолютными, но использование Ajax накладывает ограничение на использование только текущего домена.

    window.history.replaceState(data, title [, url])

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

    popstate

    Это событие срабатывает при переход от одного элемента истории к другому. При этом history.pushState() и history.replaceState() не приводят к вызову этого события. Только нажатие кнопок вперед/назад в браузере, либо вызов history.back() или аналогичной функции в Javascript.

    Window.addEventListener("popstate", function(e) { // код обработчика события }); Поддержка браузерами

    History Api и jQuery

    Существует интересный плагин History.js , который предоставляет единый интерфейс для всех популярных браузеров для работы с историей просмотра. Он базируется на HTML5 History API и содержит практически те же самые методы, что и объект window.history. Используя данный плагин, можно не беспокоиться о работе скрипта в старых браузерах. Если браузер не имеет поддержки History API, то для его эмуляции будет использован # (якорь URL).

    Для обращения к функциям плагина используется объект History. Например, вызов функции History.pushState(data,title,url) практически аналогичен вызову history.pushState. Детально ознакомиться с Api плагина можно на его сайте. Однако, есть 2 момента, на которые стоит обратить внимание:

  • Плагин использует собственное событие «statechange» вместо стандартного «popstate» для определения момента перехода по истории;
  • Методы History.pushState и History.replaceState приводят к вызову события «statechange», тогда как аналогичные методы объекта window.history нет.
  • Живой пример

    Для демонстрации работы плагина добавим Ajax с динамической сменой URL к стандартной постраничной навигации продуктов Magento.

    Скачать плагин можно по этой ссылке https://github.com/browserstate/history.js/ . Нам потребуется только один файл jquery.history.js из папки scripts/bundled/html4+html5 (минимизированная версия с поддержкой HTML4). Подключаем файл плагина и библиотеку jQuery, если она еще не подключена. В версии Magento 1.9.0.1, которую я использовал для этого примера, jQuery подключен по умолчанию, поэтому мне достаточно подключить только файл плагина.

    Копируем jquery.history.js в папку /skin/frontend///js/lib/. В моем случае это папка skin/frontend/rwd/default/js/lib/. В файле разметки page.xml текущей темы в в самый конец блока «head» добавляем:

    ... skin_jsjs/lib/jquery.history.js

    Кроме этого, нам потребуется отдельный файл для инициализации плагина и написания собственного кода обработчиков событий. Создадим файл main.js и так же поместим его в папку текущего скина по адресу skin/frontend///js/.

    Подключаем файл main.js:

    ... skin_jsjs/lib/jquery.history.js skin_jsjs/main.js

    В файл main.js добавляем следующий код:

    (function ($) { $(function(){ var $categoryProducts = $(".category-products"); $categoryProducts.on("click", ".pages a", function(e){ e.preventDefault(); History.pushState(null, document.title, $(this).attr("href")); loadPage($(this).attr("href")); }); function loadPage(url) { $categoryProducts.load(url + " .category-products > *"); } }); })(jQuery);

    Мы использовали именно такой синтаксис для избежания конфликтов с библиотекой Prototype, которую Magento использует по умолчанию.

    (function ($) { // код })(jQuery);

    Мы добавили обработчик события «click» на ссылки постраничной навигации и отменили стандартное поведение ссылок с помощью метода e.preventDefault. Затем мы используем History.pushState для добавления нового элемента в историю и в фоновом режиме загружаем новую страницу с помощью функции loadPage.

    $categoryProducts.load(url + " .category-products > *");

    Этот код загружает страницу по указанному URL с помощью Ajax и помещает в элемент $categoryProducts содержимое блока с классом ".category-products".

    Рассмотрим подробнее вызов метода History.pushState.

    History.pushState(null, document.title, $(this).attr("href"));

    Первым параметром передаем null, так как нам не требуется передавать дополнительные параметры в объект State. Вторым параметром передаем текущий заголовок документа, поскольку при переходе на следующую страницу нам не нужно менять заголовок. И третьим параметром передаем новый URL - ссылка, на которую нажал пользователь.

    Для проверки работы этого примера нужно зайти в любую категорию с товарами, где количество товаров достаточно для появления постраничной навигации, и перейти на любую другую страницу. После этого URL в адресной строке заменяется на новый, как если бы мы перешли по этому URL, и после небольшой паузы подгружаются товары с новой страницы.

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

    History.Adapter.bind(window, "statechange", function(e){ var State = History.getState(); loadPage(State.url); });

    Поскольку событие «statechange» срабатывает всякий раз, когда происходит переход по истории, нам больше не требуется вызывать функцию loadPage после History.pushState.

    После внесения необходимых правок, наш код выглядит следующим образом:

    (function ($) { $(function(){ var $categoryProducts = $(".category-products"); $categoryProducts.on("click", ".pages a", function(e){ e.preventDefault(); History.pushState(null, document.title, $(this).attr("href")); }); function loadPage(url) { $categoryProducts.load(url + " .category-products > *"); } History.Adapter.bind(window, "statechange",function(e){ var State = History.getState(); loadPage(State.url); }); }); })(jQuery);

    Теперь при нажатии в браузере кнопок вперед/назад срабатывает событие «statechange» и содержимое страницы корректно обновляется. Для наглядного отображения процесса загрузки немного изменим функцию loadPage, добавив изменение прозрачности блока с продуктами на время загрузки контента.

    Function loadPage(url) { $categoryProducts.css({opacity: 0.5}); $categoryProducts.load(url + " .category-products > *", function(){ $categoryProducts.css({opacity: 1}); }); }

    На этом наш простой пример завершен. Как видите, использование History API не представляет особых сложностей. Вы легко можете использовать красивые URL в Ваших Ajax-приложениях, не боясь проблем с поисковиками, а использованный в примере плагин позволит избежать проблем в старых браузерах.

    Спасибо за внимание!

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

    Однако теперь, обе операции доступны благодаря HTML5 History API. Теперь мы можем создавать одностраничные приложения, не применяя значение хеш-функций. Это также позволяет нам создавать приложения благоприятно совместимые с SEO. Кроме того, данная техника позволяет уменьшать трафик - но как?

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

    Отправка контента должна осуществляться со стороны сервера.

    Браузерная поддержка

    На время написания данной статьи HTML5 History API довольно-таки неплохо поддерживается браузерами. Однако, в самом начале скрипта мы создадим проверку. Это позволит проверить браузерную совместимость.

    Чтобы определить программным путем, поддерживает ли ваш браузер API, используйте следующую проверку:

    Return !!(window.history && history.pushState);

    Если вы используете Modernizr, то проверка будет следующей:

    If (Modernizr.history) { // History API Supported }

    Если ваш браузер не поддерживает History API, то вы можете использовать полизаполнение history.js .

    Взаимодействие с историей
  • history.pushState()
  • history.replaceState()
  • С помощью данных функций можно добавлять и обновлять состояние истории. Они работают почти одинаково и принимают один и тот же же набор параметров. В дополнение, можно упоминуть ещё об одной функции: popstate . Чуть позже мы увидим их в действии.

    Функции pushState и replaceState принимают одинаковое число параметров:

    • state строка в формате JSON.
    • title на данный момент игнорируется всеми браузерами поэтому его лучше установить как null.
    • url представляет собой любой электронный адрес. Данное значение будет обновлено в браузере. Нет разницы, существует данный URL или нет. Самое главное, что страница не будет перезагружена.

    Различия между данными методами состоит в том, что pushState добавит новую запись в историю, а replaceState заменит текущее значение. Давай рассмотрим работу данных функций на примере.

    Предположим у нас есть несколько блоков, расположенных в стеке, названные 1 и 2. Так же у нас есть блок 3. Когда мы выполним команду pushState , блок 3 добится в существующий стек. В результате в нём будет 3 блока.

    Теперь представьте ту же ситуацию. При выполнении функции replaceState , блок 2 будет заменён на блок 3. Таким образом количество блоков останется тем же.

    Наглядный пример:

    Метот popstate будет запускаться, при передвижении по истории, используя методы history.go или history.back . В браузерах WebKit команда popstate запускалась бы после события onload , но это не касается Firefox и IE.

    Примеры: HTML

    Click on Links above to see history API usage using pushState method. Home!

    Lorem Ipsum is simply dummy text of the printing and typesetting industry.

    JavaScript

    jQuery("document").ready(function(){ jQuery(".historyAPI").on("click", function(e){ e.preventDefault(); var href = $(this).attr("href"); // Getting Content getContent(href, true); jQuery(".historyAPI").removeClass("active"); $(this).addClass("active"); }); }); // Adding popstate event listener to handle browser back button window.addEventListener("popstate", function(e) { // Get State value using e.state getContent(location.pathname, false); }); function getContent(url, addEntry) { $.get(url) .done(function(data) { // Updating Content on Page $("#contentHolder").html(data); if(addEntry == true) { // Add History Entry using pushState history.pushState(null, null, url); } }); }

    Using history.pushState() changes the referrer that gets used in the HTTP header for XMLHttpRequest objects created after you change the state. The referrer will be the URL of the document whose window is this at the time of creation of the XMLHttpRequest object.

    Example of pushState() method

    Suppose http://mozilla.org/foo.html executes the following JavaScript:

    Let stateObj = { foo: "bar", }; history.pushState(stateObj, "page 2", "bar.html");

    This will cause the URL bar to display http://mozilla.org/bar.html , but won"t cause the browser to load bar.html or even check that bar.html exists.

    Suppose now that the user navigates to http://google.com, then clicks the Back button. At this point, the URL bar will display http://mozilla.org/bar.html and history.state will contain the stateObj . The popstate event won"t be fired because the page has been reloaded. The page itself will look like bar.html.

    If we click Back again, the URL will change to http://mozilla.org/foo.html , and the document will get a popstate event, this time with a null state object. Here too, going back doesn"t change the document"s contents from what they were in the previous step, although the document might update its contents manually upon receiving the popstate event.

    The pushState() method

    pushState() takes three parameters: a state object, a title (which is currently ignored), and (optionally) a URL. Let"s examine each of these three parameters in more detail:

      state object - The state object is a JavaScript object which is associated with the new history entry created by pushState() . Whenever the user navigates to the new state, a popstate event is fired, and the state property of the event contains a copy of the history entry"s state object.

      The state object can be anything that can be serialized. Because Firefox saves state objects to the user"s disk so they can be restored after the user restarts the browser, we impose a size limit of 640k characters on the serialized representation of a state object. If you pass a state object whose serialized representation is larger than this to pushState() , the method will throw an exception. If you need more space than this, you"re encouraged to use sessionStorage and/or localStorage .

      title - Firefox currently ignores this parameter, although it may use it in the future. Passing the empty string here should be safe against future changes to the method. Alternatively, you could pass a short title for the state to which you"re moving.

      URL - The new history entry"s URL is given by this parameter. Note that the browser won"t attempt to load this URL after a call to pushState() , but it might attempt to load the URL later, for instance after the user restarts the browser. The new URL does not need to be absolute; if it"s relative, it"s resolved relative to the current URL. The new URL must be of the same origin as the current URL; otherwise, pushState() will throw an exception. This parameter is optional; if it isn"t specified, it"s set to the document"s current URL.

    Note: In Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) through Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), the passed object is serialized using JSON. Starting in Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3), the object is serialized using the structured clone algorithm . This allows a wider variety of objects to be safely passed.

    In a sense, calling pushState() is similar to setting window.location = "#foo" , in that both will also create and activate another history entry associated with the current document. But pushState() has a few advantages:

    • The new URL can be any URL in the same origin as the current URL. In contrast, setting window.location keeps you at the same document only if you modify only the hash.
    • You don"t have to change the URL if you don"t want to. In contrast, setting window.location = "#foo"; creates a new history entry only if the current hash isn"t #foo .
    • You can associate arbitrary data with your new history entry. With the hash-based approach, you need to encode all of the relevant data into a short string.
    • If title is subsequently used by browsers, this data can be utilized (independent of, say, the hash).

    Note that pushState() never causes a hashchange event to be fired, even if the new URL differs from the old URL only in its hash.

    Specifications Specification Status Comment
    HTML Living Standard
    Living Standard No change from HTML5 .
    HTML5
    The definition of "History" in that specification.
    Recommendation Initial definition.
    Browser compatibility

    The compatibility table on this page is generated from structured data. If you"d like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

    Update compatibility data on GitHub

    Desktop Mobile Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Edge Mobile Firefox for Android Opera for Android Safari on iOS Samsung Internet History back forward go length pushState replaceState scrollRestoration state
    Chrome Full support Yes Edge Full support Yes Firefox Full support Yes IE Full support Yes Opera Full support Yes Safari Full support Yes Samsung Internet Android ?
    Chrome Full support Yes Edge Full support 12 Firefox Full support Yes IE ? Opera ? Safari ? WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile ? Firefox Android Full support Yes Opera Android ? Safari iOS ? Samsung Internet Android ?
    Chrome Full support Yes Edge Full support 12 Firefox Full support Yes IE ? Opera ? Safari ? WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile ? Firefox Android Full support Yes Opera Android ? Safari iOS ? Samsung Internet Android ?
    Chrome Full support Yes Edge Full support 12 Firefox Full support Yes IE ? Opera ? Safari ? WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile ? Firefox Android Full support Yes Opera Android ? Safari iOS ? Samsung Internet Android ?
    Chrome Full support Yes Edge Full support 12 Firefox Full support Yes IE ? Opera ? Safari ? WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile ? Firefox Android Full support Yes Opera Android ? Safari iOS ? Samsung Internet Android ?
    Chrome Full support 5 Edge Full support 12 Firefox Full support 4

    Notes

    Full support 4

    Notes

    Notes
    IE Full support 10 Opera Full support 11.5 Safari Full support 5 WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile Full support Yes Firefox Android Full support Yes Opera Android Full support Yes Samsung Internet Android ?
    Chrome Full support 5 Edge Full support 12 Firefox Full support 4

    Notes

    Full support 4

    Notes

    Notes In Firefox 2 through 5, the passed object is serialized using JSON. Starting in Firefox 6, the object is serialized using . This allows a wider variety of objects to be safely passed.
    IE Full support 10 Opera Full support 11.5 Safari Full support 5 WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile Full support Yes Firefox Android Full support Yes Opera Android Full support Yes Safari iOS Full support 4.3 Samsung Internet Android ?
    Chrome Full support 46 Edge No support No Firefox Full support 46 IE No support No Opera Full support 33 Safari Full support Yes WebView Android No support No Chrome Android Full support 46 Edge Mobile No support No Firefox Android Full support Yes Opera Android Full support Yes Safari iOS Full support Yes Samsung Internet Android ?
    Chrome Full support Yes Edge Full support 12 Firefox Full support Yes IE ? Opera ? Safari ? WebView Android Full support Yes Chrome Android Full support Yes Edge Mobile ? Firefox Android Full support Yes Opera Android ? Safari iOS ? Samsung Internet Android ?
    Legend Full support Full support No support No support Compatibility unknown Compatibility unknown See implementation notes. See implementation notes.

    До появления HTML5 единственное, что мы не могли контролировать и управлять (без перезагрузки контента или хаков с location.hash) - это история одного таба. С появлением HTML5 history API все изменилось - теперь мы можем гулять по истории (раньше тоже могли), добавлять элементы в историю, реагировать на переходы по истории и другие полезности. В этой статье мы рассмотрим HTML5 History API и напишем простой пример, иллюстрирующий его возможности.

    Основные понятия и синтаксис History API опирается на один DOM интерфейс - объект History. Каждый таб имеет уникальный объект History, который находится в window.history . History имеет несколько методов, событий и свойств, которыми мы можем управлять из JavaScript. Каждая страница таба(Document object) представляет собой объект коллекции History. Каждый элемент истории состоит из URL и/или объекта состояния (state object), может иметь заголовок (title), Document object, данные форм, позиция скролла и другую информацию, связанную со страницей.

    Основные методы объекта History:

  • window.history.length: Количество записей в текущей сессии истории
  • window.history.state: Возвращает текущий объект истории
  • window.history.go(n) : Метод, позволяющий гулять по истории. В качестве аргумента передается смещение, относительно текущей позиции. Если передан 0, то будет обновлена текущая страница. Если индекс выходит за пределы истории, то ничего не произойдет.
  • window.history.back() : Метод, идентичный вызову go(-1)
  • window.history.forward() : Метод, идентичный вызову go(1)
  • window.history.pushState(data, title [, url]) : Добавляет элемент истории.
  • window.history.replaceState(data, title [, url]) : Обновляет текущий элемент истории
  • Для перехода на 2 шага назад по истории можно использовать:
    history.go(-2)
    Для добавления элементов истории мы можем использовать history.pushState:
    history.pushState({foo: "bar"}, "Title", "/baz.html")
    Для изменения записи истории мы можем использовать history.replaceState:
    history.replaceState({foo: "bat"}, "New Title") Живой пример Теперь мы знаем основы, давайте посмотрим на живой пример. Мы будем делать веб файловый менеджер, который позволит вам найти URI выбранного изображения(). Файловый менеджер использует простую файловую структуру, написанную на JavaScript. Когда вы выбираете файл или папку картинка динамически обновляется.

    Мы используем data-* атрибуты для хранения заголовка каждой картинки и используем свойство dataset для получения этого свойства:

  • crab2.png

  • Чтобы все работало быстро мы подгружаем все картинки и обновляем атрибут src динамически. Это ускорение создает одну проблему - оно ломает кнопку назад, поэтому вы не можете переходить по картинками вперед или назад.

    HTML5 history приходит на помощь! Каждый раз когда мы выбираем файл создается новая запись истории и location документа обновляется (оно содержит уникальный URL картинки). Это означает, что мы можем использовать кнопку назад для обхода наших изображений, в то время как в строке адреса у нас будет прямая ссылка на картинку, которую мы можем сохранить в закладки или отправить кому-либо.

    Код У нас есть 2 дива. Один содержит структуру папок, другой содержит текущую картинку. Все приложение управляется с помощью JavaScript. В будут освещены только самые важные моменты. Исходный код примера очень короткий (порядка 80 строк) посмотрите его после прочтения всей статьи.

    Метод bindEvents навешивает обработчики для события popstate , который вызывается, когда пользователь переходит по истории и позволяет приложению обновлять свое состояние.
    window.addEventListener("popstate", function(e){ self.loadImage(e.state.path, e.state.note); }, false);
    Объект event , который передается в обработчик события popstate имеет свойство state - это данные, которые мы передали в качестве первого аргумента pushState или replaceState .

    Мы навешиваем обработчик на событие click на див, который представляет нашу файловую структуру. Используя делегацию событий, мы открываем или закрываем папку или загружаем картинку (с добавлением записи в историю). Мы смотрим на className родительского элемента для того, чтобы понять на какой из элементов мы нажали:
    - Если это папка мы открываем или закрываем её
    - Если это картина, то мы показываем её и добавляем элемент истории

    Dir.addEventListener("click", function(e){ e.preventDefault(); var f = e.target; // Это папка if (f.parentNode.classList.contains("folder")) { // Открываем или закрываем папку self.toggleFolders(f); } // Это картинка else if (f.parentNode.classList.contains("photo")){ note = f.dataset ? f.dataset.note: f.getAttribute("data-note"); // отрисовываем картинку self.loadImage(f.textContent, note); // добавляем элемент истории history.pushState({note: note, path:f.textContent}, "", f.textContent); } }, false);
    Метод, который изменяет содержимое картинки и обновляет её подпись очень прост:
    loadImage: function(path, note){ img.src = path; h2.textContent = note; }
    Мы получили простое приложение , демонстрирующее возможности обновленного интерфейса объекта History . Мы используем pushState для добавления элемента истории и событие popstate для обновления содержимого страницы. Кроме этого при клике на картинку мы получаем в адресной строке её действительный адрес, который мы можем сохранить или отправить кому-нибудь.

    Когда можно будет использовать? Firefox 4+
    Safari 5+
    Chrome 10+
    Opera 11.5+
    iOS Safari 4.2+
    Android 2.2+
    IE ???
    Список браузеров , поддерживающих history API