@@ -47,9 +47,15 @@ define([

// TODO a lot of duplication between popstate and hashchange
popstate: function( event ) {
var newEvent = new $.Event( "navigate" ),
beforeNavigate = new $.Event( "beforenavigate" ),
state = event.originalEvent.state || {};
var newEvent, beforeNavigate, state;

if ( event.isDefaultPrevented() ) {
return;
}

newEvent = new $.Event( "navigate" );
beforeNavigate = new $.Event( "beforenavigate" );
state = event.originalEvent.state || {};

beforeNavigate.originalEvent = event;
$win.trigger( beforeNavigate );
@@ -50,6 +50,12 @@ define(["jquery",
// is not fired.
window.history.replaceState( state, state.title || document.title, href );

// If we haven't yet received the initial popstate, we need to update the reference
// href so that we compare against the correct location
if ( this.ignoreInitialHashChange ) {
initialHref = href;
}

return state;
},

@@ -0,0 +1,13 @@
define( [ "jquery" ], function( $ ) {

// TODO: Attaching early to popstate like this becomes unnecessary once the navigate event has been
// properly implemented so that it removes its popstate handler upon teardown and attaches it upon
// setup, rather than attaching it upon setup and then simply making sure upon subsequent calls to
// setup that the handlers are attached.
$( window ).on( "popstate", function( event ) {
if ( window.preventDefaultForNextPopstate ) {
event.preventDefault();
}
} );

} );
@@ -105,6 +105,41 @@ $.testHelper.setPushState();
}
]);
});

// relies on having the early popstate handler defined in early_popstate_handler.js
asyncTest( "Default-prevented popstate does not trigger a navigate event",
function( assert ) {
var eventNs = ".defaultPreventedPopstate";

assert.expect( 2 );

$.testHelper.detailedEventCascade( [
function() {
window.history.replaceState( { foo: "bar" }, document.title,
location.href.replace(/#.*/, "" ) + "#foo" );
location.hash = "#foo2";
},
{
navigate: { src: $( window ), event: "navigate" + eventNs + "1" }
},
function( result ) {
assert.deepEqual( result.navigate.timedOut, false,
"Received navigate event going forward" );
window.preventDefaultForNextPopstate = true;
window.history.back();
},
{
navigate: { src: $( window ), event: "navigate" + eventNs + "2" }
},
function( result ) {
assert.deepEqual( result.navigate.timedOut, true,
"Received no navigate event from a default-prevented popstate" );
delete window.preventDefaultForNextPopstate;
start();
}
] );
} );

} else {
asyncTest( "hashchange navigation provides for data added in a later binding", function() {
$( window ).one( "beforenavigate", function( event, data ) {
@@ -120,4 +155,4 @@ $.testHelper.setPushState();
location.hash = "#foo2";
});
}
})( jQuery );
})( jQuery );
@@ -13,6 +13,7 @@
<link rel="stylesheet" href="../../../jqm-tests.css"/>
<script>
$.testHelper.asyncLoad([
[ "early_popstate_handler.js" ],
[ "events/navigate" ],
[ "event_core.js" ]
], "../../../../js" );
@@ -9,8 +9,10 @@
<script src="../../../../js/jquery.tag.inserter.js"></script>
<script>
$(document).bind('mobileinit',function(){

// Expect content to inherit this theme when not explicitly set
$.mobile.page.prototype.options.contentTheme = "d";
$.testHelper.setPushState();
});
</script>
<script src="../../../jquery.setNameSpace.js"></script>
@@ -9,8 +9,10 @@
<script src="../../../../js/jquery.tag.inserter.js"></script>
<script>
$(document).bind('mobileinit',function(){

// Expect content to inherit this theme when not explicitly set
$.mobile.page.prototype.options.contentTheme = "d";
$.testHelper.setPushState();
});
</script>
<script src="../../../jquery.setNameSpace.js"></script>
@@ -21,7 +23,7 @@
$.testHelper.asyncLoad([
[
"widgets/dialog",
"widgets/page",
"widgets/page.dialog",
"widgets/popup"
],
[ "init" ],
@@ -31,25 +33,23 @@
], "../../../../js");
</script>


<link rel="stylesheet" href="../../../../css/themes/default/jquery.mobile.css"/>
<link rel="stylesheet" href="../../../../external/qunit/qunit.css"/>

<script src="../../../swarminject.js"></script>
</head>
<body>

<div id="qunit"></div>
<div id="qunit"></div>

<div data-nstest-role="page" id="sequenceRedirect"></div>
<div id="internal-page" data-nstest-role="page"></div>
<div data-nstest-role="page" id="sequenceRedirect"></div>
<div id="internal-page" data-nstest-role="page"></div>

<!--
This test page is used when testing initial URLs of the form
http://domain/path/to/page1.html#/path/to/page2.html. It really only works if
you load sequence-tests.html via the hash, i.e.,
http://domain/path/to/sequence/index.html#/path/to/sequence-redirect.html
-->
<!--
This test page is used when testing initial URLs of the form
http://domain/path/to/page1.html#/path/to/page2.html. It really only works if
you load sequence-tests.html via the hash, i.e.,
http://domain/path/to/sequence/index.html#/path/to/sequence-redirect.html
-->

</body>
</html>
@@ -9,8 +9,6 @@
// The more we click around the test pages and the more combinations of paths
// we try, the better.

$.testHelper.setPushState();

// If the start page is not there, wait for it to appear. Otherwise, leave
// some time before starting the actual run to allow the popstate handler to
// awaken from its slumber
@@ -46,7 +44,8 @@

maybeWaitForStartPage([
function() {
origUrl = location.href.replace( "&ui-state=dialog", "" );
origUrl = $.mobile.path.parseUrl(
location.href.replace( "&ui-state=dialog", "" ) ).hrefNoHash;
$( "#openInternalPage" ).click();
},
{