CKEDITOR - DOM修改后无法恢复光标位置

Cle*_*man 6 ckeditor

我已经在几乎相同的问题上读到了这个优秀的答案.但是,我已经尝试了@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>
Run Code Online (Sandbox Code Playgroud)

当用户按下一个键时,该代码启动一个计时器,然后在他们停止按键进行检查后等待1秒钟.

将其复制到新的.html文件并在您喜欢的浏览器中运行(我使用的是Chrome).

加载CKEditor时,使用鼠标将光标放在文本中间的某个位置.然后按CTRL键并等待1秒钟.您将看到光标跳回文本的开头.

此代码示例使用

editor.getSelection().createBookmarks();
Run Code Online (Sandbox Code Playgroud)

创建书签.但我也尝试过:

editor.getSelection().createBookmarks(true);
Run Code Online (Sandbox Code Playgroud)

editor.getSelection().createBookmarks2();
Run Code Online (Sandbox Code Playgroud)

我也尝试过使用保存范围

var ranges = editor.getSelection().getRanges();
Run Code Online (Sandbox Code Playgroud)

editor.getSelection().selectRanges(ranges);
Run Code Online (Sandbox Code Playgroud)

在restoreCursorLocation函数中.

j.s*_*ski 6

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

我检查了你的代码,做了一些修正,上面似乎工作正常.我知道你说你已经尝试过,但对我来说createBookmarks(true)已经做到了.

说明和注释:

  1. 您需要使用createBookmarks(true)哪些插入HTML的唯一范围.这样的书签不受您在DOM内部所做的更改的影响(当然有限制,例如您的自定义更改删除书签).
  2. 这是聪明的使用getBody().getHtml()getBody().setHTML().如果你已经使用过editor.getData()这将删除代表书签的空跨度.但请注意,此类方法可能会破坏小部件,因此需要contentDomInvalidated在此类更改后触发事件.
  3. 在恢复选择之前,我也在关注编辑器,但这是"以防万一"的解决方案,因为我注意到编辑器在没有它的情况下选择书签.但是,如果出于某种原因,您正在失去选择,那么这将是另一回事.

在这里你有一个工作的例子:http://jsfiddle.net/j_swiderski/nwbsywnn/1/