CKEditor:多个小部件模板

CKEditor:多个小部件模板,ckeditor,ckeditor4.x,Ckeditor,Ckeditor4.x,我目前正在创建一个“smartobject”小部件。在widgets对话框中,用户可以选择一个“smartobject”,简单地说,它生成一些html,这些html应该添加到编辑器中。下面是棘手的部分:html有时是div元素,有时只是跨元素。对于div变量,小部件应该包装在div“模板”中。对于span变量,小部件应该包装在span中,html应该添加为“inline” 在widgets API中,我看到了以下定义模板的方法: editor.widgets.add('smartobject',

我目前正在创建一个“smartobject”小部件。在widgets对话框中,用户可以选择一个“smartobject”,简单地说,它生成一些html,这些html应该添加到编辑器中。下面是棘手的部分:html有时是div元素,有时只是跨元素。对于div变量,小部件应该包装在div“模板”中。对于span变量,小部件应该包装在span中,html应该添加为“inline”

在widgets 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());
                }
            });
但这似乎不受支持:在调用editor.getData()后导致未定义的错误

我正在使用ckeditor v4.5.9

谢谢你的帮助

正如ckeditor论坛线程中所建议的,最好的方法是将模板设置为包含所有可能的内容元素。然后,在
data
函数中,根据您的特定逻辑删除不必要的部分。

看来我已经找到了解决方法。 守则:

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'
        });
更新 我对“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结构

一切似乎都是这样


任何建议,使它更好的是感激:)

您能否在这两种情况下都使用包装div并使用css更改该div的行为?这是个好主意,但恐怕不行,因为在以下html中添加smartobject时(在选择[smartobject]文本时):此文本包含[smartobject]

html变得无效

是不允许的。但是模板看起来如何?模板:“”?我不明白这将如何帮助我解决这个问题,因为当添加div时,例如下面的html将替换下面的[TAG]

在我有机会删除不必要的元素之前,html将中断?我认为论坛中给出的示例与我的用例并不完全相同。如果我错了,请纠正我!谢谢你的帮助!我认为,如果在将内容实际写入编辑器之前删除插件中的元素,html不会崩溃,尽管我意识到我还没有一个可用的示例来支持这一点。我用另一种方式修复了它(请参见我的答案),因为我没有按照您的方式使用它:)现在一切似乎都好了。非常感谢你抽出时间来!
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: 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);
    },