Skip to content
This repository has been archived by the owner on Mar 9, 2024. It is now read-only.

Tinymce in text widget #275

Merged
merged 11 commits into from
Nov 10, 2023
2 changes: 1 addition & 1 deletion src/wp-admin/css/widgets.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* General Widgets Styles */

.widget {
margin: 0 auto 10px;
margin: 0 auto 10px !important;
position: relative;
box-sizing: border-box;
}
Expand Down
38 changes: 8 additions & 30 deletions src/wp-admin/js/customize-widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand All @@ -1421,37 +1421,26 @@
$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 () {
prevComplete();
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
Expand All @@ -1460,9 +1449,6 @@
expandControl();
}
} else {
complete = function() {
$widget.removeAttr( 'open' );
};
if ( args.completeCallback ) {
prevComplete = complete;
complete = function () {
Expand All @@ -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' );
}
},

Expand Down
41 changes: 32 additions & 9 deletions src/wp-admin/js/widgets/text-widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ 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' );
}
});

// 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() );
});
},

Expand Down Expand Up @@ -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();
});

Expand All @@ -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.
Expand All @@ -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.
*
Expand Down Expand Up @@ -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
Expand All @@ -389,8 +412,8 @@ wp.textWidgets = ( function( $ ) {
* components", the JS template is rendered outside of the normal form
* container.
*/
fieldContainer = $( '<div></div>' );
syncContainer = widgetContainer.find( '.widget-content:first' );
fieldContainer = document.createElement( 'div' );
syncContainer = widgetContainer.querySelector( '.widget-content' );
syncContainer.before( fieldContainer );

widgetControl = new component.TextWidgetControl({
Expand All @@ -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();
Expand Down
17 changes: 17 additions & 0 deletions src/wp-includes/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'
);
}

/**
Expand Down
Loading