Skip to content
This repository
Browse code

abstract backward movement in history, Fixes #4950

`window.history.back` doesn't work in phonegap applications
after a page refresh, though it does work under hashchange/replacestate.
The solution is to use their `navigator.app.backHistory` method
along with a configuration option. The reasoning for the option
is to prevent any corner cases popping up with existing phonegap
applications. Forward history movement for the same usecase is _not_
addressed but remains an even lower priority.
  • Loading branch information...
commit bd94e54e17d24d77bb488392ba750db4df52f6c6 1 parent d478003
John Bender authored September 12, 2012
29  js/jquery.mobile.navigation.js
@@ -411,10 +411,27 @@ define( [
411 411
 
412 412
 		} : undefined;
413 413
 
414  
-/*
415  
-	internal utility functions
416  
---------------------------------------*/
417  
-
  414
+	/* internal utility functions */
  415
+
  416
+	// NOTE Issue #4950 Android phonegap doesn't navigate back properly
  417
+	//      when a full page refresh has taken place. It appears that hashchange
  418
+	//      and replacestate history alterations work fine but we need to support
  419
+	//      both forms of history traversal in our code that uses backward history
  420
+	//      movement
  421
+	$.mobile.back = function() {
  422
+		var nav = window.navigator;
  423
+
  424
+		// if the setting is on and the navigator object is
  425
+		// available use the phonegap navigation capability
  426
+		if( this.phonegapNavigationEnabled &&
  427
+			nav &&
  428
+			nav.app &&
  429
+			nav.app.backHistory ){
  430
+			nav.app.backHistory();
  431
+		} else {
  432
+			window.history.back();
  433
+		}
  434
+	};
418 435
 
419 436
 	//direct focus to the page title, or otherwise first focusable element
420 437
 	$.mobile.focusPage = function ( page ) {
@@ -1329,7 +1346,7 @@ define( [
1329 1346
 
1330 1347
 			//if there's a data-rel=back attr, go back in history
1331 1348
 			if ( $link.is( ":jqmData(rel='back')" ) ) {
1332  
-				window.history.back();
  1349
+				$.mobile.back();
1333 1350
 				return false;
1334 1351
 			}
1335 1352
 
@@ -1463,7 +1480,7 @@ define( [
1463 1480
 					//the current dialog
1464 1481
 					urlHistory.directHashChange({
1465 1482
 						currentUrl: to,
1466  
-						isBack: function() { window.history.back(); },
  1483
+						isBack: function() { $.mobile.back(); },
1467 1484
 						isForward: function() { window.history.forward(); }
1468 1485
 					});
1469 1486
 
2  js/jquery.mobile.navigation.pushstate.js
@@ -95,7 +95,7 @@ define( [ "jquery", "./jquery.mobile.navigation", "depend!./jquery.hashchange[jq
95 95
 			// Note that in some cases we might be replacing an url with the
96 96
 			// same url. We do this anyways because we need to make sure that
97 97
 			// all of our history entries have a state object associated with
98  
-			// them. This allows us to work around the case where window.history.back()
  98
+			// them. This allows us to work around the case where $.mobile.back()
99 99
 			// is called to transition from an external page to an embedded page.
100 100
 			// In that particular case, a hashchange event is *NOT* generated by the browser.
101 101
 			// Ensuring each history entry has a state object means that onPopState()
2  js/widgets/dialog.js
@@ -88,7 +88,7 @@ $.widget( "mobile.dialog", $.mobile.widget, {
88 88
 		if ( this._isCloseable ) {
89 89
 			this._isCloseable = false;
90 90
 			if ( $.mobile.hashListeningEnabled ) {
91  
-				window.history.back();
  91
+				$.mobile.back();
92 92
 			} else {
93 93
 				dst = $.mobile.urlHistory.getPrev().url;
94 94
 				if ( !$.mobile.path.isPath( dst ) ) {
2  js/widgets/forms/select.custom.js
@@ -315,7 +315,7 @@ define( [
315 315
 					// doesn't solve the possible issue with calling change page
316 316
 					// where the objects don't define data urls which prevents dialog key
317 317
 					// stripping - changePage has incoming refactor
318  
-					window.history.back();
  318
+					$.mobile.back();
319 319
 				} else {
320 320
 					self.listbox.popup( "close" );
321 321
 					self.list.appendTo( self.listbox );
2  js/widgets/popup.js
@@ -753,7 +753,7 @@ define( [ "jquery",
753 753
 			}
754 754
 
755 755
 			if( this.options.history ) {
756  
-				window.history.back();
  756
+				$.mobile.back();
757 757
 			} else {
758 758
 				this._close();
759 759
 			}
18  tests/unit/navigation/navigation_helpers.js
@@ -249,4 +249,22 @@
249 249
 
250 250
 		equal( $.mobile.path.getLocation( allUriParts ), allUriParts.replace( "jblas:password@", "") );
251 251
 	});
  252
+
  253
+	test( "calling mobile back uses phonegap's navigator object when present", function() {
  254
+		var previous = $.mobile.phonegapNavigationEnabled;
  255
+
  256
+		expect( 1 );
  257
+
  258
+		$.mobile.phonegapNavigationEnabled = true;
  259
+		window.navigator = {
  260
+			app: {
  261
+				backHistory: function() {
  262
+					ok( true, "history back called" );
  263
+				}
  264
+			}
  265
+		};
  266
+
  267
+		$.mobile.back();
  268
+		$.mobile.phonegapNavigationEnabled = previous;
  269
+	});
252 270
 })(jQuery);

2 notes on commit bd94e54

Scott Jehl

Hmm, yes. +1 :)

Please sign in to comment.
Something went wrong with that request. Please try again.