Skip to content

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it wi…

License

Notifications You must be signed in to change notification settings

browserstate/history.js

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Welcome to History.js (v1.4.1 - February 10 2011)

This project is the successor of jQuery History, it aims to:

  • Support HTML5's History/State APIs
  • Provide a backwards compatible experience for Browsers which do not support HTML5's History APIs
  • Provide a backwards compatible experience for Browsers which do not support HTML4's OnHashChange
  • Provide a forwards compatible experience for HTML4 States in HTML5 Browsers (see usage section for an example)
  • Follow the original API's as much as possible and support attaching data and title properties to states as well as both the pushState and replaceState methods in both HTML4 and HTML5 browsers.
  • Support as many javascript frameworks as possible via adapters - especially jQuery, MooTools and Prototype

Licensed under the New BSD License Copyright 2011 Benjamin Arthur Lupton

Usage

Working with History.js:

(function(window,undefined){

	var History = window.History; // Note: We are using a capital H instead of a lower h

	History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
		var State = History.getState(); // Note: We are using History.getState() instead of event.state
		History.log(State.data, State.title, State.url);
	});

	History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
	History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
	History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
	History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
	History.back(); // logs {state:3}, "State 3", "?state=3"
	History.back(); // logs {state:1}, "State 1", "?state=1"
	History.back(); // logs {}, "Home Page", "?"
	History.go(2); // logs {state:3}, "State 3", "?state=3"

})(window);

So how would the above operations look in a HTML5 Browser?

  1. www.mysite.com
  2. www.mysite.com?state=1
  3. www.mysite.com?state=2
  4. www.mysite.com?state=3
  5. www.mysite.com?state=4
  6. www.mysite.com?state=3
  7. www.mysite.com?state=1
  8. www.mysite.com
  9. www.mysite.com?state=3

Note: These urls also work in HTML4 browsers and Search Engines. So no need for the #! fragment-identifier that google "recommends".

And how would they look in a HTML4 Browser?

  1. www.mysite.com
  2. www.mysite.com#?state=1/uid=1
  3. www.mysite.com#?state=2/uid=2
  4. www.mysite.com#?state=3/uid=3
  5. www.mysite.com#?state=4
  6. www.mysite.com#?state=3/uid=3
  7. www.mysite.com#?state=1/uid=1
  8. www.mysite.com
  9. www.mysite.com#?state=3/uid=3

Note 1: These urls also work in HTML5 browsers - we use replaceState to transform these HTML4 states their HTML5 equivalents so the user won't even notice :-)

Note 2: There urls will be url-encoded in Firefox 3; IE6,7,8; and Safari 5. Opera does not url-encode the urls. The url-encoding is necessary for these browsers as otherwise it won't work. There is nothing we can do about this.

What's the deal with the UIDs used in the HTML4 States?

  • UIDs are used when we utilise a title and/or data in our state. Adding a UID allows us to associate particular states with data and titles while keeping the urls as simple as possible (don't worry it's all tested, working and a lot smarter than I'm making it out to be).
  • If you aren't utilising title or data then we don't even include a UID (as there is no need for it) - as seen by State 4 above :-)
  • We also shrink the urls to make sure that the smallest url will be used. For instance we will adjust http://www.mysite.com/#http://www.mysite.com/projects/History.js to become http://www.mysite.com/#/projects/History.js automatically. (again tested, working, and smarter).
  • It works with domains, subdomains, subdirectories, whatever - doesn't matter where you put it. It's smart.

Is there a working demo?

  • Sure is, give it a download and navigate to the demo directory in your browser :-)
  • If you are after something a bit more adventurous than a end-user demo, open up the tests directory in your browser and editor - it'll rock your world and show all the vast use cases that History.js supports. Note: you will have to [run a git submodule init; git submodule update and update the tests/.htaccess for your path] prior to running the tests.

Download & Installation

  1. Download History.js and upload it to your webserver. Download links: tar.gz or zip

  2. Include JSON2 for HTML4 Browsers Only (replace www.yourwebsite.com)

     <script type="text/javascript">
     	if ( typeof JSON === 'undefined' ) {
     		var
     			url = 'http://www.yourwebsite.com/history.js/scripts/compressed/json2.min.js',
     			scriptEl = document.createElement('script');
     		scriptEl.type = 'text/javascript';
     		scriptEl.src = url;
     		document.body.appendChild(scriptEl);
     	}
     </script>
    
  3. Include the Adapter for your Framework:

    • jQuery

        <script type="text/javascript" src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.jquery.min.js"></script>
      
    • Mootools

        <script type="text/javascript" src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.mootools.min.js"></script>
      
    • Prototype

        <script type="text/javascript" src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.prototype.min.js"></script>
      
    • Would you like to support another framework? No problem! It's very easy to create adapters, and I'll be happy to include them or help out if you let me know :-)

  4. Include History.js

     <script type="text/javascript" src="http://www.yourwebsite.com/history.js/scripts/compressed/history.min.js"></script>
    

Subscribe to Updates

  • For Email Updates:
    • You can subscribe via the subscription form included in the demo page
  • For Commit RSS/Atom Updates:
  • For GitHub News Feed Updates:

Getting Support

History.js is an actively developed, supported and maintained project. You can grab support via its GitHub Issue Tracker. Alternatively you can reach Benjamin Lupton (the core developer) via twitter, skype (balupton) or email (contact@balupton.com).

Browsers: Tested and Working In

HTML5 Browsers

  • Chrome 8,9
  • Firefox 4
  • Safari 5
  • Safari iOS 4.2.1

HTML4 Browsers

  • Opera 10,11
  • Firefox 3
  • IE 6,7,8

Exposed API

Functions

  • History.pushState(data,title,url)
    Pushes a new state to the browser, data and title can be null
  • History.replaceState(data,title,url)
    Replaces the existing state with a new state to the browser, data and title can be null
  • History.getState()
    Get's the current state of the browser, returns an object with data, title and url
  • History.getHash()
    Get's the current hash of the browser
  • History.Adapter.bind(element,event,callback)
    A framework independent event binder, you may either use this or your framework's native event binder.
  • History.Adapter.trigger(element,event)
    A framework independent event trigger, you may either use this or your framework's native event trigger.
  • History.Adapter.onDomLoad(callback)
    A framework independent onDomLoad binder, you may either use this or your framework's native onDomLoad binder.
  • History.back()
    Go back once through the history (same as hitting the browser's back button)
  • History.forward()
    Go forward once through the history (same as hitting the browser's forward button)
  • History.go(X)
    If X is negative go back through history X times, if X is positive go forwards through history X times
  • History.log(...)
    Logs messages to the console, the log element, and fallbacks to alert if neither of those two exist
  • History.debug(...)
    Same as History.log but only runs if History.debug.enable === true

Events

  • window.onstatechange
    Fired when the state of the page changes (does not include hashchanges)
  • window.onanchorchange
    Fired when the anchor of the page changes (does not include state hashes)

Notes on Compatibility

  • State data will always contain the State's title and url at: data.title and data.url
  • State data and title will not persist if the page was closed then re-opened, or navigated to another website then back - this is expected/standard functionality
  • State titles will always be applied to the document.title if set
  • ReplaceState functionality is emulated in HTML4 browsers by discarding the replaced state, so when the discarded state is accessed it is skipped using the appropriate History.back() / History.forward() call
  • History.js fixes the following browser bugs:
    • Chrome does not retrieve the correct data when traversing back to the start page
    • Safari 5 and Safari iOS 4.2.1 do not fire onpopstate on page load or when the hash has changed
  • HTML4 Browsers on initial page load will have a hash inserted into the url; this is to ensure correct cross-compatibility between HTML4 browsers (as IE will refresh the page if the anchor is lost)
  • Changing the hash of the page causes onpopstate to fire; this is expected/standard functionality. To ensure correct compatibility between HTML5 and HTML4 browsers the following events have been created:
    • window.onstatechange: this is the same as onpopstate except does not fire for traditional anchors
    • window.onanchorchange: this is the same as onhashchange except does not fire for states

Changelog

  • v1.4.1 - February 10 2011

    • Added HTML History API Support for Safari 5 and Safari iOS 4.2.1
    • Cleaned code a bit (mostly with unit tests)
  • v1.4.0 - February 10 2011

    • Unit Testing now uses QUnit
    • Corrected Safari 5 Support
    • Now uses queues instead of timeouts
      • This means the API works exactly as expected, no more need to wrap calls in timeouts
    • Included a Subscribe Form in the Demo for Version Updates via Email
    • Small updates to Documentation
  • v1.3.1 - February 04 2011

    • Improved Documentation
  • v1.3.0 - January 31 2011

    • Support for cleaner HTML4 States
  • v1.2.1 - January 30 2011

    • Fixed History.log always being called - reported by dlee
    • Re-Added History.go(index) support
  • v1.2.0 - January 25 2011

    • Support for HTML4 States in HTML5 Browsers (added test)
    • Updates of Documentation
  • v1.1.0 - January 24 2011

    • Developed a series of automated test cases
    • Fixed issue with traditional anchors
    • Fixed issue with differing replaceState functionality in HTML4 Browsers
    • Fixed issue with Google Chrome artefacts being carried over to the initial state
    • Provided onstatechange and onanchorchange events
  • v1.0.0 - January 22 2011

    • Supported History.pushState and History.replaceState degradation
    • Supported jQuery, MooTools and Prototype Frameworks

Todo for Upcoming Releases

  • Normal: Style Demo
  • Minor: Add a compilation test to ensure .debug = false and no History.log calls exist.

About

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it wi…

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published