8

我在开发将不可编辑的内容插入文本流的 CKEditor 插件时遇到了麻烦。我一直在尝试使用范围函数,但由于文档不够出色,因此收效甚微。因此,给定一些文本,假设插件插入“[[uneditable stuff]]”,然后在 WYSIWYG 显示中将其包装在一个跨度中,以便可以设置颜色样式:

<p>This is some text[[uneditable stuff here]]</p>

当第一次插入不可编辑的东西时,我们希望用户能够继续输入或按 Enter 换行。以下代码(我在这里得到:How to set cursor position to end of text in CKEditor?)在 Firefox 中有效,但(自然)在 IE9、8 或 7 中无效:

var s = editor.getSelection();
editor.insertElement(e); // element 'e'= a span created earlier
var p = e.getParent();
s.selectElement(p);
var selected_ranges = s.getRanges();
selected_ranges[0].collapse(false);  //  false = to the end of the selected node
s.selectRanges(selected_ranges);  // putting the current selection there

所以我想要发生的是光标位于“^”位置:

<p>This is some text<span>[[uneditable stuff here]]</span>^</p>

如果新元素不在行尾,那么在创建之后,光标应该到这里:

<p>This is some text<span>[[uneditable stuff here]]</span>^ with more text after the new element</p>

在 FF 中,我可以将光标放在行尾,尽管不在新元素之后的位置。在 IE 中,光标仍在新的 SPAN 内,我在键入时看到它仍然是 span 的 css 颜色,当切换到 SOURCE 视图时,文本消失了(因为它是一个不可编辑的 span)。

我知道有一个 range.setStartAfter 方法,但即使在 FF/Chrome 中也完全无法使其工作。

有人对在 CKEditor 中使用范围和选择方法有很好的处理吗?我知道没有!

开始认为只使用 editor.insertElement 是错误的,我应该了解 FakeElement (insertBogus?) 函数,我还不明白。诸如链接和图像之类的股票插件似乎没有这个问题。

4

3 回答 3

7

我不得不做一些鬼鬼祟祟的事情来解决这个问题,但它确实得到了解决:在创建不可编辑项目(属性 content-editable: false 的跨度)后,我必须创建一个包含一个空格的文本的“虚拟”跨度. 所以,我插入真正的跨度,然后是虚拟的。但仅在创建新项目时。

所以这在“如果不处理编辑选定的项目”部分。这里,'a' 是编辑器实例,'e' 是所需的不可编辑项,'f' 是虚拟跨度。

var e=new CKEDITOR.dom.element('span',a.document);
e.setAttributes({// stuff to create our element});
var f=new CKEDITOR.dom.element('span',a.document);
f.setAttributes({
    'class':'dummyF'
});
f.setText(' '); // that's just one space

// after section dealing with editing a selected item, in "else":
var sel = a.getSelection(); // current cursor position
a.insertElement(e); // the real new element
if(CKEDITOR.env.ie || CKEDITOR.env.webkit){ // IE & Chrome like this way
    f.insertAfter(e);
    sel.selectElement(f);
}
else { //FF likes this way (to ensure cursor stays in the right place)
    f.insertAfter(e);
    var rangeObjForSelection = new CKEDITOR.dom.range( a.document );
    rangeObjForSelection.selectNodeContents( f );
    a.getSelection().selectRanges( [ rangeObjForSelection ] );
}

我不得不承认我并不完全理解我自己的代码。我经过数小时的反复试验才到达那里。哦,我必须添加一个 htmlFilter 规则来摆脱剩余的 'f' 元素:

e.addRules({
  // e is the htmlFilter: applied to editor data before/upon output
  elements:{
    span:function(s){ // 's' is any spans found in the editor
        if(s.attributes&&s.attributes['data-cke-myelement']) {
            //stuff to do with my element
        }
        else if(s.attributes['class']=='dummyF') { //CKEDITOR.env.ie&&
            // for dummy spans to deal with "can't type or hit enter after new element" problem
            realtext = new String(s.children[0]['value']);
            realtext.replace(/^&nbsp;/,'');
            s.children[0]['value'] = realtext;
            delete s.name;
        }
    }
  }
});

我还必须补充一点,我不记得为什么在删除跨度之前必须替换“nbsp”实体。但它有效。而且我不知道为什么要删除你使用“s.name”而不是“s”。

希望对某人有所帮助。

于 2012-11-09T14:14:08.490 回答
2

我遇到了同样的问题,通过将我的 SVG 元素包装在<span>&#8203; + element + &#8203;</span>

const eHtml = '<span>&#8203; ' + svgHtml + '&#8203;</span>';  // Wrap element in a span with sorrounding &#8203;
const wrpEl = CKEDITOR.dom.element.createFromHtml(eHtml);
editor.insertElement(wrpEl);
wrpEl.remove(true); // Remove wrapping span leaving children.

这对我来说效果很好,现在我可以在 SVG 元素的开头和结尾获得cursor。

于 2017-12-24T07:50:33.593 回答
0

我在将图像直接粘贴到编辑器时遇到了类似的问题,图像被选中,我不希望它被选中,所以我不得不取消选择图像并将光标放在图像后面:

CKEditorObject.on('afterInsertHtml', function (e) {
    setTimeout(function () {
        var range = e.editor.getSelection().getRanges()[0];
        range.collapse();
        e.editor.getSelection().selectRanges( [ range ] );
    }, 1);
});
于 2018-03-21T15:44:52.863 回答