如何在不弄乱编辑历史的情况下使用 JavaScript 将文本插入文本区域?
How to insert text into a textarea using JavaScript without messing up edit history?
基本上我想要的是,如果用户在文本区域中选择一些文本并按 ctrl + b,那么选择中的文本应该被星号包围。
所以基本上我想要的是:
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"
我已经尝试过 How can i use javascript to insert text into a textarea? and Insert text into textarea at cursor position (Javascript) 和类似的方法,但问题是在为大多数浏览器执行撤消 (ctrl + z) 时,我希望文本返回到步骤 1 中的值。但这确实不会发生。我了解 Whosebug 在其编辑器中实现了自己的撤消重做功能。但我希望不要变得那么复杂。
必须支持 chrome 和 safari
我正在考虑的一种方法是定位光标并发出合成键事件。我不知道它是否有效,是否没有问题
我从以下代码中获得了以下代码:http://www.javascriptsource.com/forms/undo-redo.html 你也可以查看它的工作示例。
尽管您可能需要实现自己的功能,例如粗体、斜体等。
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.com">The JavaScript Source</a></font>
</center><p>
我用过ckeditor in the past and would recommend to use it. You could also use niceditor
更新版本
在更改文本区域的整体值时保存用户历史记录,而不是:
textarea.value = newText;
使用:
textarea.focus();
document.execCommand('selectAll',false);
var el = document.createElement('p');
el.innerText = newText;
document.execCommand('insertHTML',false,el.innerHTML);
在我的 mid-end 游戏机上,字符串超过 4,000 个字符需要大约 ~1 秒,所以你必须弄清楚这是否可以接受对于您的用例。
旧版本
也许您熟悉 execCommand
并且想知道为什么我们不直接使用它:
textarea.focus();
document.execCommand('selectAll',false);
document.execCommand('insertText',false,newText);
在 Chromium 上 insertText
非常 慢,尤其是对于较长的字符串。对于超过 4,000 个字符的示例,在我的 mid-gaming 上编译更新版本中使用的相同字符串需要 ~10 秒.
它 确实 保存了用户历史记录,并且在历史记录状态之间移动仍然是可以接受的速度(~0.5 秒)。
这更慢是否有意义,因为我会假设我在更新版本 Chromium 中明确做的事情无论如何都在后台做?不,但我猜这就是 Chromium 今天的用武之地。如果旧版本变得更好,请在下面评论。
一般说明
不幸的是,execCommand
在 Firefox 的 textarea 元素中不起作用。 This may be fixed in an upcoming version.
已在 Chromium 和 Firefox 中测试。
如果我找到更快的解决方案(and/or 可以在 Firefox 中运行的解决方案),我一定会分享它。
基本上我想要的是,如果用户在文本区域中选择一些文本并按 ctrl + b,那么选择中的文本应该被星号包围。
所以基本上我想要的是:
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"
我已经尝试过 How can i use javascript to insert text into a textarea? and Insert text into textarea at cursor position (Javascript) 和类似的方法,但问题是在为大多数浏览器执行撤消 (ctrl + z) 时,我希望文本返回到步骤 1 中的值。但这确实不会发生。我了解 Whosebug 在其编辑器中实现了自己的撤消重做功能。但我希望不要变得那么复杂。 必须支持 chrome 和 safari
我正在考虑的一种方法是定位光标并发出合成键事件。我不知道它是否有效,是否没有问题
我从以下代码中获得了以下代码:http://www.javascriptsource.com/forms/undo-redo.html 你也可以查看它的工作示例。
尽管您可能需要实现自己的功能,例如粗体、斜体等。
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.com">The JavaScript Source</a></font>
</center><p>
我用过ckeditor in the past and would recommend to use it. You could also use niceditor
更新版本
在更改文本区域的整体值时保存用户历史记录,而不是:
textarea.value = newText;
使用:
textarea.focus();
document.execCommand('selectAll',false);
var el = document.createElement('p');
el.innerText = newText;
document.execCommand('insertHTML',false,el.innerHTML);
在我的 mid-end 游戏机上,字符串超过 4,000 个字符需要大约 ~1 秒,所以你必须弄清楚这是否可以接受对于您的用例。
旧版本
也许您熟悉 execCommand
并且想知道为什么我们不直接使用它:
textarea.focus();
document.execCommand('selectAll',false);
document.execCommand('insertText',false,newText);
在 Chromium 上 insertText
非常 慢,尤其是对于较长的字符串。对于超过 4,000 个字符的示例,在我的 mid-gaming 上编译更新版本中使用的相同字符串需要 ~10 秒.
它 确实 保存了用户历史记录,并且在历史记录状态之间移动仍然是可以接受的速度(~0.5 秒)。
这更慢是否有意义,因为我会假设我在更新版本 Chromium 中明确做的事情无论如何都在后台做?不,但我猜这就是 Chromium 今天的用武之地。如果旧版本变得更好,请在下面评论。
一般说明
不幸的是,execCommand
在 Firefox 的 textarea 元素中不起作用。 This may be fixed in an upcoming version.
已在 Chromium 和 Firefox 中测试。
如果我找到更快的解决方案(and/or 可以在 Firefox 中运行的解决方案),我一定会分享它。