Make WordPress Core

Ticket #40974: 40974.4.diff

File 40974.4.diff, 5.4 KB (added by westonruter, 7 years ago)
  • 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 1d3b51eb0b..766405416c 100644
    wp.textWidgets = ( function( $ ) { 
    164164                 * @returns {void}
    165165                 */
    166166                initializeEditor: function initializeEditor() {
    167                         var control = this, changeDebounceDelay = 1000, id, textarea, restoreTextMode = false;
     167                        var control = this, changeDebounceDelay = 1000, id, textarea, triggerChangeIfDirty, restoreTextMode = false;
    168168                        textarea = control.fields.text;
    169169                        id = textarea.attr( 'id' );
    170170
    171171                        /**
     172                         * Trigger change if dirty.
     173                         *
     174                         * @param {jQuery.Event} [event] Related event.
     175                         * @returns {void}
     176                         */
     177                        triggerChangeIfDirty = function( event ) {
     178                                var updateWidgetBuffer = 300; // See wp.customize.Widgets.WidgetControl._setupUpdateUI() which uses 250ms for updateWidgetDebounced.
     179                                if ( control.editor.isDirty() || ( event && 'paste' === event.type ) ) {
     180
     181                                        /*
     182                                         * Account for race condition in customizer where user clicks Save & Publish while
     183                                         * focus was just previously given to to the editor. Since updates to the editor
     184                                         * are debounced at 1 second and since widget input changes are only synced to
     185                                         * settings after 250ms, the customizer needs to be put into the processing
     186                                         * state during the time between the change event is triggered and updateWidget
     187                                         * logic starts. Note that the debounced update-widget request should be able
     188                                         * to be removed with the removal of the update-widget request entirely once
     189                                         * widgets are able to mutate their own instance props directly in JS without
     190                                         * having to make server round-trips to call the respective WP_Widget::update()
     191                                         * callbacks. See <https://core.trac.wordpress.org/ticket/33507>.
     192                                         */
     193                                        if ( wp.customize && wp.customize.state ) {
     194                                                wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() + 1 );
     195                                                _.delay( function() {
     196                                                        wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() - 1 );
     197                                                }, updateWidgetBuffer );
     198                                        }
     199
     200                                        if ( ! control.editor.isHidden() ) {
     201                                                control.editor.save();
     202                                        }
     203                                        textarea.trigger( 'change' );
     204                                }
     205                        };
     206
     207                        // Just-in-time force-update the hidden input fields.
     208                        control.syncContainer.closest( '.widget' ).find( '[name=savewidget]:first' ).on( 'click', function onClickSaveButton() {
     209                                triggerChangeIfDirty();
     210                                control.syncContainer.find( 'input.title' ).val( control.fields.title.val() );
     211                                control.syncContainer.find( 'input.text' ).val( control.fields.text.val() );
     212                        });
     213
     214                        /**
    172215                         * Build (or re-build) the visual editor.
    173216                         *
    174217                         * @returns {void}
    175218                         */
    176219                        function buildEditor() {
    177                                 var editor, triggerChangeIfDirty, onInit, showPointerElement;
     220                                var editor, onInit, showPointerElement;
    178221
    179222                                // Abort building if the textarea is gone, likely due to the widget having been deleted entirely.
    180223                                if ( ! document.getElementById( id ) ) {
    wp.textWidgets = ( function( $ ) { 
    230273
    231274                                        // If a prior mce instance was replaced, and it was in text mode, toggle to text mode.
    232275                                        if ( restoreTextMode ) {
    233                                                 switchEditors.go( id, 'toggle' );
     276                                                switchEditors.go( id, 'html' );
    234277                                        }
    235278
    236279                                        // Show the pointer.
    wp.textWidgets = ( function( $ ) { 
    269312                                }
    270313
    271314                                control.editorFocused = false;
    272                                 triggerChangeIfDirty = function() {
    273                                         var updateWidgetBuffer = 300; // See wp.customize.Widgets.WidgetControl._setupUpdateUI() which uses 250ms for updateWidgetDebounced.
    274                                         if ( editor.isDirty() ) {
    275 
    276                                                 /*
    277                                                  * Account for race condition in customizer where user clicks Save & Publish while
    278                                                  * focus was just previously given to to the editor. Since updates to the editor
    279                                                  * are debounced at 1 second and since widget input changes are only synced to
    280                                                  * settings after 250ms, the customizer needs to be put into the processing
    281                                                  * state during the time between the change event is triggered and updateWidget
    282                                                  * logic starts. Note that the debounced update-widget request should be able
    283                                                  * to be removed with the removal of the update-widget request entirely once
    284                                                  * widgets are able to mutate their own instance props directly in JS without
    285                                                  * having to make server round-trips to call the respective WP_Widget::update()
    286                                                  * callbacks. See <https://core.trac.wordpress.org/ticket/33507>.
    287                                                  */
    288                                                 if ( wp.customize && wp.customize.state ) {
    289                                                         wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() + 1 );
    290                                                         _.delay( function() {
    291                                                                 wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() - 1 );
    292                                                         }, updateWidgetBuffer );
    293                                                 }
    294315
    295                                                 editor.save();
    296                                                 textarea.trigger( 'change' );
    297                                         }
    298                                 };
    299                                 editor.on( 'focus', function() {
     316                                editor.on( 'focus', function onEditorFocus() {
    300317                                        control.editorFocused = true;
    301318                                });
     319                                editor.on( 'paste', function onEditorPaste( event ) {
     320                                        triggerChangeIfDirty( event );
     321                                });
    302322                                editor.on( 'NodeChange', _.debounce( triggerChangeIfDirty, changeDebounceDelay ) );
    303                                 editor.on( 'blur', function() {
     323                                editor.on( 'blur hide', function onEditorBlur( event ) {
    304324                                        control.editorFocused = false;
    305                                         triggerChangeIfDirty();
     325                                        triggerChangeIfDirty( event );
    306326                                });
    307327
    308328                                control.editor = editor;