撤消JS中的覆盖粘贴

时间:2019-04-25 14:20:19

标签: javascript jquery paste undo

我有overridden the paste event。我注意到,由于阻止了事件的默认行为,因此当前无法使用Ctrl + Z撤消“粘贴”。

<table>
  <tbody>
    <tr class="table-row">
      <td class="column-1">
          <div class="cart-img-product b-rad-4 o-f-hidden">
              <img src="../admin/uploads/<?php echo $info['product_photo']; ?>" alt="IMG-PRODUCT">
          </div>
      </td>
      <td class="column-2"><?php echo $info['product_name']; ?></td>
      <td class="column-3"><input type="text" value="<?php echo $info['product_price']; ?>" readonly></td>
      <td class="column-4"><input type="text" value="<?php echo $info['product_amount']; ?> Piece" readonly></td>
      <td class="column-5"><input style="color:red;" type="text" value="Rs 50" readonly></td>
  </tr>

  <tr class="table-row">
      <td class="column-1">
          <div class="cart-img-product b-rad-4 o-f-hidden">
              <img src="../admin/uploads/<?php echo $info['product_photo']; ?>" alt="IMG-PRODUCT">
          </div>
      </td>
      <td class="column-2"><?php echo $info['product_name']; ?></td>
      <td class="column-3"><input type="text" value="<?php echo $info['product_price']; ?>" readonly></td>
      <td class="column-4"><input type="text" value="<?php echo $info['product_amount']; ?> Piece" readonly></td>
      <td class="column-5"><input style="color:red;" type="text" value="Rs 100" readonly></td>
  </tr>
  </tbody>
</table>

是否有一种方法可以覆盖撤消功能,或者是否可以通过其他方式使Ctrl + Z起作用?

相关问题

3 个答案:

答案 0 :(得分:5)

使用

document.execCommand("insertText", false, $.trim(pastedData));

代替

 $(this).val($.trim(pastedData));

它将保留撤消历史记录。

$('#inputElement').on('paste', function (evt) {
  var clipboardData = evt.originalEvent.clipboardData || window.clipboardData;
  var pastedData = clipboardData.getData('text/plain');
  this.select(); // To replace the entire text
  document.execCommand("insertText", false, $.trim(pastedData));
  evt.preventDefault();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="inputElement"></textarea>

答案 1 :(得分:3)

可能的解决方案是手动实现撤消堆栈。该算法将类似于:

  • 撤消堆栈开始为空。
  • input事件添加一个侦听器,当输入与最后一个输入堆栈元素的输入不同时,该事件会将新条目推送到“撤消堆栈”上。此侦听器至少应进行反跳,以避免单字母撤消堆栈元素。
  • paste事件侦听器在调用时还将条目推入撤消堆栈。
  • 添加一个keydown侦听器,该侦听器将拦截CTRL-Z并从撤消堆栈中弹出最后一个条目。

对于已经内置在浏览器中的某些东西来说,似乎需要做很多工作,所以我希望有更好的解决方案。

答案 2 :(得分:1)

我找到了使之工作的方法。从this answer开始,我将其更改为使用.focus()而不是.select(),从而解决了粘贴问题。然后,要在Firefox中进行粘贴,我必须保留不会保留撤消历史记录的后备。直到Firefox修复该错误(See bug report)为止,都需要这样做。

function insertAtCaretTrim(element, text) {
    element[0].focus();
    // Attempt to preserve edit history for undo.
    var inserted = document.execCommand("insertText", false, $.trim(text));
  
    // Fallback if execCommand is not supported.
    if (!inserted) {
        var caretPos = element[0].selectionStart;
        var value = element.val();

        // Get text before and after current selection.
        var prefix = value.substring(0, caretPos);
        var suffix = value.substring(element[0].selectionEnd, value.length);

        // Overwrite selected text with pasted text and trim. Limit to maxlength.
        element.val((prefix + $.trim(text) + suffix).substring(0, element.attr('maxlength')));

        // Set the cursor position to the end of the paste.
        caretPos += text.length;
        element.focus();
        element[0].setSelectionRange(caretPos, caretPos);
    }
}

var $inputs = $("input");

$inputs.each(function () {
    $(this).on('paste', function (evt) {
    var clipboardData = evt.originalEvent.clipboardData || window.clipboardData;
    var pastedData = clipboardData.getData('text/plain');

    // Trim the data and set the value.
    insertAtCaretTrim($(this), pastedData);
    
    evt.preventDefault();
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" maxvalue="10" />

代码也位于JSFIddle中:https://jsfiddle.net/mf8v97en/5/