【问题标题】:How to detect Ctrl+V, Ctrl+C using JavaScript?如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?
【发布时间】:2011-02-23 15:26:02
【问题描述】:

如何使用Javascript检测ctrl+vctrl+c

我需要限制在我的 textarea 中粘贴,最终用户不应复制和粘贴内容,用户只能在 textarea 中键入文本。

如何做到这一点?

【问题讨论】:

  • 这样做的目的是什么?我能想到的唯一两个合法场景是密码字段(无论如何您都无法复制)和打字速度测试。我相信您可以检测到可疑的快速输入。
  • @Paul Butcher, @Propeng:有些场景,你需要这个。非常简单的例子:一个学习外语的网站。如果您手动输入单词而不是使用复制和粘贴,则可以增强学习效果。
  • 另一种合法的情况可能是需要重复输入以检测错误(例如,输入您的电子邮件两次,以便我们知道它没有错字)。尽管如此,这样的用户可能会保留一个随机生成的电子邮件地址列表(例如偷偷摸摸的电子邮件),并且可能希望将其粘贴以确保准确性。
  • @Paul Butcher - 这根本不是合法的情况,我讨厌这样做的网站,我总是复制/粘贴我的(长) 从一个输入到另一个的电子邮件地址。破坏复制/粘贴是一个主要的可用性问题。它确实让用户感到厌烦,因为它对他们的心智模型如此重要,以至于他们希望它“正常工作”。就好像你试图拉一扇门,它从你身边转开而不是朝你这边转!
  • 当这样的复制粘贴不允许在页面中时,我所做的是将文本粘贴到其他位置(我使用 URL 栏),然后 Ctrl + A(选择刚刚粘贴在url ),在浏览器中拖放禁用粘贴的字段。我想,这在今天是无法预防的。

标签: javascript jquery html


【解决方案1】:

您可以监听 keypress 事件,如果它与特定的键码匹配,则停止默认事件(输入文本)

【讨论】:

    【解决方案2】:

    我写了一个 jQuery 插件,它可以捕捉击键。它可用于在没有操作系统的情况下启用 html 表单中的多语言脚本输入(字体除外)。大概有300行代码,也许你喜欢看一下:

    一般来说,小心这种改动。我为客户编写了插件,因为没有其他解决方案。

    【讨论】:

      【解决方案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

      【讨论】:

      • 为什么keydownkeyup 处理程序在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.metaKeye.ctrlKeytrue 而不是为键分配数字值并测试它们.
      【解决方案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】:

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

          正如您在我的其他答案中看到的那样,拦截 Ctrl+vCtrl+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+CCTRL+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 objectctrlKey 属性。它指示在事件发生时是否按下了 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 时,它都会重新聚焦并在复制时调用您的自定义事件。

                        【讨论】:

                          猜你喜欢
                          • 2017-07-31
                          • 1970-01-01
                          • 2014-11-10
                          • 1970-01-01
                          • 2018-09-10
                          • 1970-01-01
                          • 2011-02-26
                          • 1970-01-01
                          相关资源
                          最近更新 更多