Skip to content

Instantly share code, notes, and snippets.

@mlewand mlewand/undo-keyboard.md Secret
Last active Aug 29, 2015

Embed
What would you like to do?
This doc sums info related to keyboard and undo plugin cooperation. It also touches change event.

Keyboard integration notes

Current issues:

Using keypress event causes an issue, when keyboard does not send it. It's not only Android case, but also you can experience it with language like Chinese:

  • Chromium does not send keypress events at all.
  • Seems to be the same with IE8.

Therefore no snapshots are created when typing. The solution for that might be textInput event, but... it seems it's not really supported at IE8.

Keypress deprecated

Keypress is deprecated so we should opt to use keydown event instead (or any onther reasonable alternative).

Input event

In specs we have two nice events: input and beforeinput - these seems to be really nice to use them to fire change event. It seems that the event is pretty reliable, althought there area few concerns:

  • beforeinput seems not to be handled in (most?) browsers - checked in Chrome, Firefox
  • input is implemented, but it triggers in whole range of cases, like
    • input a character into contenteditable
    • drop stuff into editor
    • copy, cut

IE remarks:

It's supported in IE9+, as a workaround for IE8 there is something like onpropertychange event.

The legend goes that IE9 (almost) supports input event, but it does not fire when you delete stuff.

Input event as a CKEDITOR.change event instigator

Input event handles pretty well content adding (typing, pasting, dropping). At IE it does not handle content removing - that's: backspace key, delete key.

In addition it does not handle our builtin operations, like removing anchors, enter new-line and such. (that might be really lot of work)

Undo keyboard user guide

General overview

How does undo work?

It watches for your keyboard input and triggers saveSnapshot.

Dictionary

  • functional keys - keys that modifies content, currently it's backspace and delete
  • printable keys - all the keys which input some printable characters to editable
  • keystrokes limit - maximum number of keys that can be typed within a snapshot
  • selection amend - replacing last snapshot, with the current one if content is the same and selection didn't change

When a snapshot is created?

  • When you're exceeding keystrokes limit
  • While typing and switching key group i.e. You typed aaa then you'll press backspace - key group change ocured. Snapshot should be created with aaa content.
  • When you'll use navigation key like arrows, home/end to change your caret position (in order to write something elsewhere)
  • not really keyboard related, but on click (very similar to navigation keys)

Special cases of snapshot

Amending selection - it occurs upon key navigation

What events are ignored?

Intentionally we ignore drop and paste events. Both of them are setting ignoreInputEvent variable, which forces logic in keyup to ignore the press.

Original implementation enhancements

  • make snapshot / override selection at click - is extremely handy at mobile
  • make snapshot on moving caret - useful for keyboard, feels buggy other way

Extra notes

  • I've set keystrokes limit to 5 for better debugging, when code will be ready i think we should change it back to ~20 and make it configurable.

Remaining things:

deletion bug

Bug which I faced at Friday was following tc:

  1. Open snapshot.html dev sample.
  2. Set following selection 111 ^222 333 444 555 666 777
  3. type aaa ( each char as a separate keystroke )
  4. press backspace three times
  5. type bbb
  6. ctrl + z once

Expected result: 111 222 333 444 555 666 777

Actual: 111 b222 333 444 555 666 777

remove old type() - I haven't done it at Friday, because we need remove all variables involved, like this.modifiersCount, this.typesCount, this.wasCharacter.

Implementation details

We're relaying here on input event, which fires when printable characters are inserted, or removed. input event occures always between keydown and keyup.

With that information we can listen to events:

input - mark inputFired flag keyup - check inputFired flag, if marked then it means that some characters were inserted / deleted

In addition to that we listen to drop and paste events to set ignoreInputEvent, which tells that undesired event occured, like paste.

Exception for delete

Functional keys are handled in keydown event, which does even not have access to inputFired, but it's required to make a snapshot before content removing from dom.

Working with IE

Ie doesn't fire input event in contenteditable element, so in order to reuse functionallity we're using keypress event instead of input event. I've ported this functions to IE at Friday, and they seems to work fine, but tests are bleeding.

Potential reason for test bleeding?

Part of the reason why tests are bleeding is that _fireKeyEvent() has a skipInputEvent param. But IE is not based on input, but keypress - so keypress should be conditioned there. If it's not then we have inputFired=true during keyup with any key, because it was set in keypress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.