0

I am trying to implement redo and undo in a browser. I have a solution that works, but it sometimes misinterprets the redo sequence as undo, whereas this never happens, for example, in vscode. My code is as follows:

document.addEventListener(
  'keydown',
  async function(evt) {
    evt.stopImmediatePropagation()
    if (
      evt.code === 'KeyZ' &&
      (evt.ctrlKey || evt.metaKey) &&
      evt.shiftKey
    ) {
      // handle redo action
    } else if (evt.code === 'KeyZ' && (evt.ctrlKey || evt.metaKey)) {
      // handle undo action
    }
  })

I am aware of other questions similar to this one, but they all offer solutions similar to mine. I am specifically looking for a solution that will never misinterpret an undo/redo, so that, for example, a sequence of 50 actions can be undone and redone with perfect precision (as is the case in vscode, and probably countless other browser-based tools).

adam tropp
  • 674
  • 7
  • 22

1 Answers1

3

You're in the right direction, but a few things:

  1. You can't use async for the event listener callback. Calls to callback function in addEventListener are synchronous.
  2. It is recommended to use evt.key instead of evt.code. (On the bright side, you don't need to start key arguments with "Key*")
  3. The following items in the list below are Boolean. If they are pressed, their value is true, otherwise they are false.
    • evt.shiftKey
    • evt.altKey (Option/⌥ on Mac)
    • evt.ctrlKey
    • evt.metaKey (Command/⌘ on Mac)

You can learn more about how modifier keys are detected on at MDN on the evt.getModifierState page. Character code can be found using String.prototype.charCodeAt(), but you'll probably not need to use it.

  1. In your code example, you'll also need to use window instead of document to call this event.

This should fix your code sample.

window.addEventListener('keydown', function(evt) {
    evt.stopImmediatePropagation();
    if (evt.key === 'Z' && (evt.ctrlKey || evt.metaKey) && evt.shiftKey) {
      // handle redo action
    } else if (evt.key === 'Z' && (evt.ctrlKey || evt.metaKey)) {
      // handle undo action
    }
});
JRCharney
  • 51
  • 4