WordPress.org

Make WordPress Core

Ticket #40986: 40986.0.diff

File 40986.0.diff, 13.2 KB (added by westonruter, 23 months ago)

https://github.com/xwp/wordpress-develop/pull/234

  • src/wp-admin/js/widgets/media-widgets.js

    diff --git src/wp-admin/js/widgets/media-widgets.js src/wp-admin/js/widgets/media-widgets.js
    index d1f015f605..432b5c9cfe 100644
    wp.mediaWidgets = ( function( $ ) { 
    429429                 *
    430430                 * @param {Object}         options - Options.
    431431                 * @param {Backbone.Model} options.model - Model.
    432                  * @param {jQuery}         options.el - Control container element.
     432                 * @param {jQuery}         options.el - Control field container element.
     433                 * @param {jQuery}         options.syncContainer - Container element where fields are synced for the server.
    433434                 * @returns {void}
    434435                 */
    435436                initialize: function initialize( options ) {
    wp.mediaWidgets = ( function( $ ) { 
    437438
    438439                        Backbone.View.prototype.initialize.call( control, options );
    439440
    440                         if ( ! control.el ) {
    441                                 throw new Error( 'Missing options.el' );
    442                         }
    443441                        if ( ! ( control.model instanceof component.MediaWidgetModel ) ) {
    444442                                throw new Error( 'Missing options.model' );
    445443                        }
     444                        if ( ! options.el ) {
     445                                throw new Error( 'Missing options.el' );
     446                        }
     447                        if ( ! options.syncContainer ) {
     448                                throw new Error( 'Missing options.syncContainer' );
     449                        }
     450
     451                        control.syncContainer = options.syncContainer;
     452
     453                        control.$el.addClass( 'media-widget-control' );
    446454
    447455                        // Allow methods to be passed in with control context preserved.
    448456                        _.bindAll( control, 'syncModelToInputs', 'render', 'updateSelectedAttachment', 'renderPreview' );
    wp.mediaWidgets = ( function( $ ) { 
    547555                 */
    548556                syncModelToInputs: function syncModelToInputs() {
    549557                        var control = this;
    550                         control.$el.next( '.widget-content' ).find( '.media-widget-instance-property' ).each( function() {
     558                        control.syncContainer.find( '.media-widget-instance-property' ).each( function() {
    551559                                var input = $( this ), value;
    552560                                value = control.model.get( input.data( 'property' ) );
    553561                                if ( _.isUndefined( value ) ) {
    wp.mediaWidgets = ( function( $ ) { 
    10031011         * @returns {void}
    10041012         */
    10051013        component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
    1006                 var widgetContent, controlContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone;
     1014                var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone;
    10071015                widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
    1008                 widgetContent = widgetForm.find( '> .widget-content' );
    10091016                idBase = widgetForm.find( '> .id_base' ).val();
    10101017                widgetId = widgetForm.find( '> .widget-id' ).val();
    10111018
    wp.mediaWidgets = ( function( $ ) { 
    10321039                 * components", the JS template is rendered outside of the normal form
    10331040                 * container.
    10341041                 */
    1035                 controlContainer = $( '<div class="media-widget-control"></div>' );
    1036                 widgetContent.before( controlContainer );
     1042                fieldContainer = $( '<div></div>' );
     1043                syncContainer = widgetContainer.find( '.widget-content:first' );
     1044                syncContainer.before( fieldContainer );
    10371045
    10381046                /*
    10391047                 * Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state.
    wp.mediaWidgets = ( function( $ ) { 
    10411049                 * from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>.
    10421050                 */
    10431051                modelAttributes = {};
    1044                 widgetContent.find( '.media-widget-instance-property' ).each( function() {
     1052                syncContainer.find( '.media-widget-instance-property' ).each( function() {
    10451053                        var input = $( this );
    10461054                        modelAttributes[ input.data( 'property' ) ] = input.val();
    10471055                });
    wp.mediaWidgets = ( function( $ ) { 
    10501058                widgetModel = new ModelConstructor( modelAttributes );
    10511059
    10521060                widgetControl = new ControlConstructor({
    1053                         el: controlContainer,
     1061                        el: fieldContainer,
     1062                        syncContainer: syncContainer,
    10541063                        model: widgetModel
    10551064                });
    10561065
    wp.mediaWidgets = ( function( $ ) { 
    10791088        };
    10801089
    10811090        /**
     1091         * Setup widget in accessibility mode.
     1092         *
     1093         * @returns {void}
     1094         */
     1095        component.setupAccessibleMode = function setupAccessibleMode() {
     1096                var widgetForm, widgetId, idBase, widgetControl, ControlConstructor, ModelConstructor, modelAttributes, fieldContainer, syncContainer;
     1097                widgetForm = $( '.editwidget > form' );
     1098                if ( 0 === widgetForm.length ) {
     1099                        return;
     1100                }
     1101
     1102                idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val();
     1103
     1104                ControlConstructor = component.controlConstructors[ idBase ];
     1105                if ( ! ControlConstructor ) {
     1106                        return;
     1107                }
     1108
     1109                widgetId = widgetForm.find( '> .widget-control-actions > .widget-id' ).val();
     1110
     1111                ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel;
     1112                fieldContainer = $( '<div></div>' );
     1113                syncContainer = widgetForm.find( '> .widget-inside' );
     1114                syncContainer.before( fieldContainer );
     1115
     1116                modelAttributes = {};
     1117                syncContainer.find( '.media-widget-instance-property' ).each( function() {
     1118                        var input = $( this );
     1119                        modelAttributes[ input.data( 'property' ) ] = input.val();
     1120                });
     1121                modelAttributes.widget_id = widgetId;
     1122
     1123                widgetControl = new ControlConstructor({
     1124                        el: fieldContainer,
     1125                        syncContainer: syncContainer,
     1126                        model: new ModelConstructor( modelAttributes )
     1127                });
     1128
     1129                component.modelCollection.add( [ widgetControl.model ] );
     1130                component.widgetControls[ widgetControl.model.get( 'widget_id' ) ] = widgetControl;
     1131
     1132                widgetControl.render();
     1133        };
     1134
     1135        /**
    10821136         * Sync widget instance data sanitized from server back onto widget model.
    10831137         *
    10841138         * This gets called via the 'widget-updated' event when saving a widget from
    wp.mediaWidgets = ( function( $ ) { 
    11461200                                var widgetContainer = $( this );
    11471201                                component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
    11481202                        });
     1203
     1204                        // Accessibility mode.
     1205                        $( window ).load( function() { // @todo Deprecated.
     1206                                component.setupAccessibleMode();
     1207                        });
    11491208                });
    11501209        };
    11511210
  • src/wp-admin/js/widgets/text-widgets.js

    diff --git src/wp-admin/js/widgets/text-widgets.js src/wp-admin/js/widgets/text-widgets.js
    index 2108b65548..e6a547e57b 100644
    wp.textWidgets = ( function( $ ) { 
    2424                /**
    2525                 * Initialize.
    2626                 *
    27                  * @param {Object}         options - Options.
    28                  * @param {Backbone.Model} options.model - Model.
    29                  * @param {jQuery}         options.el - Control container element.
     27                 * @param {Object} options - Options.
     28                 * @param {jQuery} options.el - Control field container element.
     29                 * @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
    3030                 * @returns {void}
    3131                 */
    3232                initialize: function initialize( options ) {
    wp.textWidgets = ( function( $ ) { 
    3535                        if ( ! options.el ) {
    3636                                throw new Error( 'Missing options.el' );
    3737                        }
     38                        if ( ! options.syncContainer ) {
     39                                throw new Error( 'Missing options.syncContainer' );
     40                        }
    3841
    3942                        Backbone.View.prototype.initialize.call( control, options );
     43                        control.syncContainer = options.syncContainer;
    4044
    41                         /*
    42                          * Create a container element for the widget control fields.
    43                          * This is inserted into the DOM immediately before the the .widget-content
    44                          * element because the contents of this element are essentially "managed"
    45                          * by PHP, where each widget update cause the entire element to be emptied
    46                          * and replaced with the rendered output of WP_Widget::form() which is
    47                          * sent back in Ajax request made to save/update the widget instance.
    48                          * To prevent a "flash of replaced DOM elements and re-initialized JS
    49                          * components", the JS template is rendered outside of the normal form
    50                          * container.
    51                          */
    52                         control.fieldContainer = $( '<div class="text-widget-fields"></div>' );
    53                         control.fieldContainer.html( wp.template( 'widget-text-control-fields' ) );
    54                         control.widgetContentContainer = control.$el.find( '.widget-content:first' );
    55                         control.widgetContentContainer.before( control.fieldContainer );
     45                        control.$el.addClass( 'text-widget-fields' );
     46                        control.$el.html( wp.template( 'widget-text-control-fields' ) );
    5647
    5748                        control.fields = {
    58                                 title: control.fieldContainer.find( '.title' ),
    59                                 text: control.fieldContainer.find( '.text' )
     49                                title: control.$el.find( '.title' ),
     50                                text: control.$el.find( '.text' )
    6051                        };
    6152
    6253                        // Sync input fields to hidden sync fields which actually get sent to the server.
    6354                        _.each( control.fields, function( fieldInput, fieldName ) {
    6455                                fieldInput.on( 'input change', function updateSyncField() {
    65                                         var syncInput = control.widgetContentContainer.find( 'input[type=hidden].' + fieldName );
     56                                        var syncInput = control.syncContainer.find( 'input[type=hidden].' + fieldName );
    6657                                        if ( syncInput.val() !== $( this ).val() ) {
    6758                                                syncInput.val( $( this ).val() );
    6859                                                syncInput.trigger( 'change' );
    wp.textWidgets = ( function( $ ) { 
    7061                                });
    7162
    7263                                // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event.
    73                                 fieldInput.val( control.widgetContentContainer.find( 'input[type=hidden].' + fieldName ).val() );
     64                                fieldInput.val( control.syncContainer.find( 'input[type=hidden].' + fieldName ).val() );
    7465                        });
    7566                },
    7667
    wp.textWidgets = ( function( $ ) { 
    8778                        var control = this, syncInput;
    8879
    8980                        if ( ! control.fields.title.is( document.activeElement ) ) {
    90                                 syncInput = control.widgetContentContainer.find( 'input[type=hidden].title' );
     81                                syncInput = control.syncContainer.find( 'input[type=hidden].title' );
    9182                                control.fields.title.val( syncInput.val() );
    9283                        }
    9384
    94                         syncInput = control.widgetContentContainer.find( 'input[type=hidden].text' );
     85                        syncInput = control.syncContainer.find( 'input[type=hidden].text' );
    9586                        if ( control.fields.text.is( ':visible' ) ) {
    9687                                if ( ! control.fields.text.is( document.activeElement ) ) {
    9788                                        control.fields.text.val( syncInput.val() );
    wp.textWidgets = ( function( $ ) { 
    219210         * @returns {void}
    220211         */
    221212        component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
    222                 var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, widgetInside, renderWhenAnimationDone;
     213                var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, widgetInside, renderWhenAnimationDone, fieldContainer, syncContainer;
    223214                widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
    224215
    225216                idBase = widgetForm.find( '> .id_base' ).val();
    wp.textWidgets = ( function( $ ) { 
    228219                }
    229220
    230221                // Prevent initializing already-added widgets.
    231                 widgetId = widgetForm.find( '> .widget-id' ).val();
     222                widgetId = widgetForm.find( '.widget-id' ).val();
    232223                if ( component.widgetControls[ widgetId ] ) {
    233224                        return;
    234225                }
    235226
     227                /*
     228                 * Create a container element for the widget control fields.
     229                 * This is inserted into the DOM immediately before the the .widget-content
     230                 * element because the contents of this element are essentially "managed"
     231                 * by PHP, where each widget update cause the entire element to be emptied
     232                 * and replaced with the rendered output of WP_Widget::form() which is
     233                 * sent back in Ajax request made to save/update the widget instance.
     234                 * To prevent a "flash of replaced DOM elements and re-initialized JS
     235                 * components", the JS template is rendered outside of the normal form
     236                 * container.
     237                 */
     238                fieldContainer = $( '<div></div>' );
     239                syncContainer = widgetContainer.find( '.widget-content:first' );
     240                syncContainer.before( fieldContainer );
     241
    236242                widgetControl = new component.TextWidgetControl({
    237                         el: widgetContainer
     243                        el: fieldContainer,
     244                        syncContainer: syncContainer
    238245                });
    239246
    240247                component.widgetControls[ widgetId ] = widgetControl;
    wp.textWidgets = ( function( $ ) { 
    257264        };
    258265
    259266        /**
     267         * Setup widget in accessibility mode.
     268         *
     269         * @returns {void}
     270         */
     271        component.setupAccessibleMode = function setupAccessibleMode() {
     272                var widgetForm, idBase, widgetControl, fieldContainer, syncContainer;
     273                widgetForm = $( '.editwidget > form' );
     274                if ( 0 === widgetForm.length ) {
     275                        return;
     276                }
     277
     278                idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val();
     279                if ( 'text' !== idBase ) {
     280                        return;
     281                }
     282
     283                fieldContainer = $( '<div></div>' );
     284                syncContainer = widgetForm.find( '> .widget-inside' );
     285                syncContainer.before( fieldContainer );
     286
     287                widgetControl = new component.TextWidgetControl({
     288                        el: fieldContainer,
     289                        syncContainer: syncContainer
     290                });
     291
     292                widgetControl.initializeEditor();
     293        };
     294
     295        /**
    260296         * Sync widget instance data sanitized from server back onto widget model.
    261297         *
    262298         * This gets called via the 'widget-updated' event when saving a widget from
    wp.textWidgets = ( function( $ ) { 
    319355                                var widgetContainer = $( this );
    320356                                component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
    321357                        });
     358
     359                        // Accessibility mode.
     360                        $( window ).load( function() {
     361                                component.setupAccessibleMode();
     362                        });
    322363                });
    323364        };
    324365