0

My current Chrome extension is supposed to programmatically insert text on user input. This works great, however, it mangles the undo/redo behavior of all text editors I've tried it on so far. So, the following routine:

  1. type some text
  2. insert some text programmatically
  3. type more text
  4. press ctrl-z thrice

does not always revert to a blank state. Very often it will get stuck somewhere in the middle. Its behaviour is mostly inconsistent.

Here's an MCVE of the content script:

function init() {
  var $input = document.getElementsByTagName("textarea")[0];
  if (!$input) {
    console.log("No input element found.");
    return true;
  }
  var $btn = document.createElement("button");
  $btn.innerHTML = "Click";
  $btn.addEventListener("click", function() {
    var caretPos = $input.selectionStart;
    $input.value = $input.value.substring(0, caretPos) + " test string " + $input.value.substring(caretPos);
  });

  $input.parentElement.insertBefore($btn, $input);

  return true;
}
window.addEventListener("load", init);
<div><textarea></textarea></div>

(I also bundled it as a Chrome extension in case you'd like that.)

I want the undo/redo to function perfectly in both textarea as well as contenteditable nodes. I also tried document.execCommand in both insertText and insertHTML modes without any success. I've looked at the other two related questions but they do not answer my query. (q1, q2)

What else can be a possible solution to this problem?

Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84
  • Setting the `value` property directly wont be undone by a ctrl-z shortcut. However using insertText command were undone with ctrl-z in at least my chrome browser for both textarea and contenteditables without fail. Note if by text editors you mean framework editors like tinymce or the like their code could be interferring with yours or chaning how ctrl-z/insertText works in their elements – Patrick Evans Jun 08 '19 at 06:14
  • If you are programatically inserting and removing text, you'll need to programatically keep track of the undo history and handle ctrl-z yourself. – skyline3000 Jun 08 '19 at 06:15
  • execCommand is the correct solution which suits all your needs. The fact that it didn't work for you may mean you've used it incorrectly in your exact situation. Maybe you didn't focus the element. Or there was something else interfering. – wOxxOm Jun 08 '19 at 06:58
  • @PatrickEvans Hi, you're right. I was using a different editor earlier. `execCommand` works! – Gaurang Tandon Jun 08 '19 at 08:35

1 Answers1

0

Thanks to the helpful comments above, my problem was doing execCommand on pre-programmed weird editors like Facebook messenger box, tinymce, etc. They might have their own customizations interfering.

In normal text editors, document.execCommand should work fine, and support undo/redo. Use it like so:

document.execCommand('insertText', false, "text");
document.execCommand('insertHTML', false, "html");
Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84