如何使用JavaScript检测Ctrl+V、Ctrl+C?

211

如何使用JavaScript检测Ctrl+VCtrl+C

我需要限制在文本区域内粘贴,请用户不要复制和粘贴内容,用户只能在文本区域中输入文本。

我该如何实现这个功能?


4
这是什么目的?我只能想到两种合理的情况,一是密码输入框(无论如何都无法复制),另一种是打字速度测试。我相信你可以检测到可疑的快速输入。 - Paul Butcher
11
有些情况下需要这样做。一个非常简单的例子是:学习外语的网站。如果您手写单词而不是使用复制粘贴,则学习效果会得到增强。 - back2dos
3
另一个合理的情况可能是需要双重输入以检测错误(例如,将您的电子邮件地址输入两次,以便我们知道它没有拼写错误)。不过,这样的用户可能会保留一份随机生成的电子邮件地址列表(例如,sneakemail),并且可能希望粘贴以确保准确性。 - Paul Butcher
52
@Paul Butcher- 这根本不是合法的情况,我讨厌那些这样做的网站,我总是复制/粘贴我的(长)电子邮件地址从一个输入到另一个输入框。破坏复制/粘贴功能是一个主要的可用性问题。它真的会让用户感到困惑,因为这对他们的思维模型非常基础,他们期望它“只是能够工作”。这就像你试图推开一扇门,但它却向你反方向打开! - EMP
7
每当页面禁止复制粘贴时,我通常会将文本粘贴到其他地方(我通常使用URL栏),然后使用Ctrl + A选择刚刚粘贴到URL栏中的文本,最后将其拖放到浏览器中无法粘贴的区域。我想,目前这种方法是不可避免的。 - Janakiram
显示剩余10条评论
21个回答

207

我只是出于兴趣这样做了,我同意这不是正确的做法,但我认为应该由操作者自行决定...此外,代码可以很容易地扩展以添加功能,而不是减少功能(例如更高级的剪贴板或通过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演示

编辑:根据Tim Down的建议(参见评论),删除了3行冗余代码(涉及e.which)

编辑:增加对Mac的支持(CMD 键代替 Ctrl


4
为什么要在document上使用keydownkeyup处理程序?您可以在$(".no-copy-paste").keydown处理程序中测试Ctrl键。另外,没有必要使用e.keyCode || e.which代码:e.keyCode适用于所有支持e.which的浏览器,因此e.which永远不会被使用。也许您正在考虑如何从keypress事件获取字符代码?最后,这将对从上下文或编辑菜单粘贴的内容无效,但我想OP并没有直接问到这个。 - Tim Down
1
我推荐Jan Wolter的JavaScript键盘处理文章:http://unixpapa.com/js/key.html 我已经多次用它作为参考,从未发现错误。 - Tim Down
4
哥们!谢谢!这正是我所需要的,让用户可以在我正在编写的Web应用程序中选择一个“元素”(日历条目),使用Ctrl+C进行“复制”,然后使用Ctrl+V进行“粘贴”,而不必实际与万能的剪贴板进行交互。Ctrl+C记住他们单击的内容,Ctrl+V复制它,所有人都赢了。 - Dan F
2
我并不是专家,但我认为最好测试 e.metaKeye.ctrlKey 是否为 true,而不是将数字值分配给键并测试它们。 - sluther
无法使用右键选择粘贴,您只能手动输入以获取翻译的文本内容。 - mkavici
显示剩余4条评论

54

使用 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/


2
不幸的是,如果未选择文本,此方法仅在Firefox上触发。 - Yassir Ennazk

47

虽然使用它作为反盗版措施可能很烦人,但我可以看到有一些情况下它可能是合法的,因此:

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下和上事件不会被触发,所以唯一检测的方法是在按住Ctrl键后在例如事件中使用event.ctrlKey。我还将ctrlKey替换为metaKey适用于Mac。

这种方法的限制:

  • Opera不允许禁用右键单击事件。
  • 据我所知,无法防止在浏览器窗口之间拖放。
  • 例如在Firefox中的edit->copy菜单项仍然可以允许复制/粘贴。
  • 对于拥有不同键盘布局/语言环境的人来说,没有保证复制/粘贴/剪切是相同的按键代码(尽管布局通常遵循与英语相同的标准),但总禁用所有控制键意味着选择全部等功能也将被禁用,因此我认为这是需要做出的妥协。

19

如果您使用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.
      } 
    }

1
这是正确的答案!如果与事件一起按下了键,则该事件具有ctrlKey = true属性。我们不需要任何额外的事件。 - JanBrus
这正是我正在寻找的。 - Venkatesh Muniyandi
在输入方面,.val() 是空的。 - Jack
1
但是keyCode已经被弃用了。 - Ricardo Machado

15

还有另一种方法:可以在IE、Firefox、Chrome和Safari(存在一些小问题)中注册并取消onpasteoncopyoncut事件。唯一不允许取消这些事件的主要浏览器是Opera。

正如您在我的另一个回答中所看到的,拦截Ctrl+VCtrl+C会带来许多副作用,而且仍然无法防止用户使用Firefox 编辑菜单等进行粘贴操作。

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中仍然存在一些小问题(阻止默认操作时它会清空剪贴板而不是剪切/复制),但这个 bug 看起来现在已经在 Chrome 中修复了。

另请参阅:有关更多信息,请访问http://www.quirksmode.org/dom/events/cutcopypaste.html以及相关的测试页面http://www.quirksmode.org/dom/events/tests/cutcopypaste.html


1
我认为这个答案是最好的,主要是因为用户可以更改他们的复制/粘贴键绑定。虽然这种情况不太可能发生,但最好涵盖所有可能的情况。 - luek baja

9

使用jQuery防止用户使用上下文菜单、复制和剪切的简短解决方案:

jQuery(document).bind("cut copy contextmenu",function(e){
    e.preventDefault();
});

在IT技术方面,禁用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;
}

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!');
        }
    });

}); 

6

3

您可以使用这段代码来检测并防止右键点击、CTRL+CCTRL+VCTRL+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();
    });

3
element.addEventListener('keydown', function (e) {
    if (e.key == 'c' && e.ctrlKey) {
        e.preventDefault(); // prevent from copying
    }
    if (e.key == 'v' && e.ctrlKey) {
        e.preventDefault(); // prevent from pasting
    }
}

你的回答可以通过添加更多关于代码的信息以及它如何帮助提问者来改进。 - Tyler2P
那是一个愚蠢的评论。请阅读整个线程并查看。 - pmad
'Stack Overflow'上不存在"线程",每个回答都必须提供一个简短的代码片段,说明代码的作用以及如何解决问题。此外,如果有其他答案,最好提供一些信息,解释为什么您的解决方案比其他解决方案更好。 - Tyler2P
阅读问题并比较答案 - 就像任何人在这里寻找答案一样。然后再发言。否则,您的评论是粗鲁和傲慢的。 - pmad
StackOverflow团队正在写有关失去访问者的文章。不知道为什么,因为他们拥有这样珍贵的资源。 - pmad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接