Javascript “我怎么能?”;撤销;将文本以编程方式插入文本区域?
我有一个文本区和一个按钮。单击按钮可将文本插入文本区域Javascript “我怎么能?”;撤销;将文本以编程方式插入文本区域?,javascript,jquery,textarea,undo,Javascript,Jquery,Textarea,Undo,我有一个文本区和一个按钮。单击按钮可将文本插入文本区域 <input type="text" class="reset actor_input" name="actor" value="add actors"></input> <input type="text" name="actors"></input> <div class="found_actors">
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
是否有一种方法允许用户按Ctrl/Cmd+z撤消文本插入并将textarea恢复到以前的状态?将
textarea
的原始值保存在其数据中:
var $textarea = $('textarea');
$('button').on('click', function () {
var val = $textarea.val();
$textarea.data('old-val', val).val(val + ' some text');
});
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
如果需要数据数组(如@ahren建议的),请使用以下命令:
var $textarea = $('textarea');
$('button').on('click', function () {
var val = $textarea.val();
if ( ! $textarea.data('old-val')) {
$textarea.data('old-val', []);
}
$textarea.data('old-val').push(val);
$textarea.val(val + ' some text');
});
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
您需要以特殊的方式插入文本,以便用户可以使用正常的撤消/重做行为
var textEvent = document.createEvent('TextEvent');
textEvent.initTextEvent('textInput', true, true, null, "new text");
document.getElementById("your-textarea").dispatchEvent(textEvent);
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
那应该是你要找的。第一次和第二次按下将需要保存为您想要的组合按下。不过,您确实需要保存一个默认文本值。即使这个问题已经提出一年了,我也想分享一下我的方法
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
您可以这样做:
$(function () {
// Check to see if an array is not already defined.
if (!$('#t').data('old-val')) {
// If the check returns True we proceed to create an array in old-val.
$('#t').data('old-val', []);
}
// Get the current content value.
inputValue = $('#t').val();
// Push it to the old-val array.
$('#t').data('old-val').push(inputValue);
// We start with a current array position of 0.
curArrPos = 0;
$('#c').click(function () {
// Append a string to the #t.
$('#t').val(' ==this is the 2nd appended text==');
// Save the current content value.
inputValue = $('#t').val();
// Push it to the array.
$('#t').data('old-val').push(inputValue);
// Increment current array position.
++curArrPos;
});
$('#b').click(function () {
// Append a string to the #t.
$('#t').val(' ==this is the 1st appended text==');
// Save the current content value.
inputValue = $('#t').val();
// Push it to the array.
$('#t').data('old-val').push(inputValue);
// Increment current array position.
++curArrPos;
});
$('#undo').click(function () {
// First check that the old-val array length is greater than 1 (It's the initial position. No need undoing to a blank state) and current array position greater than 0 (for the same reason).
if ($('#t').data('old-val').length > 1 && curArrPos > 0) {
// Set current #t value to the one in the current array position, minus one.
// Minus one gets you to the previous array position (ex. current=5; previous= current - 1 = 4).
$('#t').val($('#t').data('old-val')[curArrPos - 1]);
// Decrease current array position, because we effectively shifted back by 1 position.
--curArrPos;
}
});
$('#redo').click(function () {
if (currentArrayPos < $('#c').data('old-val').length - 1) {
$('#t').val($('#t').data('old-val')[curArrPos + 1]);
// Increase current array position, because we effectively shifted forward by 1 position.
++curArrPos;
}
});
});
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
$(函数(){
//检查是否尚未定义数组。
if(!$('#t').data('old-val')){
//如果检查返回True,我们将继续在old-val中创建一个数组。
$('t')。数据('old-val',[]);
}
//获取当前内容值。
inputValue=$('#t').val();
//将其推送到旧的val数组。
$('t').data('old-val').push(inputValue);
//我们从当前数组位置0开始。
curArrPos=0;
$('#c')。单击(函数(){
//将字符串附加到#t。
$('#t').val('==这是第二个附加文本==');
//保存当前内容值。
inputValue=$('#t').val();
//将其推到阵列中。
$('t').data('old-val').push(inputValue);
//增加当前阵列位置。
++库拉尔波斯;
});
$('#b')。单击(函数(){
//将字符串附加到#t。
$('#t').val('==这是第一个附加文本==');
//保存当前内容值。
inputValue=$('#t').val();
//将其推到阵列中。
$('t').data('old-val').push(inputValue);
//增加当前阵列位置。
++库拉尔波斯;
});
$('#撤消')。单击(函数(){
//首先检查旧的val数组长度是否大于1(它是初始位置。无需撤消为空白状态),当前数组位置是否大于0(出于相同的原因)。
if($('#t').data('old-val').length>1&&curArrPos>0){
//将当前#t值设置为当前数组位置的值减去1。
//减1将返回上一个数组位置(例如,current=5;previous=current-1=4)。
$('t').val($('t').data('old-val')[curArrPos-1]);
//减少当前阵列位置,因为我们有效地向后移动了1个位置。
--库拉尔波斯;
}
});
$('#重做')。单击(函数(){
如果(currentArrayPos<$('#c')。数据('old-val')。长度-1){
$('t').val($('t').data('old-val')[curArrPos+1]);
//增加当前阵列位置,因为我们有效地向前移动了1个位置。
++库拉尔波斯;
}
});
});
这是一把小提琴,如果你想试试的话
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
我这样写代码是为了更好地理解,但您当然应该编写比这更好、更简洁的实际代码。具体的库和技术很大程度上取决于您的堆栈
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
我可以马上想到两种方法
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
第一:
在控制器中保存以前的状态。钩住快捷方式并将内容替换为以前的状态。如果进行了其他修改,则删除挂钩。或多或少你的2013年方法
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
这是一种快速的方法,如果您想要一个包含多个一次性编辑历史的堆栈,那么这种方法并不好用
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
第二:
观察textinput并定期将状态保存在堆栈上。钩住捷径。(接管整个过程)。
这是一种更简洁的方式,因为您的修改在概念上与用户修改相同
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
对于redux/flux架构,这可能非常简单
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
为了捕获cmd/ctrl+z,您可以查看
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
如果您能详细介绍一下您的堆栈/需求,我很乐意扩展这个答案。以下是一个想法:
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
如果我们可以像用户在文本区域中键入一样生成keyborad事件,那么浏览器将自动处理撤销事件。因此,我们不应该只是附加/更改textarea的值,而应该尝试为要插入的文本模拟键盘事件
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
根据MDN上的文档(下面给出的链接),我们可以使用KeyboardEvent
对象生成如下事件:
var e1 = new KeyboardEvent(<type>, <details>);
var b1 = <textbox>.dispatchEvent(e1);
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
var e1=新键盘事件(,);
变量b1=.dispatchEvent(e1);
其中:
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
表示事件类型,例如keydown
、keypress
或keypup
表示具有事件详细信息的对象,例如键
,代码
表示要在其上触发事件的目标文本框
在这里,我尝试为给定字符串中的每个字符模拟keydown
、keypress
和keyup
事件。虽然它会触发相应的事件处理程序,但不知何故,字符没有显示/添加到textbox
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
我注意到,在文本框中键入a
时生成的事件对象与使用代码模拟a
的3个事件时生成的事件对象存在一些差异。区别在于(在Firefox 50.1.0中测试时):
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
模拟事件时,explicitOriginalTarget
与originalTarget
不同;当我在文本框中输入时,两者都有相同的值
rangeParent
和rangeOffset
在文本框中键入时,值为null
/0
;当我模拟这些事件时,它们有一些值
当我在文本框中键入时,isTrusted
属性为true
;当我模拟事件时,它的false
(对于使用脚本生成的任何事件,它将具有false
)
MDN l