]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/customize-preview.js
WordPress 4.6.3-scripts
[autoinstalls/wordpress.git] / wp-includes / js / customize-preview.js
1 /*
2  * Script run inside a Customizer preview frame.
3  */
4 (function( exports, $ ){
5         var api = wp.customize,
6                 debounce;
7
8         /**
9          * Returns a debounced version of the function.
10          *
11          * @todo Require Underscore.js for this file and retire this.
12          */
13         debounce = function( fn, delay, context ) {
14                 var timeout;
15                 return function() {
16                         var args = arguments;
17
18                         context = context || this;
19
20                         clearTimeout( timeout );
21                         timeout = setTimeout( function() {
22                                 timeout = null;
23                                 fn.apply( context, args );
24                         }, delay );
25                 };
26         };
27
28         /**
29          * @constructor
30          * @augments wp.customize.Messenger
31          * @augments wp.customize.Class
32          * @mixes wp.customize.Events
33          */
34         api.Preview = api.Messenger.extend({
35                 /**
36                  * @param {object} params  - Parameters to configure the messenger.
37                  * @param {object} options - Extend any instance parameter or method with this object.
38                  */
39                 initialize: function( params, options ) {
40                         var self = this;
41
42                         api.Messenger.prototype.initialize.call( this, params, options );
43
44                         this.body = $( document.body );
45                         this.body.on( 'click.preview', 'a', function( event ) {
46                                 var link, isInternalJumpLink;
47                                 link = $( this );
48                                 isInternalJumpLink = ( '#' === link.attr( 'href' ).substr( 0, 1 ) );
49                                 event.preventDefault();
50
51                                 if ( isInternalJumpLink && '#' !== link.attr( 'href' ) ) {
52                                         $( link.attr( 'href' ) ).each( function() {
53                                                 this.scrollIntoView();
54                                         } );
55                                 }
56
57                                 /*
58                                  * Note the shift key is checked so shift+click on widgets or
59                                  * nav menu items can just result on focusing on the corresponding
60                                  * control instead of also navigating to the URL linked to.
61                                  */
62                                 if ( event.shiftKey || isInternalJumpLink ) {
63                                         return;
64                                 }
65                                 self.send( 'scroll', 0 );
66                                 self.send( 'url', link.prop( 'href' ) );
67                         });
68
69                         // You cannot submit forms.
70                         // @todo: Allow form submissions by mixing $_POST data with the customize setting $_POST data.
71                         this.body.on( 'submit.preview', 'form', function( event ) {
72                                 event.preventDefault();
73                         });
74
75                         this.window = $( window );
76                         this.window.on( 'scroll.preview', debounce( function() {
77                                 self.send( 'scroll', self.window.scrollTop() );
78                         }, 200 ));
79
80                         this.bind( 'scroll', function( distance ) {
81                                 self.window.scrollTop( distance );
82                         });
83                 }
84         });
85
86         $( function() {
87                 var bg, setValue;
88
89                 api.settings = window._wpCustomizeSettings;
90                 if ( ! api.settings ) {
91                         return;
92                 }
93
94                 api.preview = new api.Preview({
95                         url: window.location.href,
96                         channel: api.settings.channel
97                 });
98
99                 /**
100                  * Create/update a setting value.
101                  *
102                  * @param {string}  id            - Setting ID.
103                  * @param {*}       value         - Setting value.
104                  * @param {boolean} [createDirty] - Whether to create a setting as dirty. Defaults to false.
105                  */
106                 setValue = function( id, value, createDirty ) {
107                         var setting = api( id );
108                         if ( setting ) {
109                                 setting.set( value );
110                         } else {
111                                 createDirty = createDirty || false;
112                                 setting = api.create( id, value, {
113                                         id: id
114                                 } );
115
116                                 // Mark dynamically-created settings as dirty so they will get posted.
117                                 if ( createDirty ) {
118                                         setting._dirty = true;
119                                 }
120                         }
121                 };
122
123                 api.preview.bind( 'settings', function( values ) {
124                         $.each( values, setValue );
125                 });
126
127                 api.preview.trigger( 'settings', api.settings.values );
128
129                 $.each( api.settings._dirty, function( i, id ) {
130                         var setting = api( id );
131                         if ( setting ) {
132                                 setting._dirty = true;
133                         }
134                 } );
135
136                 api.preview.bind( 'setting', function( args ) {
137                         var createDirty = true;
138                         setValue.apply( null, args.concat( createDirty ) );
139                 });
140
141                 api.preview.bind( 'sync', function( events ) {
142                         $.each( events, function( event, args ) {
143                                 api.preview.trigger( event, args );
144                         });
145                         api.preview.send( 'synced' );
146                 });
147
148                 api.preview.bind( 'active', function() {
149                         api.preview.send( 'nonce', api.settings.nonce );
150
151                         api.preview.send( 'documentTitle', document.title );
152                 });
153
154                 api.preview.bind( 'saved', function( response ) {
155                         api.trigger( 'saved', response );
156                 } );
157
158                 api.bind( 'saved', function() {
159                         api.each( function( setting ) {
160                                 setting._dirty = false;
161                         } );
162                 } );
163
164                 api.preview.bind( 'nonce-refresh', function( nonce ) {
165                         $.extend( api.settings.nonce, nonce );
166                 } );
167
168                 /*
169                  * Send a message to the parent customize frame with a list of which
170                  * containers and controls are active.
171                  */
172                 api.preview.send( 'ready', {
173                         activePanels: api.settings.activePanels,
174                         activeSections: api.settings.activeSections,
175                         activeControls: api.settings.activeControls,
176                         settingValidities: api.settings.settingValidities
177                 } );
178
179                 // Display a loading indicator when preview is reloading, and remove on failure.
180                 api.preview.bind( 'loading-initiated', function () {
181                         $( 'body' ).addClass( 'wp-customizer-unloading' );
182                 });
183                 api.preview.bind( 'loading-failed', function () {
184                         $( 'body' ).removeClass( 'wp-customizer-unloading' );
185                 });
186
187                 /* Custom Backgrounds */
188                 bg = $.map(['color', 'image', 'position_x', 'repeat', 'attachment'], function( prop ) {
189                         return 'background_' + prop;
190                 });
191
192                 api.when.apply( api, bg ).done( function( color, image, position_x, repeat, attachment ) {
193                         var body = $(document.body),
194                                 head = $('head'),
195                                 style = $('#custom-background-css'),
196                                 update;
197
198                         update = function() {
199                                 var css = '';
200
201                                 // The body will support custom backgrounds if either
202                                 // the color or image are set.
203                                 //
204                                 // See get_body_class() in /wp-includes/post-template.php
205                                 body.toggleClass( 'custom-background', !! ( color() || image() ) );
206
207                                 if ( color() )
208                                         css += 'background-color: ' + color() + ';';
209
210                                 if ( image() ) {
211                                         css += 'background-image: url("' + image() + '");';
212                                         css += 'background-position: top ' + position_x() + ';';
213                                         css += 'background-repeat: ' + repeat() + ';';
214                                         css += 'background-attachment: ' + attachment() + ';';
215                                 }
216
217                                 // Refresh the stylesheet by removing and recreating it.
218                                 style.remove();
219                                 style = $('<style type="text/css" id="custom-background-css">body.custom-background { ' + css + ' }</style>').appendTo( head );
220                         };
221
222                         $.each( arguments, function() {
223                                 this.bind( update );
224                         });
225                 });
226
227                 /**
228                  * Custom Logo
229                  *
230                  * Toggle the wp-custom-logo body class when a logo is added or removed.
231                  *
232                  * @since 4.5.0
233                  */
234                 api( 'custom_logo', function( setting ) {
235                         $( 'body' ).toggleClass( 'wp-custom-logo', !! setting.get() );
236                         setting.bind( function( attachmentId ) {
237                                 $( 'body' ).toggleClass( 'wp-custom-logo', !! attachmentId );
238                         } );
239                 } );
240
241                 api.trigger( 'preview-ready' );
242         });
243
244 })( wp, jQuery );