]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/customize-loader.js
WordPress 4.1.3-scripts
[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 }).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.pushState( src );
159
160                         this.trigger( 'open' );
161                 },
162
163                 pushState: function ( src ) {
164                         var hash = src.split( '?' )[1];
165
166                         // Ensure we don't call pushState if the user hit the forward button.
167                         if ( $.support.history && window.location.href !== src ) {
168                                 history.pushState( { customize: src }, '', src );
169                         } else if ( ! $.support.history && $.support.hashchange && hash ) {
170                                 window.location.hash = 'wp_customize=on&' + hash;
171                         }
172
173                         this.trigger( 'open' );
174                 },
175
176                 /**
177                  * Callback after the Customizer has been opened.
178                  */
179                 opened: function() {
180                         Loader.body.addClass( 'customize-active full-overlay-active' );
181                 },
182
183                 /**
184                  * Close the Customizer overlay and return focus to the link that opened it.
185                  */
186                 close: function() {
187                         if ( ! this.active ) {
188                                 return;
189                         }
190
191                         // Display AYS dialog if Customizer is dirty
192                         if ( ! this.saved() && ! confirm( Loader.settings.l10n.saveAlert ) ) {
193                                 // Go forward since Customizer is exited by history.back()
194                                 history.forward();
195                                 return;
196                         }
197
198                         this.active = false;
199
200                         this.trigger( 'close' );
201
202                         // Restore document title prior to opening the Live Preview
203                         if ( this.originalDocumentTitle ) {
204                                 document.title = this.originalDocumentTitle;
205                         }
206
207                         // Return focus to link that was originally clicked.
208                         if ( this.link ) {
209                                 this.link.focus();
210                         }
211                 },
212
213                 /**
214                  * Callback after the Customizer has been closed.
215                  */
216                 closed: function() {
217                         Loader.iframe.remove();
218                         Loader.messenger.destroy();
219                         Loader.iframe    = null;
220                         Loader.messenger = null;
221                         Loader.saved     = null;
222                         Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
223                         $( window ).off( 'beforeunload', Loader.beforeunload );
224                 },
225
226                 /**
227                  * Callback for the `load` event on the Customizer iframe.
228                  */
229                 loaded: function() {
230                         Loader.body.removeClass('customize-loading');
231                 },
232
233                 /**
234                  * Overlay hide/show utility methods.
235                  */
236                 overlay: {
237                         show: function() {
238                                 this.element.fadeIn( 200, Loader.opened );
239                         },
240
241                         hide: function() {
242                                 this.element.fadeOut( 200, Loader.closed );
243                         }
244                 }
245         });
246
247         // Bootstrap the Loader on document#ready.
248         $( function() {
249                 Loader.settings = _wpCustomizeLoaderSettings;
250                 Loader.initialize();
251         });
252
253         // Expose the API publicly on window.wp.customize.Loader
254         api.Loader = Loader;
255 })( wp, jQuery );