]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/js/customize-loader.js
WordPress 4.0
[autoinstalls/wordpress.git] / wp-includes / js / customize-loader.js
index cccf71acc8c536fac03b4c7daaf5176f39f0dc90..2ee0c0f90b0ea87b560a60bc719374c7cc37596b 100644 (file)
@@ -1,4 +1,4 @@
-/* global _wpCustomizeLoaderSettings */
+/* global _wpCustomizeLoaderSettings, confirm */
 window.wp = window.wp || {};
 
 (function( exports, $ ){
@@ -10,7 +10,20 @@ window.wp = window.wp || {};
                hashchange: ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7)
        });
 
+       /**
+        * Allows the Customizer to be overlayed on any page.
+        *
+        * By default, any element in the body with the load-customize class will open
+        * the Customizer overlay with the URL specified.
+        *
+        *     e.g. <a class="load-customize" href="http://siteurl.com/2014/01/02/post">Open customizer</a>
+        *
+        * @augments wp.customize.Events
+        */
        Loader = $.extend( {}, api.Events, {
+               /**
+                * Setup the Loader; triggered on document#ready.
+                */
                initialize: function() {
                        this.body = $( document.body );
 
@@ -23,9 +36,12 @@ window.wp = window.wp || {};
                        this.window  = $( window );
                        this.element = $( '<div id="customize-container" />' ).appendTo( this.body );
 
+                       // Bind events for opening and closing the overlay.
                        this.bind( 'open', this.overlay.show );
                        this.bind( 'close', this.overlay.hide );
 
+                       // Any element in the body with the `load-customize` class opens
+                       // the Customizer.
                        $('#wpbody').on( 'click', '.load-customize', function( event ) {
                                event.preventDefault();
 
@@ -36,8 +52,9 @@ window.wp = window.wp || {};
                        });
 
                        // Add navigation listeners.
-                       if ( $.support.history )
+                       if ( $.support.history ) {
                                this.window.on( 'popstate', Loader.popstate );
+                       }
 
                        if ( $.support.hashchange ) {
                                this.window.on( 'hashchange', Loader.hashchange );
@@ -47,35 +64,53 @@ window.wp = window.wp || {};
 
                popstate: function( e ) {
                        var state = e.originalEvent.state;
-                       if ( state && state.customize )
+                       if ( state && state.customize ) {
                                Loader.open( state.customize );
-                       else if ( Loader.active )
+                       } else if ( Loader.active ) {
                                Loader.close();
+                       }
                },
 
                hashchange: function() {
                        var hash = window.location.toString().split('#')[1];
 
-                       if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) )
+                       if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) {
                                Loader.open( Loader.settings.url + '?' + hash );
+                       }
 
-                       if ( ! hash && ! $.support.history )
+                       if ( ! hash && ! $.support.history ){
                                Loader.close();
+                       }
+               },
+
+               beforeunload: function () {
+                       if ( ! Loader.saved() ) {
+                               return Loader.settings.l10n.saveAlert;
+                       }
                },
 
+               /**
+                * Open the customizer overlay for a specific URL.
+                *
+                * @param  string src URL to load in the Customizer.
+                */
                open: function( src ) {
-                       var hash;
 
-                       if ( this.active )
+                       if ( this.active ) {
                                return;
+                       }
 
                        // Load the full page on mobile devices.
-                       if ( Loader.settings.browser.mobile )
+                       if ( Loader.settings.browser.mobile ) {
                                return window.location = src;
+                       }
 
                        this.active = true;
                        this.body.addClass('customize-loading');
 
+                       // Dirty state of customizer in iframe
+                       this.saved = new api.Value( true );
+
                        this.iframe = $( '<iframe />', { src: src }).appendTo( this.element );
                        this.iframe.one( 'load', this.loaded );
 
@@ -92,58 +127,103 @@ window.wp = window.wp || {};
                        });
 
                        this.messenger.bind( 'close', function() {
-                               if ( $.support.history )
+                               if ( $.support.history ) {
                                        history.back();
-                               else if ( $.support.hashchange )
+                               } else if ( $.support.hashchange ) {
                                        window.location.hash = '';
-                               else
+                               } else {
                                        Loader.close();
-                       });
+                               }
+                       } );
+
+                       // Prompt AYS dialog when navigating away
+                       $( window ).on( 'beforeunload', this.beforeunload );
 
                        this.messenger.bind( 'activated', function( location ) {
-                               if ( location )
+                               if ( location ) {
                                        window.location = location;
+                               }
                        });
 
-                       hash = src.split('?')[1];
+                       this.messenger.bind( 'saved', function () {
+                               Loader.saved( true );
+                       } );
+                       this.messenger.bind( 'change', function () {
+                               Loader.saved( false );
+                       } );
+
+                       this.pushState( src );
+
+                       this.trigger( 'open' );
+               },
+
+               pushState: function ( src ) {
+                       var hash;
 
                        // Ensure we don't call pushState if the user hit the forward button.
-                       if ( $.support.history && window.location.href !== src )
+                       if ( $.support.history && window.location.href !== src ) {
                                history.pushState( { customize: src }, '', src );
-                       else if ( ! $.support.history && $.support.hashchange && hash )
+                       } else if ( ! $.support.history && $.support.hashchange && hash ) {
+                               hash = src.split( '?' )[1];
                                window.location.hash = 'wp_customize=on&' + hash;
-
-                       this.trigger( 'open' );
+                       }
                },
 
+               /**
+                * Callback after the customizer has been opened.
+                */
                opened: function() {
                        Loader.body.addClass( 'customize-active full-overlay-active' );
                },
 
+               /**
+                * Close the Customizer overlay and return focus to the link that opened it.
+                */
                close: function() {
-                       if ( ! this.active )
+                       if ( ! this.active ) {
+                               return;
+                       }
+
+                       // Display AYS dialog if customizer is dirty
+                       if ( ! this.saved() && ! confirm( Loader.settings.l10n.saveAlert ) ) {
+                               // Go forward since Customizer is exited by history.back()
+                               history.forward();
                                return;
+                       }
+
                        this.active = false;
 
                        this.trigger( 'close' );
 
                        // Return focus to link that was originally clicked.
-                       if ( this.link )
+                       if ( this.link ) {
                                this.link.focus();
+                       }
                },
 
+               /**
+                * Callback after the customizer has been closed.
+                */
                closed: function() {
                        Loader.iframe.remove();
                        Loader.messenger.destroy();
                        Loader.iframe    = null;
                        Loader.messenger = null;
+                       Loader.saved     = null;
                        Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
+                       $( window ).off( 'beforeunload', Loader.beforeunload );
                },
 
+               /**
+                * Callback for the `load` event on the Customizer iframe.
+                */
                loaded: function() {
                        Loader.body.removeClass('customize-loading');
                },
 
+               /**
+                * Overlay hide/show utility methods.
+                */
                overlay: {
                        show: function() {
                                this.element.fadeIn( 200, Loader.opened );
@@ -155,11 +235,12 @@ window.wp = window.wp || {};
                }
        });
 
+       // Bootstrap the Loader on document#ready.
        $( function() {
                Loader.settings = _wpCustomizeLoaderSettings;
                Loader.initialize();
        });
 
-       // Expose the API to the world.
+       // Expose the API publicly on window.wp.customize.Loader
        api.Loader = Loader;
 })( wp, jQuery );