2

我正在构建一个 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.

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

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

4

2 回答 2

5

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

So don't reinvent the wheel and go ahead with this code (tested in latest Chrome and 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
    }   
} );

If you mix this code with cached data check (editor.getData()), you can easily avoid confirm() when nothing has really changed:

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();
} );
于 2013-03-30T15:13:01.977 回答
0

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

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

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

将光标设置在正确的位置与选择文本的特定部分相同,更多信息在这里:使用 JavaScript 突出显示文本范围

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

于 2013-03-30T13:12:59.900 回答