在执行其他操作之前如何等待 CKEditor 模糊?

How can I wait for CKEditor to blur before performing other actions?

我正在尝试解决有关使用 CKEditor 时事件排序的问题。

似乎 CKEditor 在引发 blur 事件之前有意等待一定时间(200 毫秒)。我的理解是,这是为了防止用户从编辑框点击到工具栏时出现错误blur

然而,这样做的结果是,在某些浏览器中,如果用户在使用 CKEditor 后立即单击带有 click 事件侦听器的元素,click 事件会在 blur 事件,这对我来说是个问题,因为我需要按照事件实际发生的顺序处理事件(从用户的角度来看)。

通过在 CKEditor 中输入一些文本并单击按钮或复选框而不单击或跳出 CKEditor,可以在下面的 IE 或 Edge 中观察到此行为。在我的机器上,控制台显示两个事件触发之间有大约 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. 我尝试了 forum post 中的以下代码,它基本上完全禁用了模糊延迟:
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 模糊事件,即使它们实际上以相反的顺序触发?

最可靠的解决方案似乎是检查单击输入时编辑器是否模糊:

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.
}

如果编辑器模糊,只需执行按钮单击处理程序的常规流程。如果编辑器仍然是 focused, just wait for the blur event 然后执行按钮单击处理程序的常规流程。