我已经覆盖了
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 起作用?
使用
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>
一个可能的解决方案是手动实现撤消堆栈。该算法类似于:
input
事件添加一个监听器,当输入与最后一个输入堆栈元素的输入不同时,该事件将新条目推送到“撤消堆栈”上。该侦听器至少应进行去抖以避免单字母撤消堆栈元素。paste
事件监听器在调用时也会将条目推送到撤消堆栈上。keydown
监听器,拦截 CTRL-Z
并从撤消堆栈中弹出最后一个条目。对于浏览器中已经内置的东西来说,这确实需要做很多工作,所以我希望有更好的解决方案。
我找到了一种让它发挥作用的方法。从这个答案开始,我将其更改为使用
.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/