如何“撤消”将文本编程插入文本区域?

问题描述 投票:14回答:12

我有一个textarea和一个按钮。单击该按钮可将文本插入文本区域。

有没有办法允许用户按Ctrl / Cmd + z撤消文本的插入并将textarea恢复到以前的状态?

javascript jquery textarea undo
12个回答
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('&#13;&#10;'));
    $("[name='actors']").val(items.join(','));   
}

你可以试试http://jsfiddle.net/surendra786/1v5jxaa0/

这对我有用


0
投票

这里有很多适用的答案可以满足您的需求。这是我在你的环境中会做的事情。这允许更改您最有可能使用的文本变量,您可以设置它,或者用户可以使用其他字段设置它等。

codepen here

它的主旨就是这样的。

$(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()
})

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>

我还把它打包成npm module,提高了浏览器的一致性。


1
投票
$("#target").keypress(function(event) {
  if ( event.which == 'Z' && first press == 'Cmd' && second press == 'Ctrl') {//check for key press
     event.preventDefault();
    text.value = defaultValueForTextField
   }
});

这应该是你正在寻找的。第一次和第二次按下需要保存,因为您需要组合印刷机。您确实需要保存默认文本值。


1
投票

这是一个想法:

如果我们可以生成keyborad事件,就像用户在textarea中输入一样,那么浏览器将自动处理撤消事件。因此,我们应该尝试为我们要插入的文本模拟键盘事件,而不是仅仅添加/更改textarea的值。

根据MDN的文档(下面给出的链接),我们可以使用KeyboardEvent对象生成如下事件:

  var e1 = new KeyboardEvent(<type>, <details>);
  var b1 = <textbox>.dispatchEvent(e1);

哪里:

  • <type>代表事件类型,如keydownkeypresskeyup
  • <details>代表具有事件细节的对象,如keycode
  • <textbox>表示我们想要触发事件的目标文本框

这是一个JSFiddle,我试图模拟给定字符串中每个字符的keydownkeypresskeyup事件。虽然它触发了相应的事件处理程序,但不知何时字符不会显示/添加到文本框中。

我注意到当我使用我的代码模拟a的3个事件时,在文本框中键入a时生成的事件对象存在一些差异。差异是(在Firefox 50.1.0中测试时):

  1. 当我模拟事件时,explicitOriginalTargetoriginalTarget不同;当我输入文本框时,它们都具有相同的值
  2. 当我输入文本框时,rangeParentrangeOffset值是null / 0;当我模拟事件时,他们有一些价值观
  3. 当我输入文本框时,isTrusted属性是true;当我模拟事件时它的false(对于使用脚本生成的任何事件,它将有false

MDN链接:


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/,这是一个小提琴

我编写了这样的代码以便于理解,但是你当然应该更好地编写实际的代码并且比这更简洁。


0
投票

具体的库和技术在很大程度上取决于您的堆栈。

我可以通过两种常规方式立即思考。

第一步:将以前的状态保存在控制器中。挂钩快捷方式并将内容替换为以前的状态。如果进行了其他修改,请删除钩子。或多或少你的2013年方法

这是一种快速的方法,如果您想要一个具有一次以上编辑历史记录的堆栈,则不会很好。

第二:观察textinput并定期将状态保存在堆栈中。钩入快捷方式。 (接管整个过程)。这是一种更简洁的方法,因为您的修改在概念上与用户修改相同。

使用redux / flux架构http://redux.js.org/docs/recipes/ImplementingUndoHistory.html,这可能非常简单

要捕获cmd / ctrl + z,你可以查看https://github.com/madrobby/keymaster

如果你详细说明你的堆栈/要求,我很乐意扩展这个答案。


0
投票

最简单的方法似乎是:

  • 在DOM textarea本身的属性中按钮单击保存以前的textarea内容。
  • 截取BODY级别的键盘(你不知道当命中Ctrl-Z时焦点在哪里)
  • (可选)还根据需要截取来自不同对象的许多事件:input,keyPress等,同样在BODY级别。

现在:

  • 当用户单击该按钮时,将保存旧内容并将textarea的自定义“脏”属性设置为true
  • 如果用户按Ctrl-Z或Cmd-Z,则撤消例程很简单(在jQuery中将是$('#idOfTextarea').val($('#idOfTextarea').attr('prevContents'));。撤消例程也会清除“脏”属性,以便不会调用撤消两次。
  • (可选)如果用户更改另一个字段,单击其他位置等,则textarea的dirty属性也会被清除,并且更改将变为可撤消。
  • (可选)具有自己的撤消功能的对象可以/必须停止事件传播以避免其他撤消具有两种效果。

你可能想要或不想在textarea上拦截onChange。如果onChange触发并且未设置脏,则这是初始按钮单击,可能会被忽略。否则,它可能表示用户已将其自己的一些更改添加到单击的文本中。在这种情况下,您可能希望禁用撤消以保留这些更改,或要求用户进行确认。


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

© www.soinside.com 2019 - 2024. All rights reserved.