撤消 JS 中覆盖的粘贴

问题描述 投票:0回答:3

我已经覆盖了

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

$(this).on('paste', function (evt) {
  // Get the pasted data via the Clipboard API.
  // evt.originalEvent must be used because this is jQuery, not pure JS.
  // https://stackoverflow.com/a/29831598
  var clipboardData = evt.originalEvent.clipboardData || window.clipboardData;
  var pastedData = clipboardData.getData('text/plain');

  // Trim the data and set the value.
  $(this).val($.trim(pastedData));

  // Prevent the data from actually being pasted.
  evt.preventDefault();
});

有没有办法覆盖撤消功能或以不同方式执行上述操作,以便 Ctrl+Z 起作用?

相关问题

javascript jquery paste undo
3个回答
7
投票

使用

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>


3
投票

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

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

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


1
投票

我找到了一种让它发挥作用的方法。从这个答案开始,我将其更改为使用

.focus()
而不是
.select()
,这修复了粘贴。然后,为了在 Firefox 中进行粘贴工作,我必须保留不保留撤消历史记录的后备。在 Firefox 修复该错误之前,必须执行此操作(参见错误报告)。

更新:Firefox bug 在 Firefox 89 中已修复

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/

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