ckeditor5 icon indicating copy to clipboard operation
ckeditor5 copied to clipboard

"Reverse typing" effect in some instances where selection may have been lost

Open urbanspr1nter opened this issue 1 year ago • 1 comments

📝 Provide detailed reproduction steps (if any)

Hi, I'm building off of these bugs here, as the problem still persists:

  1. https://github.com/ckeditor/ckeditor5/issues/13926#issuecomment-1761548452
  2. https://github.com/ckeditor/ckeditor5/issues/14702#issuecomment-1660318476

For some background information, the original issue was first presented and solved in this bug:

  • https://github.com/ckeditor/ckeditor5/issues/14569

This "reverse typing" effect unfortunately has many causes and manifestations which eventually lead to the same effect. The original bug #14569 had intended to solve the issue where selection was not updated in time due to heavy CPU usage while user was typing. This caused some reverse typing as the cursor would "stick" at the current selection, and not update.

This had been fixed with the PR: #14648 - https://github.com/ckeditor/ckeditor5/pull/14648

This fix has worked quite well.

Now, we run into issues where if the editor is somehow taken out of focus in a "forceful" manner, typing will result in a reverse order due to the cursor never updating its position.

For example, one can synthetically reproduce this by running this piece of JavaScript code while the cursor is within the editor:

// In 5 seconds, this will cause reverse typing
setTimeout(() => {
  const editable = document.querySelector("div.ck-editor__editable");
  editable.dispatchEvent(new FocusEvent("blur"));

  console.log("Now, try to type!");
}, 5000);

backwards

✔️ Expected result

Typing should never result in characters being visually placed in reverse order when the editor is not truly in focus.

❌ Actual result

Typing results in characters being injected in reversed order.

❓ Possible solution

To get around this, what we can do as integrators is actually listen in on the beforeinput event on the ViewDocument, at the low event priority. There's an interesting behavior that happens in this event, upon typing, if we manually dispatch a new FocusEvent with focus to the editable, the selection is restored.

For example:

editor.editing.view.document.on('beforeinput', () => {
  const editable = getEditableHelper(editor);
  editable.dispatchEvent(new FocusEvent("focus"));
});

Or building off our synthetic repro example as a demonstration:

setTimeout(() => {
  const editable = document.querySelector("div.ck-editor__editable");
  editable.dispatchEvent(new FocusEvent("blur"));

  console.log("Now, try to type!");
  
  // In 3 seconds, there will be normal typing
  setTimeout(() => {
      editable.dispatchEvent(new FocusEvent("focus"));
      console.log("Now, we are typing normally again.");
  }, 3000);
}, 5000);

Though this is a known workaround, for this specific scenario, I wonder what happens if some focus stealing of some other DOM element occurs, while the cursor is active in the inline editor will result in? For sure it's going to be reverse typing, but there are times where a specific JS library plays bad and maintains/traps focus no matter what.

The fact is that there is a cursor in the editable indicating that it is "focused" while it is not which is the tricky aspect to this all. I think if the editor truly does not have focus, it should not have a cursor. That's one scenario solved... maybe???? 🤔

📃 Other details

This happens in Chromium based browsers, Safari, etc.


If you'd like to see this fixed sooner, add a 👍 reaction to this post.

urbanspr1nter avatar Oct 13 '23 16:10 urbanspr1nter