如何使用JavaScript将文本插入textarea而不会弄乱编辑历史记录?

时间:2016-05-27 11:41:20

标签: javascript html textarea undo-redo

基本上我想要的是如果用户在textarea中选择一些文本并按ctrl + b,那么选择中的文本应该被星星包围。

基本上我想要的是:

  

1)textarea内容:"你好,这是一些文字"

     

2)用户选择一些文字然后按ctrl + b"你好这个是一些文本" (假设粗体部分是文本选择)

     

3)所以我希望textarea内容为:         "你好这个*是一些*文字"

     

4)并且如果用户按下ctrl + z(或任何撤消动作)   textarea的内容应该回归到#34;你好,这是一些文字"

我尝试了How can i use javascript to insert text into a textarea?Insert text into textarea at cursor position (Javascript),但问题是在为大多数浏览器做撤消(ctrl + z)时我希望文本返回到第1步中的值但这不会发生。我理解stackoverflow在其编辑器中实现了自己的撤销重做功能。但我希望不要那么复杂。 必须支持chrome和safari

我正在考虑的方法是定位光标并发出合成键事件。我不知道它是否有效以及是否没有问题

2 个答案:

答案 0 :(得分:1)

我从http://www.javascriptsource.com/forms/undo-redo.html获得了以下代码,您也可以查看其工作示例 虽然您可能需要实现自己的功能,如Bold,Italic等。



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];
  }
 }
&#13;
<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>
&#13;
&#13;
&#13;

我过去曾使用ckeditor并建议使用它。您也可以使用niceditor

答案 1 :(得分:0)

更新版本

要在更改文本区域的整体值时保存用户历史记录,而不是:

textarea.value = newText;

使用:

textarea.focus();
document.execCommand('selectAll',false);

var el = document.createElement('p');
el.innerText = newText;

document.execCommand('insertHTML',false,el.innerHTML);

在我的中端游戏设备上,它的字符串大约超过4,000个字符,大约需要〜1秒,因此您必须弄清楚这是否适合您的用例。

旧版本

也许您对execCommand很熟悉,想知道为什么我们不仅仅使用它:

textarea.focus();
document.execCommand('selectAll',false);
document.execCommand('insertText',false,newText);

在Chromium insertText上,非常慢,特别是对于较长的字符串。例如超过4,000个字符,在我的中级游戏中,与“更新版本”中使用的字符串相同的字符串需要〜10秒

它也可以保存用户历史记录,并且在历史记录状态之间移动仍然是可以接受的速度(〜0.5秒)。

这样做慢一点有意义吗,因为无论如何我都会假设我在更新版本Chromium的后台显式执行的操作?不。但是,我猜这就是今天的Chromium。如果旧版本变得更好,请在下面发表评论。

一般说明

不幸的是,execCommand在Firefox的textarea元素中不起作用。 This may be fixed in an upcoming version.

在Chromium和Firefox中进行了测试。

如果我找到了更快的解决方案(和/或在Firefox中可以使用的解决方案),我一定会分享它。