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