wp/wp-admin/js/customize-widgets.js
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
       
     1 /**
       
     2  * @output wp-admin/js/customize-widgets.js
       
     3  */
       
     4 
     1 /* global _wpCustomizeWidgetsSettings */
     5 /* global _wpCustomizeWidgetsSettings */
     2 (function( wp, $ ){
     6 (function( wp, $ ){
     3 
     7 
     4 	if ( ! wp || ! wp.customize ) { return; }
     8 	if ( ! wp || ! wp.customize ) { return; }
     5 
     9 
     6 	// Set up our namespace...
    10 	// Set up our namespace...
     7 	var api = wp.customize,
    11 	var api = wp.customize,
     8 		l10n;
    12 		l10n;
     9 
    13 
       
    14 	/**
       
    15 	 * @namespace wp.customize.Widgets
       
    16 	 */
    10 	api.Widgets = api.Widgets || {};
    17 	api.Widgets = api.Widgets || {};
    11 	api.Widgets.savedWidgetIds = {};
    18 	api.Widgets.savedWidgetIds = {};
    12 
    19 
    13 	// Link settings
    20 	// Link settings
    14 	api.Widgets.data = _wpCustomizeWidgetsSettings || {};
    21 	api.Widgets.data = _wpCustomizeWidgetsSettings || {};
    17 	/**
    24 	/**
    18 	 * wp.customize.Widgets.WidgetModel
    25 	 * wp.customize.Widgets.WidgetModel
    19 	 *
    26 	 *
    20 	 * A single widget model.
    27 	 * A single widget model.
    21 	 *
    28 	 *
    22 	 * @constructor
    29 	 * @class    wp.customize.Widgets.WidgetModel
    23 	 * @augments Backbone.Model
    30 	 * @augments Backbone.Model
    24 	 */
    31 	 */
    25 	api.Widgets.WidgetModel = Backbone.Model.extend({
    32 	api.Widgets.WidgetModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.WidgetModel.prototype */{
    26 		id: null,
    33 		id: null,
    27 		temp_id: null,
    34 		temp_id: null,
    28 		classname: null,
    35 		classname: null,
    29 		control_tpl: null,
    36 		control_tpl: null,
    30 		description: null,
    37 		description: null,
    43 	/**
    50 	/**
    44 	 * wp.customize.Widgets.WidgetCollection
    51 	 * wp.customize.Widgets.WidgetCollection
    45 	 *
    52 	 *
    46 	 * Collection for widget models.
    53 	 * Collection for widget models.
    47 	 *
    54 	 *
    48 	 * @constructor
    55 	 * @class    wp.customize.Widgets.WidgetCollection
    49 	 * @augments Backbone.Model
    56 	 * @augments Backbone.Collection
    50 	 */
    57 	 */
    51 	api.Widgets.WidgetCollection = Backbone.Collection.extend({
    58 	api.Widgets.WidgetCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.WidgetCollection.prototype */{
    52 		model: api.Widgets.WidgetModel,
    59 		model: api.Widgets.WidgetModel,
    53 
    60 
    54 		// Controls searching on the current widget collection
    61 		// Controls searching on the current widget collection
    55 		// and triggers an update event
    62 		// and triggers an update event
    56 		doSearch: function( value ) {
    63 		doSearch: function( value ) {
   101 	/**
   108 	/**
   102 	 * wp.customize.Widgets.SidebarModel
   109 	 * wp.customize.Widgets.SidebarModel
   103 	 *
   110 	 *
   104 	 * A single sidebar model.
   111 	 * A single sidebar model.
   105 	 *
   112 	 *
   106 	 * @constructor
   113 	 * @class    wp.customize.Widgets.SidebarModel
   107 	 * @augments Backbone.Model
   114 	 * @augments Backbone.Model
   108 	 */
   115 	 */
   109 	api.Widgets.SidebarModel = Backbone.Model.extend({
   116 	api.Widgets.SidebarModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.SidebarModel.prototype */{
   110 		after_title: null,
   117 		after_title: null,
   111 		after_widget: null,
   118 		after_widget: null,
   112 		before_title: null,
   119 		before_title: null,
   113 		before_widget: null,
   120 		before_widget: null,
   114 		'class': null,
   121 		'class': null,
   121 	/**
   128 	/**
   122 	 * wp.customize.Widgets.SidebarCollection
   129 	 * wp.customize.Widgets.SidebarCollection
   123 	 *
   130 	 *
   124 	 * Collection for sidebar models.
   131 	 * Collection for sidebar models.
   125 	 *
   132 	 *
   126 	 * @constructor
   133 	 * @class    wp.customize.Widgets.SidebarCollection
   127 	 * @augments Backbone.Collection
   134 	 * @augments Backbone.Collection
   128 	 */
   135 	 */
   129 	api.Widgets.SidebarCollection = Backbone.Collection.extend({
   136 	api.Widgets.SidebarCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.SidebarCollection.prototype */{
   130 		model: api.Widgets.SidebarModel
   137 		model: api.Widgets.SidebarModel
   131 	});
   138 	});
   132 	api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars );
   139 	api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars );
   133 
   140 
   134 	/**
   141 	api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend(/** @lends wp.customize.Widgets.AvailableWidgetsPanelView.prototype */{
   135 	 * wp.customize.Widgets.AvailableWidgetsPanelView
       
   136 	 *
       
   137 	 * View class for the available widgets panel.
       
   138 	 *
       
   139 	 * @constructor
       
   140 	 * @augments wp.Backbone.View
       
   141 	 * @augments Backbone.View
       
   142 	 */
       
   143 	api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend({
       
   144 
   142 
   145 		el: '#available-widgets',
   143 		el: '#available-widgets',
   146 
   144 
   147 		events: {
   145 		events: {
   148 			'input #widgets-search': 'search',
   146 			'input #widgets-search': 'search',
   149 			'keyup #widgets-search': 'search',
       
   150 			'focus .widget-tpl' : 'focus',
   147 			'focus .widget-tpl' : 'focus',
   151 			'click .widget-tpl' : '_submit',
   148 			'click .widget-tpl' : '_submit',
   152 			'keypress .widget-tpl' : '_submit',
   149 			'keypress .widget-tpl' : '_submit',
   153 			'keydown' : 'keyboardAccessible'
   150 			'keydown' : 'keyboardAccessible'
   154 		},
   151 		},
   160 		currentSidebarControl: null,
   157 		currentSidebarControl: null,
   161 		$search: null,
   158 		$search: null,
   162 		$clearResults: null,
   159 		$clearResults: null,
   163 		searchMatchesCount: null,
   160 		searchMatchesCount: null,
   164 
   161 
       
   162 		/**
       
   163 		 * View class for the available widgets panel.
       
   164 		 *
       
   165 		 * @constructs wp.customize.Widgets.AvailableWidgetsPanelView
       
   166 		 * @augments   wp.Backbone.View
       
   167 		 */
   165 		initialize: function() {
   168 		initialize: function() {
   166 			var self = this;
   169 			var self = this;
   167 
   170 
   168 			this.$search = $( '#widgets-search' );
   171 			this.$search = $( '#widgets-search' );
   169 
   172 
   195 
   198 
   196 			// Close the panel if the URL in the preview changes
   199 			// Close the panel if the URL in the preview changes
   197 			api.previewer.bind( 'url', this.close );
   200 			api.previewer.bind( 'url', this.close );
   198 		},
   201 		},
   199 
   202 
   200 		// Performs a search and handles selected widget
   203 		/**
   201 		search: function( event ) {
   204 		 * Performs a search and handles selected widget.
       
   205 		 */
       
   206 		search: _.debounce( function( event ) {
   202 			var firstVisible;
   207 			var firstVisible;
   203 
   208 
   204 			this.collection.doSearch( event.target.value );
   209 			this.collection.doSearch( event.target.value );
   205 			// Update the search matches count.
   210 			// Update the search matches count.
   206 			this.updateSearchMatchesCount();
   211 			this.updateSearchMatchesCount();
   238 			if ( ! this.searchMatchesCount ) {
   243 			if ( ! this.searchMatchesCount ) {
   239 				this.$el.addClass( 'no-widgets-found' );
   244 				this.$el.addClass( 'no-widgets-found' );
   240 			} else {
   245 			} else {
   241 				this.$el.removeClass( 'no-widgets-found' );
   246 				this.$el.removeClass( 'no-widgets-found' );
   242 			}
   247 			}
   243 		},
   248 		}, 500 ),
   244 
   249 
   245 		// Update the count of the available widgets that have the `search_matched` attribute.
   250 		/**
       
   251 		 * Updates the count of the available widgets that have the `search_matched` attribute.
       
   252  		 */
   246 		updateSearchMatchesCount: function() {
   253 		updateSearchMatchesCount: function() {
   247 			this.searchMatchesCount = this.collection.where({ search_matched: true }).length;
   254 			this.searchMatchesCount = this.collection.where({ search_matched: true }).length;
   248 		},
   255 		},
   249 
   256 
   250 		// Send a message to the aria-live region to announce how many search results.
   257 		/**
   251 		announceSearchMatches: _.debounce( function() {
   258 		 * Sends a message to the aria-live region to announce how many search results.
       
   259 		 */
       
   260 		announceSearchMatches: function() {
   252 			var message = l10n.widgetsFound.replace( '%d', this.searchMatchesCount ) ;
   261 			var message = l10n.widgetsFound.replace( '%d', this.searchMatchesCount ) ;
   253 
   262 
   254 			if ( ! this.searchMatchesCount ) {
   263 			if ( ! this.searchMatchesCount ) {
   255 				message = l10n.noWidgetsFound;
   264 				message = l10n.noWidgetsFound;
   256 			}
   265 			}
   257 
   266 
   258 			wp.a11y.speak( message );
   267 			wp.a11y.speak( message );
   259 		}, 500 ),
   268 		},
   260 
   269 
   261 		// Changes visibility of available widgets
   270 		/**
       
   271 		 * Changes visibility of available widgets.
       
   272  		 */
   262 		updateList: function() {
   273 		updateList: function() {
   263 			this.collection.each( function( widget ) {
   274 			this.collection.each( function( widget ) {
   264 				var widgetTpl = $( '#widget-tpl-' + widget.id );
   275 				var widgetTpl = $( '#widget-tpl-' + widget.id );
   265 				widgetTpl.toggle( widget.get( 'search_matched' ) && ! widget.get( 'is_disabled' ) );
   276 				widgetTpl.toggle( widget.get( 'search_matched' ) && ! widget.get( 'is_disabled' ) );
   266 				if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) {
   277 				if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) {
   267 					this.selected = null;
   278 					this.selected = null;
   268 				}
   279 				}
   269 			} );
   280 			} );
   270 		},
   281 		},
   271 
   282 
   272 		// Highlights a widget
   283 		/**
       
   284 		 * Highlights a widget.
       
   285  		 */
   273 		select: function( widgetTpl ) {
   286 		select: function( widgetTpl ) {
   274 			this.selected = $( widgetTpl );
   287 			this.selected = $( widgetTpl );
   275 			this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' );
   288 			this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' );
   276 			this.selected.addClass( 'selected' );
   289 			this.selected.addClass( 'selected' );
   277 		},
   290 		},
   278 
   291 
   279 		// Highlights a widget on focus
   292 		/**
       
   293 		 * Highlights a widget on focus.
       
   294 		 */
   280 		focus: function( event ) {
   295 		focus: function( event ) {
   281 			this.select( $( event.currentTarget ) );
   296 			this.select( $( event.currentTarget ) );
   282 		},
   297 		},
   283 
   298 
   284 		// Submit handler for keypress and click on widget
   299 		/**
       
   300 		 * Handles submit for keypress and click on widget.
       
   301 		 */
   285 		_submit: function( event ) {
   302 		_submit: function( event ) {
   286 			// Only proceed with keypress if it is Enter or Spacebar
   303 			// Only proceed with keypress if it is Enter or Spacebar
   287 			if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
   304 			if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
   288 				return;
   305 				return;
   289 			}
   306 			}
   290 
   307 
   291 			this.submit( $( event.currentTarget ) );
   308 			this.submit( $( event.currentTarget ) );
   292 		},
   309 		},
   293 
   310 
   294 		// Adds a selected widget to the sidebar
   311 		/**
       
   312 		 * Adds a selected widget to the sidebar.
       
   313  		 */
   295 		submit: function( widgetTpl ) {
   314 		submit: function( widgetTpl ) {
   296 			var widgetId, widget, widgetFormControl;
   315 			var widgetId, widget, widgetFormControl;
   297 
   316 
   298 			if ( ! widgetTpl ) {
   317 			if ( ! widgetTpl ) {
   299 				widgetTpl = this.selected;
   318 				widgetTpl = this.selected;
   317 			}
   336 			}
   318 
   337 
   319 			this.close();
   338 			this.close();
   320 		},
   339 		},
   321 
   340 
   322 		// Opens the panel
   341 		/**
       
   342 		 * Opens the panel.
       
   343 		 */
   323 		open: function( sidebarControl ) {
   344 		open: function( sidebarControl ) {
   324 			this.currentSidebarControl = sidebarControl;
   345 			this.currentSidebarControl = sidebarControl;
   325 
   346 
   326 			// Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens
   347 			// Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens
   327 			_( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) {
   348 			_( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) {
   344 			if ( ! api.settings.browser.mobile ) {
   365 			if ( ! api.settings.browser.mobile ) {
   345 				this.$search.focus();
   366 				this.$search.focus();
   346 			}
   367 			}
   347 		},
   368 		},
   348 
   369 
   349 		// Closes the panel
   370 		/**
       
   371 		 * Closes the panel.
       
   372 		 */
   350 		close: function( options ) {
   373 		close: function( options ) {
   351 			options = options || {};
   374 			options = options || {};
   352 
   375 
   353 			if ( options.returnFocus && this.currentSidebarControl ) {
   376 			if ( options.returnFocus && this.currentSidebarControl ) {
   354 				this.currentSidebarControl.container.find( '.add-new-widget' ).focus();
   377 				this.currentSidebarControl.container.find( '.add-new-widget' ).focus();
   360 			$( 'body' ).removeClass( 'adding-widget' );
   383 			$( 'body' ).removeClass( 'adding-widget' );
   361 
   384 
   362 			this.$search.val( '' );
   385 			this.$search.val( '' );
   363 		},
   386 		},
   364 
   387 
   365 		// Add keyboard accessiblity to the panel
   388 		/**
       
   389 		 * Adds keyboard accessiblity to the panel.
       
   390 		 */
   366 		keyboardAccessible: function( event ) {
   391 		keyboardAccessible: function( event ) {
   367 			var isEnter = ( event.which === 13 ),
   392 			var isEnter = ( event.which === 13 ),
   368 				isEsc = ( event.which === 27 ),
   393 				isEsc = ( event.which === 27 ),
   369 				isDown = ( event.which === 40 ),
   394 				isDown = ( event.which === 40 ),
   370 				isUp = ( event.which === 38 ),
   395 				isUp = ( event.which === 38 ),
   422 
   447 
   423 	/**
   448 	/**
   424 	 * Handlers for the widget-synced event, organized by widget ID base.
   449 	 * Handlers for the widget-synced event, organized by widget ID base.
   425 	 * Other widgets may provide their own update handlers by adding
   450 	 * Other widgets may provide their own update handlers by adding
   426 	 * listeners for the widget-synced event.
   451 	 * listeners for the widget-synced event.
       
   452 	 *
       
   453 	 * @alias    wp.customize.Widgets.formSyncHandlers
   427 	 */
   454 	 */
   428 	api.Widgets.formSyncHandlers = {
   455 	api.Widgets.formSyncHandlers = {
   429 
   456 
   430 		/**
   457 		/**
   431 		 * @param {jQuery.Event} e
   458 		 * @param {jQuery.Event} e
   444 				widget.find( '.widget-content:first' ).prepend( newWidgetError );
   471 				widget.find( '.widget-content:first' ).prepend( newWidgetError );
   445 			}
   472 			}
   446 		}
   473 		}
   447 	};
   474 	};
   448 
   475 
   449 	/**
   476 	api.Widgets.WidgetControl = api.Control.extend(/** @lends wp.customize.Widgets.WidgetControl.prototype */{
   450 	 * wp.customize.Widgets.WidgetControl
       
   451 	 *
       
   452 	 * Customizer control for widgets.
       
   453 	 * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type
       
   454 	 *
       
   455 	 * @constructor
       
   456 	 * @augments wp.customize.Control
       
   457 	 */
       
   458 	api.Widgets.WidgetControl = api.Control.extend({
       
   459 		defaultExpandedArguments: {
   477 		defaultExpandedArguments: {
   460 			duration: 'fast',
   478 			duration: 'fast',
   461 			completeCallback: $.noop
   479 			completeCallback: $.noop
   462 		},
   480 		},
   463 
   481 
   464 		/**
   482 		/**
       
   483 		 * wp.customize.Widgets.WidgetControl
       
   484 		 *
       
   485 		 * Customizer control for widgets.
       
   486 		 * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type
       
   487 		 *
   465 		 * @since 4.1.0
   488 		 * @since 4.1.0
       
   489 		 *
       
   490 		 * @constructs wp.customize.Widgets.WidgetControl
       
   491 		 * @augments   wp.customize.Control
   466 		 */
   492 		 */
   467 		initialize: function( id, options ) {
   493 		initialize: function( id, options ) {
   468 			var control = this;
   494 			var control = this;
   469 
   495 
   470 			control.widgetControlEmbedded = false;
   496 			control.widgetControlEmbedded = false;
   680 				}
   706 				}
   681 				self.expanded( ! self.expanded() );
   707 				self.expanded( ! self.expanded() );
   682 			} );
   708 			} );
   683 
   709 
   684 			$closeBtn = this.container.find( '.widget-control-close' );
   710 			$closeBtn = this.container.find( '.widget-control-close' );
   685 			$closeBtn.on( 'click', function( e ) {
   711 			$closeBtn.on( 'click', function() {
   686 				e.preventDefault();
       
   687 				self.collapse();
   712 				self.collapse();
   688 				self.container.find( '.widget-top .widget-action:first' ).focus(); // keyboard accessibility
   713 				self.container.find( '.widget-top .widget-action:first' ).focus(); // keyboard accessibility
   689 			} );
   714 			} );
   690 		},
   715 		},
   691 
   716 
   941 		 *
   966 		 *
   942 		 * @since 4.1.0
   967 		 * @since 4.1.0
   943 		 *
   968 		 *
   944 		 * @param {Boolean}   active
   969 		 * @param {Boolean}   active
   945 		 * @param {Object}    args
   970 		 * @param {Object}    args
   946 		 * @param {Callback}  args.completeCallback
   971 		 * @param {function}  args.completeCallback
   947 		 */
   972 		 */
   948 		onChangeActive: function ( active, args ) {
   973 		onChangeActive: function ( active, args ) {
   949 			// Note: there is a second 'args' parameter being passed, merged on top of this.defaultActiveArguments
   974 			// Note: there is a second 'args' parameter being passed, merged on top of this.defaultActiveArguments
   950 			this.container.toggleClass( 'widget-rendered', active );
   975 			this.container.toggleClass( 'widget-rendered', active );
   951 			if ( args.completeCallback ) {
   976 			if ( args.completeCallback ) {
   959 		_setupRemoveUI: function() {
   984 		_setupRemoveUI: function() {
   960 			var self = this, $removeBtn, replaceDeleteWithRemove;
   985 			var self = this, $removeBtn, replaceDeleteWithRemove;
   961 
   986 
   962 			// Configure remove button
   987 			// Configure remove button
   963 			$removeBtn = this.container.find( '.widget-control-remove' );
   988 			$removeBtn = this.container.find( '.widget-control-remove' );
   964 			$removeBtn.on( 'click', function( e ) {
   989 			$removeBtn.on( 'click', function() {
   965 				e.preventDefault();
       
   966 
       
   967 				// Find an adjacent element to add focus to when this widget goes away
   990 				// Find an adjacent element to add focus to when this widget goes away
   968 				var $adjacentFocusTarget;
   991 				var $adjacentFocusTarget;
   969 				if ( self.container.next().is( '.customize-control-widget_form' ) ) {
   992 				if ( self.container.next().is( '.customize-control-widget_form' ) ) {
   970 					$adjacentFocusTarget = self.container.next().find( '.widget-action:first' );
   993 					$adjacentFocusTarget = self.container.next().find( '.widget-action:first' );
   971 				} else if ( self.container.prev().is( '.customize-control-widget_form' ) ) {
   994 				} else if ( self.container.prev().is( '.customize-control-widget_form' ) ) {
  1572 	 * wp.customize.Widgets.WidgetsPanel
  1595 	 * wp.customize.Widgets.WidgetsPanel
  1573 	 *
  1596 	 *
  1574 	 * Customizer panel containing the widget area sections.
  1597 	 * Customizer panel containing the widget area sections.
  1575 	 *
  1598 	 *
  1576 	 * @since 4.4.0
  1599 	 * @since 4.4.0
       
  1600 	 *
       
  1601 	 * @class    wp.customize.Widgets.WidgetsPanel
       
  1602 	 * @augments wp.customize.Panel
  1577 	 */
  1603 	 */
  1578 	api.Widgets.WidgetsPanel = api.Panel.extend({
  1604 	api.Widgets.WidgetsPanel = api.Panel.extend(/** @lends wp.customize.Widgets.WigetsPanel.prototype */{
  1579 
  1605 
  1580 		/**
  1606 		/**
  1581 		 * Add and manage the display of the no-rendered-areas notice.
  1607 		 * Add and manage the display of the no-rendered-areas notice.
  1582 		 *
  1608 		 *
  1583 		 * @since 4.4.0
  1609 		 * @since 4.4.0
  1602 				 *
  1628 				 *
  1603 				 * @return {number} Number of active sidebar sections.
  1629 				 * @return {number} Number of active sidebar sections.
  1604 				 */
  1630 				 */
  1605 				getActiveSectionCount = function() {
  1631 				getActiveSectionCount = function() {
  1606 					return _.filter( panel.sections(), function( section ) {
  1632 					return _.filter( panel.sections(), function( section ) {
  1607 						return section.active();
  1633 						return 'sidebar' === section.params.type && section.active();
  1608 					} ).length;
  1634 					} ).length;
  1609 				};
  1635 				};
  1610 
  1636 
  1611 				/**
  1637 				/**
  1612 				 * Determine whether or not the notice should be displayed.
  1638 				 * Determine whether or not the notice should be displayed.
  1693 	 * wp.customize.Widgets.SidebarSection
  1719 	 * wp.customize.Widgets.SidebarSection
  1694 	 *
  1720 	 *
  1695 	 * Customizer section representing a widget area widget
  1721 	 * Customizer section representing a widget area widget
  1696 	 *
  1722 	 *
  1697 	 * @since 4.1.0
  1723 	 * @since 4.1.0
       
  1724 	 *
       
  1725 	 * @class    wp.customize.Widgets.SidebarSection
       
  1726 	 * @augments wp.customize.Section
  1698 	 */
  1727 	 */
  1699 	api.Widgets.SidebarSection = api.Section.extend({
  1728 	api.Widgets.SidebarSection = api.Section.extend(/** @lends wp.customize.Widgets.SidebarSection.prototype */{
  1700 
  1729 
  1701 		/**
  1730 		/**
  1702 		 * Sync the section's active state back to the Backbone model's is_rendered attribute
  1731 		 * Sync the section's active state back to the Backbone model's is_rendered attribute
  1703 		 *
  1732 		 *
  1704 		 * @since 4.1.0
  1733 		 * @since 4.1.0
  1720 	 * Customizer control for widgets.
  1749 	 * Customizer control for widgets.
  1721 	 * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type
  1750 	 * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type
  1722 	 *
  1751 	 *
  1723 	 * @since 3.9.0
  1752 	 * @since 3.9.0
  1724 	 *
  1753 	 *
  1725 	 * @constructor
  1754 	 * @class    wp.customize.Widgets.SidebarControl
  1726 	 * @augments wp.customize.Control
  1755 	 * @augments wp.customize.Control
  1727 	 */
  1756 	 */
  1728 	api.Widgets.SidebarControl = api.Control.extend({
  1757 	api.Widgets.SidebarControl = api.Control.extend(/** @lends wp.customize.Widgets.SidebarControl.prototype */{
  1729 
  1758 
  1730 		/**
  1759 		/**
  1731 		 * Set up the control
  1760 		 * Set up the control
  1732 		 */
  1761 		 */
  1733 		ready: function() {
  1762 		ready: function() {