]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/customize-loader.js
WordPress 4.0
[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          * the Customizer overlay with the URL specified.
18          *
19          *     e.g. <a class="load-customize" href="http://siteurl.com/2014/01/02/post">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                         this.active = true;
109                         this.body.addClass('customize-loading');
110
111                         // Dirty state of customizer in iframe
112                         this.saved = new api.Value( true );
113
114                         this.iframe = $( '<iframe />', { src: src }).appendTo( this.element );
115                         this.iframe.one( 'load', this.loaded );
116
117                         // Create a postMessage connection with the iframe.
118                         this.messenger = new api.Messenger({
119                                 url: src,
120                                 channel: 'loader',
121                                 targetWindow: this.iframe[0].contentWindow
122                         });
123
124                         // Wait for the connection from the iframe before sending any postMessage events.
125                         this.messenger.bind( 'ready', function() {
126                                 Loader.messenger.send( 'back' );
127                         });
128
129                         this.messenger.bind( 'close', function() {
130                                 if ( $.support.history ) {
131                                         history.back();
132                                 } else if ( $.support.hashchange ) {
133                                         window.location.hash = '';
134                                 } else {
135                                         Loader.close();
136                                 }
137                         } );
138
139                         // Prompt AYS dialog when navigating away
140                         $( window ).on( 'beforeunload', this.beforeunload );
141
142                         this.messenger.bind( 'activated', function( location ) {
143                                 if ( location ) {
144                                         window.location = location;
145                                 }
146                         });
147
148                         this.messenger.bind( 'saved', function () {
149                                 Loader.saved( true );
150                         } );
151                         this.messenger.bind( 'change', function () {
152                                 Loader.saved( false );
153                         } );
154
155                         this.pushState( src );
156
157                         this.trigger( 'open' );
158                 },
159
160                 pushState: function ( src ) {
161                         var hash;
162
163                         // Ensure we don't call pushState if the user hit the forward button.
164                         if ( $.support.history && window.location.href !== src ) {
165                                 history.pushState( { customize: src }, '', src );
166                         } else if ( ! $.support.history && $.support.hashchange && hash ) {
167                                 hash = src.split( '?' )[1];
168                                 window.location.hash = 'wp_customize=on&' + hash;
169                         }
170                 },
171
172                 /**
173                  * Callback after the customizer has been opened.
174                  */
175                 opened: function() {
176                         Loader.body.addClass( 'customize-active full-overlay-active' );
177                 },
178
179                 /**
180                  * Close the Customizer overlay and return focus to the link that opened it.
181                  */
182                 close: function() {
183                         if ( ! this.active ) {
184                                 return;
185                         }
186
187                         // Display AYS dialog if customizer is dirty
188                         if ( ! this.saved() && ! confirm( Loader.settings.l10n.saveAlert ) ) {
189                                 // Go forward since Customizer is exited by history.back()
190                                 history.forward();
191                                 return;
192                         }
193
194                         this.active = false;
195
196                         this.trigger( 'close' );
197
198                         // Return focus to link that was originally clicked.
199                         if ( this.link ) {
200                                 this.link.focus();
201                         }
202                 },
203
204                 /**
205                  * Callback after the customizer has been closed.
206                  */
207                 closed: function() {
208                         Loader.iframe.remove();
209                         Loader.messenger.destroy();
210                         Loader.iframe    = null;
211                         Loader.messenger = null;
212                         Loader.saved     = null;
213                         Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
214                         $( window ).off( 'beforeunload', Loader.beforeunload );
215                 },
216
217                 /**
218                  * Callback for the `load` event on the Customizer iframe.
219                  */
220                 loaded: function() {
221                         Loader.body.removeClass('customize-loading');
222                 },
223
224                 /**
225                  * Overlay hide/show utility methods.
226                  */
227                 overlay: {
228                         show: function() {
229                                 this.element.fadeIn( 200, Loader.opened );
230                         },
231
232                         hide: function() {
233                                 this.element.fadeOut( 200, Loader.closed );
234                         }
235                 }
236         });
237
238         // Bootstrap the Loader on document#ready.
239         $( function() {
240                 Loader.settings = _wpCustomizeLoaderSettings;
241                 Loader.initialize();
242         });
243
244         // Expose the API publicly on window.wp.customize.Loader
245         api.Loader = Loader;
246 })( wp, jQuery );