我读过这个 excellent answer几乎相同的问题。但是,我已经尝试了 @Reinmar 的所有技术。推荐,它们似乎都不起作用。
情况是我从编辑器中获取当前的 HTML 并将某些部分包装在 span 标签中。然后我重新设置现在修改的 HTML 并尝试恢复用户的光标位置。没有技术有效。
这是一个重现问题的非常简单的示例:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="//cdn.ckeditor.com/4.4.7/standard/ckeditor.js"></script>
</head>
<body>
<textarea id="cktest"><p>Sometimes Lorem. Sometime Ipsum. Always dolor.</p></textarea>
<script type="text/javascript">
(function () {
var checkTimeout;
var bookmark;
var storeCursorLocation = function(editor) {
bookmark = editor.getSelection().createBookmarks();
};
var restoreCursorLocation = function(editor) {
editor.getSelection().selectBookmarks(bookmark);
};
var validateText = function(editor) {
storeCursorLocation(editor);
var data = editor.document.getBody().getHtml();
data = data.replace("Lorem", "<span class='err-item'>Lorem</span>");
editor.document.getBody().setHtml(data);
restoreCursorLocation(editor);
};
CKEDITOR.replace('cktest', {
on: {
'instanceReady': function(evt) {
},
'key' : function(evt) {
clearTimeout(checkTimeout);
checkTimeout = setTimeout(function () {
validateText(evt.editor);
}, 1000);
}
}
});
})();
</script>
</body>
</html>
此代码在用户按下某个键时启动一个计时器,然后在他们停止按键后等待 1 秒进行检查。
将此复制到一个新的 .html 文件并在您喜欢的浏览器中运行它(我使用的是 Chrome)。
当 CKEditor 加载时,使用鼠标将光标放在文本中间的某个位置。然后按 CTRL 键并等待 1 秒钟。您将看到光标跳回到文本的开头。
此代码示例使用
editor.getSelection().createBookmarks();
创建书签。但我也尝试过:
editor.getSelection().createBookmarks(true);
和
editor.getSelection().createBookmarks2();
我也试过只使用保存范围
var ranges = editor.getSelection().getRanges();
和
editor.getSelection().selectRanges(ranges);
在 restoreCursorLocation 函数中。
最佳答案
(function () {
var checkTimeout;
var bookmark;
var storeCursorLocation = function( editor ) {
bookmark = editor.getSelection().createBookmarks( true );
};
var restoreCursorLocation = function( editor ) {
//editor.focus();
editor.getSelection().selectBookmarks( bookmark );
};
var validateText = function( editor ) {
storeCursorLocation( editor );
var data = editor.document.getBody().getHtml();
data = data.replace( "spaceflight", "<span class='err-item'>spaceflight</span>" );
editor.document.getBody().setHtml( data );
restoreCursorLocation( editor );
//fire this event after DOM changes if working with widgets
//editor.fire( 'contentDomInvalidated' );
};
var editor = CKEDITOR.replace( 'editor1', {
extraAllowedContent : 'span(err-item)',
on: {
"pluginsLoaded" : function( event ){
editor.on( 'contentDom', function() {
var editable = editor.editable();
editable.attachListener( editable, 'keyup', function( e ) {
clearTimeout( checkTimeout );
checkTimeout = setTimeout(function () {
validateText( editor );
}, 100 );
});
});
}
}
});
})();
我检查了你的代码,做了一些更正,上面的似乎工作正常。我知道你说你已经尝试过了,但对我来说
createBookmarks(true)
成功了。说明和注释:
createBookmarks(true)
它将唯一的跨度插入到 HTML 中。这样的书签不受您在 DOM 内部所做的更改的影响(当然有限制,例如您的自定义更改会删除书签)。 getBody().getHtml()
很聪明和 getBody().setHTML()
.如果您使用过 editor.getData()
这将删除代表书签的空跨度。但是请注意,这种方法可能会破坏小部件,因此需要触发
contentDomInvalidated
在这种变化之后的事件。 这里有工作示例:http://jsfiddle.net/j_swiderski/nwbsywnn/1/
关于CKEDITOR -- DOM 修改后无法恢复光标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29805815/