Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple (different) editors in one page #12561

Merged
merged 23 commits into from Feb 22, 2017
Merged

Allow multiple (different) editors in one page #12561

merged 23 commits into from Feb 22, 2017

Conversation

dgrammatiko
Copy link
Contributor

@dgrammatiko dgrammatiko commented Oct 25, 2016

Pull Request for Issue #12555

XTD-Buttons will NOT work if more than one (and different) editors are rendered on the page

Steps to reproduce

Make sure that the default editor is tinyMCE

Edit administrator/components/com_content/models/forms/article.xml and add after

    <fieldset addfieldpath="/administrator/components/com_categories/models/fields" >

this:

        <field
                name="test2"
                label ="Test Field"
                type="editor"
                width="300"
                filter="safehtml"
                editor="none"
                buttons="true"/>
        <field
                name="test3"
                label ="Test Field"
                type="editor"
                width="300"
                filter="safehtml"
                editor="codemirror"
                buttons="true"/>

Edit administrator/components/com_content/views/article/tmpl/edit.php and add after

                <fieldset class="adminform">
                    <?php echo $this->form->getInput('articletext'); ?>
                </fieldset>

this:

                <fieldset class="adminform">
                    <?php echo $this->form->getInput('test2'); ?>
                </fieldset>
                <fieldset class="adminform">
                    <?php echo $this->form->getInput('test3'); ?>
                </fieldset>

Then try to use the buttons to insert some images, contacts, etc. Oops it's broken for all except the last one.

Summary of Changes

Introducing a simple API which is just some setters and some getters.
This is more informative:

// An object to hold each editor instance on page, only define if not defined.
Joomla.editors.instances = Joomla.editors.instances || {
        /**
         * Editors MUST register, per instance, the following:
         *
         * getValue         Type  Function
         *          Should return the complete data from the editor
         *          Example: function () { return this.element.value; }
         * setValue         Type  Function
         *          Should replace the complete data of the editor
         *          Example: function (text) { return this.element.value = text; }
         * replaceSelection  Type  Function
         *          Should replace the selected text of the editor
         *          If nothing selected, will insert the data at the cursor
         *          Example: function (text) { return insertAtCursor(this.element, text); }
         *
         * USAGE (jform_articletext is the editor id)
         * getValue:
         *      Joomla.editors.instances['jform_articletext'].getValue();
         * setValue:
         *      Joomla.editors.instances['jform_articletext'].setValue('Joomla! rocks');
         * replaceSelection:
         *      Joomla.editors.instances['jform_articletext'].replaceSelection('Joomla! rocks')
         *
         * *********************************************************
         * ANY INTERACTION WITH THE EDITORS SHOULD USE THE ABOVE API
         * *********************************************************
         */
    };

Testing Instructions

Apply this patch
Go to back end and edit/create an article
On purpose there are all the editors in that page
Try the buttons in all of them. Cool eh?

Documentation Changes Required

The comment above comes from core.js but needs to be published also in the form->editor page.

TL;DR

Some images then:
screen shot 2016-10-26 at 01 13 16

screen shot 2016-10-26 at 01 14 23

Calling @Fedik @andrepereiradasilva @ggppdk @mbabker


This change is Reviewable

@dgrammatiko
Copy link
Contributor Author

@okonomiyaki3000 can you check the changes I did in codemirror here?

@dgrammatiko dgrammatiko changed the title Allow multiple editors in one page Allow multiple (different) editors in one page Oct 25, 2016
@okonomiyaki3000
Copy link
Contributor

I'm not sure what this media/system/js/editor-codemirror.js is about but I don't like it.

@dgrammatiko
Copy link
Contributor Author

it's just the initiator script, this way there is no inline script at all

@okonomiyaki3000
Copy link
Contributor

I don't think there's anything wrong with inline script. The problem with this is that it seems to be part of Joomla core instead of the CodeMirror plugin and it can't be overridden like the current version can (via layouts).

@dgrammatiko
Copy link
Contributor Author

@okonomiyaki3000 not quite true, you can still use the layouts although a tiny script will be missing (the one that comes from code mirror.php). But if it breaks B/C I can revert it and redo this in J4

@okonomiyaki3000
Copy link
Contributor

Sorry, I can't get behind putting files used by the editors in media/system/js/. They just don't belong there. The editors should be thought of as optional plugins, decoupled from the Joomla core.

@dgrammatiko
Copy link
Contributor Author

@okonomiyaki3000 I will revert that part, but this PR is NOT about the initialisation of the editors, it solves a very fundamentally wrong architectural concept that limits joomla to only one editor per page...

@okonomiyaki3000
Copy link
Contributor

@dgt41 Yes, I'm aware of the limitation. It limits Joomla to only one type of editor per page. You may still have multiple instances of the same type. It's quite a glaring flaw and I'm glad you're fixing it but we must first do no harm.

@dgrammatiko
Copy link
Contributor Author

@ggppdk can you test this one?

@ggppdk
Copy link
Contributor

ggppdk commented Nov 1, 2016

@dgt41

will do tomorrow, thanks for the work on this one

@dgrammatiko
Copy link
Contributor Author

@okonomiyaki3000 I've restored the inline initialisation script for codemirror...

@okonomiyaki3000
Copy link
Contributor

I don't know, I'm still seeing media/system/js/editor-codemirror.js. What about other editors?

@dgrammatiko
Copy link
Contributor Author

What about other editors?

Other editors also using static scripts in media/editors/whatever/js. Also code mirror should move to static script in J4

@okonomiyaki3000
Copy link
Contributor

Isn't media/editors/whatever/js just the editor's distro code? Is Joomla-specific code meant to go in there too?

@dgrammatiko
Copy link
Contributor Author

Right now the folders ``media/editor/whateverare maintained/manipulated by joomla, in J4 the aim is that foreign code should live inmedia/vendor/` folder and there should be an automated way to manage the updates (code is already written for that).
So here is a glimpse from the future (j4):
screen shot 2016-10-31 at 09 28 58

@okonomiyaki3000
Copy link
Contributor

I see, that makes sense I guess. Does that mean that the libraries under vendor must be used as distributed? What if we prefer custom builds?

@dgrammatiko
Copy link
Contributor Author

@okonomiyaki3000 I guess this will manage only the joomla distributed code, I have no clue if this will be extended somehow for 3rd PD (my guess is no, 3rd PD could provide their custom code in their own directory). Or you can manipulate or override the grunt script and get whatever you want, with the added step to re-run the script every time joomla updates these assets...

@infograf768
Copy link
Member

Conflicts

@@ -28,6 +28,24 @@
label="COM_CONTENT_FIELD_ARTICLETEXT_LABEL" description="COM_CONTENT_FIELD_ARTICLETEXT_DESC"
filter="JComponentHelper::filterText" buttons="true" />

<field
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgt41 Can you look into the formatting here? The indentation seems to be broken, same for closing tag. And you have some white space at the label.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yvesh this whole section is here only for testing, will be and should be removed before merging, thus the wrong indentation

@@ -111,8 +123,9 @@
<span class="<?php echo $iconStates[$this->escape($item->state)]; ?>"></span>
</td>
<td>
<a href="javascript:void(0);" onclick="if (window.parent) window.parent.<?php echo $this->escape($function); ?>('<?php echo $item->id; ?>', '<?php echo $this->escape(addslashes($item->title)); ?>', '<?php echo $this->escape($item->catid); ?>', null, '<?php echo $this->escape(ContentHelperRoute::getArticleRoute($item->id, $item->catid, $item->language)); ?>', '<?php echo $this->escape($lang); ?>', null);">
<?php echo $this->escape($item->title); ?></a>
<a class="select-link" href="javascript:void(0)" data-function="<?php echo $this->escape($onclick); ?>" data-id="<?php echo $item->id; ?>" data-title="<?php echo $this->escape(addslashes($item->title)); ?>" data-cat-id="<?php echo $this->escape($item->catid); ?>" data-uri="<?php echo $this->escape(ContentHelperRoute::getArticleRoute($item->id, $item->catid, $item->language)); ?>" data-language="<?php echo $this->escape($lang); ?>">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way to make this more readable and less long? :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not use as many attributes or start formatting our HTML the same way our XML files are formatted (and I find THAT ugly and painful to keep up with personally).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbabker would you prefer something like:

                            <?php $attribs = 'data-function="' . $this->escape($onclick) . '"'
                                . ' data-id="' . $item->id . '"'
                                . ' data-title="' . $this->escape(addslashes($item->title)) . '"'
                                . ' data-cat-id="' . $this->escape($item->catid) . '"'
                                . ' data-uri="' . $this->escape(ContentHelperRoute::getArticleRoute($item->id, $item->catid, $item->language)) . '"'
                                . ' data-language="' . $this->escape($lang) . '"';
                            ?>
                            <a class="select-link" href="javascript:void(0)" <?php echo $attribs; ?>>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, for this you could just as usually use JHtml::_('link', 'javascript:void(0)', $this->escape($item->title), $attribsArray); and it not be unbearable. What you have works too, I'm just honestly not the biggest fan of some of our code style rules with line concatenation and splitting elements on separate lines in funny places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until recently, I seriously thought our iframe and link HTML helpers were silly as all can be. But then I started thinking that they're actually pretty useful for elements where you're adding a lot of data in some form (in this case data attributes) so you can throw those elements in an array and pass them into a function which converts it to the proper string. End result is still the same; clean PHP code and clean HTML output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    /**
     * Write a `<a>` element
     *
     * @param   string        $url      The relative URL to use for the href attribute
     * @param   string        $text     The target attribute to use
     * @param   array|string  $attribs  Attributes to be added to the `<a>` element
     *
     * @return  string
     *
     * @since   1.5
     */
    public static function link($url, $text, $attribs = null)

I've learned something today 😄

editor = Joomla.getOptions('xtd-contacts').editor;

if (lang !== '')
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are mixing php and js code style here ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy-paste...

* Javascript to insert the link
* View element calls jSelectContact when a contact is clicked
* jSelectContact creates the link tag, sends it to the editor,
* and closes the select frame.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it would be nice to have since tags in js too.. Any thoughts on that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be a way, have to do some testing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yvesh so what is the @since supposed to be for all these scripts, because ok now they are static files but the code comes from way back?

hreflang = ' hreflang = "' + lang + '"';
}

tag = '<a' + hreflang + ' href="' + link + '">' + title + '</a>';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally i would prefer when you do a document.createElement('a') here etc. then hardcoding a link into a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too fast, we do support IE8, so not possible

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm document.createElement should work in IE8?

// Get the elements
var elements = document.querySelectorAll('.select-link');

for(var i = 0, l = elements.length; l>i; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, why are you saving elements length in a variable? ;) cs btw.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need for speed 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

itar in phpstorm create those...

title = (title != '') ? 'title="' + title + '"' : '';
alt = (alt != '') ? 'alt="' + alt + '"' : '';

tag = '<hr class="system-pagebreak" ' + title + ' ' + alt + '/>';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, wouldn't document.createElement be nicer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IE8

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm it should work fine in IE8? Shouldn't it? We use document.createElement in a lot of other JS files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it shouldn't be any problem, just checked...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yvesh checking this again, I am not in favour as we are passing a string to the editor and I have no clue if all editors out there will be happy with an element instead of a string

content = (new Function('return ' + options.editor))();

if (content.match(/<hr\s+id=("|')system-readmore("|')\s*\/*>/i)) {
alert(options.exists);
Copy link
Member

@yvesh yvesh Nov 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alert? :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's what was there, what else can it be?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why it is there any ways, but not a fan of alerts at all ;) Maybe use Joomla.renderMessages instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess is the same story as the buttons of the toolbar, where also an alert is utilised...
Honestly I don't mind changing it to Joomla.renderMessages()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yvesh This was a great idea generator, so J4 will come with some shiny new thingy that will cover those cases

@anibalsanchez
Copy link
Contributor

I have tested this item ✅ successfully on 3550213

Test OK


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/12561.

@dgrammatiko
Copy link
Contributor Author

@ggppdk @rvbgnu @infograf768 can we have one more test here, so we can RTC this?

@rvbgnu
Copy link
Contributor

rvbgnu commented Feb 5, 2017

So nobody for this test ?

Or should I re-test it (changes since 08/01/2017)??


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/12561.

@dgrammatiko
Copy link
Contributor Author

@rvbgnu if you can re-test this, will be great

@rvbgnu
Copy link
Contributor

rvbgnu commented Feb 5, 2017

So I've tried, but it doesn't change before or after the patch. The TinyMCe also had an update. I have to reset with repository copy and re-install I think...


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/12561.

@dgrammatiko
Copy link
Contributor Author

dgrammatiko commented Feb 11, 2017

but it doesn't change before or after the patch

@rvbgnu the article form doesn't have the extra editors anymore. That needs to be done by editing the xml and the view files. The initial approach had those extra editors as a way to make testing easier...

@laoneo
Copy link
Member

laoneo commented Feb 21, 2017

I have tested this item ✅ successfully on 3550213

If this is in, then we can offer the different editors attributes on com_fields.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/12561.

@dgrammatiko
Copy link
Contributor Author

RTC


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/12561.

@joomla-cms-bot joomla-cms-bot added the RTC This Pull Request is Ready To Commit label Feb 21, 2017
@dgrammatiko
Copy link
Contributor Author

Note to whomever might merge this: please ping to update the documentation for the editor input field, etc

@zero-24 zero-24 added this to the Joomla 3.7.0 milestone Feb 21, 2017
@rdeutz rdeutz merged commit a4b880b into joomla:staging Feb 22, 2017
@joomla-cms-bot joomla-cms-bot removed the RTC This Pull Request is Ready To Commit label Feb 22, 2017
@dgrammatiko dgrammatiko deleted the +++multiple_editors branch February 22, 2017 17:15
@zero-24
Copy link
Contributor

zero-24 commented Feb 22, 2017

Note to whomever might merge this: please ping to update the documentation for the editor input field, etc

@dgt41 ping :P

@svenbluege
Copy link
Contributor

I just grabbed the latest build and run into an issue with having multiple editors on the same page. Seems like only one of them gets initialized. I have three of them in my example. The Joomla.editors.instances object contains just the first editor instance. The tinyMCE.editors shows one as well. If I click the "toggle editor" button, this field shows up in tinyMCE.editors.

image

This can also be reproduced by changing some form elements of the com_content/forms/article.xml to type editor:

image

@dgrammatiko
Copy link
Contributor Author

I just grabbed the latest build and run into an issue with having multiple editors on the same page.

That's impossible (each tinyMCE or code mirror or none has it's own instance) according to the code: https://github.com/joomla/joomla-cms/blob/staging/media/editors/tinymce/js/tinymce.js#L65-L79
Can you type Joomla.editors and press enter in your browsers console? Do you have all the instances there?

@dgrammatiko
Copy link
Contributor Author

@svenbluege actually there is a bug, but here is the fix: #14194

Thanks for testing!

@svenbluege
Copy link
Contributor

@dgt41 works for me. Thanks!

@infograf768
Copy link
Member

It looks like this has broken inserting menu item urls
#14890

Please look @dgt41

@dgrammatiko
Copy link
Contributor Author

@infograf768 check #14902

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet