Как я могу дождаться размытия CKEditor перед выполнением других действий?

Я пытаюсь решить проблему, связанную с упорядочением событий при использовании CKEditor.

Похоже, что CKEditor намеренно ждет определенное время (200 мс), прежде чем вызвать событие blur. Насколько я понимаю, это сделано для предотвращения ошибочного blur, когда пользователь щелкает из поля редактирования на панель инструментов.

Однако результатом этого является то, что в некоторых браузерах, если пользователь щелкает элемент с прослушивателем событий click сразу после использования CKEditor, событие click срабатывает перед событием blur, и это проблема для меня, потому что мне нужно обрабатывать события в том порядке, в котором они произошли (с точки зрения пользователя).

Это поведение можно наблюдать ниже в IE или Edge, введя некоторый текст в CKEditor и щелкнув кнопку или флажок, не щелкая и не выходя из CKEditor. На моей машине консоль показывает промежуток примерно в 10-20 мс между двумя запускаемыми событиями, а иногда событие размытия даже срабатывает первым.

function timeStamp() { return new Date() % 1000000; }

CKEDITOR.disableAutoInline = true;
CKEDITOR.inline('myCkEditorBox', {
  on: {
    blur: function() {
      console.log(timeStamp(), 'CKEDITOR blur.');
    }
  }
});

document.getElementById('myButton').addEventListener('click', function() {
  console.log(timeStamp(), 'Button clicked.');
});
document.getElementById('myCheckbox').addEventListener('click', function() {
  console.log(timeStamp(), 'Checkbox clicked.');
});
#myCkEditorBox {
  border: 1px solid black;
  width: 400px;
  min-height: 200px;
  margin-top: 5em;
}
<script src="https://cdn.ckeditor.com/4.7.3/standard/ckeditor.js"></script>
<input type="button" value="Do something" id="myButton" />
<input type="checkbox" id="myCheckbox" />
<div id="myCkEditorBox" contenteditable="true"></div>

Что я пробовал:

  1. Я попробовал следующий код из ссылки сообщение на форуме, которое фактически полностью отключает задержку размытия:
CKEDITOR.focusManager.prototype.orig_blur = CKEDITOR.focusManager.prototype.blur;
CKEDITOR.focusManager.prototype.blur = function() { 
    CKEDITOR.focusManager.prototype.orig_blur.call(this,true); 
};

Это действительно приводит к немедленному запуску события размытия, но вызывает проблемы с панелью инструментов редактора, из-за чего раскрывающиеся списки на панели инструментов не раскрываются или заставляют стили, примененные через панель инструментов, мерцать, а затем исчезать.

  1. Я попытался уменьшить задержку размытия до 10 мс следующим образом:
CKEDITOR.focusManager._.blurDelay = 10;

Это также заставляет события срабатывать в желаемом порядке, но кажется плохой идеей вмешиваться во внутренние настройки CKEditor, которым, по-видимому, присваиваются определенные значения по какой-то причине (это верно и для другого подхода, который я тоже пробовал).

Так что я в некоторой растерянности относительно того, что делать. Если бы я знал, что событие размытия находится в пути от определенного элемента управления, я, вероятно, мог бы найти способ дождаться его завершения, прежде чем выполнять действия из других событий. На моей странице может быть одновременно несколько элементов управления CKEditor, поэтому я не думаю, что было бы хорошей идеей заранее активировать события размытия для всех из них и дождаться их завершения, прежде чем выполнять действия из других событий.

Итак, что я могу сделать, чтобы гарантировать, что я буду обрабатывать события размытия CKEditor до событий щелчка, даже если они фактически срабатывают в противоположном порядке?


person JLRishe    schedule 23.10.2017    source источник


Ответы (1)


Кажется, что наиболее надежным решением является проверка размытия редактора при нажатии на ввод:

var editor = CKEDITOR.inline( 'myCkEditorBox' );

document.getElementById( 'myButton' ).addEventListener( 'click', function() {
  if ( editor.focusManager.hasFocus ) {
    editor.once( 'blur', function() {
      myButtonClickHandler();
    } );
  } else {
    myButtonClickHandler();
  }
} );

function myButtonClickHandler() {
  // Code which should be executed on 'myButton' click, but only after editor is blurred.
}

Если редактор размыт, просто выполните обычный поток обработчика нажатия кнопки. Если редактор по-прежнему сфокусирован, просто дождитесь blur события, а затем выполнять обычный поток обработчика нажатия кнопки.

person f1ames    schedule 25.10.2017
comment
Спасибо, это здорово! Один вопрос: есть ли гарантия, что событие размытия, связанное с editor.once, сработает после (а не до) других событий размытия, которые уже были к нему прикреплены? Мои эксперименты, кажется, указывают на то, что это так, но мне интересно, задокументировано ли это где-нибудь. - person JLRishe; 25.10.2017
comment
Ответил на мой собственный вопрос: документы говорят, что обработчики вызываются в порядке регистрации, если они имеют одинаковый приоритет (и им тоже может быть назначен приоритет!). Я планировал назначить награду за этот вопрос, прежде чем заметил, что вы ответили на него, поэтому я все равно собираюсь начать его. Пока не появятся сокрушительные ответы, вы получите еще 50 повторений через несколько дней. - person JLRishe; 25.10.2017
comment
Рад, что это помогло, @JLRishe. Как вы упомянули, слушатели вызываются в порядке регистрации или приоритете, если он был определен. Как описано в методе ondocs.ckeditor. com/ckeditor4/docs/#!/api/. Спасибо за добавление награды! Может быть, кто-то придумает более творческий ответ;) - person f1ames; 26.10.2017