Make WordPress Core

Ticket #40974: 40974.5.diff

File 40974.5.diff, 6.0 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..282090d585 100644
    wp.textWidgets = ( function( $ ) { 
    8181                        _.each( control.fields, function( fieldInput, fieldName ) {
    8282                                fieldInput.on( 'input change', function updateSyncField() {
    8383                                        var syncInput = control.syncContainer.find( 'input[type=hidden].' + fieldName );
    84                                         if ( syncInput.val() !== $( this ).val() ) {
    85                                                 syncInput.val( $( this ).val() );
     84                                        if ( syncInput.val() !== fieldInput.val() ) {
     85                                                syncInput.val( fieldInput.val() );
    8686                                                syncInput.trigger( 'change' );
    8787                                        }
    8888                                });
    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, needsTextareaChangeTrigger = false;
    168168                        textarea = control.fields.text;
    169169                        id = textarea.attr( 'id' );
    170170
    171171                        /**
     172                         * Trigger change if dirty.
     173                         *
     174                         * @returns {void}
     175                         */
     176                        triggerChangeIfDirty = function() {
     177                                var updateWidgetBuffer = 300; // See wp.customize.Widgets.WidgetControl._setupUpdateUI() which uses 250ms for updateWidgetDebounced.
     178                                if ( control.editor.isDirty() ) {
     179
     180                                        /*
     181                                         * Account for race condition in customizer where user clicks Save & Publish while
     182                                         * focus was just previously given to to the editor. Since updates to the editor
     183                                         * are debounced at 1 second and since widget input changes are only synced to
     184                                         * settings after 250ms, the customizer needs to be put into the processing
     185                                         * state during the time between the change event is triggered and updateWidget
     186                                         * logic starts. Note that the debounced update-widget request should be able
     187                                         * to be removed with the removal of the update-widget request entirely once
     188                                         * widgets are able to mutate their own instance props directly in JS without
     189                                         * having to make server round-trips to call the respective WP_Widget::update()
     190                                         * callbacks. See <https://core.trac.wordpress.org/ticket/33507>.
     191                                         */
     192                                        if ( wp.customize && wp.customize.state ) {
     193                                                wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() + 1 );
     194                                                _.delay( function() {
     195                                                        wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() - 1 );
     196                                                }, updateWidgetBuffer );
     197                                        }
     198
     199                                        if ( ! control.editor.isHidden() ) {
     200                                                control.editor.save();
     201                                        }
     202                                }
     203
     204                                // Trigger change on textarea when it is dirty for sake of widgets in the Customizer needing to sync form inputs to setting models.
     205                                if ( needsTextareaChangeTrigger ) {
     206                                        textarea.trigger( 'change' );
     207                                        needsTextareaChangeTrigger = false;
     208                                }
     209                        };
     210
     211                        // Just-in-time force-update the hidden input fields.
     212                        control.syncContainer.closest( '.widget' ).find( '[name=savewidget]:first' ).on( 'click', function onClickSaveButton() {
     213                                triggerChangeIfDirty();
     214                        });
     215
     216                        /**
    172217                         * Build (or re-build) the visual editor.
    173218                         *
    174219                         * @returns {void}
    175220                         */
    176221                        function buildEditor() {
    177                                 var editor, triggerChangeIfDirty, onInit, showPointerElement;
     222                                var editor, onInit, showPointerElement;
    178223
    179224                                // Abort building if the textarea is gone, likely due to the widget having been deleted entirely.
    180225                                if ( ! document.getElementById( id ) ) {
    wp.textWidgets = ( function( $ ) { 
    230275
    231276                                        // If a prior mce instance was replaced, and it was in text mode, toggle to text mode.
    232277                                        if ( restoreTextMode ) {
    233                                                 switchEditors.go( id, 'toggle' );
     278                                                switchEditors.go( id, 'html' );
    234279                                        }
    235280
    236281                                        // Show the pointer.
    wp.textWidgets = ( function( $ ) { 
    269314                                }
    270315
    271316                                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                                                 }
    294317
    295                                                 editor.save();
    296                                                 textarea.trigger( 'change' );
    297                                         }
    298                                 };
    299                                 editor.on( 'focus', function() {
     318                                editor.on( 'focus', function onEditorFocus() {
    300319                                        control.editorFocused = true;
    301320                                });
     321                                editor.on( 'paste', function onEditorPaste() {
     322                                        editor.setDirty( true ); // Because pasting doesn't currently set the dirty state.
     323                                        triggerChangeIfDirty();
     324                                });
     325                                editor.on( 'NodeChange', function onNodeChange() {
     326                                        needsTextareaChangeTrigger = true;
     327                                });
    302328                                editor.on( 'NodeChange', _.debounce( triggerChangeIfDirty, changeDebounceDelay ) );
    303                                 editor.on( 'blur', function() {
     329                                editor.on( 'blur hide', function onEditorBlur() {
    304330                                        control.editorFocused = false;
    305331                                        triggerChangeIfDirty();
    306332                                });