diff --git a/js/events/navigate.js b/js/events/navigate.js index 94f374e8e12..ea94c4732b6 100644 --- a/js/events/navigate.js +++ b/js/events/navigate.js @@ -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 ); diff --git a/js/navigation/navigator.js b/js/navigation/navigator.js index ce7d1785a09..ea34ff67bf0 100644 --- a/js/navigation/navigator.js +++ b/js/navigation/navigator.js @@ -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; }, diff --git a/tests/integration/navigation/event/early_popstate_handler.js b/tests/integration/navigation/event/early_popstate_handler.js new file mode 100644 index 00000000000..7574ffa6cc7 --- /dev/null +++ b/tests/integration/navigation/event/early_popstate_handler.js @@ -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(); + } +} ); + +} ); diff --git a/tests/integration/navigation/event/event_core.js b/tests/integration/navigation/event/event_core.js index ec1437dea87..1a1bac3fe42 100644 --- a/tests/integration/navigation/event/event_core.js +++ b/tests/integration/navigation/event/event_core.js @@ -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 ); \ No newline at end of file +})( jQuery ); diff --git a/tests/integration/navigation/event/index.html b/tests/integration/navigation/event/index.html index 886b0bca7d1..9bc0a1df400 100644 --- a/tests/integration/navigation/event/index.html +++ b/tests/integration/navigation/event/index.html @@ -13,6 +13,7 @@ diff --git a/tests/integration/navigation/sequence/sequence-redirect.html b/tests/integration/navigation/sequence/sequence-redirect.html index 6c528834f11..db279930513 100644 --- a/tests/integration/navigation/sequence/sequence-redirect.html +++ b/tests/integration/navigation/sequence/sequence-redirect.html @@ -9,8 +9,10 @@ @@ -21,7 +23,7 @@ $.testHelper.asyncLoad([ [ "widgets/dialog", - "widgets/page", + "widgets/page.dialog", "widgets/popup" ], [ "init" ], @@ -31,25 +33,23 @@ ], "../../../../js"); - -
- + - - + + - +