Basically what i want is if a user selects some text in a textarea and presses ctrl + b then the text within the selection should be surrounded by stars.
so basically what I want is :
1) textarea content : "hello this is some text"
2) user selects some text and presses ctrl + b "hello this is some text" (assume the bolded part is a text selection)
3) so I want the textarea content to be : "hello this *is some* text"
4) and if the user presses ctrl + z(or whatever the undo action) the textarea content should go back to being "hello this is some text"
I have tried How can i use javascript to insert text into a textarea? and Insert text into textarea at cursor position (Javascript) and similar but the issue is that on doing undo (ctrl + z) for most browsers I expect the text to go back to go to the value in step 1. but this does not happen. I understand stackoverflow implements own undo redo functionality in its editor. but I was hoping not to go to that much plexity. Have to support chrome and safari
An approach I am thinking about would be to position the cursor and issue a synthetic key event. I don't know if it will work and if it would be free of issues
Basically what i want is if a user selects some text in a textarea and presses ctrl + b then the text within the selection should be surrounded by stars.
so basically what I want is :
1) textarea content : "hello this is some text"
2) user selects some text and presses ctrl + b "hello this is some text" (assume the bolded part is a text selection)
3) so I want the textarea content to be : "hello this *is some* text"
4) and if the user presses ctrl + z(or whatever the undo action) the textarea content should go back to being "hello this is some text"
I have tried How can i use javascript to insert text into a textarea? and Insert text into textarea at cursor position (Javascript) and similar but the issue is that on doing undo (ctrl + z) for most browsers I expect the text to go back to go to the value in step 1. but this does not happen. I understand stackoverflow implements own undo redo functionality in its editor. but I was hoping not to go to that much plexity. Have to support chrome and safari
An approach I am thinking about would be to position the cursor and issue a synthetic key event. I don't know if it will work and if it would be free of issues
Share Improve this question edited May 23, 2017 at 11:58 CommunityBot 11 silver badge asked May 27, 2016 at 11:41 sktguhasktguha 5645 silver badges23 bronze badges 2-
1
The answers below suggest
execCommand
which is deprecated. See stackoverflow./q/60581285/1066234 – Probably one way would be to track the edit states by yourself (in HTML5's localstorage) and load the former state of the textarea with each CTRL Z. – Avatar Commented May 7, 2022 at 14:02 -
Or you use a global JS variable to store the different states. For example, SCEditor does it like this with the undo.js plugin, see
var undoStates = [];
andfunction storeState()
. – Avatar Commented May 29, 2022 at 13:42
2 Answers
Reset to default 7Updated Version
To save user history when changing a textarea's overall value, instead of:
textarea.value = newText;
Use:
textarea.focus();
document.execCommand('selectAll',false);
var el = document.createElement('p');
el.innerText = newText;
document.execCommand('insertHTML',false,el.innerHTML);
It takes about ~1 second on my mid-end gaming rig with a string a little over 4,000 characters, so you'll have to figure out if that's acceptable for your use case.
Old Version
Maybe you're familiar with execCommand
and wonder why we don't just use this:
textarea.focus();
document.execCommand('selectAll',false);
document.execCommand('insertText',false,newText);
On Chromium insertText
is extremely slow, especially for longer strings. For an example over 4,000 characters, on my mid-gaming py the same string as used in the Updated Version takes ~10 seconds.
It does save user history too though, and moving between history states is still an acceptable speed (~0.5 seconds).
Does it make sense that this is slower, since I would assume what I'm doing explicitly in the Updated Version Chromium's doing in the background anyway? No. But this is where Chromium's at today, I guess. Comment below if the Old Version bees better.
General Notes
Unfortunately, execCommand
doesn't work inside of textarea elements in Firefox. This may be fixed in an uping version.
Tested in Chromium and Firefox.
If I find a still faster solution (and/or one that works in Firefox), I will definitely share it.
I got the below code from: http://www.javascriptsource./forms/undo-redo.html and you can check its working example as well.
Though you might need to implement your own functionalities such as Bold, Italic etc.
function iObject() {
this.i;
return this;
}
var myObject=new iObject();
myObject.i=0;
var myObject2=new iObject();
myObject2.i=0;
store_text=new Array();
//store_text[0] store initial textarea value
store_text[0]="";
function countclik(tag) {
myObject.i++;
var y=myObject.i;
var x=tag.value;
store_text[y]=x;
}
function undo(tag) {
if ((myObject2.i)<(myObject.i)) {
myObject2.i++;
} else {
alert("Finish Undo Action");
}
var z=store_text.length;
z=z-myObject2.i;
if (store_text[z]) {
tag.value=store_text[z];
} else {
tag.value=store_text[0];
}
}
function redo(tag) {
if((myObject2.i)>1) {
myObject2.i--;
} else {
alert("Finish Redo Action");
}
var z=store_text.length;
z=z-myObject2.i;
if (store_text[z]) {
tag.value=store_text[z];
} else {
tag.value=store_text[0];
}
}
<form name=form1>
<input type="button" class="red" value="Undo" onmousedown="undo(document.form1.text1);">
<input type="button" class="red" value="Redo" onmousedown="redo(document.form1.text1);">
<br>
<textarea rows=7 cols=50 name=text1 onkeydown="countclik(document.form1.text1);" >
</textarea>
</form>
<p><center>
<font face="arial, helvetica" size"-2">Free JavaScripts provided<br>
by <a href="http://javascriptsource.">The JavaScript Source</a></font>
</center><p>
I have used ckeditor in the past and would remend to use it. You could also use niceditor