angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

customize-loader.js (7904B)


      1 /**
      2  * @output wp-includes/js/customize-loader.js
      3  */
      4 
      5 /* global _wpCustomizeLoaderSettings */
      6 
      7 /**
      8  * Expose a public API that allows the customizer to be
      9  * loaded on any page.
     10  *
     11  * @namespace wp
     12  */
     13 window.wp = window.wp || {};
     14 
     15 (function( exports, $ ){
     16 	var api = wp.customize,
     17 		Loader;
     18 
     19 	$.extend( $.support, {
     20 		history: !! ( window.history && history.pushState ),
     21 		hashchange: ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7)
     22 	});
     23 
     24 	/**
     25 	 * Allows the Customizer to be overlayed on any page.
     26 	 *
     27 	 * By default, any element in the body with the load-customize class will open
     28 	 * an iframe overlay with the URL specified.
     29 	 *
     30 	 *     e.g. <a class="load-customize" href="<?php echo wp_customize_url(); ?>">Open Customizer</a>
     31 	 *
     32 	 * @memberOf wp.customize
     33 	 *
     34 	 * @class
     35 	 * @augments wp.customize.Events
     36 	 */
     37 	Loader = $.extend( {}, api.Events,/** @lends wp.customize.Loader.prototype */{
     38 		/**
     39 		 * Setup the Loader; triggered on document#ready.
     40 		 */
     41 		initialize: function() {
     42 			this.body = $( document.body );
     43 
     44 			// Ensure the loader is supported.
     45 			// Check for settings, postMessage support, and whether we require CORS support.
     46 			if ( ! Loader.settings || ! $.support.postMessage || ( ! $.support.cors && Loader.settings.isCrossDomain ) ) {
     47 				return;
     48 			}
     49 
     50 			this.window  = $( window );
     51 			this.element = $( '<div id="customize-container" />' ).appendTo( this.body );
     52 
     53 			// Bind events for opening and closing the overlay.
     54 			this.bind( 'open', this.overlay.show );
     55 			this.bind( 'close', this.overlay.hide );
     56 
     57 			// Any element in the body with the `load-customize` class opens
     58 			// the Customizer.
     59 			$('#wpbody').on( 'click', '.load-customize', function( event ) {
     60 				event.preventDefault();
     61 
     62 				// Store a reference to the link that opened the Customizer.
     63 				Loader.link = $(this);
     64 				// Load the theme.
     65 				Loader.open( Loader.link.attr('href') );
     66 			});
     67 
     68 			// Add navigation listeners.
     69 			if ( $.support.history ) {
     70 				this.window.on( 'popstate', Loader.popstate );
     71 			}
     72 
     73 			if ( $.support.hashchange ) {
     74 				this.window.on( 'hashchange', Loader.hashchange );
     75 				this.window.triggerHandler( 'hashchange' );
     76 			}
     77 		},
     78 
     79 		popstate: function( e ) {
     80 			var state = e.originalEvent.state;
     81 			if ( state && state.customize ) {
     82 				Loader.open( state.customize );
     83 			} else if ( Loader.active ) {
     84 				Loader.close();
     85 			}
     86 		},
     87 
     88 		hashchange: function() {
     89 			var hash = window.location.toString().split('#')[1];
     90 
     91 			if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) {
     92 				Loader.open( Loader.settings.url + '?' + hash );
     93 			}
     94 
     95 			if ( ! hash && ! $.support.history ) {
     96 				Loader.close();
     97 			}
     98 		},
     99 
    100 		beforeunload: function () {
    101 			if ( ! Loader.saved() ) {
    102 				return Loader.settings.l10n.saveAlert;
    103 			}
    104 		},
    105 
    106 		/**
    107 		 * Open the Customizer overlay for a specific URL.
    108 		 *
    109 		 * @param string src URL to load in the Customizer.
    110 		 */
    111 		open: function( src ) {
    112 
    113 			if ( this.active ) {
    114 				return;
    115 			}
    116 
    117 			// Load the full page on mobile devices.
    118 			if ( Loader.settings.browser.mobile ) {
    119 				return window.location = src;
    120 			}
    121 
    122 			// Store the document title prior to opening the Live Preview.
    123 			this.originalDocumentTitle = document.title;
    124 
    125 			this.active = true;
    126 			this.body.addClass('customize-loading');
    127 
    128 			/*
    129 			 * Track the dirtiness state (whether the drafted changes have been published)
    130 			 * of the Customizer in the iframe. This is used to decide whether to display
    131 			 * an AYS alert if the user tries to close the window before saving changes.
    132 			 */
    133 			this.saved = new api.Value( true );
    134 
    135 			this.iframe = $( '<iframe />', { 'src': src, 'title': Loader.settings.l10n.mainIframeTitle } ).appendTo( this.element );
    136 			this.iframe.one( 'load', this.loaded );
    137 
    138 			// Create a postMessage connection with the iframe.
    139 			this.messenger = new api.Messenger({
    140 				url: src,
    141 				channel: 'loader',
    142 				targetWindow: this.iframe[0].contentWindow
    143 			});
    144 
    145 			// Expose the changeset UUID on the parent window's URL so that the customized state can survive a refresh.
    146 			if ( history.replaceState ) {
    147 				this.messenger.bind( 'changeset-uuid', function( changesetUuid ) {
    148 					var urlParser = document.createElement( 'a' );
    149 					urlParser.href = location.href;
    150 					urlParser.search = $.param( _.extend(
    151 						api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
    152 						{ changeset_uuid: changesetUuid }
    153 					) );
    154 					history.replaceState( { customize: urlParser.href }, '', urlParser.href );
    155 				} );
    156 			}
    157 
    158 			// Wait for the connection from the iframe before sending any postMessage events.
    159 			this.messenger.bind( 'ready', function() {
    160 				Loader.messenger.send( 'back' );
    161 			});
    162 
    163 			this.messenger.bind( 'close', function() {
    164 				if ( $.support.history ) {
    165 					history.back();
    166 				} else if ( $.support.hashchange ) {
    167 					window.location.hash = '';
    168 				} else {
    169 					Loader.close();
    170 				}
    171 			});
    172 
    173 			// Prompt AYS dialog when navigating away.
    174 			$( window ).on( 'beforeunload', this.beforeunload );
    175 
    176 			this.messenger.bind( 'saved', function () {
    177 				Loader.saved( true );
    178 			} );
    179 			this.messenger.bind( 'change', function () {
    180 				Loader.saved( false );
    181 			} );
    182 
    183 			this.messenger.bind( 'title', function( newTitle ){
    184 				window.document.title = newTitle;
    185 			});
    186 
    187 			this.pushState( src );
    188 
    189 			this.trigger( 'open' );
    190 		},
    191 
    192 		pushState: function ( src ) {
    193 			var hash = src.split( '?' )[1];
    194 
    195 			// Ensure we don't call pushState if the user hit the forward button.
    196 			if ( $.support.history && window.location.href !== src ) {
    197 				history.pushState( { customize: src }, '', src );
    198 			} else if ( ! $.support.history && $.support.hashchange && hash ) {
    199 				window.location.hash = 'wp_customize=on&' + hash;
    200 			}
    201 
    202 			this.trigger( 'open' );
    203 		},
    204 
    205 		/**
    206 		 * Callback after the Customizer has been opened.
    207 		 */
    208 		opened: function() {
    209 			Loader.body.addClass( 'customize-active full-overlay-active' ).attr( 'aria-busy', 'true' );
    210 		},
    211 
    212 		/**
    213 		 * Close the Customizer overlay.
    214 		 */
    215 		close: function() {
    216 			var self = this, onConfirmClose;
    217 			if ( ! self.active ) {
    218 				return;
    219 			}
    220 
    221 			onConfirmClose = function( confirmed ) {
    222 				if ( confirmed ) {
    223 					self.active = false;
    224 					self.trigger( 'close' );
    225 
    226 					// Restore document title prior to opening the Live Preview.
    227 					if ( self.originalDocumentTitle ) {
    228 						document.title = self.originalDocumentTitle;
    229 					}
    230 				} else {
    231 
    232 					// Go forward since Customizer is exited by history.back().
    233 					history.forward();
    234 				}
    235 				self.messenger.unbind( 'confirmed-close', onConfirmClose );
    236 			};
    237 			self.messenger.bind( 'confirmed-close', onConfirmClose );
    238 
    239 			Loader.messenger.send( 'confirm-close' );
    240 		},
    241 
    242 		/**
    243 		 * Callback after the Customizer has been closed.
    244 		 */
    245 		closed: function() {
    246 			Loader.iframe.remove();
    247 			Loader.messenger.destroy();
    248 			Loader.iframe    = null;
    249 			Loader.messenger = null;
    250 			Loader.saved     = null;
    251 			Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
    252 			$( window ).off( 'beforeunload', Loader.beforeunload );
    253 			/*
    254 			 * Return focus to the link that opened the Customizer overlay after
    255 			 * the body element visibility is restored.
    256 			 */
    257 			if ( Loader.link ) {
    258 				Loader.link.focus();
    259 			}
    260 		},
    261 
    262 		/**
    263 		 * Callback for the `load` event on the Customizer iframe.
    264 		 */
    265 		loaded: function() {
    266 			Loader.body.removeClass( 'customize-loading' ).attr( 'aria-busy', 'false' );
    267 		},
    268 
    269 		/**
    270 		 * Overlay hide/show utility methods.
    271 		 */
    272 		overlay: {
    273 			show: function() {
    274 				this.element.fadeIn( 200, Loader.opened );
    275 			},
    276 
    277 			hide: function() {
    278 				this.element.fadeOut( 200, Loader.closed );
    279 			}
    280 		}
    281 	});
    282 
    283 	// Bootstrap the Loader on document#ready.
    284 	$( function() {
    285 		Loader.settings = _wpCustomizeLoaderSettings;
    286 		Loader.initialize();
    287 	});
    288 
    289 	// Expose the API publicly on window.wp.customize.Loader.
    290 	api.Loader = Loader;
    291 })( wp, jQuery );