WordPress.org

Make WordPress Core

Ticket #27491: 27491.3.diff

File 27491.3.diff, 12.7 KB (added by westonruter, 6 years ago)

Fix logic error for when to update setting. Also pushed to https://github.com/x-team/wordpress-develop/pull/5/files

  • src/wp-admin/css/customize-widgets.css

    diff --git src/wp-admin/css/customize-widgets.css src/wp-admin/css/customize-widgets.css
    index 86c08bd..063361f 100644
     
    3737.customize-control-widget_form.previewer-loading .spinner {
    3838        opacity: 1.0;
    3939}
     40.customize-control-widget_form.widget-form-disabled .widget-content {
     41        opacity: 0.7;
     42        pointer-events: none;
     43        -moz-user-select: none;
     44        -webkit-user-select: none;
     45        -ms-user-select: none;
     46        user-select: none;
     47}
    4048
    4149.customize-control-widget_form .widget {
    4250        margin-bottom: 0;
  • src/wp-admin/js/customize-widgets.js

    diff --git src/wp-admin/js/customize-widgets.js src/wp-admin/js/customize-widgets.js
    index 7dbb92b..4dd5a35 100644
    var WidgetCustomizer = ( function ($) { 
    88                Sidebar,
    99                SidebarCollection,
    1010                OldPreviewer,
     11                builtin_form_update_handlers,
    1112                customize = wp.customize, self = {
    1213                update_widget_ajax_action: null,
    1314                update_widget_nonce_value: null,
    var WidgetCustomizer = ( function ($) { 
    137138        self.registered_sidebars = new SidebarCollection( self.registered_sidebars );
    138139
    139140        /**
     141         * Handlers for the widget-form-update event, organized by widget ID base.
     142         * Other widgets may provide their own update handlers by adding
     143         * listeners for the widget-form-update event.
     144         */
     145        builtin_form_update_handlers = {
     146
     147                /**
     148                 * @param {jQuery.Event} e
     149                 * @param {String} args.widget_id
     150                 * @param {String} args.widget_id_base
     151                 * @param {String} args.new_form
     152                 * @param {Boolean} args.hard
     153                 * @param {wp.customize.controlConstructor.widget_form} args.customize_control
     154                 */
     155                rss: function ( e, args ) {
     156                        var old_widget_error = args.customize_control.container.find( '.widget-error:first' ),
     157                                new_widget_error = $( '<div>' + args.new_form + '</div>' ).find( '.widget-error:first' );
     158
     159                        if ( old_widget_error.length && new_widget_error.length ) {
     160                                old_widget_error.replaceWith( new_widget_error );
     161                        } else if ( old_widget_error.length ) {
     162                                old_widget_error.remove();
     163                        } else if ( new_widget_error.length ) {
     164                                args.customize_control.container.find( '.widget-content:first' ).prepend( new_widget_error );
     165                        }
     166                }
     167        };
     168
     169        /**
    140170         * On DOM ready, initialize some meta functionality independent of specific
    141171         * customizer controls.
    142172         */
    var WidgetCustomizer = ( function ($) { 
    630660                        control._setupHighlightEffects();
    631661                        control._setupUpdateUI();
    632662                        control._setupRemoveUI();
    633                         control.hook( 'init' );
    634                 },
    635 
    636                 /**
    637                  * Hooks for widgets to support living in the customizer control
    638                  */
    639                 hooks: {
    640                         _default: {},
    641                         rss: {
    642                                 formUpdated: function ( serialized_form ) {
    643                                         var control = this,
    644                                                 old_widget_error = control.container.find( '.widget-error:first' ),
    645                                                 new_widget_error = serialized_form.find( '.widget-error:first' );
    646 
    647                                         if ( old_widget_error.length && new_widget_error.length ) {
    648                                                 old_widget_error.replaceWith( new_widget_error );
    649                                         } else if ( old_widget_error.length ) {
    650                                                 old_widget_error.remove();
    651                                         } else if ( new_widget_error.length ) {
    652                                                 control.container.find( '.widget-content' ).prepend( new_widget_error );
    653                                         }
    654                                 }
    655                         }
    656                 },
    657 
    658                 /**
    659                  * Trigger an 'action' which a specific widget type can handle
    660                  *
    661                  * @param name
    662                  */
    663                 hook: function ( name ) {
    664                         var args = Array.prototype.slice.call( arguments, 1 ), handler;
    665 
    666                         if ( this.hooks[this.params.widget_id_base] && this.hooks[this.params.widget_id_base][name] ) {
    667                                 handler = this.hooks[this.params.widget_id_base][name];
    668                         } else if ( this.hooks._default[name] ) {
    669                                 handler = this.hooks._default[name];
    670                         }
    671                         if ( handler ) {
    672                                 handler.apply( this, args );
    673                         }
    674663                },
    675664
    676665                /**
    var WidgetCustomizer = ( function ($) { 
    688677
    689678                        control._update_count = 0;
    690679                        control.is_widget_updating = false;
     680                        control.live_update_mode = true;
    691681
    692682                        // Update widget whenever model changes
    693683                        control.setting.bind( function( to, from ) {
    var WidgetCustomizer = ( function ($) { 
    976966                        var control = this,
    977967                                widget_content,
    978968                                save_btn,
    979                                 update_widget_debounced;
     969                                update_widget_debounced,
     970                                form_update_event_handler;
    980971
    981972                        widget_content = control.container.find( '.widget-content' );
    982973
    var WidgetCustomizer = ( function ($) { 
    987978                        save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' );
    988979                        save_btn.on( 'click', function ( e ) {
    989980                                e.preventDefault();
    990                                 control.updateWidget();
     981                                control.updateWidget( { disable_form: true } );
    991982                        } );
    992983
    993984                        update_widget_debounced = _.debounce( function () {
    var WidgetCustomizer = ( function ($) { 
    1005996
    1006997                        // Handle widgets that support live previews
    1007998                        widget_content.on( 'change input propertychange', ':input', function ( e ) {
    1008                                 if ( e.type === 'change' ) {
    1009                                         control.updateWidget();
    1010                                 } else if ( this.checkValidity && this.checkValidity() ) {
    1011                                         update_widget_debounced();
     999                                if ( control.live_update_mode ) {
     1000                                        if ( e.type === 'change' ) {
     1001                                                control.updateWidget();
     1002                                        } else if ( this.checkValidity && this.checkValidity() ) {
     1003                                                update_widget_debounced();
     1004                                        }
    10121005                                }
    10131006                        } );
    10141007
    var WidgetCustomizer = ( function ($) { 
    10271020                                var is_rendered = !! rendered_widgets[control.params.widget_id];
    10281021                                control.container.toggleClass( 'widget-rendered', is_rendered );
    10291022                        } );
     1023
     1024                        form_update_event_handler = builtin_form_update_handlers[ control.params.widget_id_base ];
     1025                        if ( form_update_event_handler ) {
     1026                                control.container.find( '.widget:first' ).on( 'widget-form-update', form_update_event_handler );
     1027                        }
    10301028                },
    10311029
    10321030                /**
    var WidgetCustomizer = ( function ($) { 
    11561154                        var control = this,
    11571155                                instance_override,
    11581156                                complete_callback,
     1157                                widget_root,
    11591158                                update_number,
    11601159                                widget_content,
    1161                                 element_id_to_refocus = null,
    1162                                 active_input_selection_start = null,
    1163                                 active_input_selection_end = null,
    11641160                                params,
    11651161                                data,
    11661162                                inputs,
    var WidgetCustomizer = ( function ($) { 
    11791175                        control._update_count += 1;
    11801176                        update_number = control._update_count;
    11811177
    1182                         widget_content = control.container.find( '.widget-content' );
     1178                        widget_root = control.container.find( '.widget:first' );
     1179                        widget_content = control.container.find( '.widget-content:first' );
    11831180
    11841181                        // Remove a previous error message
    11851182                        widget_content.find( '.widget-error' ).remove();
    11861183
    1187                         // @todo Support more selectors than IDs?
    1188                         if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) {
    1189                                 element_id_to_refocus = $( document.activeElement ).prop( 'id' );
    1190                                 // @todo IE8 support: http://stackoverflow.com/a/4207763/93579
    1191                                 try {
    1192                                         active_input_selection_start = document.activeElement.selectionStart;
    1193                                         active_input_selection_end = document.activeElement.selectionEnd;
    1194                                 }
    1195                                 catch( e ) {} // catch InvalidStateError in case of checkboxes
    1196                         }
    1197 
    11981184                        control.container.addClass( 'widget-form-loading' );
    11991185                        control.container.addClass( 'previewer-loading' );
    12001186                        processing = wp.customize.state( 'processing' );
    12011187                        processing( processing() + 1 );
    12021188
     1189                        if ( ! control.live_update_mode ) {
     1190                                control.container.addClass( 'widget-form-disabled' );
     1191                        }
     1192
    12031193                        params = {};
    12041194                        params.action = self.update_widget_ajax_action;
    12051195                        params.wp_customize = 'on';
    var WidgetCustomizer = ( function ($) { 
    12291219                                        sanitized_form,
    12301220                                        sanitized_inputs,
    12311221                                        has_same_inputs_in_response,
    1232                                         is_instance_identical;
     1222                                        is_live_update_aborted = false,
     1223                                        event_data;
    12331224
    12341225                                // Check if the user is logged out.
    12351226                                if ( '0' === r ) {
    var WidgetCustomizer = ( function ($) { 
    12491240
    12501241                                if ( r.success ) {
    12511242                                        sanitized_form = $( '<div>' + r.data.form + '</div>' );
    1252 
    1253                                         control.hook( 'formUpdate', sanitized_form );
    1254 
    12551243                                        sanitized_inputs = sanitized_form.find( ':input, option' );
    12561244                                        has_same_inputs_in_response = control._getInputsSignature( inputs ) === control._getInputsSignature( sanitized_inputs );
    12571245
    1258                                         if ( has_same_inputs_in_response ) {
     1246                                        if ( has_same_inputs_in_response && control.live_update_mode ) {
    12591247                                                inputs.each( function ( i ) {
    12601248                                                        var input = $( this ),
    12611249                                                                sanitized_input = $( sanitized_inputs[i] ),
    12621250                                                                property = control._getInputStatePropertyName( this ),
    1263                                                                 state,
     1251                                                                submitted_state,
    12641252                                                                sanitized_state;
    12651253
    1266                                                         state = input.data( 'state' + update_number );
     1254                                                        submitted_state = input.data( 'state' + update_number );
    12671255                                                        sanitized_state = sanitized_input.prop( property );
    12681256                                                        input.data( 'sanitized', sanitized_state );
     1257                                                        event_data = {
     1258                                                                'sanitized_state': sanitized_state,
     1259                                                                'submitted_state': submitted_state,
     1260                                                                'customize_control': control
     1261                                                        };
    12691262
    1270                                                         if ( state !== sanitized_state ) {
     1263                                                        if ( submitted_state !== sanitized_state ) {
    12711264
    12721265                                                                // Only update now if not currently focused on it,
    12731266                                                                // so that we don't cause the cursor
    12741267                                                                // it will be updated upon the change event
    12751268                                                                if ( args.ignore_active_element || ! input.is( document.activeElement ) ) {
    12761269                                                                        input.prop( property, sanitized_state );
     1270                                                                        input.trigger( 'widget-sanitary-field', [ event_data ] );
     1271                                                                } else {
     1272                                                                        input.trigger( 'widget-unsanitary-field', [ event_data ] );
    12771273                                                                }
    1278                                                                 control.hook( 'unsanitaryField', input, sanitized_state, state );
    12791274
    12801275                                                        } else {
    1281                                                                 control.hook( 'sanitaryField', input, state );
     1276                                                                input.trigger( 'widget-sanitary-field', [ event_data ] );
    12821277                                                        }
    12831278                                                } );
    1284                                                 control.hook( 'formUpdated', sanitized_form );
     1279
     1280                                        } else if ( control.live_update_mode ) {
     1281                                                control.live_update_mode = false;
     1282                                                control.container.find( 'input[name="savewidget"]' ).show();
     1283                                                is_live_update_aborted = true;
    12851284                                        } else {
    1286                                                 widget_content.html( sanitized_form.html() );
    1287                                                 if ( element_id_to_refocus ) {
    1288                                                         // not using jQuery selector so we don't have to worry about escaping IDs with brackets and other characters
    1289                                                         $( document.getElementById( element_id_to_refocus ) )
    1290                                                                 .prop( {
    1291                                                                         selectionStart: active_input_selection_start,
    1292                                                                         selectionEnd: active_input_selection_end
    1293                                                                 } )
    1294                                                                 .focus();
    1295                                                 }
    1296                                                 control.hook( 'formRefreshed' );
     1285                                                widget_content.html( r.data.form );
     1286                                                control.container.removeClass( 'widget-form-disabled' );
     1287                                        }
     1288
     1289                                        if ( ! is_live_update_aborted ) {
     1290                                                event_data = {
     1291                                                        'widget_id': control.params.widget_id,
     1292                                                        'widget_id_base': control.params.widget_id_base,
     1293                                                        'new_form': r.data.form,
     1294                                                        'hard': ! control.live_update_mode, // dynamic fields may need to be re-initialized (e.g. Chosen)
     1295                                                        'customize_control': control
     1296                                                };
     1297                                                widget_root.trigger( 'widget-form-update', [ event_data ] );
    12971298                                        }
    12981299
    12991300                                        /**
    var WidgetCustomizer = ( function ($) { 
    13011302                                         * needing to be rendered, and so we can preempt the event for the
    13021303                                         * preview finishing loading.
    13031304                                         */
    1304                                         is_instance_identical = _( control.setting() ).isEqual( r.data.instance );
    1305                                         if ( ! is_instance_identical ) {
     1305                                        if ( ! is_live_update_aborted && ! _( control.setting() ).isEqual( r.data.instance ) ) {
    13061306                                                control.is_widget_updating = true; // suppress triggering another updateWidget
    13071307                                                control.setting( r.data.instance );
    13081308                                                control.is_widget_updating = false;
    13091309                                        }
    13101310
    13111311                                        if ( complete_callback ) {
    1312                                                 complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } );
     1312                                                complete_callback.call( control, null, { no_change: no_setting_change, ajax_finished: true } );
    13131313                                        }
    13141314                                } else {
    13151315                                        message = self.i18n.error;
  • src/wp-admin/js/widgets.js

    diff --git src/wp-admin/js/widgets.js src/wp-admin/js/widgets.js
    index 046907b..9f935ed 100644
    wpWidgets = { 
    332332
    333333        save : function( widget, del, animate, order ) {
    334334                var sidebarId = widget.closest('div.widgets-sortables').attr('id'),
    335                         data = widget.find('form').serialize(), a;
     335                        data = widget.find('form').serialize(), a, eventData;
    336336
    337337                widget = $(widget);
    338338                $('.spinner', widget).show();
    wpWidgets = { 
    374374                        } else {
    375375                                $('.spinner').hide();
    376376                                if ( r && r.length > 2 ) {
    377                                         $( 'div.widget-content', widget ).html(r);
     377                                        $( 'div.widget-content', widget ).html( r );
    378378                                        wpWidgets.appendTitle( widget );
     379                                        eventData = {
     380                                                'widget_id': widget.find( 'input.widget-id' ).val(),
     381                                                'widget_id_base': widget.find( 'input.id_base' ).val(),
     382                                                'new_form': r,
     383                                                'hard': true, // soft updates only in customizer
     384                                                'customize_control': null
     385                                        };
     386                                        widget.trigger( 'widget-form-update', [ eventData ] );
    379387                                }
    380388                        }
    381389                        if ( order ) {