w3c / input-events

Input Events
https://w3c.github.io/input-events/
Other
24 stars 16 forks source link

How to make 'undo'/'redo' useful #36

Open chong-z opened 8 years ago

chong-z commented 8 years ago

Background Currently 'undo'/'redo' is targeting the Element to be modified (but not the focused Element)

Issues

  1. An editing host will never receive 'undo' if it prevents all 'beforeinput'
  2. No 'undo' will be fired if the stack is empty

Solution

Or alternately:

johanneswilm commented 8 years ago

From the JS perspective: Interrupting CTRL+Z is not that difficult and is what can be done now, so unless we offer something just as simple, JS editors will likely continue with that.

Solution

  • Provide an API to push dummy 'undo' entries into the stack (with 'target')

Or alternately:

  • Use the opt-in/opt-out feature to mark 'undo'/'redo' as always enabled
    • Events should be dispatch to focused document if the stack is empty
    • JS will have to catch 'undo'/'redo' from document

This would solve one thing in relation to what we have today: The undo in various menus would be enabled and the user making use of those menus could be handled the same way that ctrl+z would be handled.

But: also the JS editor history will be of limited length. There will be times when there is nothing to redo (so 'redo' should be disabled) or nothing to undo (so 'undo' should be disabled). If these elements are "always enabled" in the menus, then that seems slightly wrong. If we have a way to dynamically enable and disable features from the editor, then that might work.

chong-z commented 8 years ago

From the JS perspective: Interrupting CTRL+Z is not that difficult and is what can be done now, so unless we offer something just as simple, JS editors will likely continue with that.

Yep, but it won't work if you have multiple input fields on the same document, unless JS covers the entire document.

johanneswilm commented 8 years ago

Yep, but it won't work if you have multiple input fields on the same document, unless JS covers the entire document.

True. But also, if JS interrupts any of the editing operations of any of the editors, the browser-internal history won't be usable. Right?

rniwa commented 8 years ago

Ctrl+Z doesn't exist on iOS yet iOS definitely supports undo. I once wrote an undo manager API: https://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html

The challenge here is that WebKit must use AppKit's NSUndoManager behind the scene, which means that we can't simply enable/disable undo/redo menu. We actually need an undo/redo item in our undo stack.

johanneswilm commented 8 years ago

Yep, but it won't work if you have multiple input fields on the same document, unless JS covers the entire document.

Testing Google Docs main editor and title input field: The history is handled separately for each of them. If the caret is in the main editor, only the edits in that editor are undone. If in the title field, only changes in that input field are undone.

Testing in Office 365 with a comment and text in the main editor, the same behavior applies.

This mirrors the behavior of how the various JS editors that are not maintained by browser makers are handling undo on a per-editor basis. A global edit history for the page doesn't really seem to be of interest to those creating such editors. If we want to preserve this global undo stack for other, unhandled areas, such as input fields, etc., maybe we can add some option for the browser to entirely ignore a specific contenteditable area when it comes to editing history?

The challenge here is that WebKit must use AppKit's NSUndoManager behind the scene, which means that we can't simply enable/disable undo/redo menu. We actually need an undo/redo item in our undo stack.

@rniwa: Would there be a practical way of faking it? Given that the JS editor will have to handle undo/redo itself anyway, what would the most practical way be to achieve that on iOS?

rniwa commented 8 years ago

Really, the only practical way is for web apps to be inserting undo/redo items onto the browser's undo stack.

johanneswilm commented 8 years ago

@rniwa That sounds like an unfortunate coupling. I guess one could add dummy items into the clipboard (?) and then only use that system on iOS. Is it possible to add and remove an arbitrary number of such dummy items?

johanneswilm commented 8 years ago

Although there is no formal resolution ( https://www.w3.org/2016/09/22-webapps-minutes.html#item05 ), it seems the browser vendors at the F2F believed the menu items for undo and redo can be enabled by default for contenteditable, given that they have been useless hitherto. They can then be disabled by means of turning features off for the editing host. Is that also your understanding of the outcome, @choniong ?

Alternatively, there is a hack to achieve this in JavaScript in Chrome and Firefox: https://github.com/w3c/editing/issues/150#issuecomment-249782860

Apple has later declared that it will not support a switch to turn on the editing menu when the browser's history is empty. Instead it will wait for the creation of a global undo stack manager. There is a draft spec from 2012: https://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html . Correct @rniwa ?

johanneswilm commented 8 years ago

@reinmar: Would this code snippet make the beforeinput events for undo/redo work for you while we are waiting for some more complex undo manager some time in the future? https://github.com/w3c/editing/issues/150#issuecomment-249782860