将CKEditor重新聚焦到正确的光标位置

时间:2013-03-30 13:08:13

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

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

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上直接执行的操作相同。

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

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

2 个答案:

答案 0 :(得分:5)

原生解决方案(通过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();
} );

答案 1 :(得分:0)

我不确定它是否适用于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。