2

Я строю систему CMS, где я использую jQuery и CKEditor для редактирования встроенного контента. Когда редактор размывается, пользователю предлагается подтвердить, что он хочет отменить изменения. Если выбрано «нет», событие размытия должно быть отменено, и редактор сохраняет фокус, не изменяя позицию курсора. Поскольку мне кажется, что это невозможно, я пытаюсь переориентировать редактор после размытия. Следующий фрагмент кода из обработчика размытия события:Refocus CKEditor при правильной позиции курсора

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

Родные решения (через 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(); 
}); 
+0

Это работает блестяще, спасибо вам большое! В случае, если кому-то интересно, я все еще сохраняю старый контент как данные DOM, устанавливая «var $ this = $ (editor.element. $);». –

+0

Это, похоже, больше не работает с версией 4.4.8 – Clawfire

0

Я не уверен, если он работает с CKEditor, но с текстовым полем, например, вы можете получить текущую позицию курсора с помощью:.

вара курсора = window.getSelection() getRangeAt (0) .startOffset ;

В этих вопросах есть функция JQuery: Cursor position in a textarea (character index, not x/y coordinates)

Установка курсора на нужном месте, будет таким же, как выбор определенной частью текста, подробнее здесь: Highlight text range using JavaScript

Я предполагаю, что это нужно немного думать, поскольку CKEditor скорее всего заменит текстовое поле.

+0

Благодарим за ответ. Однако я использую встроенный экземпляр CKEditor без каких-либо 'textarea'. –

Смежные вопросы