run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
10.3 KB
2026-03-11 16:18:51
R W Run
3.41 KB
2026-03-11 16:18:51
R W Run
3.25 KB
2026-03-11 16:18:51
R W Run
1023 By
2026-03-11 16:18:51
R W Run
21.95 KB
2026-03-11 16:18:51
R W Run
5.67 KB
2026-03-11 16:18:51
R W Run
78.51 KB
2026-03-11 16:18:51
R W Run
23.73 KB
2026-03-11 16:18:51
R W Run
26.18 KB
2026-03-11 16:18:51
R W Run
8.8 KB
2026-03-11 16:18:51
R W Run
28.4 KB
2026-03-11 16:18:51
R W Run
16.11 KB
2026-03-11 16:18:51
R W Run
12.22 KB
2026-03-11 16:18:51
R W Run
2.96 KB
2026-03-11 16:18:51
R W Run
25.22 KB
2026-03-11 16:18:51
R W Run
7.67 KB
2026-03-11 16:18:51
R W Run
7.72 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:51
R W Run
6.66 KB
2026-03-11 16:18:51
R W Run
3.59 KB
2026-03-11 16:18:51
R W Run
14.67 KB
2026-03-11 16:18:51
R W Run
4.92 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
7.64 KB
2026-03-11 16:18:51
R W Run
27.93 KB
2026-03-11 16:18:51
R W Run
10.75 KB
2026-03-11 16:18:51
R W Run
32.55 KB
2026-03-11 16:18:51
R W Run
10.44 KB
2026-03-11 16:18:51
R W Run
5.1 KB
2026-03-11 16:18:51
R W Run
2.51 KB
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
5.81 KB
2026-03-11 16:18:51
R W Run
7.06 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
1.68 KB
2026-03-11 16:18:51
R W Run
5.39 KB
2026-03-11 16:18:51
R W Run
31 By
2026-03-11 16:18:51
R W Run
35 By
2026-03-11 16:18:51
R W Run
23.57 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:51
R W Run
9.54 KB
2026-03-11 16:18:51
R W Run
24.24 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
28.44 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
26.15 KB
2026-03-11 16:18:51
R W Run
12.98 KB
2026-03-11 16:18:51
R W Run
42.58 KB
2026-03-11 16:18:51
R W Run
12.97 KB
2026-03-11 16:18:51
R W Run
266.99 KB
2026-03-11 16:18:51
R W Run
108.18 KB
2026-03-11 16:18:51
R W Run
22.07 KB
2026-03-11 16:18:51
R W Run
10.87 KB
2026-03-11 16:18:51
R W Run
10.51 KB
2026-03-11 16:18:51
R W Run
2.58 KB
2026-03-11 16:18:51
R W Run
0 By
2026-03-11 16:18:51
R W Run
35 By
2026-03-11 16:18:51
R W Run
4.85 KB
2026-03-11 16:18:51
R W Run
3.21 KB
2026-03-11 16:18:51
R W Run
36.32 KB
2026-03-11 16:18:51
R W Run
19.39 KB
2026-03-11 16:18:51
R W Run
67.12 KB
2026-03-11 16:18:51
R W Run
18.46 KB
2026-03-11 16:18:51
R W Run
4.56 KB
2026-03-11 16:18:51
R W Run
1.82 KB
2026-03-11 16:18:51
R W Run
3.81 KB
2026-03-11 16:18:51
R W Run
2.51 KB
2026-03-11 16:18:51
R W Run
45.88 KB
2026-03-11 16:18:51
R W Run
14.34 KB
2026-03-11 16:18:51
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
1.62 KB
2026-03-11 16:18:51
R W Run
14.88 KB
2026-03-11 16:18:51
R W Run
2.97 KB
2026-03-11 16:18:51
R W Run
10.22 KB
2026-03-11 16:18:51
R W Run
4.34 KB
2026-03-11 16:18:51
R W Run
6.62 KB
2026-03-11 16:18:51
R W Run
3.1 KB
2026-03-11 16:18:51
R W Run
3.14 KB
2026-03-11 16:18:51
R W Run
1.22 KB
2026-03-11 16:18:51
R W Run
12.89 KB
2026-03-11 16:18:51
R W Run
2.82 KB
2026-03-11 16:18:51
R W Run
22.23 KB
2026-03-11 16:18:51
R W Run
8.59 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:51
R W Run
970 By
2026-03-11 16:18:51
R W Run
597 By
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
9.99 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
1.3 KB
2026-03-11 16:18:51
R W Run
444 By
2026-03-11 16:18:51
R W Run
4.58 KB
2026-03-11 16:18:51
R W Run
1.4 KB
2026-03-11 16:18:51
R W Run
569 By
2026-03-11 16:18:51
R W Run
281 By
2026-03-11 16:18:51
R W Run
20.74 KB
2026-03-11 16:18:51
R W Run
11.05 KB
2026-03-11 16:18:51
R W Run
821 By
2026-03-11 16:18:51
R W Run
351 By
2026-03-11 16:18:51
R W Run
802.97 KB
2026-03-11 16:18:51
R W Run
error_log
📄customize-preview-widgets.js
1/**
2 * @output wp-includes/js/customize-preview-widgets.js
3 */
4
5/* global _wpWidgetCustomizerPreviewSettings */
6
7/**
8 * Handles the initialization, refreshing and rendering of widget partials and sidebar widgets.
9 *
10 * @since 4.5.0
11 *
12 * @namespace wp.customize.widgetsPreview
13 *
14 * @param {jQuery} $ The jQuery object.
15 * @param {Object} _ The utilities library.
16 * @param {Object} wp Current WordPress environment instance.
17 * @param {Object} api Information from the API.
18 *
19 * @return {Object} Widget-related variables.
20 */
21wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( $, _, wp, api ) {
22
23 var self;
24
25 self = {
26 renderedSidebars: {},
27 renderedWidgets: {},
28 registeredSidebars: [],
29 registeredWidgets: {},
30 widgetSelectors: [],
31 preview: null,
32 l10n: {
33 widgetTooltip: ''
34 },
35 selectiveRefreshableWidgets: {}
36 };
37
38 /**
39 * Initializes the widgets preview.
40 *
41 * @since 4.5.0
42 *
43 * @memberOf wp.customize.widgetsPreview
44 *
45 * @return {void}
46 */
47 self.init = function() {
48 var self = this;
49
50 self.preview = api.preview;
51 if ( ! _.isEmpty( self.selectiveRefreshableWidgets ) ) {
52 self.addPartials();
53 }
54
55 self.buildWidgetSelectors();
56 self.highlightControls();
57
58 self.preview.bind( 'highlight-widget', self.highlightWidget );
59
60 api.preview.bind( 'active', function() {
61 self.highlightControls();
62 } );
63
64 /*
65 * Refresh a partial when the controls pane requests it. This is used currently just by the
66 * Gallery widget so that when an attachment's caption is updated in the media modal,
67 * the widget in the preview will then be refreshed to show the change. Normally doing this
68 * would not be necessary because all of the state should be contained inside the changeset,
69 * as everything done in the Customizer should not make a change to the site unless the
70 * changeset itself is published. Attachments are a current exception to this rule.
71 * For a proposal to include attachments in the customized state, see #37887.
72 */
73 api.preview.bind( 'refresh-widget-partial', function( widgetId ) {
74 var partialId = 'widget[' + widgetId + ']';
75 if ( api.selectiveRefresh.partial.has( partialId ) ) {
76 api.selectiveRefresh.partial( partialId ).refresh();
77 } else if ( self.renderedWidgets[ widgetId ] ) {
78 api.preview.send( 'refresh' ); // Fallback in case theme does not support 'customize-selective-refresh-widgets'.
79 }
80 } );
81 };
82
83 self.WidgetPartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.widgetsPreview.WidgetPartial.prototype */{
84
85 /**
86 * Represents a partial widget instance.
87 *
88 * @since 4.5.0
89 *
90 * @constructs
91 * @augments wp.customize.selectiveRefresh.Partial
92 *
93 * @alias wp.customize.widgetsPreview.WidgetPartial
94 * @memberOf wp.customize.widgetsPreview
95 *
96 * @param {string} id The partial's ID.
97 * @param {Object} options Options used to initialize the partial's
98 * instance.
99 * @param {Object} options.params The options parameters.
100 */
101 initialize: function( id, options ) {
102 var partial = this, matches;
103 matches = id.match( /^widget\[(.+)]$/ );
104 if ( ! matches ) {
105 throw new Error( 'Illegal id for widget partial.' );
106 }
107
108 partial.widgetId = matches[1];
109 partial.widgetIdParts = self.parseWidgetId( partial.widgetId );
110 options = options || {};
111 options.params = _.extend(
112 {
113 settings: [ self.getWidgetSettingId( partial.widgetId ) ],
114 containerInclusive: true
115 },
116 options.params || {}
117 );
118
119 api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
120 },
121
122 /**
123 * Refreshes the widget partial.
124 *
125 * @since 4.5.0
126 *
127 * @return {Promise|void} Either a promise postponing the refresh, or void.
128 */
129 refresh: function() {
130 var partial = this, refreshDeferred;
131 if ( ! self.selectiveRefreshableWidgets[ partial.widgetIdParts.idBase ] ) {
132 refreshDeferred = $.Deferred();
133 refreshDeferred.reject();
134 partial.fallback();
135 return refreshDeferred.promise();
136 } else {
137 return api.selectiveRefresh.Partial.prototype.refresh.call( partial );
138 }
139 },
140
141 /**
142 * Sends the widget-updated message to the parent so the spinner will get
143 * removed from the widget control.
144 *
145 * @inheritDoc
146 * @param {wp.customize.selectiveRefresh.Placement} placement The placement
147 * function.
148 *
149 * @return {void}
150 */
151 renderContent: function( placement ) {
152 var partial = this;
153 if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
154 api.preview.send( 'widget-updated', partial.widgetId );
155 api.selectiveRefresh.trigger( 'widget-updated', partial );
156 }
157 }
158 });
159
160 self.SidebarPartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.widgetsPreview.SidebarPartial.prototype */{
161
162 /**
163 * Represents a partial widget area.
164 *
165 * @since 4.5.0
166 *
167 * @class
168 * @augments wp.customize.selectiveRefresh.Partial
169 *
170 * @memberOf wp.customize.widgetsPreview
171 * @alias wp.customize.widgetsPreview.SidebarPartial
172 *
173 * @param {string} id The partial's ID.
174 * @param {Object} options Options used to initialize the partial's instance.
175 * @param {Object} options.params The options parameters.
176 */
177 initialize: function( id, options ) {
178 var partial = this, matches;
179 matches = id.match( /^sidebar\[(.+)]$/ );
180 if ( ! matches ) {
181 throw new Error( 'Illegal id for sidebar partial.' );
182 }
183 partial.sidebarId = matches[1];
184
185 options = options || {};
186 options.params = _.extend(
187 {
188 settings: [ 'sidebars_widgets[' + partial.sidebarId + ']' ]
189 },
190 options.params || {}
191 );
192
193 api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
194
195 if ( ! partial.params.sidebarArgs ) {
196 throw new Error( 'The sidebarArgs param was not provided.' );
197 }
198 if ( partial.params.settings.length > 1 ) {
199 throw new Error( 'Expected SidebarPartial to only have one associated setting' );
200 }
201 },
202
203 /**
204 * Sets up the partial.
205 *
206 * @since 4.5.0
207 *
208 * @return {void}
209 */
210 ready: function() {
211 var sidebarPartial = this;
212
213 // Watch for changes to the sidebar_widgets setting.
214 _.each( sidebarPartial.settings(), function( settingId ) {
215 api( settingId ).bind( _.bind( sidebarPartial.handleSettingChange, sidebarPartial ) );
216 } );
217
218 // Trigger an event for this sidebar being updated whenever a widget inside is rendered.
219 api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
220 var isAssignedWidgetPartial = (
221 placement.partial.extended( self.WidgetPartial ) &&
222 ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), placement.partial.widgetId ) )
223 );
224 if ( isAssignedWidgetPartial ) {
225 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
226 }
227 } );
228
229 // Make sure that a widget partial has a container in the DOM prior to a refresh.
230 api.bind( 'change', function( widgetSetting ) {
231 var widgetId, parsedId;
232 parsedId = self.parseWidgetSettingId( widgetSetting.id );
233 if ( ! parsedId ) {
234 return;
235 }
236 widgetId = parsedId.idBase;
237 if ( parsedId.number ) {
238 widgetId += '-' + String( parsedId.number );
239 }
240 if ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), widgetId ) ) {
241 sidebarPartial.ensureWidgetPlacementContainers( widgetId );
242 }
243 } );
244 },
245
246 /**
247 * Gets the before/after boundary nodes for all instances of this sidebar
248 * (usually one).
249 *
250 * Note that TreeWalker is not implemented in IE8.
251 *
252 * @since 4.5.0
253 *
254 * @return {Array.<{before: Comment, after: Comment, instanceNumber: number}>}
255 * An array with an object for each sidebar instance, containing the
256 * node before and after the sidebar instance and its instance number.
257 */
258 findDynamicSidebarBoundaryNodes: function() {
259 var partial = this, regExp, boundaryNodes = {}, recursiveCommentTraversal;
260 regExp = /^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/;
261 recursiveCommentTraversal = function( childNodes ) {
262 _.each( childNodes, function( node ) {
263 var matches;
264 if ( 8 === node.nodeType ) {
265 matches = node.nodeValue.match( regExp );
266 if ( ! matches || matches[2] !== partial.sidebarId ) {
267 return;
268 }
269 if ( _.isUndefined( boundaryNodes[ matches[3] ] ) ) {
270 boundaryNodes[ matches[3] ] = {
271 before: null,
272 after: null,
273 instanceNumber: parseInt( matches[3], 10 )
274 };
275 }
276 if ( 'dynamic_sidebar_before' === matches[1] ) {
277 boundaryNodes[ matches[3] ].before = node;
278 } else {
279 boundaryNodes[ matches[3] ].after = node;
280 }
281 } else if ( 1 === node.nodeType ) {
282 recursiveCommentTraversal( node.childNodes );
283 }
284 } );
285 };
286
287 recursiveCommentTraversal( document.body.childNodes );
288 return _.values( boundaryNodes );
289 },
290
291 /**
292 * Gets the placements for this partial.
293 *
294 * @since 4.5.0
295 *
296 * @return {Array} An array containing placement objects for each of the
297 * dynamic sidebar boundary nodes.
298 */
299 placements: function() {
300 var partial = this;
301 return _.map( partial.findDynamicSidebarBoundaryNodes(), function( boundaryNodes ) {
302 return new api.selectiveRefresh.Placement( {
303 partial: partial,
304 container: null,
305 startNode: boundaryNodes.before,
306 endNode: boundaryNodes.after,
307 context: {
308 instanceNumber: boundaryNodes.instanceNumber
309 }
310 } );
311 } );
312 },
313
314 /**
315 * Get the list of widget IDs associated with this widget area.
316 *
317 * @since 4.5.0
318 *
319 * @throws {Error} If there's no settingId.
320 * @throws {Error} If the setting doesn't exist in the API.
321 * @throws {Error} If the API doesn't pass an array of widget IDs.
322 *
323 * @return {Array} A shallow copy of the array containing widget IDs.
324 */
325 getWidgetIds: function() {
326 var sidebarPartial = this, settingId, widgetIds;
327 settingId = sidebarPartial.settings()[0];
328 if ( ! settingId ) {
329 throw new Error( 'Missing associated setting.' );
330 }
331 if ( ! api.has( settingId ) ) {
332 throw new Error( 'Setting does not exist.' );
333 }
334 widgetIds = api( settingId ).get();
335 if ( ! _.isArray( widgetIds ) ) {
336 throw new Error( 'Expected setting to be array of widget IDs' );
337 }
338 return widgetIds.slice( 0 );
339 },
340
341 /**
342 * Reflows widgets in the sidebar, ensuring they have the proper position in the
343 * DOM.
344 *
345 * @since 4.5.0
346 *
347 * @return {Array.<wp.customize.selectiveRefresh.Placement>} List of placements
348 * that were reflowed.
349 */
350 reflowWidgets: function() {
351 var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = [];
352 widgetIds = sidebarPartial.getWidgetIds();
353 sidebarPlacements = sidebarPartial.placements();
354
355 widgetPartials = {};
356 _.each( widgetIds, function( widgetId ) {
357 var widgetPartial = api.selectiveRefresh.partial( 'widget[' + widgetId + ']' );
358 if ( widgetPartial ) {
359 widgetPartials[ widgetId ] = widgetPartial;
360 }
361 } );
362
363 _.each( sidebarPlacements, function( sidebarPlacement ) {
364 var sidebarWidgets = [], needsSort = false, thisPosition, lastPosition = -1;
365
366 // Gather list of widget partial containers in this sidebar, and determine if a sort is needed.
367 _.each( widgetPartials, function( widgetPartial ) {
368 _.each( widgetPartial.placements(), function( widgetPlacement ) {
369
370 if ( sidebarPlacement.context.instanceNumber === widgetPlacement.context.sidebar_instance_number ) {
371 thisPosition = widgetPlacement.container.index();
372 sidebarWidgets.push( {
373 partial: widgetPartial,
374 placement: widgetPlacement,
375 position: thisPosition
376 } );
377 if ( thisPosition < lastPosition ) {
378 needsSort = true;
379 }
380 lastPosition = thisPosition;
381 }
382 } );
383 } );
384
385 if ( needsSort ) {
386 _.each( sidebarWidgets, function( sidebarWidget ) {
387 sidebarPlacement.endNode.parentNode.insertBefore(
388 sidebarWidget.placement.container[0],
389 sidebarPlacement.endNode
390 );
391
392 // @todo Rename partial-placement-moved?
393 api.selectiveRefresh.trigger( 'partial-content-moved', sidebarWidget.placement );
394 } );
395
396 sortedSidebarContainers.push( sidebarPlacement );
397 }
398 } );
399
400 if ( sortedSidebarContainers.length > 0 ) {
401 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
402 }
403
404 return sortedSidebarContainers;
405 },
406
407 /**
408 * Makes sure there is a widget instance container in this sidebar for the given
409 * widget ID.
410 *
411 * @since 4.5.0
412 *
413 * @param {string} widgetId The widget ID.
414 *
415 * @return {wp.customize.selectiveRefresh.Partial} The widget instance partial.
416 */
417 ensureWidgetPlacementContainers: function( widgetId ) {
418 var sidebarPartial = this, widgetPartial, wasInserted = false, partialId = 'widget[' + widgetId + ']';
419 widgetPartial = api.selectiveRefresh.partial( partialId );
420 if ( ! widgetPartial ) {
421 widgetPartial = new self.WidgetPartial( partialId, {
422 params: {}
423 } );
424 }
425
426 // Make sure that there is a container element for the widget in the sidebar, if at least a placeholder.
427 _.each( sidebarPartial.placements(), function( sidebarPlacement ) {
428 var foundWidgetPlacement, widgetContainerElement;
429
430 foundWidgetPlacement = _.find( widgetPartial.placements(), function( widgetPlacement ) {
431 return ( widgetPlacement.context.sidebar_instance_number === sidebarPlacement.context.instanceNumber );
432 } );
433 if ( foundWidgetPlacement ) {
434 return;
435 }
436
437 widgetContainerElement = $(
438 sidebarPartial.params.sidebarArgs.before_widget.replace( /%1\$s/g, widgetId ).replace( /%2\$s/g, 'widget' ) +
439 sidebarPartial.params.sidebarArgs.after_widget
440 );
441
442 // Handle rare case where before_widget and after_widget are empty.
443 if ( ! widgetContainerElement[0] ) {
444 return;
445 }
446
447 widgetContainerElement.attr( 'data-customize-partial-id', widgetPartial.id );
448 widgetContainerElement.attr( 'data-customize-partial-type', 'widget' );
449 widgetContainerElement.attr( 'data-customize-widget-id', widgetId );
450
451 /*
452 * Make sure the widget container element has the customize-container context data.
453 * The sidebar_instance_number is used to disambiguate multiple instances of the
454 * same sidebar are rendered onto the template, and so the same widget is embedded
455 * multiple times.
456 */
457 widgetContainerElement.data( 'customize-partial-placement-context', {
458 'sidebar_id': sidebarPartial.sidebarId,
459 'sidebar_instance_number': sidebarPlacement.context.instanceNumber
460 } );
461
462 sidebarPlacement.endNode.parentNode.insertBefore( widgetContainerElement[0], sidebarPlacement.endNode );
463 wasInserted = true;
464 } );
465
466 api.selectiveRefresh.partial.add( widgetPartial );
467
468 if ( wasInserted ) {
469 sidebarPartial.reflowWidgets();
470 }
471
472 return widgetPartial;
473 },
474
475 /**
476 * Handles changes to the sidebars_widgets[] setting.
477 *
478 * @since 4.5.0
479 *
480 * @param {Array} newWidgetIds New widget IDs.
481 * @param {Array} oldWidgetIds Old widget IDs.
482 *
483 * @return {void}
484 */
485 handleSettingChange: function( newWidgetIds, oldWidgetIds ) {
486 var sidebarPartial = this, needsRefresh, widgetsRemoved, widgetsAdded, addedWidgetPartials = [];
487
488 needsRefresh = (
489 ( oldWidgetIds.length > 0 && 0 === newWidgetIds.length ) ||
490 ( newWidgetIds.length > 0 && 0 === oldWidgetIds.length )
491 );
492 if ( needsRefresh ) {
493 sidebarPartial.fallback();
494 return;
495 }
496
497 // Handle removal of widgets.
498 widgetsRemoved = _.difference( oldWidgetIds, newWidgetIds );
499 _.each( widgetsRemoved, function( removedWidgetId ) {
500 var widgetPartial = api.selectiveRefresh.partial( 'widget[' + removedWidgetId + ']' );
501 if ( widgetPartial ) {
502 _.each( widgetPartial.placements(), function( placement ) {
503 var isRemoved = (
504 placement.context.sidebar_id === sidebarPartial.sidebarId ||
505 ( placement.context.sidebar_args && placement.context.sidebar_args.id === sidebarPartial.sidebarId )
506 );
507 if ( isRemoved ) {
508 placement.container.remove();
509 }
510 } );
511 }
512 delete self.renderedWidgets[ removedWidgetId ];
513 } );
514
515 // Handle insertion of widgets.
516 widgetsAdded = _.difference( newWidgetIds, oldWidgetIds );
517 _.each( widgetsAdded, function( addedWidgetId ) {
518 var widgetPartial = sidebarPartial.ensureWidgetPlacementContainers( addedWidgetId );
519 addedWidgetPartials.push( widgetPartial );
520 self.renderedWidgets[ addedWidgetId ] = true;
521 } );
522
523 _.each( addedWidgetPartials, function( widgetPartial ) {
524 widgetPartial.refresh();
525 } );
526
527 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
528 },
529
530 /**
531 * Refreshes the sidebar partial.
532 *
533 * Note that the meat is handled in handleSettingChange because it has the
534 * context of which widgets were removed.
535 *
536 * @since 4.5.0
537 *
538 * @return {Promise} A promise postponing the refresh.
539 */
540 refresh: function() {
541 var partial = this, deferred = $.Deferred();
542
543 deferred.fail( function() {
544 partial.fallback();
545 } );
546
547 if ( 0 === partial.placements().length ) {
548 deferred.reject();
549 } else {
550 _.each( partial.reflowWidgets(), function( sidebarPlacement ) {
551 api.selectiveRefresh.trigger( 'partial-content-rendered', sidebarPlacement );
552 } );
553 deferred.resolve();
554 }
555
556 return deferred.promise();
557 }
558 });
559
560 api.selectiveRefresh.partialConstructor.sidebar = self.SidebarPartial;
561 api.selectiveRefresh.partialConstructor.widget = self.WidgetPartial;
562
563 /**
564 * Adds partials for the registered widget areas (sidebars).
565 *
566 * @since 4.5.0
567 *
568 * @return {void}
569 */
570 self.addPartials = function() {
571 _.each( self.registeredSidebars, function( registeredSidebar ) {
572 var partial, partialId = 'sidebar[' + registeredSidebar.id + ']';
573 partial = api.selectiveRefresh.partial( partialId );
574 if ( ! partial ) {
575 partial = new self.SidebarPartial( partialId, {
576 params: {
577 sidebarArgs: registeredSidebar
578 }
579 } );
580 api.selectiveRefresh.partial.add( partial );
581 }
582 } );
583 };
584
585 /**
586 * Calculates the selector for the sidebar's widgets based on the registered
587 * sidebar's info.
588 *
589 * @memberOf wp.customize.widgetsPreview
590 *
591 * @since 3.9.0
592 *
593 * @return {void}
594 */
595 self.buildWidgetSelectors = function() {
596 var self = this;
597
598 $.each( self.registeredSidebars, function( i, sidebar ) {
599 var widgetTpl = [
600 sidebar.before_widget,
601 sidebar.before_title,
602 sidebar.after_title,
603 sidebar.after_widget
604 ].join( '' ),
605 emptyWidget,
606 widgetSelector,
607 widgetClasses;
608
609 emptyWidget = $( widgetTpl );
610 widgetSelector = emptyWidget.prop( 'tagName' ) || '';
611 widgetClasses = emptyWidget.prop( 'className' ) || '';
612
613 // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
614 if ( ! widgetClasses ) {
615 return;
616 }
617
618 // Remove class names that incorporate the string formatting placeholders %1$s and %2$s.
619 widgetClasses = widgetClasses.replace( /\S*%[12]\$s\S*/g, '' );
620 widgetClasses = widgetClasses.replace( /^\s+|\s+$/g, '' );
621 if ( widgetClasses ) {
622 widgetSelector += '.' + widgetClasses.split( /\s+/ ).join( '.' );
623 }
624 self.widgetSelectors.push( widgetSelector );
625 });
626 };
627
628 /**
629 * Highlights the widget on widget updates or widget control mouse overs.
630 *
631 * @memberOf wp.customize.widgetsPreview
632 *
633 * @since 3.9.0
634 * @param {string} widgetId ID of the widget.
635 *
636 * @return {void}
637 */
638 self.highlightWidget = function( widgetId ) {
639 var $body = $( document.body ),
640 $widget = $( '#' + widgetId );
641
642 $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
643
644 $widget.addClass( 'widget-customizer-highlighted-widget' );
645 setTimeout( function() {
646 $widget.removeClass( 'widget-customizer-highlighted-widget' );
647 }, 500 );
648 };
649
650 /**
651 * Shows a title and highlights widgets on hover. On shift+clicking focuses the
652 * widget control.
653 *
654 * @memberOf wp.customize.widgetsPreview
655 *
656 * @since 3.9.0
657 *
658 * @return {void}
659 */
660 self.highlightControls = function() {
661 var self = this,
662 selector = this.widgetSelectors.join( ',' );
663
664 // Skip adding highlights if not in the customizer preview iframe.
665 if ( ! api.settings.channel ) {
666 return;
667 }
668
669 $( selector ).attr( 'title', this.l10n.widgetTooltip );
670 // Highlights widget when entering the widget editor.
671 $( document ).on( 'mouseenter', selector, function() {
672 self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
673 });
674
675 // Open expand the widget control when shift+clicking the widget element.
676 $( document ).on( 'click', selector, function( e ) {
677 if ( ! e.shiftKey ) {
678 return;
679 }
680 e.preventDefault();
681
682 self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
683 });
684 };
685
686 /**
687 * Parses a widget ID.
688 *
689 * @memberOf wp.customize.widgetsPreview
690 *
691 * @since 4.5.0
692 *
693 * @param {string} widgetId The widget ID.
694 *
695 * @return {{idBase: string, number: number|null}} An object containing the idBase
696 * and number of the parsed widget ID.
697 */
698 self.parseWidgetId = function( widgetId ) {
699 var matches, parsed = {
700 idBase: '',
701 number: null
702 };
703
704 matches = widgetId.match( /^(.+)-(\d+)$/ );
705 if ( matches ) {
706 parsed.idBase = matches[1];
707 parsed.number = parseInt( matches[2], 10 );
708 } else {
709 parsed.idBase = widgetId; // Likely an old single widget.
710 }
711
712 return parsed;
713 };
714
715 /**
716 * Parses a widget setting ID.
717 *
718 * @memberOf wp.customize.widgetsPreview
719 *
720 * @since 4.5.0
721 *
722 * @param {string} settingId Widget setting ID.
723 *
724 * @return {{idBase: string, number: number|null}|null} Either an object containing the idBase
725 * and number of the parsed widget setting ID,
726 * or null.
727 */
728 self.parseWidgetSettingId = function( settingId ) {
729 var matches, parsed = {
730 idBase: '',
731 number: null
732 };
733
734 matches = settingId.match( /^widget_([^\[]+?)(?:\[(\d+)])?$/ );
735 if ( ! matches ) {
736 return null;
737 }
738 parsed.idBase = matches[1];
739 if ( matches[2] ) {
740 parsed.number = parseInt( matches[2], 10 );
741 }
742 return parsed;
743 };
744
745 /**
746 * Converts a widget ID into a Customizer setting ID.
747 *
748 * @memberOf wp.customize.widgetsPreview
749 *
750 * @since 4.5.0
751 *
752 * @param {string} widgetId The widget ID.
753 *
754 * @return {string} The setting ID.
755 */
756 self.getWidgetSettingId = function( widgetId ) {
757 var parsed = this.parseWidgetId( widgetId ), settingId;
758
759 settingId = 'widget_' + parsed.idBase;
760 if ( parsed.number ) {
761 settingId += '[' + String( parsed.number ) + ']';
762 }
763
764 return settingId;
765 };
766
767 api.bind( 'preview-ready', function() {
768 $.extend( self, _wpWidgetCustomizerPreviewSettings );
769 self.init();
770 });
771
772 return self;
773})( jQuery, _, wp, wp.customize );
774
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1