• Stars
    star
    1,016
  • Rank 45,279 (Top 0.9 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 12 years ago
  • Updated about 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

HTML5 History API expansion for browsers not supporting pushState, replaceState

ENGLISH

This Javascript library provides an emulation of HTML5 History API for older browsers.

The library operates according to W3C specification, adding no new or incompatible methods. The library can be used exactly as described, for example, in Dive Into HTML5 book (http://diveintohtml5.info/history.html) or in the History API Specification (http://www.w3.org/TR/html5/browsers.html#the-history-interface).

You may install this plugin with this command:

npm install html5-history-api

Browser Support:

history.js - IE8+ and other browsers

history.ielte7.js - IE6+ and other browsers

For library developers:

To enable support for HTML5-History-API polyfill in your library, you need to add one line of code:

var location = window.history.location || window.location;

code of library looks like this:

(function(){
  // To enable support for HTML5-History-API polyfill in your library
  var location = window.history.location || window.location;

  // you library code here
  // ....
  // ....
  // ....
})();

AMD Support:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="/require.js"></script>
    <script type="text/javascript">
      requirejs(['/history'], function() {
        if (history.emulate) {
          console.log('In your browser is emulated HTML5-History-API');
        } else {
          console.log('In your browser is natively support HTML5-History-API');
        }
      });
    </script>
  </head>
  <body>
  </body>
</html>

Example of using the library in the pure JS context:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="history.js"></script>
    <script type="text/javascript">
      (function(eventInfo) {
        // we get a normal Location object

        /*
         * Note, this is the only difference when using this library,
         * because the object window.location cannot be overriden,
         * so library the returns generated "location" object within
         * an object window.history, so get it out of "history.location".
         * For browsers supporting "history.pushState" get generated
         * object "location" with the usual "window.location".
         */
        var location = window.history.location || window.location;

        // hang on the event, all references in this document
        document[eventInfo[0]](eventInfo[1] + 'click', function(event) {
          event = event || window.event;
          var target = event.target || event.srcElement;
          // looking for all the links with 'ajax' class found
          if (target && target.nodeName === 'A' &&
             (' ' + target.className + ' ').indexOf(' ajax ') >= 0)
          {
            // keep the link in the browser history
            history.pushState(null, null, target.href);

            // here can cause data loading, etc.

            // do not give a default action
            if (event.preventDefault) {
              event.preventDefault();
            } else {
              event.returnValue = false;
            }
          }
        }, false);

        // hang on popstate event triggered by pressing back/forward in browser
        window[eventInfo[0]](eventInfo[1] + 'popstate', function(event) {

          // here can cause data loading, etc.

          // just post
          alert("We returned to the page with a link: " + location.href);
        }, false);
      })(window.addEventListener ? ['addEventListener', ''] : ['attachEvent', 'on']);
    </script>
  </head>
  <body>
    <a class="ajax" href="/mylink.html">My Link</a>
    <a class="ajax" href="/otherlink.html">Other Link</a>
  </body>
</html>

Example of using the library along with JQuery:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="history.js"></script>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      $(function() {
        // we get a normal Location object

        /*
         * Note, this is the only difference when using this library,
         * because the object window.location cannot be overriden,
         * so library the returns generated "location" object within
         * an object window.history, so get it out of "history.location".
         * For browsers supporting "history.pushState" get generated
         * object "location" with the usual "window.location".
         */
        var location = window.history.location || window.location;

        // looking for all the links and hang on the event, all references in this document
        $(document).on('click', 'a.ajax', function() {
          // keep the link in the browser history
          history.pushState(null, null, this.href);

          // here can cause data loading, etc.

          // do not give a default action
          return false;
        });

        // hang on popstate event triggered by pressing back/forward in browser
        $(window).on('popstate', function(e) {

          // here can cause data loading, etc.

          // just post
          alert("We returned to the page with a link: " + location.href);
        });
      });
    </script>
  </head>
  <body>
    <a class="ajax" href="/mylink.html">My Link</a>
    <a class="ajax" href="/otherlink.html">Other Link</a>
  </body>
</html>

Advanced library configuration:

history.js?basepath=/pathtosite/ - the base path to the site; defaults to the root "/".
history.js?redirect=true - enable link translation.
history.js?type=/ - substitute the string after the anchor; by default "/".

You can also combine options:

history.js?type=/&redirect=true&basepath=/pathtosite/ - the order of options does not matter.

Or execute special method in JavaScript:

history.redirect(/* type = */ '/', /* basepath = */ '/pathtosite/');

Demo Site: http://history.spb-piksel.ru/ or http://devote.github.io/demos/history/

Follow me on Twitter: https://twitter.com/DimaPakhtinov


Π Π£Π‘Π‘ΠšΠ˜Π™ (Russian)

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° эмулируСт HTML5 History API Π² старых Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°Ρ….

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°, которая Π½Π΅ добавляСт Π½Π΅Π½ΡƒΠΆΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, заставляя ΠΈΡ… ΠΈΠ·ΡƒΡ‡Π°Ρ‚ΡŒ, Π° ΠΎΠΏΠ΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠΎ спСцификации w3c, ΠΏΠΎ интСрфСйсу History.

Для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΠΎΠ³Ρƒ привСсти ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ ΠΊΠΎΠ΄ ΠΊΠ°ΠΊ с Π½Π΅ΠΉ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ.

По ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ ΠΌΡ‹ Ρ€Π°Π±ΠΎΡ‚Π°Π΅ΠΌ с HTML5 History API Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ описано, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‚ΡƒΡ‚ http://htmlbook.ru/html5/history ΠΈΠ»ΠΈ ΠΏΠΎ спСцификации http://www.w3.org/TR/html5/history.html#the-history-interface

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ»Π°Π³ΠΈΠ½ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

npm install html5-history-api

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΎΠ²:

history.js - IE8+ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Ρ‹

history.ielte7.js - IE6+ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Ρ‹

Для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ:

Для Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ ΠΏΠ»Π°Π³ΠΈΠ½Π° HTML5-History-API polyfill Π² своих Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ…, Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ строку ΠΊΠΎΠ΄Π°:

var location = window.history.location || window.location;

ΠΊΠΎΠ΄ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ:

(function(){
  // Π’ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ ΠΏΠ»Π°Π³ΠΈΠ½Π° HTML5-History-API polyfill
  var location = window.history.location || window.location;

  // ΠΊΠΎΠ΄ вашСй Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ
  // ....
  // ....
  // ....
})();

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° AMD:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="/require.js"></script>
    <script type="text/javascript">
      requirejs(['/history'], function() {
        if (history.emulate) {
          console.log('Π’ вашСм Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅ эмулируСтся HTML5-History-API');
        } else {
          console.log('Π’ вашСм Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅ Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° HTML5-History-API');
        }
      });
    </script>
  </head>
  <body>
  </body>
</html>

ΠšΠΎΡ€ΠΎΡ‚Π΅Π½ΡŒΠΊΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° чистом JS:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="history.js"></script>
    <script type="text/javascript">
      (function(eventInfo) {
        // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Location

        /*
         * Π·Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, это СдинствСнная Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с Π΄Π°Π½Π½ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ,
         * Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ window.location нСльзя ΠΏΠ΅Ρ€Π΅Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ, поэтому
         * Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° history Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ сформированный "location" ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π²Π½ΡƒΡ‚Ρ€ΠΈ
         * ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° window.history, поэтому ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π΅Π³ΠΎ ΠΈΠ· "history.location".
         * Для Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΎΠ² ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΡ… "history.pushState" ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ
         * сформированный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ "location" с ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ "window.location".
         */
        var location = window.history.location || window.location;

        // вСшаСм события Π½Π° всС ссылки Π² нашСм Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅
        document[eventInfo[0]](eventInfo[1] + 'click', function(event) {
          event = event || window.event;
          var target = event.target || event.srcElement;
          // ΠΈΡ‰Π΅ΠΌ всС ссылки с классом 'ajax'
          if (target && target.nodeName === 'A' &&
             (' ' + target.className + ' ').indexOf('ajax') >= 0)
          {
            // заносим ссылку Π² ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ
            history.pushState(null, null, target.href);

            // Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠ·ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚.ΠΏ.

            // Π½Π΅ Π΄Π°Π΅ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ дСйствиС ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ
            if (event.preventDefault) {
              event.preventDefault();
            } else {
              event.returnValue = false;
            }
          }
        }, false);

        // вСшаСм событиС Π½Π° popstate ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ срабатываСт ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ back/forward Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅
        window[eventInfo[0]](eventInfo[1] + 'popstate', function(event) {

          // Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠ·ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚.ΠΏ.

          // просто сообщСниС
          alert("We returned to the page with a link: " + location.href);
        }, false);
      })(window.addEventListener ? ['addEventListener', ''] : ['attachEvent', 'on']);
    </script>
  </head>
  <body>
    <a class="ajax" href="/mylink.html">My Link</a>
    <a class="ajax" href="/otherlink.html">Other Link</a>
  </body>
</html>

А Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°ΡŽ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π² связкС с jQuery:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="history.js"></script>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      $(function() {
        // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Location

        /*
         * Π·Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, это СдинствСнная Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с Π΄Π°Π½Π½ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ,
         * Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ window.location нСльзя ΠΏΠ΅Ρ€Π΅Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ, поэтому
         * Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° history Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ сформированный "location" ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π²Π½ΡƒΡ‚Ρ€ΠΈ
         * ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° window.history, поэтому ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π΅Π³ΠΎ ΠΈΠ· "history.location".
         * Для Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΎΠ² ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΡ… "history.pushState" ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ
         * сформированный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ "location" с ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ "window.location".
         */
        var location = window.history.location || window.location;

        // ΠΈΡ‰Π΅ΠΌ всС ссылки ΠΈ вСшаСм события Π½Π° всС ссылки Π² нашСм Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅
        $(document).on('click', 'a.ajax', function() {
          // заносим ссылку Π² ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ
          history.pushState(null, null, this.href);

          // Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠ·ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚.ΠΏ.

          // Π½Π΅ Π΄Π°Π΅ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ дСйствиС ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ
          return false;
        });

        // вСшаСм событиС Π½Π° popstate ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ срабатываСт ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ back/forward Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅
        $(window).on('popstate', function(e) {

          // Ρ‚ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠ·ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚.ΠΏ.

          // просто сообщСниС
          alert("ΠœΡ‹ Π²Π΅Ρ€Π½ΡƒΠ»ΠΈΡΡŒ Π½Π° страницу со ссылкой: " + location.href);
        });
      });
    </script>
  </head>
  <body>
    <a class="ajax" href="/mylink.html">My Link</a>
    <a class="ajax" href="/otherlink.html">Other Link</a>
  </body>
</html>

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ:

history.js?basepath=/pathtosite/ - Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ ΠΊ сайту, ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ корня "/".
history.js?redirect=true - Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ссылок.
history.js?type=/ - ΠΏΠΎΠ΄ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ подстроку послС якоря, ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈΠΌΠ΅Π΅Ρ‚ символ "/".

Π’Π°ΠΊΠΆΠ΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠΏΡ†ΠΈΠΈ:

history.js?type=/&redirect=true&basepath=/pathtosite/ - порядок ΠΎΠΏΡ†ΠΈΠΉ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

Или Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π² JavaScript:

history.redirect(/* type = */ '/', /* basepath = */ '/pathtosite/');

Π”Π΅ΠΌΠΎ-сайт: http://history.spb-piksel.ru/ ΠΈΠ»ΠΈ http://devote.github.io/demos/history/

Π― Π² Twitter: https://twitter.com/DimaPakhtinov