Permalink
Browse files

fix initial state for alternate init case

  • Loading branch information...
johnbender committed Dec 17, 2012
1 parent 47f82a0 commit 76663b0c91b5f81516f864dfb5481c4f7b929656
Showing with 121 additions and 117 deletions.
  1. +7 −3 js/jquery.mobile.init.js
  2. +114 −114 js/navigation/navigate.js
View
@@ -104,8 +104,12 @@ define([
$.mobile.urlHistory.initialDst = hash.replace( "#", "" );
}
var loc = path.parseLocation();
// $.navigate.history.add( loc.href, {hash: loc.hash} );
// make sure to set initial popstate state if it exists
// so that navigation back to the initial page works properly
if( $.event.special.navigate.isPushStateEnabled() ) {
$.navigate.navigator.squash( path.parseLocation().href );
}
$.mobile.changePage( $.mobile.firstPage, {
transition: "none",
reverse: true,
@@ -115,7 +119,7 @@ define([
} else {
// trigger hashchange or navigate to squash and record the correct
// history entry for an initial hash path
if( $.event.special.navigate.originalEventName === "hashchange" ) {
if( !$.event.special.navigate.isPushStateEnabled() ) {
$window.trigger( "hashchange", [true] );
} else {
// TODO figure out how to simplify this interaction with the initial history entry
View
@@ -17,121 +17,121 @@ define([
this.history = history;
};
$.extend($.Navigator.prototype, {
squash: function( url, data ) {
var state, href,
hash = path.isPath(url) ? path.stripHash(url) : url;
href = path.squash( url );
// make sure to provide this information when it isn't explicitly set in the
// data object that was passed to the squash method
state = $.extend({
hash: hash,
url: href
}, data);
// 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 $.mobile.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.
window.history.replaceState( state, state.title || document.title, href );
return state;
},
go: function( url, data, noEvents ) {
var state, href, parsed, loc, hash, popstateEvent,
isPopStateEvent = $.event.special.navigate.isPushStateEnabled(),
resolutionUrl = path.isPath( url ) ? path.getLocation() : $.mobile.getDocumentUrl();
// Get the url as it would look squashed on to the current resolution url
href = path.squash( url );
// Grab the hash for recording. If the passed url is a path
// we used the parsed version of the squashed url to reconstruct,
// otherwise we assume it's a hash and store it directly
parsed = path.parseUrl( url );
loc = path.parseLocation();
if( loc.pathname + loc.search === parsed.pathname + parsed.search ) {
// If the pathname and search of the passed url is identical to the current loc
// then we must use the hash. Otherwise there will be no event
// eg, url = "/foo/bar?baz#bang", location.href = "http://example.com/foo/bar?baz"
hash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;
} else if ( path.isPath(url) ) {
var resolved = path.parseUrl( href );
// If the passed url is a path, make it domain relative and remove any trailing hash
hash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( "#", "" ) : "");
} else {
hash = url;
}
// Here we prevent the next hash change or popstate event from doing any
// history management. In the case of hashchange we don't swallow it
// if there will be no hashchange fired (since that won't reset the value)
// and will swallow the following hashchange
history.ignoreNextHashChange = true;
if( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {
history.preventNextHashChange = noEvents;
}
// IMPORTANT in the case where popstate is supported the event will be triggered
// directly, stopping further execution - ie, interupting the flow of this
// method call to fire bindings at this expression. Below the navigate method
// there is a binding to catch this event and stop its propagation.
//
// We then trigger a new popstate event on the window with a null state
// so that the navigate events can conclude their work properly
//
// if the url is a path we want to preserve the query params that are available on
// the current url.
window.location.hash = hash;
state = $.extend({
url: href,
hash: hash,
title: document.title
}, data);
if( isPopStateEvent ) {
popstateEvent = new $.Event( "popstate" );
popstateEvent.originalEvent = {
type: "popstate",
state: null
};
this.squash( url, state );
// Trigger a new faux popstate event to replace the one that we
// caught that was triggered by the hash setting above.
if( !noEvents ) {
history.ignoreNextPopState = true;
$( window ).trigger( popstateEvent );
}
}
// record the history entry so that the information can be included
// in hashchange event driven navigate events in a similar fashion to
// the state that's provided by popstate
history.add( state.url, state );
}
});
// TODO replace singleton history object
$.History = function() {
this.stack = [];
this.activeIndex = 0;
this.initialDst = path.parseLocation().hash.replace( /^#/, "" );
$.extend($.Navigator.prototype, {
squash: function( url, data ) {
var state, href,
hash = path.isPath(url) ? path.stripHash(url) : url;
href = path.squash( url );
// make sure to provide this information when it isn't explicitly set in the
// data object that was passed to the squash method
state = $.extend({
hash: hash,
url: href
}, data);
// 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 $.mobile.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.
window.history.replaceState( state, state.title || document.title, href );
return state;
},
// TODO reconsider name
go: function( url, data, noEvents ) {
var state, href, parsed, loc, hash, popstateEvent,
isPopStateEvent = $.event.special.navigate.isPushStateEnabled(),
resolutionUrl = path.isPath( url ) ? path.getLocation() : $.mobile.getDocumentUrl();
// Get the url as it would look squashed on to the current resolution url
href = path.squash( url );
// Grab the hash for recording. If the passed url is a path
// we used the parsed version of the squashed url to reconstruct,
// otherwise we assume it's a hash and store it directly
parsed = path.parseUrl( url );
loc = path.parseLocation();
if( loc.pathname + loc.search === parsed.pathname + parsed.search ) {
// If the pathname and search of the passed url is identical to the current loc
// then we must use the hash. Otherwise there will be no event
// eg, url = "/foo/bar?baz#bang", location.href = "http://example.com/foo/bar?baz"
hash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;
} else if ( path.isPath(url) ) {
var resolved = path.parseUrl( href );
// If the passed url is a path, make it domain relative and remove any trailing hash
hash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( "#", "" ) : "");
} else {
hash = url;
}
// Here we prevent the next hash change or popstate event from doing any
// history management. In the case of hashchange we don't swallow it
// if there will be no hashchange fired (since that won't reset the value)
// and will swallow the following hashchange
history.ignoreNextHashChange = true;
if( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {
history.preventNextHashChange = noEvents;
}
// IMPORTANT in the case where popstate is supported the event will be triggered
// directly, stopping further execution - ie, interupting the flow of this
// method call to fire bindings at this expression. Below the navigate method
// there is a binding to catch this event and stop its propagation.
//
// We then trigger a new popstate event on the window with a null state
// so that the navigate events can conclude their work properly
//
// if the url is a path we want to preserve the query params that are available on
// the current url.
window.location.hash = hash;
state = $.extend({
url: href,
hash: hash,
title: document.title
}, data);
if( isPopStateEvent ) {
popstateEvent = new $.Event( "popstate" );
popstateEvent.originalEvent = {
type: "popstate",
state: null
};
this.squash( url, state );
// Trigger a new faux popstate event to replace the one that we
// caught that was triggered by the hash setting above.
if( !noEvents ) {
history.ignoreNextPopState = true;
$( window ).trigger( popstateEvent );
}
}
// record the history entry so that the information can be included
// in hashchange event driven navigate events in a similar fashion to
// the state that's provided by popstate
history.add( state.url, state );
}
});
$.History = function( stack, index, initialDestination ) {
this.stack = stack || [];
this.activeIndex = index || 0;
this.initialDst = initialDestination || path.parseLocation().hash.replace( /^#/, "" );
};
$.extend($.History.prototype, {
$.extend($.History.prototype, {
getActive: function() {
return this.stack[ this.activeIndex ];
},
@@ -253,7 +253,7 @@ define([
// existing navigation functionalty that is tightly coupled to the history information
$.navigate.history = history = new $.History();
// instantiate an instance of the navigator for use within the $.navigate method
// instantiate an instance of the navigator for use within the $.navigate method
$.navigate.navigator = new $.Navigator( history );
// This binding is intended to catch the popstate events that are fired

0 comments on commit 76663b0

Please sign in to comment.