【问题标题】:Refocus CKEditor at correct cursor position将 CKEditor 重新聚焦在正确的光标位置
【发布时间】:2013-03-21 01:51:36
【问题描述】:

我正在构建一个 CMS 系统,我使用 jQuery 和 CKEditor 在线编辑内容。当编辑器模糊时,要求用户确认他/她想要丢弃编辑。如果选择“否”,则应取消模糊事件,并且编辑器保持焦点而不更改光标位置。因为在我看来这是不可能的,所以我尝试在模糊完成后重新调整编辑器的焦点。以下代码 sn-p 来自模糊事件处理程序:

var $this = $(this);
if (confirm('Discard your changes?')) {
    $this.html($this.data('previous'));
} else {
    // Optimally prevent the blur event, but alternatively
    // reintroduce focus at correct position...
    $this.data('editor').focus();
}

请注意,focus 调用是在 $this.data('editor') 中包含的编辑器实例上完成的,但结果似乎与我直接在 $this 上执行的结果相同。

这个解决方案的问题在于,虽然它重新引入了焦点,但光标现在定位在文本的开头,这对最终用户来说非常不直观和烦人,他们认为没有任何改变。另一方面,仅仅放弃焦点不是一种选择,因为我不希望用户能够阻止重置内容然后继续进行其他更改,认为这些更改是持久的。

因此,我想要一个解决方案,我可以完全防止模糊,或者将光标重新引入它的最后一个位置。

【问题讨论】:

    标签: javascript jquery content-management-system editor ckeditor


    【解决方案1】:

    本机解决方案(通过window.getSelection()...)是不安全的,因为浏览器以不同的方式实现此 API 或/和存在错误。问题是选择系统、范围和内容可编辑(通常)的“标准”非常差、模糊和被忽视。 CKEditor 绕过了这些问题(许多 kLOC),并通过其自己的 API 保持了可移植性和可预测性。

    所以不要重新发明轮子,继续使用这段代码(在最新的 Chrome 和 IE10 中测试):

    var editor = CKEDITOR.instances.editor1;
    
    editor.on( 'blur', function() {
        console.log( 'Editor blurred.' );
    
        var range = editor.getSelection().getRanges()[ 0 ]; // store the selection
    
        if ( confirm( 'Discard your changes?' ) ) {
            console.log( 'Changes discarded.' );
        } else {
            editor.focus(); // focus the instance again
            range.select(); // restore previous selection
        }   
    } );
    

    如果您将此代码与缓存数据检查 (editor.getData()) 混合使用,您可以轻松避免 confirm() 在没有真正改变的情况下:

    var editor = CKEDITOR.instances.editor1, cached;
    
    editor.on( 'blur', function() {
        console.log( 'Editor blurred.' );
        var range = editor.getSelection().getRanges()[ 0 ]
    
        if ( editor.getData() != cached && confirm( 'Discard your changes?' ) ) {
            console.log( 'Changes discarded.' );
        } else {
            editor.once( 'focus', function( event ) { 
               event.cancel();  // cancel the *very next* event, nothing will be cached
            }, null, null, 0 );
    
            editor.focus();
            range.select();
        }   
    } );
    
    editor.on( 'focus', function() {
        console.log( 'Cached editor contents.' );
        cached = editor.getData();
    } );
    

    【讨论】:

    • 这很好用,非常感谢!如果有人感兴趣,我仍然通过设置 var $this = $(editor.element.$); 将旧内容保留为 DOM 数据。
    • 这似乎不再适用于 4.4.8 版
    【解决方案2】:

    我不确定它是否适用于 CKEditor,但对于 textarea,您可以使用以下方法获取当前光标位置:

    var cursor = window.getSelection().getRangeAt(0).startOffset;

    在这个问题中有一个 jQuery 函数:Cursor position in a textarea (character index, not x/y coordinates)

    将光标设置在正确的位置与选择文本的特定部分相同,更多信息在这里:Highlight text range using JavaScript

    我想这需要一点思考,因为 CKEditor 很可能会替换 textarea。

    【讨论】:

    • 感谢您的回答。但是,我使用 CKEditor 的内联实例,没有任何 textareas。
    猜你喜欢
    • 2019-07-27
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多