Velvet Star Monitor

Standout celebrity highlights with iconic style.

updates

Is it possible to edit a text input with javascript and add to the Undo stack?

Writer Andrew Henderson

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

3 Answers

I found a solution that works at

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.

4

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) { // 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.

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(); // if ( ! document.execCommand('insertText', false, text) ) { textarea.setRangeText(text); }
}

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy