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

标签 ckeditor

我读过这个 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/

    相关文章:

    css - @font-face 添加到 ckeditors contentsCSS 可以选择内联在结果 html 中吗?

    php - CKEditor - 自定义图像浏览器

    javascript - CKEditor 4.7 无法读取未定义的属性 'on',请用ajax咨询并重置

    html - 使用 CKEditor 编辑整个网站

    height - 如何更改 CKEditor 工具栏的大小?

    python - Django CMS 如何以编程方式创建嵌套插件

    reactjs - 使用 ReactJS 将插件添加到 CKEditor5 的自定义构建中

    javascript - 如何在CKEditor中保存变量?

    javascript - 我如何控制 CKEditor API 在何处为 filebrowserBrowseUrl 打开一个新窗口?

    jquery - 按需加载CKeditor和Jquery