jQuery hashchange event
This jQuery plugin enables very basic bookmarkable #hash history via a cross-browser HTML5 window.onhashchange event.
While this functionality was initially tied to the jQuery BBQ plugin, the event.special window.onhashchange functionality has now been broken out into a separate plugin for users who want just the basic event & back button support, without all the extra awesomeness that BBQ provides.
- Release v1.3
- Tested with jQuery 1.2.6, 1.3.2, 1.4.1, 1.4.2 in Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
- Download Source, Minified (0.8kb gzipped)
- Follow the project on GitHub project page or report a bug!
- View Full Documentation
- View Unit Tests
- Examples: hashchange, document.domain
Why is a plugin needed for the hashchange event?
Right now, in Internet Explorer 8, Firefox 3.6+, and Chrome 5+, you can bind callbacks to the window.onhashchange event and use it without any kind of plugin. Of course, what happens when you want your code to work in a browser that doesn’t support window.onhashchange?
Well, nothing happens.. because the event doesn’t exist, so it never fires. But because jQuery provides a layer of abstraction between actual events and bound callbacks, it’s relatively easy to create a new event using jQuery’s special events.
How does the plugin work?
When a browser-native window.onhashchange event is detected, that event is used for the hashchange
event automatically. However, when that event isn’t detected, at the first attempt to bind to the event, a polling loop is started to monitor location.hash
for changes, firing the event whenever appropriate.
Additionally, since history entries aren’t added when the hash changes in IE6/7, a hidden Iframe is created and updated whenever the hash changes to trick the browser into thinking that the page’s URL has changed, thus forcing new entries to be added into the history. Without this Iframe, the hashchange
event would still fire, but without back button support the utility of the event is reduced substantially.
When the last window.onhashchange event is unbound, the polling loop is stopped (except in IE6/7, because it is still needed for back button support).
A basic usage example
Simple. Bind the "hashchange"
event to $(window)
and every time the hash changes, the callback will fire. Check out the [working example][ex] to see this in action.
$(function(){ // Bind the event. $(window).hashchange( function(){ // Alerts every time the hash changes! alert( location.hash ); }) // Trigger the event (useful on page load). $(window).hashchange(); });
A more robust solution
This plugin is, by design, very basic. If you want to add lot of extra utility around getting and setting the hash as a state, and parsing and merging fragment params, check out the jQuery BBQ plugin. It includes this plugin at its core, plus a whole lot more, and has thorough documentation and examples as well. You can’t have too much of a good thing!
Known hashchange issues
While this jQuery hashchange event implementation is quite stable and robust, there are a few unfortunate browser bugs surrounding expected hashchange event-based behaviors, independent of any JavaScript window.onhashchange abstraction. See the following pages for more information:
- Chrome: Back Button
- Firefox: Remote XMLHttpRequest
- WebKit: Back Button in an Iframe
- Safari: Back Button from a different domain
Also note that should a browser natively support the window.onhashchange event, but not report that it does, the fallback polling loop will be used.
If you have any non-bug-related feedback or suggestions, please let me know below in the comments, and if you have any bug reports, please report them in the issues tracker, thanks!
I want to thank Brandon Aaron for explaining parts of the jQuery.event.special API for me and providing me the example code on which I based this plugin.
a
,b
,i
,br
,p
,strong
,em
,pre
,code
.<pre class="brush:js"></pre>
(supported syntax highlighting brushes:
js
,css
,php
,plain
,bash
,ruby
,html
,xml
)<
instead of<
and>
instead of>
in the examples themselves.