? Feature NPM Resource Changed PR-5.0-dev Pending

User tests: Successful: Unsuccessful:

avatar Fedik
Fedik
26 Mar 2023

Summary of Changes

This is an atempt to improve our client side API for Editor and Editor XTD buttons.
In addittion to #40082 for server side.

I made it for 4.x to be able easily test on "production" codebase. However main target > 5.x

Currently it conflicts with #40082, that will be need to adjust depending which one will be merged first.
To run this PR need to apply changes from #40150.

What and why

Currently we have Joomla.editors.instances which just a collection of bare Objects.
And no easy way to determine active/interacted editor.
The XTD Buttons is very limited and not able to work in Subform.

Main idea is next: Editor script register an Instance in JoomlaEditor, mark this instance as active whenever User interact with editor or an XTD button. When User click XTD button then JoomlaEditorButton (or Editor which integrated this XTD buttons like we do in TinyMCE) will run registered action. The action will be applied to active editor instance.

JoomlaEditor

JoomlaEditor is for managing an Editors on the page: register, unregister, retrieve active instance.

I have replaced a bare Object of editors with JoomlaEditorDecorator, with set of specific methods for correct "cross-editor" interaction. The Decorator is basicaly a wrapper around Editor (TinyMCE, Codemirror etc) instance.
The Decorator should be implemented by Editor script and registered in JoomlaEditor.register().

Also Editor script now should set an active instance, everytime when User intercat with editor or with one of editor XTD button, with JoomlaEditor.setActive(<decorator|id>).

Example:
TinyMCEDecorator

class TinyMCEDecorator extends JoomlaEditorDecorator {

TinyMCE set active:
// Find out when editor is interacted
editor.addEventListener('click', (event) => {
Joomla.Editor.setActive(currentEditor.id);

JoomlaEditorButton

JoomlaEditorButton is for managing an actions that can be executed by XTD button.
From now each button will run specific "action", which should be registered with JoomlaEditorButton.registerAction().
This allows more transparent "cross-editor" integration.

Example:
insert action:

JoomlaEditorButton.registerAction('insert', (editor, options) => {

modal action:
PHP:
JavaScript:
JoomlaEditorButton.registerAction('modal', (editor, options) => {

Backward compatibility

I tried to address potential issues that may break older editors.
However it still may fail, example when editor does not provide Active instance and "b.c. code" cannot find it then XTD button will fail.

Notes

Here still a room for improve, and work to do. Example it will be need to update all our "modal-select" scripts, which accessing old Joomla.editors.instances directly.

Testing Instructions

Apply patch and apply #40150.
Run npm install.
Try to use diferent editors, and XTD buttons.
Try run the test within subform.

Link to documentations

Please select:

  • Documentation link for docs.joomla.org: TBD
  • Pull Request link for manual.joomla.org: joomla/Manual#97
avatar joomla-cms-bot joomla-cms-bot - change - 26 Mar 2023
Category JavaScript Repository NPM Change Layout Libraries Front End Plugins
avatar Fedik Fedik - open - 26 Mar 2023
avatar Fedik Fedik - change - 26 Mar 2023
Status New Pending
avatar Fedik Fedik - change - 26 Mar 2023
Labels Added: ? NPM Resource Changed PR-4.4-dev
avatar Fedik
Fedik - comment - 26 Mar 2023

Note: the test will fail, because the PR depend from #40150.

avatar laoneo
laoneo - comment - 30 Mar 2023

I guess it is better to rebase this pr to the 5.0-dev branch, as it will get more attention for new features. Thanks for understanding.

avatar Fedik Fedik - change - 2 Apr 2023
The description was changed
avatar Fedik Fedik - edited - 2 Apr 2023
avatar Fedik Fedik - change - 2 Apr 2023
The description was changed
avatar Fedik Fedik - edited - 2 Apr 2023
avatar Fedik Fedik - change - 7 Apr 2023
Labels Added: ? PR-5.0-dev
Removed: PR-4.4-dev
avatar Fedik Fedik - change - 23 Apr 2023
Title
[RFC] Joomla.Editor and Joomla.EditorButton client side API
[5.0][RFC] Joomla.Editor and Joomla.EditorButton client side API
avatar Fedik Fedik - edited - 23 Apr 2023
avatar Fedik Fedik - change - 24 Jun 2023
Labels Added: Feature
Removed: ?
avatar Fedik
Fedik - comment - 24 Jun 2023

The ESM version with use of importmap 5.0-dev...Fedik:joomla-cms:editor-js-api2

Main difference between ESM and current approcah, is reducing of globals.
Example instead of global Joomla.Editor.getActive() the script should import JoomlaEditor module and then use:

import { JoomlaEditor } from 'editor-api';

// And somewhere in code:
JoomlaEditor.setActive(...);
...
JoomlaEditor.getActive();
avatar Fedik
Fedik - comment - 1 Jul 2023

Note: Need to update PR to use ES modules

avatar Fedik Fedik - change - 2 Jul 2023
The description was changed
avatar Fedik Fedik - edited - 2 Jul 2023
avatar HLeithner HLeithner - close - 2 Sep 2023
avatar HLeithner HLeithner - merge - 2 Sep 2023
avatar HLeithner HLeithner - change - 2 Sep 2023
Status Pending Fixed in Code Base
Closed_Date 0000-00-00 00:00:00 2023-09-02 16:08:07
Closed_By HLeithner
avatar HLeithner
HLeithner - comment - 2 Sep 2023

thanks, merging this for beta1 to get real world feedback

avatar Ruud68
Ruud68 - comment - 7 Sep 2023

After this change my editor-xtd plugin stopped working. it was working on J3 / J4.
Note, that this is a plugin that will show a modal that I construct myself as there is no possibility to construct the modal via an iframe (like all other Joomla buttons are doing (as these have components generating the content of the iframe).

So the button is displaying, the modal window is constructed correctly (hidden), but clicking the button doesn't show / open the modal.

I have worked around this by setting the button->modal to true (which would then display an empty modal and not the one I created and setting the $button->options = ['confirmCallback' => true];

Now the modal I created works again.

So as far i can see this is just a workaround for having a button in the editor displaying your own modal when you do not have the option to.

Not even sure as to what the confirmCallback option will do, or if it is even possible to have a editor button open a custom BS modal without triggering the 'legacyModal' modus (which I presume is called legacy because it will be removed some day.

avatar Fedik
Fedik - comment - 7 Sep 2023

How is your button looks like?

The following "legacy code" should produce iframe:

$button  = new CMSObject();
$button->modal  = true;
$button->link = $link;

Would be good to have some more details, maybe we can improve something.

Note, that this is a plugin that will show a modal that I construct myself as there is no possibility to construct the modal via an iframe

How you doing it?

if it is even possible to have a editor button open a custom BS modal without triggering

With new API, you not limited to joomla modal, you can register your own "button action", and do whatever you want to do when button clicked. (joomla/Manual#97)

But legacy code still should work, maybe something missed.

avatar Ruud68
Ruud68 - comment - 7 Sep 2023

Hi @Fedik thanks for following up.
there is no $button->link as this is plugin does not have a way to produce the contents of an iFrame. Instead it produces the modal itself.

        $button          = new CMSObject();
        $button->modal   = true;
        $button->editor  = $name;
        $button->text    = Text::_('PLG_EDITORS-XTD_OCHELEMENTS_BUTTON_OCHELEMENTS');
        $button->name    = $this->_type . '_' . $this->_name;
        $button->icon    = 'code';
        $button->iconSVG = '<svg viewBox="0 0 24 24" style="fill:none;" width="24" height="24" fill="none" stroke="currentColor" focusable="false"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path></svg>';
        $button->options = ['confirmCallback' => true];

        // Create the Bootstrap Modal, the Joomla Helper class for this is to limited
        $modalId         = $button->editor . '_' . $button->name . '_modal';
        $modalLayout     = new FileLayout('modal', JPATH_PLUGINS . '/editors-xtd/ochelements/layouts/');
        $modalBodyLayout = new FileLayout('buttons', JPATH_PLUGINS . '/editors-xtd/ochelements/layouts/');
        $modalBody       = $modalBodyLayout->render(['editor' => $button->editor, 'content' => $pluginResults]);
        echo $modalLayout->render(['modalId' => $modalId, 'modalBody' => $modalBody]);

        return $button;

So the above code works because I added the confirmCallback option, without it the button shows, but will not open the modal.

I took a quick look at the new api and this is not an option for me: 70% of my customers is still on J3, and I do not want to maintain 3 versions of my extensions: Already noticed other B/C that required refactoring going to 5.0 for some of my extensions. So I need to be able to do it the way it was in J4 (which worked in J3) without B/C or with a workaround that will not break things.

This is what the modal looks like: the editor-xtd plugin triggers an event to which my other plugins / extensions respond: so the other plugins provide the content for the modal. ochElement (the editor plugin) then shows the collected results (buttons) in the form. Clicking the buttons in the modal will then insert the appropriate tag for the clicked button / functionality

image

avatar Fedik
Fedik - comment - 7 Sep 2023

@Ruud68 Please test #41633 that should keep old behavior untill Joomla 6.

avatar Ruud68
Ruud68 - comment - 7 Sep 2023

Just to understand what is happening here:
previously we had (bootstrap) modals, you are replacing these with (custom Joomla) dialogs. Correct?

If so, would it then not make more sense to have the $button->action have the values:

  • modal > which will then use / display the templates (bootstrap) modal
  • dialog > the (custom joomla) dialogs

That makes more sense (at least to me) then trying to figure out what the difference is between $button->modal = true and $button->action = modal

Another benefit is that there is no need to deprecate things, as both template (bootstrap) modals are supported (also beyond v6) and the new (custom Joomla) dialogues can perfectly coexist and then the developer can decide what to use without being forced into dialogues.

Just my 2cts.

avatar Fedik
Fedik - comment - 7 Sep 2023

$button->modal = true

This is old way to make modal.

The problem with existing BS modals, in the way they are rendered they does not work properly when the field is used in repeatable mode, example in a subform field.
That why I would not do $button->action = 'modal' and $button->action = 'dialog'

$button->action = 'foobar'

This is a new API to asign specific action to your button.
In core Joomla provide modal action, that will display a Dialog.
Hovewer you can do your custom action, and it will run when user click the button

Look the link https://manual.joomla.org/docs/next/building-extensions/plugins/editors-xtd-plugin
There you can find how to do $button->action = 'insert-cat';

avatar Ruud68
Ruud68 - comment - 7 Sep 2023

Thanks for the explanation and i understand what you are trying to solve, but when an extension developer doesn't migrate to dialogue and sticks to (bootstrap) modal then the issue in the subform field is not solved, correct?

Is the issue in the subform field related / caused by the id of the modal not being unique anymore (so multiple buttons share an id?), if so then IMO that is where things should be fixed, not by introducing new technology.

Again, just my 2cts

avatar HLeithner
HLeithner - comment - 17 Sep 2023

for consistent we only should support one look and feel, if 3rd party would like to use another popup tool then they can do it. It's not nice but possible. For us we fixed the subform issue with the new dialog, so "bug fixed" for us. If you or someone else provide a b/c fix for the bootstrap issue we will of course consider it. But it's hard to support multiple ways to do the same thing with our resources.

anyway thanks for bringing this up and I hope the solution provided by Fedir works at least the same as before without b/c break.

Add a Comment

Login with GitHub to post a comment