diff --git a/wp-includes/js/customize-loader.dev.js b/wp-includes/js/customize-loader.dev.js index 1e1032765..c2e92a639 100644 --- a/wp-includes/js/customize-loader.dev.js +++ b/wp-includes/js/customize-loader.dev.js @@ -6,9 +6,15 @@ if ( typeof wp === 'undefined' ) Loader; Loader = { + supports: { + history: !! ( window.history && history.pushState ), + hashchange: ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7) + }, + initialize: function() { - this.body = $( document.body ).addClass('customize-support'); - this.element = $( '
' ).appendTo( this.body ); + this.body = $( document.body ).addClass('customize-support'); + this.window = $( window ); + this.element = $( '' ).appendTo( this.body ); $('#wpbody').on( 'click', '.load-customize', function( event ) { event.preventDefault(); @@ -16,8 +22,35 @@ if ( typeof wp === 'undefined' ) // Load the theme. Loader.open( $(this).attr('href') ); }); + + // Add navigation listeners. + if ( this.supports.history ) + this.window.on( 'popstate', Loader.popstate ); + + if ( this.supports.hashchange ) + this.window.on( 'hashchange', Loader.hashchange ); + }, + popstate: function( e ) { + var state = e.originalEvent.state; + if ( state && state.customize ) + Loader.open( state.customize ); + else if ( Loader.active ) + Loader.close(); + }, + hashchange: function( e ) { + var hash = window.location.toString().split('#')[1]; + + if ( hash && 0 === hash.indexOf( 'customize=on' ) ) + Loader.open( wpCustomizeLoaderL10n.url + '?' + hash ); + + if ( ! hash ) + Loader.close(); }, open: function( src ) { + if ( this.active ) + return; + this.active = true; + this.iframe = $( '', { src: src }).appendTo( this.element ); // Create a postMessage connection with the iframe. @@ -29,14 +62,31 @@ if ( typeof wp === 'undefined' ) }); this.messenger.bind( 'close', function() { - Loader.close(); + if ( Loader.supports.history ) + history.back(); + else if ( Loader.supports.hashchange ) + window.location.hash = ''; + else + Loader.close(); }); this.element.fadeIn( 200, function() { + var hash = src.split('?')[1]; + Loader.body.addClass( 'customize-active full-overlay-active' ); + + // Ensure we don't call pushState if the user hit the forward button. + if ( Loader.supports.history && window.location.href !== src ) + history.pushState( { customize: src }, '', src ); + else if ( Loader.supports.hashchange && hash ) + window.location.hash = hash; }); }, close: function() { + if ( ! this.active ) + return; + this.active = false; + this.element.fadeOut( 200, function() { Loader.iframe.remove(); Loader.iframe = null; @@ -47,7 +97,7 @@ if ( typeof wp === 'undefined' ) }; $( function() { - if ( !! window.postMessage ) + if ( window.postMessage ) Loader.initialize(); }); diff --git a/wp-includes/theme.php b/wp-includes/theme.php index 5a6785a8a..ce9bb55f5 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -1590,6 +1590,7 @@ add_action( 'plugins_loaded', '_wp_customize_include' ); function _wp_customize_loader_localize() { wp_localize_script( 'customize-loader', 'wpCustomizeLoaderL10n', array( 'back' => sprintf( __( '← Return to %s' ), get_admin_page_title() ), + 'url' => admin_url( 'admin.php' ), ) ); } add_action( 'admin_enqueue_scripts', '_wp_customize_loader_localize' );