Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make undo work in an HTML textarea after setting the value?

I have a <textarea> element that I listen for certain key presses from. Like if a user types the Tab key, I prevent the default action of changing focus and add the tab character at the correct position.

The problem is when users press one of the keys I listen for, undo goes a little haywire. How do I get the undo/redo functionality to work? I thought about listening for ctrl/cmd-z and ctrl/cmd-shift-z key presses, recording everything, and processing the undos/redos, but then the edit and context menu choices wouldn't work...

You can see by typing letters with tabs and enters and then trying to undo and redo:

const textarea = document.querySelector('textarea')
textarea.addEventListener('keydown', function (event) {
  if (event.key == "Tab") {
    event.preventDefault()
    const cursor = textarea.selectionStart
    textarea.value = textarea.value.slice(0, cursor) + '\t' + textarea.value.slice(textarea.selectionEnd)
    textarea.selectionStart = textarea.selectionEnd = cursor + 1
  } else if (event.key == "Enter") {
    event.preventDefault()
    const cursor = textarea.selectionStart
    textarea.value = textarea.value.slice(0, cursor) + '\n' + textarea.value.slice(textarea.selectionEnd)
    textarea.selectionStart = textarea.selectionEnd = cursor + 1
  }
})
<textarea cols="50" rows="20"></textarea>
like image 222
at. Avatar asked Jun 10 '17 09:06

at.


People also ask

How do you do undo in HTML?

To learn about the keyboard shortcuts in the new content editor, see Keyboard shortcut functions. To reverse your last action, press CTRL+Z. You can reverse more than one action. To reverse your last Undo, press CTRL+Y.

Does textarea support value attribute?

<textarea> does not support the value attribute.

How do you delete textarea text?

To clear the value of a textarea element, set it's value property to an empty string, e.g. textarea. value = '' . Setting the element's value to an empty string removes any of the text from the element. Here is the HTML for the examples in this article.

How do I edit text in textarea?

Alternatively, you can use jQuery's . html() method, which uses the browser's innerHTML property to replace textarea content with the new content completely. Another good solution is to use the . val() method to set the text value of the textarea element.


1 Answers

I believe the problem's core is the lack of interaction between Javascript and the browser's default methods of undoing. Appending text using Javascript to a textarea does not in any way tell the browser's "undo" to delete the appended text, as the browser's "undo" is only meant for removing text the user inputted, not text Javascript inputted.

Take for example your code. Upon pushing Enter, you tell the eventListener to preventDefault, which alltogether prevents the Enter key from appending user input to the textarea. You then synthesize the input using Javascript, which the browser's "undo" does not keep track of.

You can overcome this lack of interaction by using Document.execCommand(). You can check it's browser support via the link.

const textarea = document.querySelector('textarea');
textarea.addEventListener('keydown', function (event) {
    const cursor = textarea.selectionStart;
    if(event.key == "Tab"){
        event.preventDefault();
        document.execCommand("insertText", false, '\t');//appends a tab and makes the browser's default undo/redo aware and automatically moves cursor
    } else if (event.key == "Enter") {
        event.preventDefault();
        document.execCommand("insertText", false, '\n');
    }

});
like image 162
Siracle Avatar answered Sep 25 '22 10:09

Siracle