我有一个textarea和一个按钮。单击该按钮可将文本插入文本区域。
有没有办法允许用户按Ctrl / Cmd + z撤消文本的插入并将textarea恢复到以前的状态?
答案 0 :(得分:7)
我认为最简单的方法是利用浏览器的撤销堆栈而不是捕获事件。
为此,您需要为不同的浏览器使用不同的代码。幸运的是,在所有主流浏览器中,只有Firefox有不同的方法。
// http://stackoverflow.com/a/9851769/529024
// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';
// Safari 3.0+ "[object HTMLElementConstructor]"
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || (function(p) {
return p.toString() === "[object SafariRemoteNotification]";
})(!window['safari'] || safari.pushNotification);
// Internet Explorer 6-11
var isIE = /*@cc_on!@*/ false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
var isChrome = !!window.chrome && !!window.chrome.webstore;
var position = 0;
// text to anser
var text = 'Inserted Text';
// Just for fun :)
if (isFirefox)
text = " __ Firefox __ ";
else if (isIE)
text = " __ IE __ ";
else if (isEdge)
text = " __ Edge __ ";
else if (isSafari)
text = " __ Safari __ ";
else if (isOpera)
text = " __ Opera __ ";
else if (isChrome)
text = " __ Chrome __ ";
/* Adding text on click based on browser */
jQuery(".addText").on("click", function() {
if (isFirefox) {
// Firefox
var val = jQuery(".textArea").val();
var firstText = val.substring(0, position);
var secondText = val.substring(position);
jQuery(".textArea").val(firstText + text + secondText);
} else {
jQuery(".textArea").focus();
var val = jQuery(".textArea").val();
jQuery(".textArea")[0].selectionStart = position;
jQuery(".textArea")[0].selectionEnd = position;
document.execCommand('insertText', false, text);
}
});
jQuery(".textArea").on("focusout", function(e) {
position = jQuery(this)[0].selectionStart;
});

textarea {
padding: 10px;
font-family: Calibri;
font-size: 18px;
line-height: 1.1;
resize: none;
}
.addText {
padding: 5px 15px;
transition: all 0.5s;
border: 1px solid black;
border-radius: 2px;
background-color: #169c16;
width: 70px;
margin: 10px 0;
color: white;
cursor: pointer;
}
.addText:hover {
background-color: #2776b9;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea name='textArea' class='textArea' rows="7" cols="50">Suspendisse convallis, metus at laoreet congue, sapien dui ornare magna, a porttitor felis purus a ipsum. Morbi vulputate erat rhoncus, luctus neque ut, lacinia orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas. Fusce aliquam, nulla nec fringilla ultrices, ipsum lectus maximus nisl, ut laoreet purus lectus eget nisl. Duis blandit cursus nulla. Vestibulum consectetur, nunc non viverra condimentum, neque neque tincidunt diam, nec vestibulum neque nisi
ac sem. Integer aliquam a leo id laoreet. Mauris ultrices mauris lorem, eu hendrerit odio volutpat ut. Nam eget hendrerit metus.</textarea>
<div class='addText'>
Add Text
</div>
&#13;
经过测试:
答案 1 :(得分:6)
您需要以特殊方式插入文本,以便用户可以使用正常的撤消/重做行为。
var textEvent = document.createEvent('TextEvent');
textEvent.initTextEvent('textInput', true, true, null, "new text");
document.getElementById("your-textarea").dispatchEvent(textEvent);
答案 2 :(得分:4)
将textarea
的原始值保存在data
:
var $textarea = $('textarea');
$('button').on('click', function () {
var val = $textarea.val();
$textarea.data('old-val', val).val(val + ' some text');
});
如果你想要一个数据数组(如@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');
});
答案 3 :(得分:1)
$("#target").keypress(function(event) {
if ( event.which == 'Z' && first press == 'Cmd' && second press == 'Ctrl') {//check for key press
event.preventDefault();
text.value = defaultValueForTextField
}
});
那应该是你要找的东西。第一次和第二次按下需要保存,因为您需要组合印刷机。您确实需要保存默认文本值。
答案 4 :(得分:1)
这是一个想法:
如果我们可以生成keyborad事件,就像用户在textarea中输入一样,那么浏览器将自动处理撤消事件。因此,我们应该尝试为我们想要插入的文本模拟键盘事件,而不是仅仅添加/更改textarea的值。
根据MDN的文档(下面给出的链接),我们可以使用KeyboardEvent
对象生成如下事件:
var e1 = new KeyboardEvent(<type>, <details>);
var b1 = <textbox>.dispatchEvent(e1);
其中:
<type>
代表事件类型,例如keydown
,keypress
或keyup
<details>
代表具有key
,code
<textbox>
表示我们想要触发事件的目标文本框以下是JSFiddle,我尝试为给定字符串中的每个字符模拟keydown
,keypress
和keyup
个事件。虽然它会触发相应的事件处理程序,但不会显示/添加到文本框中。
我注意到,当我使用我的代码模拟a
的3个事件时,在文本框中键入a
时生成的事件对象存在一些差异。差异是(在Firefox 50.1.0中测试时):
explicitOriginalTarget
与originalTarget
不同;当我输入文本框时,它们都具有相同的值rangeParent
和rangeOffset
值为null
/ 0
;当我模拟事件时,他们有一些价值观isTrusted
属性为true
;当我模拟事件时false
(对于使用脚本生成的任何事件,它将具有false
)MDN链接:
答案 5 :(得分:0)
即使这个问题是一年前的问题,我也想分享我的方式。
你可以这样做:
$(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;
}
});
});
如果你想试验它http://jsfiddle.net/45Jwz/1/
,这是一个小提琴我为了很好的理解而编写了这样的代码,但你当然应该更好地编写实际的代码而不是这个代码。
答案 6 :(得分:0)
具体的库和技术在很大程度上取决于您的堆栈。
我可以立即想到两种一般方式。
第一: 将以前的状态保存在控制器中。挂钩快捷方式并将内容替换为以前的状态。如果进行了其他修改,请删除钩子。或多或少你的2013年方法
这是一种快速的方法,如果你想要一个具有超过一次编辑历史的堆栈,那么它就不会很好。
第二: 观察textinput并定期将状态保存在堆栈中。钩入快捷方式。 (接管整个过程)。 这是一种更简洁的方式,因为您的修改在概念上与用户修改相同。
使用redux / flux架构可能非常简单 http://redux.js.org/docs/recipes/ImplementingUndoHistory.html
要捕获cmd / ctrl + z,您可以查看https://github.com/madrobby/keymaster
如果你详细说明你的堆栈/要求,我很乐意扩展这个答案。
答案 7 :(得分:0)
最简单的方法似乎是这样:
现在:
$('#idOfTextarea').val($('#idOfTextarea').attr('prevContents'));
。撤消例程也会清除&#34; dirty&#34;属性以便撤消没有被召唤两次。您可能想要或不想在textarea上拦截onChange。如果onChange触发并且未设置脏,则这是初始按钮单击,可能会被忽略。否则,它可能表示用户已将其自己的一些更改添加到单击的文本中。在这种情况下,您可能希望禁用撤消以保留这些更改,或者要求用户进行确认。
答案 8 :(得分:0)
你可以这样做,
<强> HTML 强>
<div id="text-content">
<textarea rows="10" cols="50"></textarea>
<input type="button" name="Insert" value="Insert" />
</div>
<强> Jquery的强>
var oldText = [],ctrl=false;
$(function(){
$("input[name=Insert]").click(function(){
var text = oldText.length+1;
oldText.push(text);
var textAreaText = $('textarea').val();
textAreaText +=text;
$('textarea').val(textAreaText);
$("input[name=insertText]").val('');
});
$('textarea').keydown(function(e){
if(e.which == 17){ ctrl = true;}
});
$('textarea').keyup(function(e){
var c = e.which;
if(c == 17){ ctrl = false;}
if(ctrl==true && c==90 ){
oldText.pop();
var text = '';
$.each(oldText,function(i,ele){
text += ele;
});
$('textarea').val(text);
}
})
})
您还可以查看并试用fiddle。
答案 9 :(得分:0)
首先添加html,然后您可以使用按键事件撤消
你也可以在这里试试http://jsfiddle.net/surendra786/1v5jxaa0/
<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>
**然后添加jquery **
var items = [];
$("#add").click(function() {
// Push the new actor in the array
items.push($("[name='actor']").val());
populate();
});
$(document).keydown(function(e){
if( e.which === 90 && e.ctrlKey ){
console.log('control + z');
if (items.length > 0) {
// remove last element of the array
items.splice(-1,1);
populate();
}
}
});
populate = function() {
$("[name='actors-list']").text('');
$("[name='actors-list']").append(items.join(' '));
$("[name='actors']").val(items.join(','));
}
你可以在这里试试http://jsfiddle.net/surendra786/1v5jxaa0/
这对我有用
答案 10 :(得分:0)
这里有很多适用的答案可以满足您的需求。这是我在你的环境中会做的事情。这允许更改您最有可能使用的文本变量,您可以设置它或者用户可以使用其他字段设置它等。
它的主旨就是这样。
$(document).ready(function(){
function deployText(){
var textArray = [];
var textToAdd = 'let\'s go ahead and add some more text';
var textarea = $('textarea');
var origValue = textarea.text();
textArray.push(origValue);
$('button').on('click', function(e){
textArray.push(textToAdd);
textarea.text(textArray);
console.log(textArray.length);
console.log(textArray);
});
$(document).on('keypress', function(e){
var zKey = 26;
if(e.ctrlKey && e.which === zKey){
removePreviousText();
}
})
function removePreviousText(){
console.log(textArray);
if(textArray.length > 1){
textArray.pop();
$('textarea').text(textArray);
}
}
}
deployText()
})
答案 11 :(得分:0)
这是一个简短的,非jQuery的解决方案,也可以在Firefox中使用(但没有撤消功能,例如当前接受的解决方案)
// Solution
function insertText(textarea, text) {
// https://stackoverflow.com/a/55174581/288906
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>
此页面上的大多数解决方案已被弃用或模板代码过多。当前接受的解决方案可以执行类似的操作,但是代码更多。