在CKEditor中创建新段落时,前一段的属性(样式,类)将被复制到新段落中。有办法防止这种情况吗?
例如,如果我正在写一个居中的段落并按回车键来创建一个新的段落,我的用户希望新的段落是一个简单的
,而不是“继承”前面的任何内容。默认值。
修改
我设法得到它(危险地未经测试)使用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);
}
});
});
答案 0 :(得分:10)
我对即将到来的CKEditor v4(当前的夜莺)也有类似的问题。我在自定义图像浏览器中插入了带有图像和自定义类的段落,CKEditor不断将类复制到图像后创建的段落。
我不喜欢key
事件后跟setTimeout
调用的想法,所以我对源代码进行了一些检查,结果非常简单。
当您按Enter键时,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
}
});
希望这有帮助!
答案 1 :(得分:2)
过去两天我在考虑你的问题而且我有一个想法。我检查了输入插件代码,最好不要接触它。相反,您可以听取输入键,在执行自定义输入后,您应该清除新创建的块中的样式。
这些方法很有用:
editor.on( 'key', function( evt ) { evt.data.key... } )
editor.getSelection().getStartElement()
- 在输入选择之后,start将被放置在新创建的块中(+内联元素,如粗体,下划线等)。CKEDITOR.dtd.*
- 元素集可以帮助您决定哪些元素是内联样式并且应该被删除。element.isEmptyInlineRemoveable
- 您应该删除放置光标的空内联元素。editor.createRange().setStartAt( block, 0 ).select()
- 最后,您应将插入符号放在正确的位置(在块的开头 - <p>
/ <div>
/ <li>
/等。)。不幸的是,正如你所看到的,写这不是一件容易的事情,祝你好运:)
答案 2 :(得分:2)
这是一篇老帖子,但我一直有同样的问题,我终于有了一些工作,所以我想分享我的解决方案。对于那些不知道为什么我们想要这个功能的人,这里有我的解释:
默认情况下,当按下回车键插入新行时,CKEDITOR会尝试允许用户继续使用相同的样式。换句话说,如果您的文本是粗体并居中并按Enter键,则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将事件绑定到enter键的所有实例。接下来,它检查按下Enter时创建的元素是否在HTML或BODY以外的父元素内(即,它是较大元素树的一部分)。最后,如果它不在容器元素内部,它会从该元素中删除所有不在&#34; safe_classes&#34;中的类。先前创建的对象。
2个重要的附注: 1)你仍然需要设置&#34; forceEnterMode:true&#34; 2)因为&#34; forceEnterMode&#34;设置为true,最好只嵌套段落元素。例如:
<div class="container"><p class="title">Title Text</p><p class="content">Content Goes Here</p></div>
否则,如果您在嵌套div中按Enter键,ckeditor会将所有div属性复制到段落元素中。