mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-04-19 22:00:59 +00:00
- Make sure that our hashchange resolves non-path hashes against the documentBase. This prevents the resulting changePath() call from incorrectly resolving against the URL for the current active (external) page. - Fixed a problem in the push-state code. A hashchange event is *NOT* fired when navigating back (window.history.back()) from an external page to an internal page. This makes sense when you think about it since hashchange is only ever fired when the hash of the current document url changes, not when the document url itself changes. The fix was to make sure that the pushstate hashchange callback always sets a state object, even on embedded page URLs. This allows the hashchange callback to be triggered from within onPopState().
126 lines
No EOL
4.1 KiB
JavaScript
126 lines
No EOL
4.1 KiB
JavaScript
/*
|
|
* 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
|
|
// Scope self to pushStateHandler so we can reference it sanely within the
|
|
// methods handed off as event handlers
|
|
var pushStateHandler = {},
|
|
self = pushStateHandler,
|
|
$win = $( window ),
|
|
url = $.mobile.path.parseUrl( location.href );
|
|
|
|
$.extend( pushStateHandler, {
|
|
// TODO move to a path helper, this is rather common functionality
|
|
initialFilePath: (function() {
|
|
return url.pathname + url.search;
|
|
})(),
|
|
|
|
initialHref: url.hrefNoHash,
|
|
|
|
// 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,
|
|
|
|
// persist across refresh
|
|
initialHref: self.initialHref
|
|
};
|
|
},
|
|
|
|
resetUIKeys: function( url ) {
|
|
var dialog = $.mobile.dialogHashKey,
|
|
subkey = "&" + $.mobile.subPageUrlKey,
|
|
dialogIndex = url.indexOf( dialog );
|
|
|
|
if( dialogIndex > -1 ) {
|
|
url = url.slice( 0, dialogIndex ) + "#" + url.slice( dialogIndex );
|
|
} else if( url.indexOf( subkey ) > -1 ) {
|
|
url = url.split( subkey ).join( "#" + subkey );
|
|
}
|
|
|
|
return url;
|
|
},
|
|
|
|
// on hash change we want to clean up the url
|
|
// NOTE this takes place *after* the vanilla navigation hash change
|
|
// handling has taken place and set the state of the DOM
|
|
onHashChange: function( e ) {
|
|
var href, state,
|
|
hash = location.hash,
|
|
isPath = $.mobile.path.isPath( hash );
|
|
hash = isPath ? hash.replace( "#", "" ) : hash;
|
|
|
|
self.hashchangeFired = true;
|
|
|
|
// propulate the hash when its not available
|
|
state = self.state();
|
|
|
|
// make the hash abolute with the current href
|
|
href = $.mobile.path.makeUrlAbsolute( hash, location.href );
|
|
|
|
if ( isPath ) {
|
|
href = self.resetUIKeys( href );
|
|
}
|
|
|
|
// replace the current url with the new href and store the state
|
|
// Note that in some cases we might be replacing an url with the
|
|
// same url. We do this anyways because we need to make sure that
|
|
// all of our history entries have a state object associated with
|
|
// them. This allows us to work around the case where window.history.back()
|
|
// is called to transition from an external page to an embedded page.
|
|
// In that particular case, a hashchange event is *NOT* generated by the browser.
|
|
// Ensuring each history entry has a state object means that onPopState()
|
|
// will always trigger our hashchange callback even when a hashchange event
|
|
// is not fired.
|
|
history.replaceState( state, document.title, href );
|
|
},
|
|
|
|
// on popstate (ie back or forward) we need to replace the hash that was there previously
|
|
// cleaned up by the additional hash handling
|
|
onPopState: function( e ) {
|
|
var poppedState = e.originalEvent.state, holdnexthashchange = false;
|
|
|
|
// if there's no state its not a popstate we care about, ie chrome's initial popstate
|
|
// or forward popstate
|
|
if( poppedState ) {
|
|
// disable any hashchange triggered by the browser
|
|
$.mobile.urlHistory.ignoreNextHashChange = true;
|
|
|
|
// defer our manual hashchange until after the browser fired
|
|
// version has come and gone
|
|
setTimeout(function() {
|
|
// make sure that the manual hash handling takes place
|
|
$.mobile.urlHistory.ignoreNextHashChange = false;
|
|
|
|
// change the page based on the hash
|
|
$.mobile._handleHashChange( poppedState.hash );
|
|
}, 100);
|
|
}
|
|
},
|
|
|
|
init: function() {
|
|
$win.bind( "hashchange", self.onHashChange );
|
|
|
|
// 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 );
|
|
}
|
|
}
|
|
});
|
|
|
|
$( function() {
|
|
if( $.mobile.pushStateEnabled && $.support.pushState ){
|
|
pushStateHandler.init();
|
|
}
|
|
});
|
|
})( jQuery, this ); |