10

在 CKEditor 中创建新段落时,前一段的属性(样式、类)会被复制到新段落中。有没有办法防止这种情况?

例如,如果我在一个居中的段落中写作,然后按 Enter 创建一个新段落,我的用户希望新段落是一个简单的

默认情况下没有“继承”以前的任何东西。


编辑

我设法让它(危险地未经测试)与 Reinmar 的技巧一起工作。这就是我的结论;我希望这对其他人有帮助。如果你们在这里看到明显的错误,请告诉我

CKEDITOR.on('instanceCreated', function(e) {
    e.editor.on('key', function(evt) {
        if (evt.data.keyCode === 13) {
            // if we call getStartElement too soon, we get the wrong element
            setTimeout(function () {
                var se = e.editor.getSelection().getStartElement();
                if(se.getName() == "span") {
                    var text = se.getText(); // Store text, we are about to nuke the spans
                    while (se.getName() == "span") { // possible infinite loop danger
                        se = se.getParent();
                    }
                    if (text.length == 0)
                        se.setHtml(" "); // It's important that this is not empty
                    else
                        se.setHtml(text);
                }
                debug(se.getHtml());
                se.removeAttribute("class");
                se.removeAttribute("mycustomattr");
                se.removeAttribute("myothercustomattr");
                window.bla = se; // useful for debugging
            }, 10);
        }
    });
}); 
4

3 回答 3

12

即将推出的 CKEditor v4(当前的夜间)也有类似的问题。我从我的自定义图像浏览器中插入一个带有图像和自定义类的段落,CKEditor 不断将这些类复制到图像之后创建的段落。

我不喜欢keyevent 之后 call of的想法setTimeout,所以我稍微检查了源代码,结果发现它非常简单。

当您按下回车键时,CKEditor 实际上会发出enter命令。您需要做的就是设置一个afterCommandExec事件并找到新创建的空元素:

editor.on('afterCommandExec', function (e) {
    if (e.data.name == 'enter') {
        var el = e.editor.getSelection().getStartElement();

        // when splitting a paragrah before it's first character,
        // the second one is selected
        if (el.getHtml() != '<br>') {
            if (el.hasPrevious() && el.getPrevious().getHtml() == '<br>') {
                el = el.getPrevious();
            } else {
                // both paragraphs are non-empty, do nothing
                return;
            }
        }

        // modify el according to your needs
    }
});

希望这可以帮助!

于 2012-11-15T15:20:45.937 回答
2

这是一个旧帖子,但我一直有同样的问题,我终于得到了一些工作,所以我想分享我的解决方案。对于那些不知道我们为什么想要这个功能的人,这是我的解释:

默认情况下,CKEDITOR 尝试允许用户在按下回车键插入新行时继续使用相同的样式。换句话说,如果您的文本是粗体且居中的,并且您按下回车键,ckeditor 会复制该样式,以便新行也是粗体和居中的。除非您想插入更复杂的东西,例如具有属性的嵌套元素(例如通过插件),否则这非常有用。当您在具有类的元素中按 Enter 键时,ckeditor 会创建一个具有相同类的新段落元素,如果该类依赖于父元素的存在,则该元素将不起作用(这是一个成为问题的示例:http: //jsfiddle.net/B4yGJ/158/)。

我提出的解决方案结合了 Reinmar 和 Nenotlep 的代码和建议:

// create object of safe classes
var safe_classes = {};
$.each(ckeditor_styles_full, function(i, style) {
    if(style['attributes']) {
        var style_classes = style['attributes'].class;
        var style_element = style['element'];

        if(typeof safe_classes[style_element] != "object") {
            safe_classes[style_element] = [];
        }

        style_classes = style_classes.split(" ");
        $.each(style_classes, function(i, v) {
            if($.inArray(v, safe_classes[style_element]) <= -1) {
                safe_classes[style_element].push(v);
            }
        });
    }
});

$.each(CKEDITOR.instances, function(i, editor) {
    editor.on('key', function(e) {
        if (e.data.keyCode === 13) {
            setTimeout(function () {
                var se = e.editor.getSelection().getStartElement();
                var parent = se.getParent().getName();
                if(parent == "html" || parent == "body") {
                    var se_classes = se.getAttribute('class');
                    var new_classes = [];
                    se.removeAttribute("class");

                    if(se_classes !== null) {
                        se_classes = se_classes.split(" ");
                        $.each(se_classes, function(i, v) {
                            if(typeof safe_classes[se.getName()] != 'undefined') {
                                if($.inArray(v, safe_classes[se.getName()]) > -1) {
                                    se.addClass(v);
                                }
                            }
                        });
                    }
                }
            }, 10);
        }
    });
});

下面是它的工作原理:首先,脚本从所选样式列表中抓取类名,并按元素类型将它们编译成一个对象。然后,它遍历将事件绑定到回车键的所有 CKEDITOR 实例。接下来,它检查当您按下回车键时创建的元素是否在 HTML 或 BODY 之外的父元素内(即,它是较大元素树的一部分)。最后,如果它不在容器元素内,它会从该元素中删除所有不在之前创建的“safe_classes”对象中的类。

2 个重要的旁注: 1) 你仍然需要设置 "forceEnterMode: true" 2) 因为 "forceEnterMode" 设置为 true,所以最好只嵌套段落元素。例子:

<div class="container"><p class="title">Title Text</p><p class="content">Content Goes Here</p></div>

否则,如果您在嵌套的 div 中按 enter,ckeditor 会将所有该 div 的属性复制到一个段落元素中。

于 2014-08-13T00:34:24.587 回答
2

这两天我一直在想你的问题,我有了一个想法。我检查了输入插件代码,最好不要动它。相反,您可以收听 enter 键,在执行我们的自定义输入后,您应该从新创建的块中清除样式。

这些方法将很有用:

  • editor.on( 'key', function( evt ) { evt.data.key... } )
  • editor.getSelection().getStartElement()- 输入选择开始后将被放置在新创建的块中(+ 行内元素,如粗体、下划线等)。
  • CKEDITOR.dtd.*- 元素集可以帮助您决定哪些元素是内联样式并且应该被删除。
  • element.isEmptyInlineRemoveable- 您应该删除放置光标的空行内元素。
  • editor.createRange().setStartAt( block, 0 ).select()- 最后你应该将插入符号放在正确的位置(在块的开头 - <p>/ <div>/ <li>/等)。

不幸的是,正如你所见,这不是一件容易写的事情,祝你好运:)

于 2012-10-18T07:09:08.840 回答