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

TinyMCE 5 Preview: Create new UI controls by extending existing ones #4588

Open
ryandemmer opened this issue Oct 3, 2018 · 15 comments

Comments

@ryandemmer
Copy link
Contributor

commented Oct 3, 2018

In Tinymce 4.x it is possible to create new UI controls by extending existing controls, eg:

var DataList = tinymce.ui.ComboBox.extend({
    init: function() {
         this._super();
    },
    value: function(value) {
        this._super(value);
    }
});
tinymce.ui.Factory.add('DataList', DataList);

but this does not appear to be possible in Tinymce 5, as the UI controls are not exposed in the API.

Is there another way this is done in Tinymce 5?

@androb androb added the v5 label Oct 3, 2018

@TheSpyder TheSpyder added 5.x and removed v5 labels Oct 3, 2018

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Oct 4, 2018

You're right, the intention of the new UI is that controls are not exposed in the API directly.

The aim is to provide flexible components that don't need to be extended, making it easier to create dialogs that adjust to the active skin. The reduced API surface will also be easier for us to maintain.

Whether we are able to maintain that separation is something we hope to find out with this Developer Preview :)

Can you tell us more about why you need to extend controls?

@ryandemmer

This comment has been minimized.

Copy link
Contributor Author

commented Oct 4, 2018

You're right, the intention of the new UI is that controls are not exposed in the API directly.

The aim is to provide flexible components that don't need to be extended, making it easier to create dialogs that adjust to the active skin

That makes the UI less useful, as it restricts developers to the rather limited set of controls that you create an maintain, which are suitable for only simple dialogs. It also prevents developers from creating new controls for the toolbar, or adding features to existing ones.

Can you tell us more about why you need to extend controls?

Quite simply because the UI, in its present form and in Tinymce 5, does not provide the controls I require to accomplish the tasks that I need them to. Over quite a long period of time, I have created and tested a number of controls to suit my purposes.

Here is an example of some of the controls I have created in use:

JCE custom controls example

@ryandemmer

This comment has been minimized.

Copy link
Contributor Author

commented Oct 4, 2018

All of these custom controls (and others not pictured) require extension of existing controls. Although Tinymce 5 appears to include versions of some of the controls I have created - ColorPicker, SizeInput, UrlInput - they do not contain the features I require for my use cases.

I'm sure other developers appreciate the ability to extend controls in Tinymce 4 and would also like to see that option in Tinymce 5.

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Oct 4, 2018

Thanks for the example! Along with the new controls you've found, some of that is already possible but not documented or fully exposed such as autocompleting input fields. For the initial release we've focussed on matching TinyMCE 4 in a lot of cases while the framework actually supports much more.

I'm raising this with the appropriate people and we will get a discussion rolling.

@ryandemmer

This comment has been minimized.

Copy link
Contributor Author

commented Oct 4, 2018

Thank you.

I would like to stress that even if the core UI supports many similar controls, it would still be beneficial (or essential in my case) to be able to create custom controls and extend core UI controls. There will always be a case where something extra is required.

Here is the code for my "CustomValue" control demonstrated in the Attributes tab (without the repeatable option) to show the kind of control extension I am referring to:

/**
   * This class creates a CustomValue control.
   *
   * @class tinymce.ui.CustomValue
   * @extends tinymce.ui.FormItem
   */
tinymce.ui.CustomValue = tinymce.ui.FormItem.extend({

    Defaults: {
        spacing: 5
    },

    /**
     * Constructs a instance with the specified settings.
     *
     * @constructor
     * @param {Object} settings Name/value object with settings.
     */
    init: function (settings) {
        var self = this;

        settings.values = settings.values || [];

        settings.size = settings.size || 35;

        self._super(settings);
        self.classes.add('customvalue');
    },

    name: function () {
        var prefix = this.settings.prefix || '';

        return prefix + this._items[0].value();
    },

    /**
     * Getter/setter function for the control value.
     *
     * @method value
     * @param {Object} [value] Value to be set.
     * @return {Object|tinymce.ui.CustomValue} Value or self if it's a set operation.
     */
    value: function (value) {
        if (typeof value !== 'undefined') {

            if (typeof value !== "object") {
                return this;
            }

            this.state.set('value', value);

            if (this.state.get('rendered')) {

                for (var key in value) {
                    this._items[0].value(key);
                    this._items[1].value(value[key]);
                }
            }

            return this;
        }

        // Make sure the real state is in sync
        if (this.state.get('rendered')) {
            value = "";

            var key = this._items[0].value();

            if (key) {
                value = {};
                value[key] = this._items[1].value();
            }

            this.state.set('value', value);
        }

        return this.state.get('value');
    },

    /**
     * Post render method. Called after the control has been rendered to the target.
     *
     * @method postRender
     * @return {tinymce.ui.CustomValue} Current CustomValue instance.
     */
    postRender: function () {
        var self = this,
            id = this._id,
            settings = self.settings;
        self._super();

        var name = {
            type: 'textbox',
            size: settings.size,
            placeholder: 'Name'
        };

        var value = {
            type: 'textbox',
            size: Math.floor(settings.size * 1.25),
            placeholder: 'Value'
        };

        if (settings.values.length) {
            name = {
                type: 'datalist',
                placeholder: 'Name',
                values: settings.values
            }

            value.size = settings.size;
        }

        // create datalist of attribute names
        self.append(name).append(value).reflow();

        return self;
    }
});

tinymce.ui.Factory.add('CustomValue', tinymce.ui.CustomValue);

@androb androb changed the title Tinymce 5 Preview: Create new UI controls by extending existing ones TinyMCE 5 Preview: Create new UI controls by extending existing ones Oct 4, 2018

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Oct 8, 2018

Would it be enough if we included a plugin with all of the 4.x UI controls? Dialogs created that way may not match the TinyMCE 5 dialog style (unless you apply that yourself), but that would let you retain the benefits of our improved default dialogs and toolbar while also using custom dialogs as necessary.

@ryandemmer

This comment has been minimized.

Copy link
Contributor Author

commented Oct 8, 2018

Does mean that each dialog that contains at least one custom control will have to be built entirely with the old UI? I assume that it would not be possible to mix and match the old and new UI.

Unfortunately this does not solve the original problem, which is that the new UI is not extendable, and therefore any ambitious developer must therefore either accept the limitations of the new UI, or use some other solution to display complex dialogs.

@cshelleig

This comment has been minimized.

Copy link

commented Jan 21, 2019

I see that tinymce.ui is still referenced in the docs, but, is in fact, gone. viz.
https://www.tiny.cloud/docs-beta/api/tinymce.ui/tinymce.ui.factory/
Is there a plan to re-implement tinymce.ui.factory?

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Jan 21, 2019

No, the factory was left in by accident when we deleted the ui folder. The documentation generator is a bit unstable due to the age of the code so the website can be out of date at times.

The release will happen as scheduled without extendable controls, we will evaluate our options to fill this need afterwards.

@cshelleig

This comment has been minimized.

Copy link

commented Jan 21, 2019

I rather assumed so. We create some lighter weight instances of the editor, and/or use the same textarea with a light weight one of our own. Up til now we used methods like
tinymce.ui.Factory.create({
type: 'buttongroup',
and so on.
Is there a known work around for something like that?
I'm still reading docs and code to see what might work.

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Jan 22, 2019

Are you talking about the toolbar? This discussion was centred around dialogs. I'm wondering whether toolbar customisation could be replaced with tweaks to the inline or quickbars (previously inlite) UIs.

@cshelleig

This comment has been minimized.

Copy link

commented Jan 22, 2019

Ding! my bad. will search around and see what i can see.
thanks, and sorry for polluting the thread.

@TheSpyder

This comment has been minimized.

Copy link
Member

commented Jan 22, 2019

That's ok! We appreciate feedback on this release in all forms ☺️

@josh18

This comment has been minimized.

Copy link

commented Apr 24, 2019

Is there any info around how to customise toolbar buttons? Or is it the same boat as dialogues? TheSpyder mentioned something but I can't really find any other info.

Specifically I want to be able to manage the enable / disable state of built in buttons such as indent without having to rebuild the whole button but I can't see any way to do this.

@TheSpyder

This comment has been minimized.

Copy link
Member

commented May 7, 2019

There isn't a supported way, no. I can think of a trick that would make re-registering the built in button easier but it relies on implementation details which may be subject to change in the future.

@androb androb unpinned this issue May 23, 2019

@TheSpyder TheSpyder pinned this issue Jul 5, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.