location.hashmay still be the recommended solution for saving application state.
location.hashcan't be updated. (it should still dispatch
changedsignal at each
Include JS-Signals and hasher to your HTML file:
signals.js should be included before
//handle hash changesconsole.lognewHash;hasherchangedaddhandleChanges; //add hash change listenerhasherinitializedaddhandleChanges; //add initialized listener (to grab initial value in case it is already set)hasherinit; //initialize hasher (start listening for history changes)hashersetHash'foo'; //change hash value (generates new history record)
Google have a proposal for making Ajax content crawlable by specifying that a certain hash value also have an static snapshot. Those hash values should start with an exclamation mark
hasherprependHash = '!'; //default value is "/"hashersetHash'foo'; //will update location.hash to "#!foo" -> htttp://example.com/#!foo
PS: Only use the hashbang if you are generating static snapshots for the hash.
One of the greatest benefits of Hasher over other solutions is that it uses JS-Signals for the event dispatch, which provides many advanced features. This can be useful when you are setting the hash value and your
changed handler doesn't need to be called (e.g. updating hash value during scroll). Use it with care.
hasherchangedactive = false; //disable changed signalhashersetHashhash; //set hash without dispatching changed signalhasherchangedactive = true; //re-enable signalhasherinit; //start listening for changeshasherchangedaddconsole.log console; //log all changeshashersetHash'foo';setHashSilently'lorem/ipsum'; //set hash value without dispatching changed event (will generate history record anyway)hashersetHash'bar';
Hasher also contains the method
replaceHash(). It works very similarly to the
setHash() method (will also dispatch a
changed signal), the main difference
it that it won't keep the previous hash on the history record (similar to
location.replace()). It's useful for redirections and any other change that
shouldn't be on the browser history.
if curHash == ''// redirect to "home" hash without keeping the empty hash on the historyhasherreplaceHash'home';hasherinitializedaddonHasherInit;hasherchangedaddconsole.log console; // log all hasheshasherinit;
Hasher is only focused on providing a reliable and clear API for setting hash values and listening to hash state change event. If you need an advanced routing system check crossroads.js. Both were designed to work together easily:
//setup crossroadscrossroadsaddRoute'home';crossroadsaddRoute'lorem';crossroadsaddRoute'lorem/ipsum';crossroadsroutedaddconsole.log console; //log all routes//setup hashercrossroadsparsenewHash;hasherinitializedaddparseHash; // parse initial hashhasherchangedaddparseHash; //parse hash changeshasherinit; //start listening for history change
Hasher will listen for the browser
onhashchange event if it is supported (FF3.6+, IE8+, Chrome 5+, Safari 5+, Opera 10.6+)
or it will fallback to pooling the
window.location on an interval to check if
hash value changed. On IE 6-7 it also uses an hidden iframe to trigger
the history state changes (since updating the hash value won't do the trick).
This is the same method used by most of the other available solutions like swfaddress,
jQuery Address, YUI History, jqBBQ, Really Simple History, etc...
The main difference from the other solutions are the API, code structure and the fact that it doesn't require jQuery/YUI/dojo/moootools/etc to work. It also uses JS-Signals for the events which provides a sane way of handling events and some really useful advanced features.
Besides the fact of making history state work across multiple browsers it also normalizes and fixes many bugs, here are a few of the advantges:
location.hashcontains a "?" character and file is being accessed locally it would break the history stack. [iss #6]
location.hashto a value that contain non-printable ASCII chars (non-latin, accents, etc..). [iss #8]
location.hashisn't available, will dispatch the
changedsignal at each
hasher.setHash()and application can still work, it just won't generate a new history record.
Documentation can be found inside the
dist/docs folder or at http://millermedeiros.github.com/Hasher/docs/.
Hasher is usually tested on IE (6,7,8,9), FF (3.6, 4.0, 5.0+ - mac/pc), Chrome (latest stable - mac/pc), Safari Mac (4.3, 5.0) and Opera (latest - mac/pc).
You can also run the test by yourself at http://millermedeiros.github.com/Hasher/test/unit.html
master -> always contain code from the latest stable version release-** -> code canditate for the next stable version (alpha/beta) dev -> main development branch (nightly) gh-pages -> project page **other** -> features/hotfixes/experimental, probably non-stable code
Documentation is inside the
This project uses Apache Ant for the build process. If for some reason you need to build a custom version install Ant and run:
This will delete all JS files inside the
dist folder, merge/update/compress source files and copy the output to the
This will delete all files inside dist folder, is runs
ant compile and generate documentation files.
dist folder always contain the latest version, regular users should not need to run build task.
Released under the MIT license.
changedsignal even if it can't update the browser
location.hash, so application should keep working even if back/prev buttons doesn't work as expected.