jquery-mobile/js/jquery.mobile.navigation.pushstate.js

94 lines
2.8 KiB
JavaScript
Raw Normal View History

/*
* jQuery Mobile Framework : history.pushState support, layered on top of hashchange
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
( function( $, window ) {
// For now, let's Monkeypatch this onto the end of $.mobile._registerInternalEvents
2011-08-16 00:01:37 +00:00
var pushStateHandler = self = {},
oldRegisterInternalEvents = $.mobile._registerInternalEvents,
$win = $( window );
2011-08-16 00:01:37 +00:00
$.extend( pushStateHandler, {
initialFilePath: location.pathname,
// Begin with popstate listening disabled, since it fires at onload in chrome
popListeningEnabled: false,
// Flag for tracking if a Hashchange naturally occurs after each popstate + replace
hashchangeFired: false,
state: function() {
return {
hash: location.hash || "#" + self.initialFilePath,
title: document.title,
originalHref: self.initialFilePath
};
},
onHashChange: function( e ) {
2011-08-20 14:21:49 +00:00
var href, state;
2011-08-16 00:01:37 +00:00
self.hashchangeFired = true;
// only replaceState when pushState support is present and
// the hash doesn't represent an embeded page
2011-08-17 00:06:55 +00:00
if( $.support.pushState && $.mobile.path.isPath(location.hash) ) {
// propulate the hash when its not available
2011-08-20 14:21:49 +00:00
state = self.state();
// make the hash abolute with the current href
href = $.mobile.path.makeUrlAbsolute( state.hash.replace("#", ""), location.href );
2011-08-17 23:32:59 +00:00
// replace the current url with the new href and store the state
history.replaceState( state, document.title, href );
}
2011-08-16 00:01:37 +00:00
},
2011-08-16 00:01:37 +00:00
onPopState: function( e ) {
var poppedState = e.originalEvent.state;
if( self.popListeningEnabled && poppedState ) {
history.replaceState( poppedState, poppedState.title, poppedState.originalHref + poppedState.hash );
2011-08-16 00:01:37 +00:00
// Urls that reference subpages will fire their own hashchange, so we don't want to trigger 2 in that case.
self.hashchangeFired = false;
2011-08-16 00:01:37 +00:00
setTimeout(function() {
if( !self.hashchangeFired ) {
$win.trigger( "hashchange" );
}
2011-08-16 00:01:37 +00:00
self.hashchangeFired = false;
}, 0);
}
2011-08-16 00:01:37 +00:00
},
2011-08-16 00:01:37 +00:00
init: function() {
$win.bind( "hashchange", self.onHashChange );
2011-08-16 00:01:37 +00:00
// Handle popstate events the occur through history changes
$win.bind( "popstate", self.onPopState );
// if there's no hash, we need to replacestate for returning to home
if ( location.hash === "" ) {
history.replaceState( self.state(), document.title, location.href );
}
2011-08-16 00:01:37 +00:00
// Enable pushstate listening *after window onload
// To ignore the initial pop that Chrome calls at onload
$win.load(function() {
setTimeout(function() {
self.popListeningEnabled = true;
}, 0 );
});
}
});
$.mobile._registerInternalEvents = function(){
// Call previous function
oldRegisterInternalEvents();
pushStateHandler.init();
};
})( jQuery, this );