Changeset 36586 for trunk/src/wp-includes/js/customize-preview-widgets.js
- Timestamp:
- 02/19/2016 06:40:06 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/js/customize-preview-widgets.js
r35783 r36586 1 (function( wp, $ ){ 2 3 if ( ! wp || ! wp.customize ) { return; } 4 5 var api = wp.customize; 6 7 /** 8 * wp.customize.WidgetCustomizerPreview 9 * 10 */ 11 api.WidgetCustomizerPreview = { 12 renderedSidebars: {}, // @todo Make rendered a property of the Backbone model 13 renderedWidgets: {}, // @todo Make rendered a property of the Backbone model 14 registeredSidebars: [], // @todo Make a Backbone collection 15 registeredWidgets: {}, // @todo Make array, Backbone collection 1 /* global _wpWidgetCustomizerPreviewSettings */ 2 wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( $, _, wp, api ) { 3 4 var self; 5 6 self = { 7 renderedSidebars: {}, 8 renderedWidgets: {}, 9 registeredSidebars: [], 10 registeredWidgets: {}, 16 11 widgetSelectors: [], 17 12 preview: null, 18 l10n: {}, 19 20 init: function () { 21 var self = this; 22 23 this.preview = api.preview; 24 this.buildWidgetSelectors(); 25 this.highlightControls(); 26 27 this.preview.bind( 'highlight-widget', self.highlightWidget ); 28 }, 13 l10n: { 14 widgetTooltip: '' 15 } 16 }; 17 18 /** 19 * Init widgets preview. 20 * 21 * @since 4.5.0 22 */ 23 self.init = function() { 24 var self = this; 25 26 self.preview = api.preview; 27 if ( api.selectiveRefresh ) { 28 self.addPartials(); 29 } 30 31 self.buildWidgetSelectors(); 32 self.highlightControls(); 33 34 self.preview.bind( 'highlight-widget', self.highlightWidget ); 35 36 api.preview.bind( 'active', function() { 37 self.highlightControls(); 38 } ); 39 }; 40 41 if ( api.selectiveRefresh ) { 29 42 30 43 /** 31 * Calculate the selector for the sidebar's widgets based on the registered sidebar's info 44 * Partial representing a widget instance. 45 * 46 * @class 47 * @augments wp.customize.selectiveRefresh.Partial 48 * @since 4.5.0 32 49 */ 33 buildWidgetSelectors: function () { 34 var self = this; 35 36 $.each( this.registeredSidebars, function ( i, sidebar ) { 37 var widgetTpl = [ 38 sidebar.before_widget.replace('%1$s', '').replace('%2$s', ''), 39 sidebar.before_title, 40 sidebar.after_title, 41 sidebar.after_widget 42 ].join(''), 43 emptyWidget, 44 widgetSelector, 45 widgetClasses; 46 47 emptyWidget = $(widgetTpl); 48 widgetSelector = emptyWidget.prop('tagName'); 49 widgetClasses = emptyWidget.prop('className'); 50 51 // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty. 52 if ( ! widgetClasses ) { 50 self.WidgetPartial = api.selectiveRefresh.Partial.extend({ 51 52 /** 53 * Constructor. 54 * 55 * @since 4.5.0 56 * @param {string} id - Partial ID. 57 * @param {Object} options 58 * @param {Object} options.params 59 */ 60 initialize: function( id, options ) { 61 var partial = this, matches; 62 matches = id.match( /^widget\[(.+)]$/ ); 63 if ( ! matches ) { 64 throw new Error( 'Illegal id for widget partial.' ); 65 } 66 67 partial.widgetId = matches[1]; 68 options = options || {}; 69 options.params = _.extend( 70 { 71 /* Note that a selector of ('#' + partial.widgetId) is faster, but jQuery will only return the one result. */ 72 selector: '[id="' + partial.widgetId + '"]', // Alternatively, '[data-customize-widget-id="' + partial.widgetId + '"]' 73 settings: [ self.getWidgetSettingId( partial.widgetId ) ], 74 containerInclusive: true 75 }, 76 options.params || {} 77 ); 78 79 api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options ); 80 }, 81 82 /** 83 * Send widget-updated message to parent so spinner will get removed from widget control. 84 * 85 * @inheritdoc 86 * @param {wp.customize.selectiveRefresh.Placement} placement 87 */ 88 renderContent: function( placement ) { 89 var partial = this; 90 if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) { 91 api.preview.send( 'widget-updated', partial.widgetId ); 92 api.selectiveRefresh.trigger( 'widget-updated', partial ); 93 } 94 } 95 }); 96 97 /** 98 * Partial representing a widget area. 99 * 100 * @class 101 * @augments wp.customize.selectiveRefresh.Partial 102 * @since 4.5.0 103 */ 104 self.SidebarPartial = api.selectiveRefresh.Partial.extend({ 105 106 /** 107 * Constructor. 108 * 109 * @since 4.5.0 110 * @param {string} id - Partial ID. 111 * @param {Object} options 112 * @param {Object} options.params 113 */ 114 initialize: function( id, options ) { 115 var partial = this, matches; 116 matches = id.match( /^sidebar\[(.+)]$/ ); 117 if ( ! matches ) { 118 throw new Error( 'Illegal id for sidebar partial.' ); 119 } 120 partial.sidebarId = matches[1]; 121 122 options = options || {}; 123 options.params = _.extend( 124 { 125 settings: [ 'sidebars_widgets[' + partial.sidebarId + ']' ] 126 }, 127 options.params || {} 128 ); 129 130 api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options ); 131 132 if ( ! partial.params.sidebarArgs ) { 133 throw new Error( 'The sidebarArgs param was not provided.' ); 134 } 135 if ( partial.params.settings.length > 1 ) { 136 throw new Error( 'Expected SidebarPartial to only have one associated setting' ); 137 } 138 }, 139 140 /** 141 * Set up the partial. 142 * 143 * @since 4.5.0 144 */ 145 ready: function() { 146 var sidebarPartial = this; 147 148 // Watch for changes to the sidebar_widgets setting. 149 _.each( sidebarPartial.settings(), function( settingId ) { 150 api( settingId ).bind( _.bind( sidebarPartial.handleSettingChange, sidebarPartial ) ); 151 } ); 152 153 // Trigger an event for this sidebar being updated whenever a widget inside is rendered. 154 api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) { 155 var isAssignedWidgetPartial = ( 156 placement.partial.extended( self.WidgetPartial ) && 157 ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), placement.partial.widgetId ) ) 158 ); 159 if ( isAssignedWidgetPartial ) { 160 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial ); 161 } 162 } ); 163 164 // Make sure that a widget partial has a container in the DOM prior to a refresh. 165 api.bind( 'change', function( widgetSetting ) { 166 var widgetId, parsedId; 167 parsedId = self.parseWidgetSettingId( widgetSetting.id ); 168 if ( ! parsedId ) { 169 return; 170 } 171 widgetId = parsedId.idBase; 172 if ( parsedId.number ) { 173 widgetId += '-' + String( parsedId.number ); 174 } 175 if ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), widgetId ) ) { 176 sidebarPartial.ensureWidgetPlacementContainers( widgetId ); 177 } 178 } ); 179 }, 180 181 /** 182 * Get the before/after boundary nodes for all instances of this sidebar (usually one). 183 * 184 * Note that TreeWalker is not implemented in IE8. 185 * 186 * @since 4.5.0 187 * @returns {Array.<{before: Comment, after: Comment, instanceNumber: number}>} 188 */ 189 findDynamicSidebarBoundaryNodes: function() { 190 var partial = this, regExp, boundaryNodes = {}, recursiveCommentTraversal; 191 regExp = /^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/; 192 recursiveCommentTraversal = function( childNodes ) { 193 _.each( childNodes, function( node ) { 194 var matches; 195 if ( 8 === node.nodeType ) { 196 matches = node.nodeValue.match( regExp ); 197 if ( ! matches || matches[2] !== partial.sidebarId ) { 198 return; 199 } 200 if ( _.isUndefined( boundaryNodes[ matches[3] ] ) ) { 201 boundaryNodes[ matches[3] ] = { 202 before: null, 203 after: null, 204 instanceNumber: parseInt( matches[3], 10 ) 205 }; 206 } 207 if ( 'dynamic_sidebar_before' === matches[1] ) { 208 boundaryNodes[ matches[3] ].before = node; 209 } else { 210 boundaryNodes[ matches[3] ].after = node; 211 } 212 } else if ( 1 === node.nodeType ) { 213 recursiveCommentTraversal( node.childNodes ); 214 } 215 } ); 216 }; 217 218 recursiveCommentTraversal( document.body.childNodes ); 219 return _.values( boundaryNodes ); 220 }, 221 222 /** 223 * Get the placements for this partial. 224 * 225 * @since 4.5.0 226 * @returns {Array} 227 */ 228 placements: function() { 229 var partial = this; 230 return _.map( partial.findDynamicSidebarBoundaryNodes(), function( boundaryNodes ) { 231 return new api.selectiveRefresh.Placement( { 232 partial: partial, 233 container: null, 234 startNode: boundaryNodes.before, 235 endNode: boundaryNodes.after, 236 context: { 237 instanceNumber: boundaryNodes.instanceNumber 238 } 239 } ); 240 } ); 241 }, 242 243 /** 244 * Get the list of widget IDs associated with this widget area. 245 * 246 * @since 4.5.0 247 * 248 * @returns {Array} 249 */ 250 getWidgetIds: function() { 251 var sidebarPartial = this, settingId, widgetIds; 252 settingId = sidebarPartial.settings()[0]; 253 if ( ! settingId ) { 254 throw new Error( 'Missing associated setting.' ); 255 } 256 if ( ! api.has( settingId ) ) { 257 throw new Error( 'Setting does not exist.' ); 258 } 259 widgetIds = api( settingId ).get(); 260 if ( ! _.isArray( widgetIds ) ) { 261 throw new Error( 'Expected setting to be array of widget IDs' ); 262 } 263 return widgetIds.slice( 0 ); 264 }, 265 266 /** 267 * Reflow widgets in the sidebar, ensuring they have the proper position in the DOM. 268 * 269 * @since 4.5.0 270 * 271 * @return {Array.<wp.customize.selectiveRefresh.Placement>} List of placements that were reflowed. 272 */ 273 reflowWidgets: function() { 274 var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = []; 275 widgetIds = sidebarPartial.getWidgetIds(); 276 sidebarPlacements = sidebarPartial.placements(); 277 278 widgetPartials = {}; 279 _.each( widgetIds, function( widgetId ) { 280 var widgetPartial = api.selectiveRefresh.partial( 'widget[' + widgetId + ']' ); 281 if ( widgetPartial ) { 282 widgetPartials[ widgetId ] = widgetPartial; 283 } 284 } ); 285 286 _.each( sidebarPlacements, function( sidebarPlacement ) { 287 var sidebarWidgets = [], needsSort = false, thisPosition, lastPosition = -1; 288 289 // Gather list of widget partial containers in this sidebar, and determine if a sort is needed. 290 _.each( widgetPartials, function( widgetPartial ) { 291 _.each( widgetPartial.placements(), function( widgetPlacement ) { 292 293 if ( sidebarPlacement.context.instanceNumber === widgetPlacement.context.sidebar_instance_number ) { 294 thisPosition = widgetPlacement.container.index(); 295 sidebarWidgets.push( { 296 partial: widgetPartial, 297 placement: widgetPlacement, 298 position: thisPosition 299 } ); 300 if ( thisPosition < lastPosition ) { 301 needsSort = true; 302 } 303 lastPosition = thisPosition; 304 } 305 } ); 306 } ); 307 308 if ( needsSort ) { 309 _.each( sidebarWidgets, function( sidebarWidget ) { 310 sidebarPlacement.endNode.parentNode.insertBefore( 311 sidebarWidget.placement.container[0], 312 sidebarPlacement.endNode 313 ); 314 315 // @todo Rename partial-placement-moved? 316 api.selectiveRefresh.trigger( 'partial-content-moved', sidebarWidget.placement ); 317 } ); 318 319 sortedSidebarContainers.push( sidebarPlacement ); 320 } 321 } ); 322 323 if ( sortedSidebarContainers.length > 0 ) { 324 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial ); 325 } 326 327 return sortedSidebarContainers; 328 }, 329 330 /** 331 * Make sure there is a widget instance container in this sidebar for the given widget ID. 332 * 333 * @since 4.5.0 334 * 335 * @param {string} widgetId 336 * @returns {wp.customize.selectiveRefresh.Partial} Widget instance partial. 337 */ 338 ensureWidgetPlacementContainers: function( widgetId ) { 339 var sidebarPartial = this, widgetPartial, wasInserted = false, partialId = 'widget[' + widgetId + ']'; 340 widgetPartial = api.selectiveRefresh.partial( partialId ); 341 if ( ! widgetPartial ) { 342 widgetPartial = new self.WidgetPartial( partialId, { 343 params: {} 344 } ); 345 api.selectiveRefresh.partial.add( widgetPartial.id, widgetPartial ); 346 } 347 348 // Make sure that there is a container element for the widget in the sidebar, if at least a placeholder. 349 _.each( sidebarPartial.placements(), function( sidebarPlacement ) { 350 var foundWidgetPlacement, widgetContainerElement; 351 352 foundWidgetPlacement = _.find( widgetPartial.placements(), function( widgetPlacement ) { 353 return ( widgetPlacement.context.sidebar_instance_number === sidebarPlacement.context.instanceNumber ); 354 } ); 355 if ( foundWidgetPlacement ) { 356 return; 357 } 358 359 widgetContainerElement = $( 360 sidebarPartial.params.sidebarArgs.before_widget.replace( '%1$s', widgetId ).replace( '%2$s', 'widget' ) + 361 sidebarPartial.params.sidebarArgs.after_widget 362 ); 363 364 widgetContainerElement.attr( 'data-customize-partial-id', widgetPartial.id ); 365 widgetContainerElement.attr( 'data-customize-partial-type', 'widget' ); 366 widgetContainerElement.attr( 'data-customize-widget-id', widgetId ); 367 368 /* 369 * Make sure the widget container element has the customize-container context data. 370 * The sidebar_instance_number is used to disambiguate multiple instances of the 371 * same sidebar are rendered onto the template, and so the same widget is embedded 372 * multiple times. 373 */ 374 widgetContainerElement.data( 'customize-partial-placement-context', { 375 'sidebar_id': sidebarPartial.sidebarId, 376 'sidebar_instance_number': sidebarPlacement.context.instanceNumber 377 } ); 378 379 sidebarPlacement.endNode.parentNode.insertBefore( widgetContainerElement[0], sidebarPlacement.endNode ); 380 wasInserted = true; 381 } ); 382 383 if ( wasInserted ) { 384 sidebarPartial.reflowWidgets(); 385 } 386 387 return widgetPartial; 388 }, 389 390 /** 391 * Handle change to the sidebars_widgets[] setting. 392 * 393 * @since 4.5.0 394 * 395 * @param {Array} newWidgetIds New widget ids. 396 * @param {Array} oldWidgetIds Old widget ids. 397 */ 398 handleSettingChange: function( newWidgetIds, oldWidgetIds ) { 399 var sidebarPartial = this, needsRefresh, widgetsRemoved, widgetsAdded, addedWidgetPartials = []; 400 401 needsRefresh = ( 402 ( oldWidgetIds.length > 0 && 0 === newWidgetIds.length ) || 403 ( newWidgetIds.length > 0 && 0 === oldWidgetIds.length ) 404 ); 405 if ( needsRefresh ) { 406 sidebarPartial.fallback(); 53 407 return; 54 408 } 55 409 56 widgetClasses = widgetClasses.replace(/^\s+|\s+$/g, ''); 57 58 if ( widgetClasses ) { 59 widgetSelector += '.' + widgetClasses.split(/\s+/).join('.'); 60 } 61 self.widgetSelectors.push(widgetSelector); 62 }); 63 }, 410 // Handle removal of widgets. 411 widgetsRemoved = _.difference( oldWidgetIds, newWidgetIds ); 412 _.each( widgetsRemoved, function( removedWidgetId ) { 413 var widgetPartial = api.selectiveRefresh.partial( 'widget[' + removedWidgetId + ']' ); 414 if ( widgetPartial ) { 415 _.each( widgetPartial.placements(), function( placement ) { 416 var isRemoved = ( 417 placement.context.sidebar_id === sidebarPartial.sidebarId || 418 ( placement.context.sidebar_args && placement.context.sidebar_args.id === sidebarPartial.sidebarId ) 419 ); 420 if ( isRemoved ) { 421 placement.container.remove(); 422 } 423 } ); 424 } 425 } ); 426 427 // Handle insertion of widgets. 428 widgetsAdded = _.difference( newWidgetIds, oldWidgetIds ); 429 _.each( widgetsAdded, function( addedWidgetId ) { 430 var widgetPartial = sidebarPartial.ensureWidgetPlacementContainers( addedWidgetId ); 431 addedWidgetPartials.push( widgetPartial ); 432 } ); 433 434 _.each( addedWidgetPartials, function( widgetPartial ) { 435 widgetPartial.refresh(); 436 } ); 437 438 api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial ); 439 }, 440 441 /** 442 * Note that the meat is handled in handleSettingChange because it has the context of which widgets were removed. 443 * 444 * @since 4.5.0 445 */ 446 refresh: function() { 447 var partial = this, deferred = $.Deferred(); 448 449 deferred.fail( function() { 450 partial.fallback(); 451 } ); 452 453 if ( 0 === partial.placements().length ) { 454 deferred.reject(); 455 } else { 456 _.each( partial.reflowWidgets(), function( sidebarPlacement ) { 457 api.selectiveRefresh.trigger( 'partial-content-rendered', sidebarPlacement ); 458 } ); 459 deferred.resolve(); 460 } 461 462 return deferred.promise(); 463 } 464 }); 465 466 api.selectiveRefresh.partialConstructor.sidebar = self.SidebarPartial; 467 api.selectiveRefresh.partialConstructor.widget = self.WidgetPartial; 64 468 65 469 /** 66 * Highlight the widget on widget updates or widget control mouse overs.470 * Add partials for the registered widget areas (sidebars). 67 471 * 68 * @ param {string} widgetId ID of the widget.472 * @since 4.5.0 69 473 */ 70 highlightWidget: function( widgetId ) { 71 var $body = $( document.body ), 72 $widget = $( '#' + widgetId ); 73 74 $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' ); 75 76 $widget.addClass( 'widget-customizer-highlighted-widget' ); 77 setTimeout( function () { 78 $widget.removeClass( 'widget-customizer-highlighted-widget' ); 79 }, 500 ); 80 }, 81 82 /** 83 * Show a title and highlight widgets on hover. On shift+clicking 84 * focus the widget control. 85 */ 86 highlightControls: function() { 87 var self = this, 88 selector = this.widgetSelectors.join(','); 89 90 $(selector).attr( 'title', this.l10n.widgetTooltip ); 91 92 $(document).on( 'mouseenter', selector, function () { 93 self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) ); 94 }); 95 96 // Open expand the widget control when shift+clicking the widget element 97 $(document).on( 'click', selector, function ( e ) { 98 if ( ! e.shiftKey ) { 99 return; 100 } 101 e.preventDefault(); 102 103 self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) ); 104 }); 474 self.addPartials = function() { 475 _.each( self.registeredSidebars, function( registeredSidebar ) { 476 var partial, partialId = 'sidebar[' + registeredSidebar.id + ']'; 477 partial = api.selectiveRefresh.partial( partialId ); 478 if ( ! partial ) { 479 partial = new self.SidebarPartial( partialId, { 480 params: { 481 sidebarArgs: registeredSidebar 482 } 483 } ); 484 api.selectiveRefresh.partial.add( partial.id, partial ); 485 } 486 } ); 487 }; 488 489 } 490 491 /** 492 * Calculate the selector for the sidebar's widgets based on the registered sidebar's info. 493 * 494 * @since 3.9.0 495 */ 496 self.buildWidgetSelectors = function() { 497 var self = this; 498 499 $.each( self.registeredSidebars, function( i, sidebar ) { 500 var widgetTpl = [ 501 sidebar.before_widget.replace( '%1$s', '' ).replace( '%2$s', '' ), 502 sidebar.before_title, 503 sidebar.after_title, 504 sidebar.after_widget 505 ].join( '' ), 506 emptyWidget, 507 widgetSelector, 508 widgetClasses; 509 510 emptyWidget = $( widgetTpl ); 511 widgetSelector = emptyWidget.prop( 'tagName' ); 512 widgetClasses = emptyWidget.prop( 'className' ); 513 514 // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty. 515 if ( ! widgetClasses ) { 516 return; 517 } 518 519 widgetClasses = widgetClasses.replace( /^\s+|\s+$/g, '' ); 520 521 if ( widgetClasses ) { 522 widgetSelector += '.' + widgetClasses.split( /\s+/ ).join( '.' ); 523 } 524 self.widgetSelectors.push( widgetSelector ); 525 }); 526 }; 527 528 /** 529 * Highlight the widget on widget updates or widget control mouse overs. 530 * 531 * @since 3.9.0 532 * @param {string} widgetId ID of the widget. 533 */ 534 self.highlightWidget = function( widgetId ) { 535 var $body = $( document.body ), 536 $widget = $( '#' + widgetId ); 537 538 $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' ); 539 540 $widget.addClass( 'widget-customizer-highlighted-widget' ); 541 setTimeout( function() { 542 $widget.removeClass( 'widget-customizer-highlighted-widget' ); 543 }, 500 ); 544 }; 545 546 /** 547 * Show a title and highlight widgets on hover. On shift+clicking 548 * focus the widget control. 549 * 550 * @since 3.9.0 551 */ 552 self.highlightControls = function() { 553 var self = this, 554 selector = this.widgetSelectors.join( ',' ); 555 556 $( selector ).attr( 'title', this.l10n.widgetTooltip ); 557 558 $( document ).on( 'mouseenter', selector, function() { 559 self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) ); 560 }); 561 562 // Open expand the widget control when shift+clicking the widget element 563 $( document ).on( 'click', selector, function( e ) { 564 if ( ! e.shiftKey ) { 565 return; 566 } 567 e.preventDefault(); 568 569 self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) ); 570 }); 571 }; 572 573 /** 574 * Parse a widget ID. 575 * 576 * @since 4.5.0 577 * 578 * @param {string} widgetId Widget ID. 579 * @returns {{idBase: string, number: number|null}} 580 */ 581 self.parseWidgetId = function( widgetId ) { 582 var matches, parsed = { 583 idBase: '', 584 number: null 585 }; 586 587 matches = widgetId.match( /^(.+)-(\d+)$/ ); 588 if ( matches ) { 589 parsed.idBase = matches[1]; 590 parsed.number = parseInt( matches[2], 10 ); 591 } else { 592 parsed.idBase = widgetId; // Likely an old single widget. 105 593 } 106 }; 107 108 $(function () { 109 var settings = window._wpWidgetCustomizerPreviewSettings; 110 if ( ! settings ) { 111 return; 594 595 return parsed; 596 }; 597 598 /** 599 * Parse a widget setting ID. 600 * 601 * @since 4.5.0 602 * 603 * @param {string} settingId Widget setting ID. 604 * @returns {{idBase: string, number: number|null}|null} 605 */ 606 self.parseWidgetSettingId = function( settingId ) { 607 var matches, parsed = { 608 idBase: '', 609 number: null 610 }; 611 612 matches = settingId.match( /^widget_([^\[]+?)(?:\[(\d+)])?$/ ); 613 if ( ! matches ) { 614 return null; 112 615 } 113 114 $.extend( api.WidgetCustomizerPreview, settings ); 115 116 api.WidgetCustomizerPreview.init(); 616 parsed.idBase = matches[1]; 617 if ( matches[2] ) { 618 parsed.number = parseInt( matches[2], 10 ); 619 } 620 return parsed; 621 }; 622 623 /** 624 * Convert a widget ID into a Customizer setting ID. 625 * 626 * @since 4.5.0 627 * 628 * @param {string} widgetId Widget ID. 629 * @returns {string} settingId Setting ID. 630 */ 631 self.getWidgetSettingId = function( widgetId ) { 632 var parsed = this.parseWidgetId( widgetId ), settingId; 633 634 settingId = 'widget_' + parsed.idBase; 635 if ( parsed.number ) { 636 settingId += '[' + String( parsed.number ) + ']'; 637 } 638 639 return settingId; 640 }; 641 642 api.bind( 'preview-ready', function() { 643 $.extend( self, _wpWidgetCustomizerPreviewSettings ); 644 self.init(); 117 645 }); 118 646 119 })( window.wp, jQuery ); 647 return self; 648 })( jQuery, _, wp, wp.customize );
Note: See TracChangeset
for help on using the changeset viewer.