12

A few days ago, I posted a question regarding how to update text in Internet Explorer. As it appears, the method used doesn't also works in Firefox.

This made me thinks if there is a way to modify the value of a textarea and update the undo/redo queue as well (calling ctrl-Z or document.execCommand('undo');)

So far, I have found two possibilities, but they don't work in all the browsers :

Option 1:

var event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, null, text, 9, "en-US");
textarea.focus();
textarea[0].setSelectionRange(selection.start, selection.end);
textarea[0].dispatchEvent(event);

Note: Doesn't seems to work in IE (at all) and Firefox

Option 2 :

document.execCommand("insertText", false, "the text to insert");

Doesn't work in IE (tested under 9, but seems to not be implemented at all), I don't know for the others browsers.

Community
  • 1
  • 1
Cyril N.
  • 38,875
  • 36
  • 142
  • 243

4 Answers4

7

The solution I come up so far is this one, but I'm open for betters ideas :

I check for the existence of the insertText via document.queryCommandSupported. If it does exists, I use it. If not, I simply replace the text :

var text = "hello world",
    textarea = jQuery("textarea"),
    selection = {'start': textarea[0].selectionStart, 'end': textarea[0].selectionEnd};

if (document.queryCommandSupported('insertText')) {
    document.execCommand('insertText', false, text);
}
else {
    textarea.val(textarea.val().substring(0, selection.start) + text + textarea.val().substring(selection.end, textarea.val().length));
}
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
  • 1
    I'm looking for this too, and `insertText` works, but still somehow messes up the undo/redo history a bit. See http://jsfiddle.net/rudiedirkx/k4spa0dv/ After undoing and redoing a few programmatic changes, it loses the last few history items, so redo won't redo everything... Any idea? (Chrome btw) – Rudie Jan 14 '15 at 23:21
  • document.execCommand returns true if the command was executed successfully, i used the return value instead of checking queryCommandSupported first. Also don't forget to update the carret position using `.setSelectionRange(start,end)` after you changed the value without execCommand. – w.stoettinger Oct 23 '17 at 06:14
  • 1
    Note! This does not work for Firefox! `insertText` command is supported but only for `contenteditable` elements. Not for textarea. – Nux Dec 31 '19 at 17:14
2

Option 1 works well as of now (8/19/2016), but is deprecated in Chrome for one of the upcoming releases. Dispatching the event generates the following warning:

A DOM event generated from JavaScript has triggered a default action inside the browser. This behavior is non-standard and will be removed in M53, around September 2016. See https://www.chromestatus.com/features/5718803933560832 for more details.

Michal Filip
  • 870
  • 8
  • 9
0

It seems that as of today, all modern browsers support your option #1, dispatchEvent. See more here:

http://help.dottoro.com/ljrinokx.php

Stan Lin
  • 928
  • 7
  • 6
  • Still has messed up history (Chrome): http://jsfiddle.net/rudiedirkx/k4spa0dv/ After undoing and redoing a few times, he's totally confused and redo/undo history is lost. Firefox doesn't work at all. – Rudie Mar 05 '15 at 23:20
  • It seems there's still no cross-browser solution for this. At least IE doesn't work properly with any of the proposed methods in the jsfiddle. What a shame. – Joshua Muheim Jun 14 '17 at 10:39
0

Only browsers that support document.execCommand("insertText") have undo support (at the moment: Chrome, Safari, Opera). Other browsers have various ways to insert text but no undo support.

Try insert-text-textarea to wrap some of the solutions on this page for modern browser support. If you need IE8+ support, try the insert-text-at-cursor package.

fregante
  • 29,050
  • 14
  • 119
  • 159