In Chrome undo does not work properly for input element after contents changed programmatically
Asked Answered
K

1

6

In Chrome, I noticed that undo does not work properly for input element after the contents of the element has been changed programmatically. Although I get different behaviours for different browsers, they're not as bad as Chrome.

FF20      good
IE9       some support (undo stack cleared when input loses focus)
Safari5   some support (undo stack cleared when input loses focus)
Chrome26  unreliable

For example, a script that trims spaces (see also jsfiddle below)

  • type some spaces before "hello!",
  • click outside the input element
  • click on the input element and press Ctrl-Z

now the text is gone (in Chome)

jsfiddle here

<input type="text" id="input1" value="hello!">

document.getElementById("input1").addEventListener('blur', function(evt){elementLosesFocus(evt, this);}, false);

function elementLosesFocus(evt, caller)
{
    caller.value = caller.value.trim();
}

I think the best thing I can hope for is a method to somehow clear the undo history of the input when it loses focus (as is the case with IE and Safari).

Kaplan answered 24/4, 2013 at 15:11 Comment(0)
G
5

Chrome doesn't store the field's states, but rather a diff or set of deltas for each undo/redo. It takes less memory, but causes the bug you're dealing with.

You can effectively simulate the user pasting a value into the field by using document.execCommand("insertText", false, "text to insert");.

For your particular case:

  1. First, save the field's value to a variable. var temp = caller.value;
  2. Next, clear the field's value or set its selectionStart to 0 and selectionEnd to the field's length. This way a simulated paste replaces the field's contents.
  3. Next, make sure the field has the focus. caller.focus();
  4. Finally, simulate the user pasting in the modified value. document.execCommand("insertText", false, temp.trim());

I found this solution in another SO question, https://mcmap.net/q/589160/-javascript-textarea-undo-redo

Geographer answered 19/11, 2014 at 22:33 Comment(3)
This is gold. Thank you! There are tons of libraries that handle carets, selections and replacing them but all of them use input.value or textarea.text in the end which lead to the undo-problems the OP described.Shamble
Just note the it will NOT work in Firefox. If document.execCommand returns false then you need to fallback to setting value directly (not by pasting text). See bug in Firefox: bugzilla.mozilla.org/show_bug.cgi?id=1220696Mozellemozes
document.execCommand() is deprecated.Leastwise

© 2022 - 2024 — McMap. All rights reserved.