diff --git a/src/wp-admin/css/widgets.css b/src/wp-admin/css/widgets.css index cde369954d..1564b2058a 100644 --- a/src/wp-admin/css/widgets.css +++ b/src/wp-admin/css/widgets.css @@ -1,7 +1,7 @@ /* General Widgets Styles */ .widget { - margin: 0 auto 10px; + margin: 0 auto 10px !important; position: relative; box-sizing: border-box; } diff --git a/src/wp-admin/js/customize-widgets.js b/src/wp-admin/js/customize-widgets.js index c24c8f355c..68b98424d9 100644 --- a/src/wp-admin/js/customize-widgets.js +++ b/src/wp-admin/js/customize-widgets.js @@ -1400,7 +1400,7 @@ * @param {Object} args merged on top of this.defaultActiveArguments */ onChangeExpanded: function ( expanded, args ) { - var self = this, $widget, $inside, complete, prevComplete, expandControl, $details; + var self = this, $widget, $inside, complete, prevComplete, expandControl, $details, $allWidgets; self.embedWidgetControl(); // Make sure the outer form is embedded so that the expanded state can be set in the UI. if ( expanded ) { @@ -1421,18 +1421,12 @@ $inside = $widget.find( '.widget-inside:first' ); $details = $widget.children( 'details' ); - expandControl = function() { + // Close all other widget controls before expanding this one. + $allWidgets = $details.closest( 'ul' ).find( 'details'); + $allWidgets.removeAttr( 'open' ); - // Close all other widget controls before expanding this one. - api.control.each( function( otherControl ) { - if ( self.params.type === otherControl.params.type && self !== otherControl ) { - otherControl.collapse(); - } - } ); + expandControl = function() { - complete = function() { - $details.attr( 'open', 'open' ); - }; if ( args.completeCallback ) { prevComplete = complete; complete = function () { @@ -1440,18 +1434,13 @@ args.completeCallback(); }; } - - if ( self.params.is_wide ) { - $inside.fadeIn( args.duration, complete ); - } else { - $inside.slideDown( args.duration, complete ); - } + $details.attr( 'open', 'open' ); self.container.trigger( 'expand' ); self.container.addClass( 'expanding' ); }; - if ( ! $details[0].hasAttribute( 'open' ) ) { + if ( ! $details.attr( 'open' ) ) { if ( api.section.has( self.section() ) ) { api.section( self.section() ).expand( { completeCallback: expandControl @@ -1460,9 +1449,6 @@ expandControl(); } } else { - complete = function() { - $widget.removeAttr( 'open' ); - }; if ( args.completeCallback ) { prevComplete = complete; complete = function () { @@ -1472,15 +1458,7 @@ } self.container.trigger( 'collapse' ); - - if ( self.params.is_wide ) { - $inside.fadeOut( args.duration, complete ); - } else { - $inside.slideUp( args.duration, function() { - $widget.css( { width:'', margin:'' } ); - complete(); - } ); - } + $widget.removeAttr( 'open' ); } }, diff --git a/src/wp-admin/js/widgets/text-widgets.js b/src/wp-admin/js/widgets/text-widgets.js index 925c36a362..b0e99d36b9 100644 --- a/src/wp-admin/js/widgets/text-widgets.js +++ b/src/wp-admin/js/widgets/text-widgets.js @@ -87,7 +87,7 @@ wp.textWidgets = ( function( $ ) { // Sync input fields to hidden sync fields which actually get sent to the server. _.each( control.fields, function( fieldInput, fieldName ) { fieldInput.on( 'input change', function updateSyncField() { - var syncInput = control.syncContainer.find( '.sync-input.' + fieldName ); + var syncInput = $(control.syncContainer).find( '.sync-input.' + fieldName ); if ( syncInput.val() !== fieldInput.val() ) { syncInput.val( fieldInput.val() ); syncInput.trigger( 'change' ); @@ -95,7 +95,7 @@ wp.textWidgets = ( function( $ ) { }); // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event. - fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() ); + fieldInput.val( $(control.syncContainer).find( '.sync-input.' + fieldName ).val() ); }); }, @@ -216,7 +216,7 @@ wp.textWidgets = ( function( $ ) { }; // Just-in-time force-update the hidden input fields. - control.syncContainer.closest( '.widget' ).find( '[name=savewidget]:first' ).on( 'click', function onClickSaveButton() { + control.syncContainer.closest( '.widget' ).querySelector( '[name=savewidget]' ).addEventListener( 'click', function onClickSaveButton() { triggerChangeIfDirty(); }); @@ -235,12 +235,18 @@ wp.textWidgets = ( function( $ ) { // The user has disabled TinyMCE. if ( typeof window.tinymce === 'undefined' ) { + wp.oldEditor.initialize( id, { + quicktags: true, + mediaButtons: true + }); + return; } // Destroy any existing editor so that it can be re-initialized after a widget-updated event. if ( tinymce.get( id ) ) { restoreTextMode = tinymce.get( id ).isHidden(); + wp.oldEditor.remove( id ); } // Add or enable the `wpview` plugin. @@ -254,6 +260,14 @@ wp.textWidgets = ( function( $ ) { } } ); + wp.oldEditor.initialize( id, { + tinymce: { + wpautop: true + }, + quicktags: true, + mediaButtons: true + } ); + /** * Show a pointer, focus on dismiss, and speak the contents for a11y. * @@ -364,20 +378,29 @@ wp.textWidgets = ( function( $ ) { * @return {void} */ component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { - var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer; + var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 200, renderWhenAnimationDone, fieldContainer, syncContainer; widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. - idBase = widgetContainer.find( '.id_base' ).val(); + if ( widgetContainer instanceof jQuery ) { + widgetContainer = widgetContainer[0]; + } + + idBase = widgetContainer.querySelector( '.id_base' ).value; if ( -1 === component.idBases.indexOf( idBase ) ) { return; } // Prevent initializing already-added widgets. - widgetId = widgetForm.find( '.widget-id' ).val(); + widgetId = widgetContainer.querySelector( '.widget-id' ).value; if ( component.widgetControls[ widgetId ] ) { return; } + // Bypass using TinyMCE when widget is in legacy mode. + if ( ! widgetContainer.querySelector( '.visual' ).value ) { + return; + } + /* * Create a container element for the widget control fields. * This is inserted into the DOM immediately before the .widget-content @@ -389,8 +412,8 @@ wp.textWidgets = ( function( $ ) { * components", the JS template is rendered outside of the normal form * container. */ - fieldContainer = $( '
' ); - syncContainer = widgetContainer.find( '.widget-content:first' ); + fieldContainer = document.createElement( 'div' ); + syncContainer = widgetContainer.querySelector( '.widget-content' ); syncContainer.before( fieldContainer ); widgetControl = new component.TextWidgetControl({ @@ -407,7 +430,7 @@ wp.textWidgets = ( function( $ ) { * with TinyMCE being able to set contenteditable on it. */ renderWhenAnimationDone = function() { - if ( ! widgetContainer.hasClass( 'open' ) ) { + if ( ! widgetContainer.querySelector( 'details' ).hasAttribute( 'open' ) ) { setTimeout( renderWhenAnimationDone, animatedCheckDelay ); } else { widgetControl.initializeEditor(); diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index c82aa01eed..3d0083f2ba 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -212,6 +212,23 @@ function wp_default_packages_inline_scripts( $scripts ) { ), 'after' ); + + // Loading the old editor and its config to ensure the classic block works as expected. + $scripts->add_inline_script( + 'editor', + 'window.wp.oldEditor = window.wp.editor;', + 'after' + ); + + // wp-editor module is exposed as window.wp.editor + // Problem: there is quite some code expecting window.wp.oldEditor object available under window.wp.editor + // Solution: fuse the two objects together to maintain backward compatibility + // For more context, see https://github.com/WordPress/gutenberg/issues/33203 + $scripts->add_inline_script( + 'wp-editor', + 'Object.assign( window.wp.editor, window.wp.oldEditor );', + 'after' + ); } /**