在 JS 中撤消覆盖的粘贴
Undo an overridden paste in JS
我有overridden the paste
event。我注意到由于事件的默认行为被阻止,目前无法使用 Ctrl+Z 撤消 "paste"。
$(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.
//
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 get clipboard data on paste event (Cross browser)
- Paste event modify content and return it at the same place
一个可能的解决方案是手动实现撤消堆栈。该算法类似于:
- 撤消堆栈开始时为空。
- 为
input
事件添加一个侦听器,当输入与最后一个输入堆栈元素的输入不同时,在 "undo stack" 上推送一个新条目。这个侦听器至少应该去抖动以避免single-letter撤销堆栈元素。
paste
事件侦听器在被调用时还会将一个条目压入撤消堆栈。
- 添加一个
keydown
拦截器 CTRL-Z
并从撤消堆栈中弹出最后一个条目。
浏览器已经 built-in 的东西看起来确实需要做很多工作,所以我希望有更好的解决方案。
使用
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>
我找到了让它工作的方法。以 , I changed it to use .focus()
instead of .select()
, which fixes the pasting. Then, to make pasting work in Firefox, I had to keep the fallback that doesn't preserve undo history. This will have to do until Firefox fixes the bug (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/
我有overridden the paste
event。我注意到由于事件的默认行为被阻止,目前无法使用 Ctrl+Z 撤消 "paste"。
$(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.
//
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 get clipboard data on paste event (Cross browser)
- Paste event modify content and return it at the same place
一个可能的解决方案是手动实现撤消堆栈。该算法类似于:
- 撤消堆栈开始时为空。
- 为
input
事件添加一个侦听器,当输入与最后一个输入堆栈元素的输入不同时,在 "undo stack" 上推送一个新条目。这个侦听器至少应该去抖动以避免single-letter撤销堆栈元素。 paste
事件侦听器在被调用时还会将一个条目压入撤消堆栈。- 添加一个
keydown
拦截器CTRL-Z
并从撤消堆栈中弹出最后一个条目。
浏览器已经 built-in 的东西看起来确实需要做很多工作,所以我希望有更好的解决方案。
使用
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>
我找到了让它工作的方法。以 .focus()
instead of .select()
, which fixes the pasting. Then, to make pasting work in Firefox, I had to keep the fallback that doesn't preserve undo history. This will have to do until Firefox fixes the bug (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/