Skip to content
This repository was archived by the owner on Oct 8, 2021. It is now read-only.

Commit 6602c21

Browse files
committed
address browsers that don't fire popstate on hash assignment Fixes #5414
1 parent b36f023 commit 6602c21

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed

js/jquery.mobile.navigation.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1181,7 +1181,6 @@ define( [
11811181
});
11821182

11831183
$.mobile._handleHashChange = function( url, data ) {
1184-
11851184
//find first page via hash
11861185
var to = path.stripHash(url),
11871186
//transition is false if it's the first page, undefined otherwise (and may be overridden by default)

js/navigation/navigator.js

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
99

1010
$.Navigator = function( history ) {
1111
this.history = history;
12+
this.ignoreInitialHashChange = true;
13+
14+
// This ensures that browsers which don't fire the initial popstate
15+
// like opera don't have further hash assignment popstates blocked
16+
setTimeout($.proxy(function() {
17+
this.ignoreInitialHashChange = false;
18+
}, this), 200);
1219

1320
$.mobile.window.bind({
1421
"popstate.history": $.proxy( this.popstate, this ),
@@ -18,8 +25,7 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
1825

1926
$.extend($.Navigator.prototype, {
2027
squash: function( url, data ) {
21-
var state, href, self = this,
22-
hash = path.isPath(url) ? path.stripHash(url) : url;
28+
var state, href, hash = path.isPath(url) ? path.stripHash(url) : url;
2329

2430
href = path.squash( url );
2531

@@ -42,19 +48,6 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
4248
// is not fired.
4349
window.history.replaceState( state, state.title || document.title, href );
4450

45-
46-
// If popstate is enabled and the browser triggers `popstate` events when the hash
47-
// is set (this often happens immediately in browsers like Chrome), then the
48-
// this flag will be set to false already. If it's a browser that does not trigger
49-
// a `popstate` on hash assignement or `replaceState` then we need to unlock the
50-
// At the time of this writing this happens with Opera 12
51-
// NOTE I hate the fact that we have to do this but it captures all the possible
52-
// issues with browsers that won't trigger a popstate in either case
53-
// ie, hash assignment/replaceState
54-
setTimeout(function() {
55-
self.ignoreNextHashChange = false;
56-
}, 100);
57-
5851
return state;
5952
},
6053

@@ -85,7 +78,7 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
8578

8679
// TODO reconsider name
8780
go: function( url, data, noEvents ) {
88-
var state, href, hash, popstateEvent;
81+
var state, href, hash, popstateEvent,
8982
isPopStateEvent = $.event.special.navigate.isPushStateEnabled();
9083

9184
// Get the url as it would look squashed on to the current resolution url
@@ -115,15 +108,21 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
115108
// the current url.
116109
window.location.hash = hash;
117110

111+
// If popstate is enabled and the browser triggers `popstate` events when the hash
112+
// is set (this often happens immediately in browsers like Chrome), then the
113+
// this flag will be set to false already. If it's a browser that does not trigger
114+
// a `popstate` on hash assignement or `replaceState` then we need avoid the branch
115+
// that swallows the event created by the popstate generated by the hash assignment
116+
// At the time of this writing this happens with Opera 12 and some version of IE
117+
this.ignoreNextHashChange = false;
118+
118119
state = $.extend({
119120
url: href,
120121
hash: hash,
121122
title: document.title
122123
}, data);
123124

124125
if( isPopStateEvent ) {
125-
126-
127126
popstateEvent = new $.Event( "popstate" );
128127
popstateEvent.originalEvent = {
129128
type: "popstate",
@@ -178,6 +177,17 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
178177
return;
179178
}
180179

180+
// If there is no state, and the history stack length is one were
181+
// probably getting the page load popstate fired by browsers like chrome
182+
// avoid it and set the one time flag to false
183+
if( !event.originalEvent.state
184+
&& this.history.stack.length == 1
185+
&& this.ignoreInitialHashChange ) {
186+
this.ignoreInitialHashChange = false;
187+
188+
return;
189+
}
190+
181191
// account for direct manipulation of the hash. That is, we will receive a popstate
182192
// when the hash is changed by assignment, and it won't have a state associated. We
183193
// then need to squash the hash. See below for handling of hash assignment that
@@ -186,10 +196,9 @@ define([ "jquery", "../events/navigate", "./path", "./history" ], function( $ )
186196
hash = path.parseLocation().hash;
187197
active = this.history.getActive();
188198

189-
// Avoid adding a history entry in two cases
190-
// 1) on the initial hashchange
191-
// 2) when the current history entry hash is identical to the
192-
// current location hash
199+
// We want to avoid adding a history entry in for the initial
200+
// hash change, but we also want to permit hash assignment to work
201+
// when there is only
193202
if( this.history.stack.length !== 1 || hash !== active.hash ) {
194203
state = $.navigate.navigator.squash( hash );
195204
// TODO it might be better to only add to the history stack

0 commit comments

Comments
 (0)