CKEditor:多个小部件模板

标签 ckeditor ckeditor4.x

我目前正在创建一个“智能对象”小部件。在小部件对话框中,用户可以选择一个“智能对象”,简单地说,它会生成一些应该添加到编辑器中的 html。棘手的部分来了:html 有时是 div 元素,有时只是简单的 span 元素。在 div 变体的情况下,小部件应包装在 div"template"中。在 span 变体的情况下,小部件应包装在 span 中,并且 html 应添加为“内联”。

在小部件 API 中,我看到了以下定义模板的方法:

editor.widgets.add('smartobject', {
                dialog: 'smartobject',
                pathName: lang.pathName,
                template: '<div class="cke_smartobject"></div>', // <------

                upcast: function(element) {
                    return element.hasClass('smartObject');
                },

                init: function() {
                    this.setData('editorHtml', this.element.getOuterHtml());
                },

                data: function() {
                    var editorHtml = this.data.editorHtml;

                    var newElement = new CKEDITOR.dom.element.createFromHtml(editorHtml);

                    newElement.copyAttributes(this.element);

                    this.element.setText(newElement.getText());
                }
            });

但在我的例子中,模板更加动态:有时 div 有时 span 会做正确的事情..

如何解决这个问题而不需要创建两个小部件来做完全相同的事情,只是包装元素不同?

我已经尝试在“数据”方法中替换整个元素,例如:

newElement.replace(this.element);
this.element = newElement;

但这似乎不受支持:在调用 editor.getData() 后导致未定义的错误。

我正在使用 ckeditor v4.5.9

感谢您的帮助!

最佳答案

看来我让它工作了(有解决方法)。 代码:

CKEDITOR.dialog.add('smartobject', this.path + 'dialogs/smartobject.js');

        editor.widgets.add('smartobject', {
            pathName: lang.pathName,

            // This template is needed, to activate the widget logic, but does nothing.
            // The entire widgets html is defined and created in the dialog.
            template: '<div class="cke_smartobject"></div>',

            init: function() {
                var widget = this;
                widget.on('doubleclick', function(evt) {
                    editor.execCommand('smartobject');
                }, null, null, 5);
            },

            upcast: function(element) {
                return element.hasClass('smartObject');
            }
        });

        // Add a custom command, instead of using the default widget command,
        // otherwise multiple smartobject variants (div / span / img) are not supported. 
        editor.addCommand('smartobject', new CKEDITOR.dialogCommand('smartobject'));

        editor.ui.addButton && editor.ui.addButton('CreateSmartobject', {
            label: lang.toolbar,
            command: 'smartobject',
            toolbar: 'insert,5',
            icon: 'smartobject'
        });

在对话框中,插入代码如下所示:

return {
    title: lang.title,
    minWidth: 300,
    minHeight: 80,

    onOk: function() {
        var element = CKEDITOR.dom.element.createFromHtml(smartobjectEditorHtml);

        editor.insertElement(element);

        // Trigge the setData method, so the widget html is transformed,
        // to an actual widget!
        editor.setData(editor.getData());
    },
...etc.

更新 我改进了“onOk”方法:插入后现在选择了 smartobject 元素。

onOk: function() {
        var element = CKEDITOR.dom.element.createFromHtml(smartobjectEditorHtml);
        var elementId = "ckeditor-element-" + element.getUniqueId();

        element.setAttribute("id", elementId);

        editor.insertElement(element);

        // Trigger the setData method, so the widget html is transformed,
        // to an actual widget!
        editor.setData(editor.getData());

        // Get the element 'fresh' by it's ID, because the setData method,
        // makes the element change into a widget, and thats the element which should be selected,
        // after adding.
        var refreshedElement = CKEDITOR.document.getById(elementId);
        var widgetWrapperElement = CKEDITOR.document.getById(elementId).getParent();

        // Better safe then sorry: if the fresh element doesn't have a parent, simply select the element itself.
        var elementToSelect = widgetWrapperElement != null ? widgetWrapperElement : refreshedElement;

        // Normally the 'insertElement' makes sure the inserted element is selected,
        // but because we call the setData method (to ensure the element is transformed to a widget)
        // the selection is cleared and the cursor points to the start of the editor.
        editor.getSelection().selectElement(elementToSelect);
    },

简而言之,我部分使用了小部件 API 来实现我想要的部分: - 使小部件的 html 不可编辑 - 使其可移动

但我创建了一个自定义对话框命令,它简单地绕过了默认的小部件插入,所以我可以完全决定我自己的小部件的 html 结构。

一切似乎都是这样。

如有任何改进建议,我们将不胜感激:)!

关于CKEditor:多个小部件模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37675811/

相关文章:

javascript - CKEditor 中的自定义模板

javascript - CKEditor:我想在所见即所得编辑器中禁止 <ul> 标签

javascript - 使用 ckeditor 功能对小段文本进行样式化

ckeditor - 仅在有效文本选择的情况下启用 CKEditor 工具栏按钮?

javascript - 有没有办法使用单个工具栏 DOM 元素来拥有多个内联配置的 ckeditors

javascript - CKEDITOR 拖放插件集成在编辑器实例被销毁并重新创建后停止工作

angular - 如何在Angular项目中集成CKEditor的上传图片插件

javascript - 如何在ckeditor中对一个元素应用多种样式?

javascript - 如何使用 javascript 选择 CKEditor 工具栏项?

javascript - CKEditor - 在一个页面中限制多个编辑器的字符