如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?
Posted
技术标签:
【中文标题】如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?【英文标题】:How to detect Ctrl+V, Ctrl+C using JavaScript? 【发布时间】:2011-02-23 15:26:02 【问题描述】:如何使用javascript检测ctrl+v、ctrl+c?
我需要限制在我的 textarea 中粘贴,最终用户不应复制和粘贴内容,用户只能在 textarea 中键入文本。
如何做到这一点?
【问题讨论】:
这样做的目的是什么?我能想到的唯一两个合法场景是密码字段(无论如何您都无法复制)和打字速度测试。我相信您可以检测到可疑的快速输入。 @Paul Butcher, @Propeng:有些场景,你需要这个。非常简单的例子:一个学习外语的网站。如果您手动输入单词而不是使用复制和粘贴,则可以增强学习效果。 另一种合法的情况可能是需要重复输入以检测错误(例如,输入您的电子邮件两次,以便我们知道它没有错字)。尽管如此,这样的用户可能会保留一个随机生成的电子邮件地址列表(例如偷偷摸摸的电子邮件),并且可能希望将其粘贴以确保准确性。 @Paul Butcher - 这根本不是合法的情况,我讨厌这样做的网站,我总是复制/粘贴我的(长) 从一个输入到另一个的电子邮件地址。破坏复制/粘贴是一个主要的可用性问题。它确实让用户感到厌烦,因为它对他们的心智模型如此重要,以至于他们希望它“正常工作”。就好像你试图拉一扇门,它从你身边转开而不是朝你这边转! 当这样的复制粘贴不允许在页面中时,我所做的是将文本粘贴到其他位置(我使用 URL 栏),然后 Ctrl + A(选择刚刚粘贴在url ),在浏览器中拖放禁用粘贴的字段。我想,这在今天是无法预防的。 【参考方案1】:您可以监听 keypress 事件,如果它与特定的键码匹配,则停止默认事件(输入文本)
【讨论】:
【参考方案2】:我写了一个 jQuery 插件,它可以捕捉击键。它可用于在没有操作系统的情况下启用 html 表单中的多语言脚本输入(字体除外)。大概有300行代码,也许你喜欢看一下:
http://miku.github.com/jquery-retype一般来说,小心这种改动。我为客户编写了插件,因为没有其他解决方案。
【讨论】:
【参考方案3】:有一些方法可以防止它。
但是,用户将始终能够关闭 javascript 或只查看页面的源代码。
一些例子(需要 jQuery)
/**
* Stop every keystroke with ctrl key pressed
*/
$(".textbox").keydown(function()
if (event.ctrlKey==true)
return false;
);
/**
* Clear all data of clipboard on focus
*/
$(".textbox").focus(function()
if ( window.clipboardData )
window.clipboardData.setData('text','');
);
/**
* Block the paste event
*/
$(".textbox").bind('paste',function(e)return false;);
编辑:Tim Down 怎么说,这些功能都依赖于浏览器。
【讨论】:
这有很多问题:首先,它在没有paste
事件的浏览器中不起作用,其中包括版本 3 之前的所有版本的 Firefox。其次,@987654323 @ 仅在 IE 中,我相信现在在 IE 中默认禁用。第三,禁用所有按下 Ctrl 键的keydown
事件是多余的:您阻止了有用的键盘快捷键,例如 Ctrl-A(全选)和 Ctrl-Z(撤消)。第四,正如其他人所说,这是一件非常糟糕的事情。
你说得对,并不是在所有浏览器上都可以使用。没有人 ctrl 块确实很烦人。当客户想要阻止“确认电子邮件和密码”字段时,它很方便。【参考方案4】:
我只是出于兴趣才这样做。我同意这不是正确的做法,但我认为这应该是操作人员的决定......而且代码可以很容易地扩展以添加功能,而不是把它拿走(比如更高级的剪贴板,或 Ctrl +s 触发服务器端保存)。
$(document).ready(function()
var ctrlDown = false,
ctrlKey = 17,
cmdKey = 91,
vKey = 86,
cKey = 67;
$(document).keydown(function(e)
if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = true;
).keyup(function(e)
if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = false;
);
$(".no-copy-paste").keydown(function(e)
if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)) return false;
);
// Document Ctrl + C/V
$(document).keydown(function(e)
if (ctrlDown && (e.keyCode == cKey)) console.log("Document catch Ctrl+C");
if (ctrlDown && (e.keyCode == vKey)) console.log("Document catch Ctrl+V");
);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>Ctrl+c Ctrl+v disabled</h3>
<textarea class="no-copy-paste"></textarea>
<br><br>
<h3>Ctrl+c Ctrl+v allowed</h3>
<textarea></textarea>
另外澄清一下,这个脚本需要 jQuery 库。
Codepen demo
编辑:由于 Tim Down 的建议,删除了 3 条多余的行(涉及 e.which)(参见 cmets)
编辑:添加了对 Mac 的支持(cmd 键而不是 ctrl)
【讨论】:
为什么keydown
和keyup
处理程序在document
上?您可以在 $(".no-copy-paste").keydown
处理程序中测试 Ctrl 键。此外,不需要e.keyCode || e.which
位:e.keyCode
适用于所有e.which
工作的浏览器,因此永远不会使用e.which
。也许您正在考虑如何从keypress
事件中获取字符代码?最后,这对从上下文或编辑菜单中的粘贴没有任何作用,但我想 OP 没有直接询问这个问题。
@Tim:文档上的 Ctrl 键处理程序是通用的 - 因为他们可能不希望 ctrlDown 变量专门链接到无复制粘贴输入。这可能是OTT。感谢 e.which 的提示 - 从那以后我花了半个小时研究 e.keyCode 和 e.which 的不同用例与 keydown() 和 keypress(),真是一团糟(尤其是在 Firefox 中)!跨度>
jackocnr:我推荐Jan Wolter的JavaScript密钥处理文章:unixpapa.com/js/key.html我参考了很多次,没有发现错误。
老兄!谢谢!这正是我需要让用户在我正在编写的网络应用程序中选择一个“元素”(日历条目),点击 ctrl + c 来“复制”它,然后 ctrl + v 来“粘贴”它,所有这些都没有实际上与全能的祝福剪贴板进行交互。 ctrl+c 我记得他们点击了什么, ctrl+v 我复制它,每个人都赢了。
我不是专家或任何东西,但我认为最好测试 e.metaKey
或 e.ctrlKey
是 true
而不是为键分配数字值并测试它们.【参考方案5】:
虽然它在用作反盗版措施时可能很烦人,但我可以看到在某些情况下它可能是合法的,所以:
function disableCopyPaste(elm)
// Disable cut/copy/paste key events
elm.onkeydown = interceptKeys
// Disable right click events
elm.oncontextmenu = function()
return false
function interceptKeys(evt)
evt = evt||window.event // IE support
var c = evt.keyCode
var ctrlDown = evt.ctrlKey||evt.metaKey // Mac support
// Check for Alt+Gr (http://en.wikipedia.org/wiki/AltGr_key)
if (ctrlDown && evt.altKey) return true
// Check for ctrl+c, v and x
else if (ctrlDown && c==67) return false // c
else if (ctrlDown && c==86) return false // v
else if (ctrlDown && c==88) return false // x
// Otherwise allow
return true
我使用了event.ctrlKey
,而不是像在 Mac OS X 上的大多数浏览器上那样检查密钥代码 Ctrl/Alt “向下”和“向上”事件永远不会触发,所以唯一的检测方法是在例如使用event.ctrlKey
按住 Ctrl 键后的 c 事件。我还用metaKey
替换了ctrlKey
来代替mac。
此方法的局限性:
Opera 不允许禁用右键单击事件 据我所知,无法阻止浏览器窗口之间的拖放。edit
->copy
菜单项在例如Firefox 仍然可以允许复制/粘贴。
也不能保证对于具有不同键盘布局/语言环境的人来说,复制/粘贴/剪切是相同的键代码(尽管布局通常只遵循与英语相同的标准),但“禁用所有控制键”意味着全选等也将被禁用,所以我认为这是需要做出的妥协。
【讨论】:
【参考方案6】:我已经遇到了你的问题,我通过以下代码解决了它.. 只接受数字
$('#<%= mobileTextBox.ClientID %>').keydown(function(e)
///// e.which Values
// 8 : BackSpace , 46 : Delete , 37 : Left , 39 : Rigth , 144: Num Lock
if (e.which != 8 && e.which != 46 && e.which != 37 && e.which != 39 && e.which != 144
&& (e.which < 96 || e.which > 105 ))
return false;
);
你可以检测到 Ctrl id e.which == 17
【讨论】:
【参考方案7】:还有另一种方法: onpaste
、oncopy
和 oncut
事件可以在 IE、Firefox、Chrome、Safari 中注册和取消(有一些小问题),唯一不允许取消这些事件的主要浏览器是 Opera。
正如您在我的其他答案中看到的那样,拦截 Ctrl+v 和 Ctrl+c 有很多副作用,它仍然不会阻止用户使用 Firefox Edit
菜单等进行粘贴。
function disable_cutcopypaste(e)
var fn = function(evt)
// IE-specific lines
evt = evt||window.event
evt.returnValue = false
// Other browser support
if (evt.preventDefault)
evt.preventDefault()
return false
e.onbeforepaste = e.onbeforecopy = e.onbeforecut = fn
e.onpaste = e.oncopy = e.oncut = fn
Safari 使用此方法仍有一些小问题(当阻止默认设置时,它会清除剪贴板而不是剪切/复制),但该错误似乎已在 Chrome 中得到修复。
另请参阅:http://www.quirksmode.org/dom/events/cutcopypaste.html 和相关的测试页 http://www.quirksmode.org/dom/events/tests/cutcopypaste.html 了解更多信息。
【讨论】:
【参考方案8】:使用 jquery,您可以通过绑定函数轻松检测复制、粘贴等:
$("#textA").bind('copy', function()
$('span').text('copy behaviour detected!')
);
$("#textA").bind('paste', function()
$('span').text('paste behaviour detected!')
);
$("#textA").bind('cut', function()
$('span').text('cut behaviour detected!')
);
更多信息在这里:http://www.mkyong.com/jquery/how-to-detect-copy-paste-and-cut-behavior-with-jquery/
【讨论】:
不幸的是,如果选择了文本,此方法只会在 Firefox 上触发【参考方案9】:现场演示: http://jsfiddle.net/abdennour/ba54W/
$(document).ready(function()
$("#textA").bind(
copy : function()
$('span').text('copy behaviour detected!');
,
paste : function()
$('span').text('paste behaviour detected!');
,
cut : function()
$('span').text('cut behaviour detected!');
);
);
【讨论】:
【参考方案10】:使用 onkeydown 代替 onkeypress。
<input type="text" onkeydown="if(event.ctrlKey && event.keyCode==86)return false;" name="txt">
【讨论】:
【参考方案11】:不要忘记,虽然您可能能够检测并阻止 Ctrl+C/V,但您仍然可以更改某个字段的值。 最好的例子是 Chrome 的 Inspect Element 功能,它允许您更改字段的值属性。
【讨论】:
【参考方案12】:在jQuery中防止用户使用上下文菜单、复制和剪切的简短解决方案:
jQuery(document).bind("cut copy contextmenu",function(e)
e.preventDefault();
);
在 CSS 中禁用文本选择也可能会派上用场:
.noselect
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
【讨论】:
【参考方案13】:您可以将此代码用于右键单击、CTRL+C、CTRL+V、 CTRL+X 检测并阻止他们的动作
$(document).bind('copy', function(e)
alert('Copy is not allowed !!!');
e.preventDefault();
);
$(document).bind('paste', function()
alert('Paste is not allowed !!!');
e.preventDefault();
);
$(document).bind('cut', function()
alert('Cut is not allowed !!!');
e.preventDefault();
);
$(document).bind('contextmenu', function(e)
alert('Right Click is not allowed !!!');
e.preventDefault();
);
【讨论】:
【参考方案14】:另一种方法(不需要插件)它只使用传入的event object 的ctrlKey
属性。它指示在事件发生时是否按下了 Ctrl,如下所示:
$(document).keypress("c",function(e)
if(e.ctrlKey)
alert("Ctrl+C was pressed!!");
);
另见jquery: keypress, ctrl+c (or some combo like that)。
【讨论】:
【参考方案15】:如果使用ctrlKey
属性,则不需要维护状态。
$(document).keydown(function(event)
// Ctrl+C or Cmd+C pressed?
if ((event.ctrlKey || event.metaKey) && event.keyCode == 67)
// Do stuff.
// Ctrl+V or Cmd+V pressed?
if ((event.ctrlKey || event.metaKey) && event.keyCode == 86)
// Do stuff.
// Ctrl+X or Cmd+X pressed?
if ((event.ctrlKey || event.metaKey) && event.keyCode == 88)
// Do stuff.
【讨论】:
这是正确答案!如果按下了某个键,则该事件具有属性 ctrlKey = true。我们不需要任何额外的事件。 这正是我要找的【参考方案16】:重要提示
我使用e.keyCode
有一段时间了,我发现当我按下 ctrl + . 时,此属性返回一个错误的数字,190,而 ascii 码.
是 46!
所以你应该使用 e.key.toUpperCase().charCodeAt(0)
而不是e.keyCode
。
$(document).keydown(function(event)
let keyCode = e.key.toUpperCase().charCodeAt(0);
...
【讨论】:
那 46 个!不是阶乘。 :)【参考方案17】:允许覆盖复制事件的钩子可用于对粘贴事件执行相同操作。输入元素不能显示:无;或可见性:隐藏;很遗憾
export const useOverrideCopy = () =>
const [copyListenerEl, setCopyListenerEl] = React.useState(
null as HTMLInputElement | null
)
const [, setCopyHandler] = React.useState<(e: ClipboardEvent) => void | null>(
() => () =>
)
// appends a input element to the DOM, that will be focused.
// when using copy/paste etc, it will target focused elements
React.useEffect(() =>
const el = document.createElement("input")
// cannot focus a element that is not "visible" aka cannot use display: none or visibility: hidden
el.style.width = "0"
el.style.height = "0"
el.style.opacity = "0"
el.style.position = "fixed"
el.style.top = "-20px"
document.body.appendChild(el)
setCopyListenerEl(el)
return () =>
document.body.removeChild(el)
, [])
// adds a event listener for copying, and removes the old one
const overrideCopy = (newOverrideAction: () => any) =>
setCopyHandler((prevCopyHandler: (e: ClipboardEvent) => void) =>
const copyHandler = (e: ClipboardEvent) =>
e.preventDefault()
newOverrideAction()
copyListenerEl?.removeEventListener("copy", prevCopyHandler)
copyListenerEl?.addEventListener("copy", copyHandler)
copyListenerEl?.focus() // when focused, all copy events will trigger listener above
return copyHandler
)
return overrideCopy
这样使用:
const customCopyEvent = () =>
console.log("doing something")
const overrideCopy = useOverrideCopy()
overrideCopy(customCopyEvent)
每次您调用 overrideCopy 时,它都会重新聚焦并在复制时调用您的自定义事件。
【讨论】:
以上是关于如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?的主要内容,如果未能解决你的问题,请参考以下文章