23

Is there a way to edit the contents of an input or textarea with javascript, and have that change be undo-able with the browser's "undo" command (eg ctrl-Z)?

I am trying to insert a string, such as "Foo {0} bar", into the value at the selection, and if the user has selected a range, the selected range is inserted into the string in place of the "{0}".

For example if the textarea contains "Example 1 2 3" and the cursor is at "Example 1| 2 3", then the function would change the value to "Example 1Foo blah bar 2 3" (valueIfNothingSelected being "blah" in this case). If the range "1 2" was selected, the function would instead change the value to "Example Foo 1 2 bar 3".

In Chrome I tested this function out, and it does what it is supposed to, but I cannot reverse the change with undo.

function insertTextAtCursor(text, valueIfNothingSelected) {
    var field = $('textarea[name="task_log_description"]')[0];
    var startPos = field.selectionStart;
    var endPos = field.selectionEnd;
    var processedText;
    if (startPos == endPos) {
        processedText = text.replace('{0}', valueIfNothingSelected);
        field.value = field.value.substring(0, startPos) + processedText + field.value.substring(endPos, field.value.length);
        field.selectionStart = startPos + text.indexOf('{0}');
        field.selectionEnd = field.selectionStart + valueIfNothingSelected.length;
    } else {
        var selectedText = field.value.substring(startPos, endPos);
        processedText = text.replace('{0}', selectedText);
        field.value = field.value.substring(0, startPos) + processedText + field.value.substring(endPos, field.value.length);
        field.selectionStart = startPos + text.indexOf('{0}');
        field.selectionEnd = field.selectionStart + selectedText.length;
    }
    field.focus();
}
3
  • 1
    ctrl-z already works for me in Chrome+Firefox on Ubuntu 14.04. What's the situation where it's not working for you? Commented Nov 19, 2014 at 22:09
  • @Jack Expanded question to include my javascript method. For whatever reason, Ctrl-z doesn't work when this method is used. Commented Nov 19, 2014 at 22:18
  • possible duplicate of Javascript textarea undo redo Commented Nov 19, 2014 at 22:34

3 Answers 3

21

I found a solution that works at https://stackoverflow.com/a/10345596/1021426

By replacing the "field.value = ..." lines with:

document.execCommand("insertText", false, processedText);

...and moving "field.focus()" to before that line, I was able to achieve the undo/redo functionality I desired.

Sign up to request clarification or add additional context in comments.

3 Comments

it's funny how google works, this is the front result, not the one you linked to :D
3

Edit: Firefox now supports execCommand too. You just need that.


Here's a solution which works in Firefox too, is the most performant one and offers undo functionality everywhere except Firefox (where it just isn't possible natively)

// Solution
function insertText(textarea, text) {
    // https://stackoverflow.com/a/55174561/288906
    if (!document.execCommand('insertText', false, text)) {
        textarea.setRangeText(text);
    }
}

// Demo code to add text on click
const textarea = document.querySelector('textarea');
textarea.onclick = () => insertText(
  textarea,
  '@'
);
<textarea>Click in here to add text</textarea>

I also packaged this up as an npm module, improving consistency across browsers and adding utilities like "insert", "replace", "search and replace", etc

Comments

0

Here's code to replace the contents of a <textarea> instead of just inserting.

function setValueAndUpdateUndoStack(textarea, text) {
    // Must select all, so that the old text is deleted.
    textarea.focus();
    textarea.select();
    
    // https://stackoverflow.com/a/55174561/3480193
    if ( ! document.execCommand('insertText', false, text) ) {
        textarea.setRangeText(text);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.