插入不可编辑元素后的CKEditor光标位置

eon*_*eon 8 plugins insert range cursor ckeditor

我在开发将不可编辑的内容插入文本流中的CKEditor插件时遇到了麻烦.我一直在尝试使用范围功能,但由于文档不是很好,所以收效甚微.所以,给定一些文本,让我们说插件插入"[[uneditable stuff]]",然后在WYSIWYG显示包裹在一个范围内,以便它可以用颜色设置样式:

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

当第一次插入不可编辑的东西时,我们希望用户能够继续键入或按Enter键换新行.下面的代码(我在这里得到:如何将光标位置设置为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
Run Code Online (Sandbox Code Playgroud)

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

<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中,光标仍在新跨越,这是我看到的时候我键入内,它仍然是在跨度的CSS颜色,并切换到源视图时,该文本是走了(因为它是一个不可编辑的跨度).

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

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

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

eon*_*eon 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 ] );
}
Run Code Online (Sandbox Code Playgroud)

我不得不承认我并不完全理解我自己的代码.我经历了数小时的反复试验.哦,我必须添加一个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;
        }
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

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

希望能帮助别人.