ckeditor / ckeditor5

Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.
https://ckeditor.com/ckeditor-5
Other
8.22k stars 3.58k forks source link

Adding balloons and toolbars to widgets #7825

Open piernik opened 3 years ago

piernik commented 3 years ago

We have tutorial for creating new elements and widgets which is great, but there is no tutorial how to use tools in those widgets. I mean tools like in edit link or image styles. I need to make bootstrap card which has different colors (for headers or borders). I want to pick those classes from floating tools. Maybe You can give me some guidance? A sample code?

piernik commented 3 years ago

Any news on this one? Tutorial, stackblitz example or anything? Right now I need to make only two buttons in my widget to set an attribute.

Reinmar commented 3 years ago

Hi! Sorry for replying so late.

I'm afraid we don't have a tutorial. In fact, we want to rewrite a big part of the balloons API as it got awfully complex when we added all the features.

However, this may help you:

piernik commented 3 years ago

Thanks for response. I managed to make my own plugin with help of Your existing code, but I have to admit - it is very complex. Please rewrite the code or make some helper classes for us.

piernik commented 3 years ago

Can You please add tutorial with using custom toolbars and balloons to docs? I'm still not able to do what I want. :/

piernik commented 3 years ago

@Reinmar You posted that balloons API will be changed. I didn't see any changes in previous versions. Are You planning to change API any soon? In my free time want to come back and try to make my plugins. Are You planning posting some tutorials?

leevigraham commented 1 year ago

+1 for a simple explanation of triggering a balloon. I think a good place for this could be the simple block documentation. Maybe changing the css class of the block?

leevigraham commented 1 year ago

@piernik

Here's my working toolbar.

import {Plugin} from '@ckeditor/ckeditor5-core';
import {isWidget, WidgetToolbarRepository} from '@ckeditor/ckeditor5-widget';

export default class CalloutBoxToolbar extends Plugin {

    static get requires() {
        return [WidgetToolbarRepository];
    }

    static get pluginName() {
        return 'CalloutBoxToolbar';
    }

    afterInit() {
        console.log('CalloutBoxUI#afterInit() got called');
        const editor = this.editor;
        const t = editor.t;
        const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);
        widgetToolbarRepository.register('calloutBox', {
            ariaLabel: t('Callout Box toolbar'),
            // Toolbar Buttons
            items: ['calloutBoxStyle'],
            // If a related element is returned the toolbar is attached
            getRelatedElement: (selection) => {
                const viewElement = selection.getSelectedElement();

                // If the viewElement is a widget and
                // the viewElement has a custom property `calloutbox`
                // return it.
                //
                // `calloutbox` is set on the view element when it is created by the writer
                // during downcast in _defineConverters
                // @see: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/tutorials/implementing-a-block-widget.html#making-simple-box-a-widget
                // @see: https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-media-embed/src/mediaembedediting.js#L215
                if (viewElement && isWidget(viewElement) && !!viewElement.getCustomProperty('calloutbox')) {
                    return viewElement;
                }

                return null;
            }
        });
    }
}
hannsta commented 1 year ago

@leevigraham can you elaborate on how calloutBoxStyle is defined in your example?

leevigraham commented 1 year ago

calloutBoxStyle is a toolbar button which is defined as another plugin. If you leave items empty you'll see an empty toolbar appear.

gregg-cbs commented 5 months ago

I have been reading through the docs and web for about 4 hours and I still have not seen an example on how to add a custom balloon toolbar or edit an existing balloon, like the one used on links.

This issue is the only place I have seen someone post a code example and its not even a proper balloon. Please CK authors, help out here. You boast that this is the editor of the future now.

This is just a few of the pages I have gone through and I still have not found a decent answer: image

leevigraham commented 5 months ago

@gregg-cbs I agree it can be super frustrating. Here's a GitHub issue that might help: https://github.com/ckeditor/ckeditor5/issues/4836#issuecomment-1422740830

Witoso commented 5 months ago

Hey @gregg-cbs, thanks for your feedback. I added the mentioned comment to our how-to's (PR: #15387), we will also prioritize the tutorial that will guide how to set up a toolbar on a widget: #15360.

That said, this form of how-to's is not the best for the discoverability, beginning of the next year we have a project planned for the docs restructuring.

gregg-cbs commented 5 months ago

@leevigraham - 🤯 how is that code!

gregg-cbs commented 5 months ago

@Witoso I appreciate the links, i will have a look but in terms of manageability I dont think this is going to work for my team. The code you have to write for balloons and plugins is so bespoke that its going to be confusing to manage. It doesnt follow any existing convention - not the html api or javascript dom api, its a whole new language and interface on its own... and its one thats not very clear.

In my opinion the plugin / balloon layer should just manage the container and its placement. Everything else should be standard html, js and css. I dont get why i have to register a button with this.button = this._createButton(); and render it with this.button.render(); . This code is too custom and far away from the practices that exist to create UI.

why is button click now on 'execute' what was wrong with 'click'?

button.on( 'execute', () => {
  this.linkFormView.urlInputView.value = 'http://some.internal.link';
});

It looks like a backend guy wrote a frontend library.

Witoso commented 5 months ago

Yes, it's a bespoke framework because it was written before some current “best practices frameworks” existed. We know its shortcomings, next year there will be an initiative on our side to shake things up on the UI framework side. 

But as a WYSIWYG component that exists for over 8y on the market, we care a lot about backward compatibility, and not breaking things for our users, customers, and integrators.

It looks like a backend guy wrote a frontend library.

And here constructive feedback ended, so I'm not sure how to discuss this further with you :shrug: Maybe reassurance that we have a team that creates frontend editors for around 20 years.

gregg-cbs commented 5 months ago

@Witoso im sorry for the dig. im just frustrated i guess. ckeditor has already been implemented in our codebase and i have spent more time than i would like reading the docs and not making any progress and I guess that has gotten the best of me. im frustrated and im being bratty 😄

I will come check in again next year. Thanks!