Make WordPress Core

Changeset 41726


Ignore:
Timestamp:
10/04/2017 06:47:37 AM (7 years ago)
Author:
westonruter
Message:

Customize: Improve usability of Customize JS API.

  • Eliminate need to pass both ID and instance in calls to Values#add() for panels, sections, controls, settings, partials, and notifications.
  • Eliminate need to supply content param when constructing a Control.
  • Unwrap the options.params object passed in constructors to just pass a flat options. (Back-compat is maintained.)
  • Add support for templateId param for Control to override which template is used for the content.
  • Remove unused previewer being supplied in Control instances.
  • Rename classes to containerClasses on Notification.
  • Automatically supply instanceNumber to improve stable sorting.
  • Use api.Notifications for notifications in settings instead of api.Value.

See #30741.
Fixes #42083.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/customize-controls.js

    r41709 r41726  
    3131            var notification = this;
    3232            api.Notification.prototype.initialize.call( notification, code, params );
    33             notification.classes += ' notification-overlay';
     33            notification.containerClasses += ' notification-overlay';
    3434            if ( notification.loading ) {
    35                 notification.classes += ' notification-loading';
     35                notification.containerClasses += ' notification-loading';
    3636            }
    3737        }
     
    106106         *
    107107         * @since 4.9.0
    108          * @param {string} code - Notification code.
    109          * @param {object} params - Notification params.
    110          * @return {api.Notification} Added instance (or existing instance if it was already added).
    111          */
    112         add: function( code, params ) {
    113             var collection = this;
     108         *
     109         * @param {string|wp.customize.Notification} - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
     110         * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string.
     111         * @returns {wp.customize.Notification} Added notification (or existing instance if it was already added).
     112         */
     113        add: function( notification, notificationObject ) {
     114            var collection = this, code, instance;
     115            if ( 'string' === typeof notification ) {
     116                code = notification;
     117                instance = notificationObject;
     118            } else {
     119                code = notification.code;
     120                instance = notification;
     121            }
    114122            if ( ! collection.has( code ) ) {
    115123                collection._addedIncrement += 1;
    116124                collection._addedOrder[ code ] = collection._addedIncrement;
    117125            }
    118             return api.Values.prototype.add.call( this, code, params );
     126            return api.Values.prototype.add.call( collection, code, instance );
    119127        },
    120128
     
    270278            setting.transport = setting.transport || 'refresh';
    271279            setting._dirty = options.dirty || false;
    272             setting.notifications = new api.Values({ defaultConstructor: api.Notification });
     280            setting.notifications = new api.Notifications();
    273281
    274282            // Whenever the setting's value changes, refresh the preview.
     
    746754         * @param {string}         id - The ID for the container.
    747755         * @param {object}         options - Object containing one property: params.
    748          * @param {object}         options.params - Object containing the following properties.
    749          * @param {string}         options.params.title - Title shown when panel is collapsed and expanded.
    750          * @param {string=}        [options.params.description] - Description shown at the top of the panel.
    751          * @param {number=100}     [options.params.priority] - The sort priority for the panel.
    752          * @param {string=default} [options.params.type] - The type of the panel. See wp.customize.panelConstructor.
    753          * @param {string=}        [options.params.content] - The markup to be used for the panel container. If empty, a JS template is used.
    754          * @param {boolean=true}   [options.params.active] - Whether the panel is active or not.
     756         * @param {string}         options.title - Title shown when panel is collapsed and expanded.
     757         * @param {string=}        [options.description] - Description shown at the top of the panel.
     758         * @param {number=100}     [options.priority] - The sort priority for the panel.
     759         * @param {string}         [options.templateId] - Template selector for container.
     760         * @param {string=default} [options.type] - The type of the panel. See wp.customize.panelConstructor.
     761         * @param {string=}        [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
     762         * @param {boolean=true}   [options.active] - Whether the panel is active or not.
     763         * @param {object}         [options.params] - Deprecated wrapper for the above properties.
    755764         */
    756765        initialize: function ( id, options ) {
    757766            var container = this;
    758767            container.id = id;
    759             options = options || {};
    760 
    761             options.params = _.defaults(
    762                 options.params || {},
    763                 container.defaults
    764             );
    765 
    766             $.extend( container, options );
     768
     769            if ( ! Container.instanceCounter ) {
     770                Container.instanceCounter = 0;
     771            }
     772            Container.instanceCounter++;
     773
     774            $.extend( container, {
     775                params: _.defaults(
     776                    options.params || options, // Passing the params is deprecated.
     777                    container.defaults
     778                )
     779            } );
     780            if ( ! container.params.instanceNumber ) {
     781                container.params.instanceNumber = Container.instanceCounter;
     782            }
    767783            container.notifications = new api.Notifications();
    768             container.templateSelector = 'customize-' + container.containerType + '-' + container.params.type;
     784            container.templateSelector = container.params.templateId || 'customize-' + container.containerType + '-' + container.params.type;
    769785            container.container = $( container.params.content );
    770786            if ( 0 === container.container.length ) {
     
    12071223         *
    12081224         * @param {string}         id - The ID for the section.
    1209          * @param {object}         options - Object containing one property: params.
    1210          * @param {object}         options.params - Object containing the following properties.
    1211          * @param {string}         options.params.title - Title shown when section is collapsed and expanded.
    1212          * @param {string=}        [options.params.description] - Description shown at the top of the section.
    1213          * @param {number=100}     [options.params.priority] - The sort priority for the section.
    1214          * @param {string=default} [options.params.type] - The type of the section. See wp.customize.sectionConstructor.
    1215          * @param {string=}        [options.params.content] - The markup to be used for the section container. If empty, a JS template is used.
    1216          * @param {boolean=true}   [options.params.active] - Whether the section is active or not.
    1217          * @param {string}         options.params.panel - The ID for the panel this section is associated with.
    1218          * @param {string=}        [options.params.customizeAction] - Additional context information shown before the section title when expanded.
     1225         * @param {object}         options - Options.
     1226         * @param {string}         options.title - Title shown when section is collapsed and expanded.
     1227         * @param {string=}        [options.description] - Description shown at the top of the section.
     1228         * @param {number=100}     [options.priority] - The sort priority for the section.
     1229         * @param {string=default} [options.type] - The type of the section. See wp.customize.sectionConstructor.
     1230         * @param {string=}        [options.content] - The markup to be used for the section container. If empty, a JS template is used.
     1231         * @param {boolean=true}   [options.active] - Whether the section is active or not.
     1232         * @param {string}         options.panel - The ID for the panel this section is associated with.
     1233         * @param {string=}        [options.customizeAction] - Additional context information shown before the section title when expanded.
     1234         * @param {object}         [options.params] - Deprecated wrapper for the above properties.
    12191235         */
    12201236        initialize: function ( id, options ) {
     
    18391855            request = wp.ajax.post( 'customize_load_themes', params );
    18401856            request.done(function( data ) {
    1841                 var themes = data.themes, themeControl, newThemeControls;
     1857                var themes = data.themes, newThemeControls;
    18421858
    18431859                // Stop and try again if the term changed while loading.
     
    18611877                    // Add controls for each theme.
    18621878                    _.each( themes, function( theme ) {
    1863                         var customizeId = section.params.action + '_theme_' + theme.id;
    1864                         themeControl = new api.controlConstructor.theme( customizeId, {
    1865                             params: {
    1866                                 type: 'theme',
    1867                                 content: '<li id="customize-control-theme-' + section.params.action + '_' + theme.id + '" class="customize-control customize-control-theme"></li>',
    1868                                 section: section.params.id,
    1869                                 active: true,
    1870                                 theme: theme,
    1871                                 priority: section.loaded + 1
    1872                             },
    1873                             previewer: api.previewer
     1879                        var themeControl = new api.controlConstructor.theme( section.params.action + '_theme_' + theme.id, {
     1880                            type: 'theme',
     1881                            section: section.params.id,
     1882                            theme: theme,
     1883                            priority: section.loaded + 1
    18741884                        } );
    18751885
    1876                         api.control.add( customizeId, themeControl );
     1886                        api.control.add( themeControl );
    18771887                        newThemeControls.push( themeControl );
    18781888                        section.loaded = section.loaded + 1;
     
    24832493         * @param {string}         id - The ID for the panel.
    24842494         * @param {object}         options - Object containing one property: params.
    2485          * @param {object}         options.params - Object containing the following properties.
    2486          * @param {string}         options.params.title - Title shown when panel is collapsed and expanded.
    2487          * @param {string=}        [options.params.description] - Description shown at the top of the panel.
    2488          * @param {number=100}     [options.params.priority] - The sort priority for the panel.
    2489          * @param {string=default} [options.params.type] - The type of the panel. See wp.customize.panelConstructor.
    2490          * @param {string=}        [options.params.content] - The markup to be used for the panel container. If empty, a JS template is used.
    2491          * @param {boolean=true}   [options.params.active] - Whether the panel is active or not.
     2495         * @param {string}         options.title - Title shown when panel is collapsed and expanded.
     2496         * @param {string=}        [options.description] - Description shown at the top of the panel.
     2497         * @param {number=100}     [options.priority] - The sort priority for the panel.
     2498         * @param {string=default} [options.type] - The type of the panel. See wp.customize.panelConstructor.
     2499         * @param {string=}        [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
     2500         * @param {boolean=true}   [options.active] - Whether the panel is active or not.
     2501         * @param {object}         [options.params] - Deprecated wrapper for the above properties.
    24922502         */
    24932503        initialize: function ( id, options ) {
     
    28572867
    28582868            $( document ).one( 'wp-theme-install-success', function( event, response ) {
    2859                 var theme = false, customizeId, themeControl;
     2869                var theme = false, themeControl;
    28602870                if ( preview ) {
    28612871                    api.notifications.remove( 'theme_installing' );
     
    28782888                    // Add theme control to installed section.
    28792889                    theme.type = 'installed';
    2880                     customizeId = 'installed_theme_' + theme.id;
    2881                     themeControl = new api.controlConstructor.theme( customizeId, {
    2882                         params: {
    2883                             type: 'theme',
    2884                             content: $( '<li class="customize-control customize-control-theme"></li>' ).attr( 'id', 'customize-control-theme-installed_' + theme.id ).prop( 'outerHTML' ),
    2885                             section: 'installed_themes',
    2886                             active: true,
    2887                             theme: theme,
    2888                             priority: 0 // Add all newly-installed themes to the top.
    2889                         },
    2890                         previewer: api.previewer
     2890                    themeControl = new api.controlConstructor.theme( 'installed_theme_' + theme.id, {
     2891                        type: 'theme',
     2892                        section: 'installed_themes',
     2893                        theme: theme,
     2894                        priority: 0 // Add all newly-installed themes to the top.
    28912895                    } );
    28922896
    2893                     api.control.add( customizeId, themeControl );
    2894                     api.control( customizeId ).container.trigger( 'render-screenshot' );
     2897                    api.control.add( themeControl );
     2898                    api.control( themeControl.id ).container.trigger( 'render-screenshot' );
    28952899
    28962900                    // Close the details modal if it's open to the installed theme.
     
    29142918                preview = true;
    29152919
    2916                 api.notifications.add( 'theme_installing', new api.OverlayNotification( 'theme_installing', {
     2920                api.notifications.add( new api.OverlayNotification( 'theme_installing', {
    29172921                    message: api.l10n.themeDownloading,
    29182922                    type: 'info',
     
    29512955
    29522956            // Update loading message. Everything else is handled by reloading the page.
    2953             api.notifications.add( 'theme_previewing', new api.OverlayNotification( 'theme_previewing', {
     2957            api.notifications.add( new api.OverlayNotification( 'theme_previewing', {
    29542958                message: api.l10n.themePreviewWait,
    29552959                type: 'info',
     
    30773081     * @augments wp.customize.Class
    30783082     *
    3079      * @param {string} id                              Unique identifier for the control instance.
    3080      * @param {object} options                         Options hash for the control instance.
    3081      * @param {object} options.params
    3082      * @param {object} options.params.type             Type of control (e.g. text, radio, dropdown-pages, etc.)
    3083      * @param {string} options.params.content          The HTML content for the control.
    3084      * @param {string} options.params.priority         Order of priority to show the control within the section.
    3085      * @param {string} options.params.active
    3086      * @param {string} options.params.section          The ID of the section the control belongs to.
    3087      * @param {string} options.params.settings.default The ID of the setting the control relates to.
    3088      * @param {string} options.params.settings.data
    3089      * @param {string} options.params.label
    3090      * @param {string} options.params.description
    3091      * @param {string} options.params.instanceNumber Order in which this instance was created in relation to other instances.
     3083     * @param {string} id                       - Unique identifier for the control instance.
     3084     * @param {object} options                  - Options hash for the control instance.
     3085     * @param {object} options.type             - Type of control (e.g. text, radio, dropdown-pages, etc.)
     3086     * @param {string} [options.content]        - The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId.
     3087     * @param {string} [options.templateId]     - Template ID for control's content.
     3088     * @param {string} [options.priority=10]    - Order of priority to show the control within the section.
     3089     * @param {string} [options.active=true]    - Whether the control is active.
     3090     * @param {string} options.section          - The ID of the section the control belongs to.
     3091     * @param {string} options.settings.default - The ID of the setting the control relates to.
     3092     * @param {string} options.settings.data
     3093     * @param {string} options.label            - Label.
     3094     * @param {string} options.description      - Description.
     3095     * @param {number} [options.instanceNumber] - Order in which this instance was created in relation to other instances.
     3096     * @param {object} [options.params]         - Deprecated wrapper for the above properties.
    30923097     */
    30933098    api.Control = api.Class.extend({
    30943099        defaultActiveArguments: { duration: 'fast', completeCallback: $.noop },
    30953100
     3101        defaults: {
     3102            active: true,
     3103            priority: 10
     3104        },
     3105
    30963106        initialize: function( id, options ) {
    30973107            var control = this,
    30983108                nodes, radios, settings;
    30993109
    3100             control.params = {};
    3101             $.extend( control, options || {} );
     3110            control.params = _.extend( {}, control.defaults );
     3111
     3112            if ( ! api.Control.instanceCounter ) {
     3113                api.Control.instanceCounter = 0;
     3114            }
     3115            api.Control.instanceCounter++;
     3116            if ( ! control.params.instanceNumber ) {
     3117                control.params.instanceNumber = api.Control.instanceCounter;
     3118            }
     3119
     3120            _.extend( control.params, options.params || options );
     3121            if ( ! control.params.content ) {
     3122                control.params.content = $( '<li></li>', {
     3123                    id: 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ),
     3124                    'class': 'customize-control customize-control-' + control.params.type
     3125                } );
     3126            }
     3127
    31023128            control.id = id;
    3103             control.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' );
    3104             control.templateSelector = 'customize-control-' + control.params.type + '-content';
    3105             control.container = control.params.content ? $( control.params.content ) : $( control.selector );
     3129            control.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' ); // Deprecated, likely dead code from time before #28709.
     3130            control.templateSelector = control.params.templateId || 'customize-control-' + control.params.type + '-content';
     3131            if ( control.params.content ) {
     3132                control.container = $( control.params.content );
     3133            } else {
     3134                control.container = $( control.selector ); // Likely dead, per above. See #28709.
     3135            }
    31063136
    31073137            control.deferred = {
     
    31813211                    _.each( control.settings, function( setting ) {
    31823212                        setting.notifications.bind( 'add', function( settingNotification ) {
    3183                             var controlNotification, code, params;
    3184                             code = setting.id + ':' + settingNotification.code;
    3185                             params = _.extend(
     3213                            var params = _.extend(
    31863214                                {},
    31873215                                settingNotification,
     
    31903218                                }
    31913219                            );
    3192                             controlNotification = new api.Notification( code, params );
    3193                             control.notifications.add( controlNotification.code, controlNotification );
     3220                            control.notifications.add( new api.Notification( setting.id + ':' + settingNotification.code, params ) );
    31943221                        } );
    31953222                        setting.notifications.bind( 'remove', function( settingNotification ) {
     
    34733500        _toggleActive: Container.prototype._toggleActive,
    34743501
     3502        // @todo This function appears to be dead code and can be removed.
    34753503        dropdownInit: function() {
    34763504            var control      = this,
     
    34793507                toggleFreeze = false,
    34803508                update       = function( to ) {
    3481                     if ( typeof to === 'string' && params.statuses && params.statuses[ to ] )
     3509                    if ( 'string' === typeof to && params.statuses && params.statuses[ to ] ) {
    34823510                        statuses.html( params.statuses[ to ] ).show();
    3483                     else
     3511                    } else {
    34843512                        statuses.hide();
     3513                    }
    34853514                };
    34863515
     
    34933522                event.preventDefault();
    34943523
    3495                 if (!toggleFreeze)
    3496                     control.container.toggleClass('open');
    3497 
    3498                 if ( control.container.hasClass('open') )
    3499                     control.container.parent().parent().find('li.library-selected').focus();
     3524                if ( ! toggleFreeze ) {
     3525                    control.container.toggleClass( 'open' );
     3526                }
     3527
     3528                if ( control.container.hasClass( 'open' ) ) {
     3529                    control.container.parent().parent().find( 'li.library-selected' ).focus();
     3530                }
    35003531
    35013532                // Don't want to fire focus and click at same time
     
    48704901                    message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
    48714902                }
    4872                 control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
     4903                control.setting.notifications.add( new api.Notification( 'csslint_error', {
    48734904                    message: message,
    48744905                    type: 'error'
     
    52575288                    message: api.l10n.futureDateError
    52585289                } );
    5259                 control.notifications.add( notificationCode, notification );
     5290                control.notifications.add( notification );
    52605291            } else {
    52615292                control.notifications.remove( notificationCode );
     
    52765307    api.PreviewLinkControl = api.Control.extend({
    52775308
    5278         /**
    5279          * Override the templateSelector before embedding the control into the page.
    5280          *
    5281          * @since 4.9.0
    5282          * @return {void}
    5283          */
    5284         embed: function() {
    5285             var control = this;
    5286             control.templateSelector = 'customize-preview-link-control';
    5287             return api.Control.prototype.embed.apply( control, arguments );
    5288         },
     5309        defaults: _.extend( {}, api.Control.prototype.defaults, {
     5310            templateId: 'customize-preview-link-control'
     5311        } ),
    52895312
    52905313        /**
     
    53875410                    message: api.l10n.saveBeforeShare
    53885411                } );
    5389                 control.notifications.add( notificationCode, notification );
     5412                control.notifications.add( notification );
    53905413            } else {
    53915414                control.notifications.remove( notificationCode );
     
    60156038                deferred, messenger, iframe;
    60166039
    6017             if ( this._login )
     6040            if ( this._login ) {
    60186041                return this._login;
     6042            }
    60196043
    60206044            deferred = $.Deferred();
     
    61426166
    61436167                        if ( ! setting.notifications.has( notification.code ) ) {
    6144                             setting.notifications.add( code, notification );
     6168                            setting.notifications.add( notification );
    61456169                        }
    61466170                        invalidSettings.push( setting.id );
     
    63326356
    63336357        api.section( 'publish_settings', function( section ) {
    6334             var updateButtonsState, previewLinkControl, TrashControl, trashControlInstance, trashControlId = 'trash_changeset', previewLinkControlId = 'changeset_preview_link', updateSectionActive, isSectionActive;
    6335 
    6336             TrashControl = api.Control.extend( {
    6337 
    6338                 // This is a temporary hack while waiting for richer JS templating and dynamic instantiation.
    6339                 embed: function() {
    6340                     var control = this;
    6341                     control.templateSelector = 'customize-trash-changeset-control';
    6342                     return api.Control.prototype.embed.apply( control, arguments );
    6343                 }
     6358            var updateButtonsState, trashControl, updateSectionActive, isSectionActive;
     6359
     6360            trashControl = new api.Control( 'trash_changeset', {
     6361                type: 'button',
     6362                section: section.id,
     6363                priority: 30,
     6364                templateId: 'customize-trash-changeset-control'
    63446365            } );
    6345 
    6346             trashControlInstance = new TrashControl( trashControlId, {
    6347                 params: {
    6348                     type: 'button',
    6349                     section: section.id,
    6350                     active: true,
    6351                     priority: 30,
    6352                     content: '<li id="customize-control-' + trashControlId + '" class="customize-control"></li>'
    6353                 }
    6354             } );
    6355             api.control.add( trashControlId, trashControlInstance );
    6356             trashControlInstance.deferred.embedded.done( function() {
    6357                 trashControlInstance.container.find( 'button' ).on( 'click', function() {
     6366            api.control.add( trashControl );
     6367            trashControl.deferred.embedded.done( function() {
     6368                trashControl.container.find( 'button' ).on( 'click', function() {
    63586369                    if ( confirm( api.l10n.trashConfirm ) ) {
    63596370                        wp.customize.previewer.trash();
     
    63626373            } );
    63636374
    6364             previewLinkControl = new api.PreviewLinkControl( previewLinkControlId, {
    6365                 params: {
    6366                     section: section.id,
    6367                     active: true,
    6368                     priority: 100,
    6369                     content: '<li id="customize-control-' + previewLinkControlId + '" class="customize-control"></li>'
    6370                 }
    6371             } );
    6372 
    6373             api.control.add( previewLinkControlId, previewLinkControl );
     6375            api.control.add( new api.PreviewLinkControl( 'changeset_preview_link', {
     6376                section: section.id,
     6377                priority: 100
     6378            } ) );
    63746379
    63756380            /**
     
    65896594
    65906595                        if ( invalidSettings.length ) {
    6591                             api.notifications.add( errorCode, new api.Notification( errorCode, {
     6596                            api.notifications.add( new api.Notification( errorCode, {
    65926597                                message: ( 1 === invalidSettings.length ? api.l10n.saveBlockedError.singular : api.l10n.saveBlockedError.plural ).replace( /%s/g, String( invalidSettings.length ) ),
    65936598                                type: 'error',
     
    66916696
    66926697                        if ( notification ) {
    6693                             api.notifications.add( notification.code, notification );
     6698                            api.notifications.add( notification );
    66946699                        }
    66956700
     
    67966801                    nonce: api.settings.nonce.trash
    67976802                } );
    6798                 api.notifications.add( 'changeset_trashing', new api.OverlayNotification( 'changeset_trashing', {
     6803                api.notifications.add( new api.OverlayNotification( 'changeset_trashing', {
    67996804                    type: 'info',
    68006805                    message: api.l10n.revertingChanges,
     
    68246829                    api.state( 'trashing' ).set( false );
    68256830                    api.notifications.remove( 'changeset_trashing' );
    6826                     api.notifications.add( notificationCode, new api.Notification( notificationCode, {
     6831                    api.notifications.add( new api.Notification( notificationCode, {
    68276832                        message: message || api.l10n.unknownError,
    68286833                        dismissible: true,
     
    68926897        // Create Settings
    68936898        $.each( api.settings.settings, function( id, data ) {
    6894             var constructor = api.settingConstructor[ data.type ] || api.Setting,
    6895                 setting;
    6896 
    6897             setting = new constructor( id, data.value, {
     6899            var Constructor = api.settingConstructor[ data.type ] || api.Setting;
     6900            api.add( new Constructor( id, data.value, {
    68986901                transport: data.transport,
    68996902                previewer: api.previewer,
    69006903                dirty: !! data.dirty
    6901             } );
    6902             api.add( id, setting );
     6904            } ) );
    69036905        });
    69046906
    69056907        // Create Panels
    69066908        $.each( api.settings.panels, function ( id, data ) {
    6907             var constructor = api.panelConstructor[ data.type ] || api.Panel,
    6908                 panel;
    6909 
    6910             panel = new constructor( id, {
    6911                 params: data
    6912             } );
    6913             api.panel.add( id, panel );
     6909            var Constructor = api.panelConstructor[ data.type ] || api.Panel;
     6910            api.panel.add( new Constructor( id, data ) );
    69146911        });
    69156912
    69166913        // Create Sections
    69176914        $.each( api.settings.sections, function ( id, data ) {
    6918             var constructor = api.sectionConstructor[ data.type ] || api.Section,
    6919                 section;
    6920 
    6921             section = new constructor( id, {
    6922                 params: data
    6923             } );
    6924             api.section.add( id, section );
     6915            var Constructor = api.sectionConstructor[ data.type ] || api.Section;
     6916            api.section.add( new Constructor( id, data ) );
    69256917        });
    69266918
    69276919        // Create Controls
    69286920        $.each( api.settings.controls, function( id, data ) {
    6929             var constructor = api.controlConstructor[ data.type ] || api.Control,
    6930                 control;
    6931 
    6932             control = new constructor( id, {
    6933                 params: data,
    6934                 previewer: api.previewer
    6935             } );
    6936             api.control.add( id, control );
     6921            var Constructor = api.controlConstructor[ data.type ] || api.Control;
     6922            api.control.add( new Constructor( id, data ) );
    69376923        });
    69386924
     
    72417227
    72427228                // Since there is an autosave revision and the user hasn't loaded with autosaved, add notification to prompt to load autosaved version.
    7243                 api.notifications.add( code, new api.Notification( code, {
     7229                api.notifications.add( new api.Notification( code, {
    72447230                    message: api.l10n.autosaveNotice,
    72457231                    type: 'warning',
     
    78947880
    78957881            control.element.bind( function( to ) {
    7896                 if ( ! to )
     7882                if ( ! to ) {
    78977883                    last = api( 'header_textcolor' ).get();
     7884                }
    78987885
    78997886                control.setting.set( to ? last : 'blank' );
     
    79277914                // Toggle notification when the homepage and posts page are both set and the same.
    79287915                if ( 'page' === showOnFront() && pageOnFrontId && pageForPostsId && pageOnFrontId === pageForPostsId ) {
    7929                     showOnFront.notifications.add( errorCode, new api.Notification( errorCode, {
     7916                    showOnFront.notifications.add( new api.Notification( errorCode, {
    79307917                        type: 'error',
    79317918                        message: api.l10n.pageOnFrontError
     
    80788065                        section.notifications.remove( noticeCode );
    80798066                    } else {
    8080                         section.notifications.add( noticeCode, new api.Notification( noticeCode, {
     8067                        section.notifications.add( new api.Notification( noticeCode, {
    80818068                            type: 'info',
    80828069                            message: api.l10n.videoHeaderNotice
  • trunk/src/wp-admin/js/customize-nav-menus.js

    r41697 r41726  
    969969            if ( ! menuNameControl ) {
    970970                menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, {
    971                     params: {
    972                         type: 'nav_menu_name',
    973                         content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '-name" class="customize-control customize-control-nav_menu_name"></li>', // @todo core should do this for us; see #30741
    974                         label: api.Menus.data.l10n.menuNameLabel,
    975                         active: true,
    976                         section: section.id,
    977                         priority: 0,
    978                         settings: {
    979                             'default': section.id
    980                         }
     971                    type: 'nav_menu_name',
     972                    label: api.Menus.data.l10n.menuNameLabel,
     973                    section: section.id,
     974                    priority: 0,
     975                    settings: {
     976                        'default': section.id
    981977                    }
    982978                } );
    983                 api.control.add( menuNameControl.id, menuNameControl );
     979                api.control.add( menuNameControl );
    984980                menuNameControl.active.set( true );
    985981            }
     
    989985            if ( ! menuControl ) {
    990986                menuControl = new api.controlConstructor.nav_menu( section.id, {
    991                     params: {
    992                         type: 'nav_menu',
    993                         content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '" class="customize-control customize-control-nav_menu"></li>', // @todo core should do this for us; see #30741
    994                         section: section.id,
    995                         priority: 998,
    996                         active: true,
    997                         settings: {
    998                             'default': section.id
    999                         },
    1000                         menu_id: section.params.menu_id
    1001                     }
     987                    type: 'nav_menu',
     988                    section: section.id,
     989                    priority: 998,
     990                    settings: {
     991                        'default': section.id
     992                    },
     993                    menu_id: section.params.menu_id
    1002994                } );
    1003                 api.control.add( menuControl.id, menuControl );
     995                api.control.add( menuControl );
    1004996                menuControl.active.set( true );
    1005997            }
     
    10101002            if ( ! menuAutoAddControl ) {
    10111003                menuAutoAddControl = new api.controlConstructor.nav_menu_auto_add( menuAutoAddControlId, {
    1012                     params: {
    1013                         type: 'nav_menu_auto_add',
    1014                         content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '-auto-add" class="customize-control customize-control-nav_menu_auto_add"></li>', // @todo core should do this for us
    1015                         label: '',
    1016                         active: true,
    1017                         section: section.id,
    1018                         priority: 999,
    1019                         settings: {
    1020                             'default': section.id
    1021                         }
     1004                    type: 'nav_menu_auto_add',
     1005                    label: '',
     1006                    section: section.id,
     1007                    priority: 999,
     1008                    settings: {
     1009                        'default': section.id
    10221010                    }
    10231011                } );
    1024                 api.control.add( menuAutoAddControl.id, menuAutoAddControl );
     1012                api.control.add( menuAutoAddControl );
    10251013                menuAutoAddControl.active.set( true );
    10261014            }
     
    26782666            // Add the menu item control.
    26792667            menuItemControl = new api.controlConstructor.nav_menu_item( customizeId, {
    2680                 params: {
    2681                     type: 'nav_menu_item',
    2682                     content: '<li id="customize-control-nav_menu_item-' + String( placeholderId ) + '" class="customize-control customize-control-nav_menu_item"></li>',
    2683                     section: menuControl.id,
    2684                     priority: priority,
    2685                     active: true,
    2686                     settings: {
    2687                         'default': customizeId
    2688                     },
    2689                     menu_item_id: placeholderId
     2668                type: 'nav_menu_item',
     2669                section: menuControl.id,
     2670                priority: priority,
     2671                settings: {
     2672                    'default': customizeId
    26902673                },
    2691                 previewer: api.previewer
     2674                menu_item_id: placeholderId
    26922675            } );
    26932676
    2694             api.control.add( customizeId, menuItemControl );
     2677            api.control.add( menuItemControl );
    26952678            setting.preview();
    26962679            menuControl.debouncedReflowMenuItems();
     
    27762759             */
    27772760            menuSection = new api.Menus.MenuSection( customizeId, {
    2778                 params: {
    2779                     id: customizeId,
    2780                     panel: 'nav_menus',
    2781                     title: displayNavMenuName( name ),
    2782                     customizeAction: api.Menus.data.l10n.customizingMenus,
    2783                     type: 'nav_menu',
    2784                     priority: 10,
    2785                     menu_id: placeholderId
    2786                 }
     2761                panel: 'nav_menus',
     2762                title: displayNavMenuName( name ),
     2763                customizeAction: api.Menus.data.l10n.customizingMenus,
     2764                type: 'nav_menu',
     2765                priority: 10,
     2766                menu_id: placeholderId
    27872767            } );
    2788             api.section.add( customizeId, menuSection );
     2768            api.section.add( menuSection );
    27892769
    27902770            // Clear name field.
     
    29102890                // Add the menu section.
    29112891                newSection = new api.Menus.MenuSection( newCustomizeId, {
    2912                     params: {
    2913                         id: newCustomizeId,
    2914                         panel: 'nav_menus',
    2915                         title: settingValue.name,
    2916                         customizeAction: api.Menus.data.l10n.customizingMenus,
    2917                         type: 'nav_menu',
    2918                         priority: oldSection.priority.get(),
    2919                         active: true,
    2920                         menu_id: update.term_id
    2921                     }
     2892                    panel: 'nav_menus',
     2893                    title: settingValue.name,
     2894                    customizeAction: api.Menus.data.l10n.customizingMenus,
     2895                    type: 'nav_menu',
     2896                    priority: oldSection.priority.get(),
     2897                    menu_id: update.term_id
    29222898                } );
    29232899
    29242900                // Add new control for the new menu.
    2925                 api.section.add( newCustomizeId, newSection );
     2901                api.section.add( newSection );
    29262902
    29272903                // Update the values for nav menus in Custom Menu controls.
     
    30533029                // Add the menu control.
    30543030                newControl = new api.controlConstructor.nav_menu_item( newCustomizeId, {
    3055                     params: {
    3056                         type: 'nav_menu_item',
    3057                         content: '<li id="customize-control-nav_menu_item-' + String( update.post_id ) + '" class="customize-control customize-control-nav_menu_item"></li>',
    3058                         menu_id: update.post_id,
    3059                         section: 'nav_menu[' + String( settingValue.nav_menu_term_id ) + ']',
    3060                         priority: oldControl.priority.get(),
    3061                         active: true,
    3062                         settings: {
    3063                             'default': newCustomizeId
    3064                         },
    3065                         menu_item_id: update.post_id
     3031                    type: 'nav_menu_item',
     3032                    menu_id: update.post_id,
     3033                    section: 'nav_menu[' + String( settingValue.nav_menu_term_id ) + ']',
     3034                    priority: oldControl.priority.get(),
     3035                    settings: {
     3036                        'default': newCustomizeId
    30663037                    },
    3067                     previewer: api.previewer
     3038                    menu_item_id: update.post_id
    30683039                } );
    30693040
     
    30733044
    30743045                // Add new control to take its place.
    3075                 api.control.add( newCustomizeId, newControl );
     3046                api.control.add( newControl );
    30763047
    30773048                // Delete the placeholder and preview the new setting.
  • trunk/src/wp-admin/js/customize-widgets.js

    r41374 r41726  
    20992099            controlConstructor = api.controlConstructor[controlType];
    21002100            widgetFormControl = new controlConstructor( settingId, {
    2101                 params: {
    2102                     settings: {
    2103                         'default': settingId
    2104                     },
    2105                     content: controlContainer,
    2106                     sidebar_id: self.params.sidebar_id,
    2107                     widget_id: widgetId,
    2108                     widget_id_base: widget.get( 'id_base' ),
    2109                     type: controlType,
    2110                     is_new: ! isExistingWidget,
    2111                     width: widget.get( 'width' ),
    2112                     height: widget.get( 'height' ),
    2113                     is_wide: widget.get( 'is_wide' ),
    2114                     active: true
     2101                settings: {
     2102                    'default': settingId
    21152103                },
    2116                 previewer: self.setting.previewer
    2117             } );
    2118             api.control.add( settingId, widgetFormControl );
     2104                content: controlContainer,
     2105                sidebar_id: self.params.sidebar_id,
     2106                widget_id: widgetId,
     2107                widget_id_base: widget.get( 'id_base' ),
     2108                type: controlType,
     2109                is_new: ! isExistingWidget,
     2110                width: widget.get( 'width' ),
     2111                height: widget.get( 'height' ),
     2112                is_wide: widget.get( 'is_wide' )
     2113            } );
     2114            api.control.add( widgetFormControl );
    21192115
    21202116            // Make sure widget is removed from the other sidebars
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r41720 r41726  
    36053605        ?>
    36063606        <script type="text/html" id="tmpl-customize-notification">
    3607             <li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.classes || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
     3607            <li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.containerClasses || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
    36083608                <div class="notification-message">{{{ data.message || data.code }}}</div>
    36093609                <# if ( data.dismissible ) { #>
  • trunk/src/wp-includes/js/customize-base.js

    r41667 r41726  
    377377         * Add an item to the collection.
    378378         *
    379          * @param {string} id    The ID of the item.
    380          * @param {mixed}  value The item instance.
    381          * @return {mixed} The new item's instance.
    382          */
    383         add: function( id, value ) {
    384             if ( this.has( id ) )
    385                 return this.value( id );
    386 
    387             this._value[ id ] = value;
    388             value.parent = this;
     379         * @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add. When an ID string is supplied, then itemObject must be provided.
     380         * @param {wp.customize.Class}        [itemObject] - The item instance when the first argument is a ID string.
     381         * @return {wp.customize.Class} The new item's instance, or an existing instance if already added.
     382         */
     383        add: function( item, itemObject ) {
     384            var collection = this, id, instance;
     385            if ( 'string' === typeof item ) {
     386                id = item;
     387                instance = itemObject;
     388            } else {
     389                if ( 'string' !== typeof item.id ) {
     390                    throw new Error( 'Unknown key' );
     391                }
     392                id = item.id;
     393                instance = item;
     394            }
     395
     396            if ( collection.has( id ) ) {
     397                return collection.value( id );
     398            }
     399
     400            collection._value[ id ] = instance;
     401            instance.parent = collection;
    389402
    390403            // Propagate a 'change' event on an item up to the collection.
    391             if ( value.extended( api.Value ) )
    392                 value.bind( this._change );
    393 
    394             this.trigger( 'add', value );
     404            if ( instance.extended( api.Value ) ) {
     405                instance.bind( collection._change );
     406            }
     407
     408            collection.trigger( 'add', instance );
    395409
    396410            // If a deferred object exists for this item,
    397411            // resolve it.
    398             if ( this._deferreds[ id ] )
    399                 this._deferreds[ id ].resolve();
    400 
    401             return this._value[ id ];
     412            if ( collection._deferreds[ id ] ) {
     413                collection._deferreds[ id ].resolve();
     414            }
     415
     416            return collection._value[ id ];
    402417        },
    403418
     
    816831         * @var {string}
    817832         */
    818         classes: '',
     833        containerClasses: '',
    819834
    820835        /**
     
    830845         * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
    831846         * @param {string}   [params.templateId] - ID for template to render the notification.
    832          * @param {string}   [params.classes] - Additional class names to add to the notification container.
     847         * @param {string}   [params.containerClasses] - Additional class names to add to the notification container.
    833848         * @param {boolean}  [params.dismissible] - Whether the notification can be dismissed.
    834849         */
     
    845860                    template: null,
    846861                    dismissible: false,
    847                     classes: ''
     862                    containerClasses: ''
    848863                },
    849864                params
  • trunk/src/wp-includes/js/customize-preview-widgets.js

    r41351 r41726  
    408408            } );
    409409
    410             api.selectiveRefresh.partial.add( widgetPartial.id, widgetPartial );
     410            api.selectiveRefresh.partial.add( widgetPartial );
    411411
    412412            if ( wasInserted ) {
     
    511511                    }
    512512                } );
    513                 api.selectiveRefresh.partial.add( partial.id, partial );
     513                api.selectiveRefresh.partial.add( partial );
    514514            }
    515515        } );
  • trunk/src/wp-includes/js/customize-selective-refresh.js

    r41358 r41726  
    878878                Constructor = self.partialConstructor[ containerElement.data( 'customize-partial-type' ) ] || self.Partial;
    879879                partial = new Constructor( id, partialOptions );
    880                 self.partial.add( partial.id, partial );
     880                self.partial.add( partial );
    881881            }
    882882
     
    919919                Constructor = self.partialConstructor[ data.type ] || self.Partial;
    920920                partial = new Constructor( id, { params: data } );
    921                 self.partial.add( id, partial );
     921                self.partial.add( partial );
    922922            } else {
    923923                _.extend( partial.params, data );
  • trunk/tests/qunit/wp-admin/js/customize-controls.js

    r41670 r41726  
    307307            content: null,
    308308            active: true,
    309             instanceNumber: null,
    310309            customizeAction: ''
    311310        };
     
    314313            equal( value, section.params[ key ] );
    315314        } );
     315        ok( _.isNumber( section.params.instanceNumber ) );
    316316    } );
    317317
     
    418418            type: 'default',
    419419            content: null,
    420             active: true,
    421             instanceNumber: null
     420            active: true
    422421        };
    423422        jQuery.each( defaultParams, function ( key, value ) {
     
    425424            equal( value, panel.params[ key ] );
    426425        } );
     426        ok( _.isNumber( panel.params.instanceNumber ) );
    427427    } );
    428428
Note: See TracChangeset for help on using the changeset viewer.