禁止将文本粘贴到HTML表单中

108

有没有一种使用JavaScript禁用在HTML表单中的文本字段上粘贴文本的方法?

例如,我有一个简单的注册表单,用户需要输入两次电子邮件地址。第二个电子邮件地址是为了验证第一个电子邮件地址是否没有输错。但是,如果用户复制/粘贴其电子邮件地址,则会打破这个目的。我已经遇到一些用户因为他们输入了错误的电子邮件地址并将其复制/粘贴而导致问题。

也许我的问题不够清晰,但我并不想防止人们在浏览器上复制(或拖动选择)文本。我只想阻止他们将输入粘贴到文本字段中,以最小化用户错误。

也许,与其使用这种“hack”,你可以提出另一个解决我所要解决的核心问题的解决方案?我进行了不到半打的用户测试,这已经发生了两次。我的受众群体在计算机熟练度方面并不高。


32
客户坚持要求更改时,我们无能为力。祝您喝得愉快 :) - justinl
16
如果在电子邮件未被粘贴到原始字段时,他仅禁用验证字段中的粘贴功能,那么这可能是完全正常的。换句话说,用户必须将电子邮件粘贴到两个字段中或都不粘贴。 - GJ.
33
如果客户要求这样做,请告诉他们这是多么糟糕的主意。这是在客户最有可能在注册时离开的时候惹怒客户的好方法。您不希望客户关系以顾客被疏远开始。随着更多人使用密码管理器,这种做法越来越常见,并且越来越令人反感。另请参阅:http://ux.stackexchange.com/q/21062/9529 和ob. xkcd:http://xkcd.com/970/ - Mark Booth
1
13年过去了,网站仍在这样做。我从我的密码管理器中复制粘贴各种东西,不仅仅是密码。向客户展示如何通过浏览器扩展或进入开发者控制台来击败这一点,然后问他们为什么要让客户的生活变得更加困难,同时又没有添加任何安全措施来阻止决心坚定的高级用户。 - durette
1
@justinl 你可以选择不这样做。只有怪物才会禁用复制/粘贴功能。 - Philip Rego
显示剩余2条评论
25个回答

171

不要这样做。不要干扰用户的浏览器。通过复制+粘贴到电子邮件确认字段中,用户将对其键入的内容负责。如果他们愚蠢到复制+粘贴错误的地址(我也曾遇到过这种情况),那就是他们自己的错。

如果您想确保电子邮件确认成功,请让用户在您的网站等待时检查他们的电子邮件(“请在新窗口中打开您的网络邮件程序”)。使用大号字母显示电子邮件地址(“确认电子邮件已发送至...有错误吗?单击此处进行更正)。

更好的方法是,如果可能的话,让用户拥有某种有限访问权限而无需确认。这样,他们可以立即登录,并提高您与访客保持联系的机会,即使确认邮件由于其他原因(例如垃圾邮件过滤器)被阻止。


8
针对用户自己输入数据的场景,我同意您的答案。然而,当用户代表他人输入电子邮件地址时(例如CRM系统或类似系统),实施您的解决方案是不可行的。在这些情况下,用户不会输入自己的电子邮件地址,因此可能会拼写错误。如果允许将内容粘贴到电子邮件确认框中,则会得到大量不正确的数据,因此防止粘贴没有任何问题。作为开发人员,您必须采取措施防止“足够愚蠢”的用户以保护企业数据。 - theyetiman
27
常见情况是,开发人员在看到这个问题时很少或没有对他们正在工作的项目的需求控制。这并不是对这里提出的问题的回答,所以扣1分。 - Nick
9
说“不要这样做”并不能回答问题。我目前有一个要求,需要禁用粘贴功能。 - Darian Everett
25
如果你收到这样的需求,作为专业人士,你需要反驳它。你不仅仅是一个能写代码的工具。 - Dan
9
拒绝回答别人问题的原因可能是合理的,但因为你觉得对方提出的原因不合理就拒绝回答会让人感到烦躁。比如说,如果你正在实施一项需要复杂答案的测验,禁用复制粘贴功能并强制学生手打答案有助于让他们将答案记在脑中,而仅仅复制粘贴可能毫无价值。这是个有理由这么做的原因。可以提醒别人,在大多数情况下他们想要做的事情不是好主意,但还是要给一个回答,否则最好不要回复。 - Halfhoot
显示剩余10条评论

77

将“disablecopypaste”类添加到您想要禁用复制粘贴功能的输入框中,并添加以下jQuery脚本。

  $(document).ready(function () {
    $('input.disablecopypaste').bind('copy paste', function (e) {
       e.preventDefault();
    });
  });

59

最近我不情愿地不得不禁用表单元素中的粘贴功能。为此,我编写了一个跨浏览器*实现Internet Explorer(和其他浏览器)onpaste事件处理程序的解决方案。我的解决方案必须独立于任何第三方JavaScript库。

这是我的解决方案。它并不能完全禁用粘贴功能(例如用户仍然可以一次粘贴一个字符),但它满足了我的需求,并避免了处理keyCodes等问题。

// Register onpaste on inputs and textareas in browsers that don't
// natively support it.
(function () {
    var onload = window.onload;

    window.onload = function () {
        if (typeof onload == "function") {
            onload.apply(this, arguments);
        }

        var fields = [];
        var inputs = document.getElementsByTagName("input");
        var textareas = document.getElementsByTagName("textarea");

        for (var i = 0; i < inputs.length; i++) {
            fields.push(inputs[i]);
        }

        for (var i = 0; i < textareas.length; i++) {
            fields.push(textareas[i]);
        }

        for (var i = 0; i < fields.length; i++) {
            var field = fields[i];

            if (typeof field.onpaste != "function" && !!field.getAttribute("onpaste")) {
                field.onpaste = eval("(function () { " + field.getAttribute("onpaste") + " })");
            }

            if (typeof field.onpaste == "function") {
                var oninput = field.oninput;

                field.oninput = function () {
                    if (typeof oninput == "function") {
                        oninput.apply(this, arguments);
                    }

                    if (typeof this.previousValue == "undefined") {
                        this.previousValue = this.value;
                    }

                    var pasted = (Math.abs(this.previousValue.length - this.value.length) > 1 && this.value != "");

                    if (pasted && !this.onpaste.apply(this, arguments)) {
                        this.value = this.previousValue;
                    }

                    this.previousValue = this.value;
                };

                if (field.addEventListener) {
                    field.addEventListener("input", field.oninput, false);
                } else if (field.attachEvent) {
                    field.attachEvent("oninput", field.oninput);
                }
            }
        }
    }
})();

为了利用此功能禁用粘贴:
<input type="text" onpaste="return false;" />

我知道oninput不是W3C DOM规范的一部分,但我已经测试了一下这段代码的所有浏览器- Chrome 2、Safari 4、Firefox 3、Opera 10、IE6、IE7都支持oninput或onpaste。在所有这些浏览器中,只有Opera不支持onpaste,但它支持oninput。

注意:这在使用屏幕键盘的控制台或其他系统上不起作用(假设当选中每个键时屏幕键盘不会将按键发送给浏览器)。如果您的页面/应用程序可能被使用具有屏幕键盘和Opera(例如:Nintendo Wii,某些手机)的人使用,请勿使用此脚本,除非您已经测试过以确保屏幕键盘在每次键选择后将按键发送到浏览器。


71
为了防止 Firefox 遵循这个愚蠢的规则,前往 about:config 并将 dom.event.clipboardevents.enabled 改为 false。 - lolesque
2
即使我没有包含你编写的js,我仍然可以通过包含onpaste="return false"来防止用户粘贴任何内容,如果我采用这种方法会有什么问题吗? - viveksinghggits
@viveksinghggits 这段代码实现了在不支持 onpaste 的浏览器中使用它。你说“我能够阻止用户粘贴任何内容”,但是你在哪些浏览器中测试过呢? - AnnanFay
关于实现方面,我看到两个明显的改进:1)仅在不支持onpaste的浏览器中运行代码,2)当DOM被修改时重新执行 - 目前它不会应用于动态添加的输入。 - AnnanFay
@Rick,你认为用户可以在文本区域中粘贴任何内容吗?因为他们会期望在显示粘贴数据的其他屏幕上看到完全相同的内容,并且当该数据插入电子邮件时,他们也会期望它看起来完全相同。对我来说,我不想要由此带来的电话和支持电子邮件。在特定字段禁用粘贴是一个可行的选择和问题,我个人认为。我们大多数人遇到的问题是使用“富文本编辑器”时 - 这些东西似乎会覆盖任何防止粘贴的javascript或jquery命令。 - McAuley
1
@McAuley 那又怎样?禁止粘贴尤其是对于像文本区域这样可能很长的东西来说,更加糟糕。如果我需要粘贴而无法粘贴,我可能根本不会填写那个表格。如果我非常需要,内容也会简洁不完整,可能还会很粗鲁。你不想因为格式未被保留而接到支持电话吗?我怀疑这种情况并不经常发生,这表明你很懒。为了避免一些工作而损害一大批用户。好极了。 - Rick

35

刚收到这个,我们可以使用 onpaste:"return false" 来实现,感谢: http://sumtips.com/2011/11/prevent-copy-cut-paste-text-field.html

我们还有其他可用选项,如下所列。

<input type="text" onselectstart="return false" onpaste="return false;" onCopy="return false" onCut="return false" onDrag="return false" onDrop="return false" autocomplete=off/><br>

19

你可以......但不要这么做。

你不应该修改用户浏览器的默认行为。这对你的Web应用来说实在是糟糕的易用性。而且,如果用户想要禁用这个 hack,他们可以在浏览器上禁用 Javascript。

只需将这些属性添加到文本框即可。

ondragstart=”return falseonselectstart=”return false

7
这个问题涉及禁用粘贴。这种技术只会使复制变得困难,而不会影响粘贴。 - bendman

9
疯狂的想法:要求用户在注册过程中发送电子邮件给你。当点击mailto链接无效时(例如,如果他们使用Webmail),这显然是不方便的,但我认为这是一种同时确保防止输错和确认电子邮件地址的方法。
操作如下:他们填写大部分表单,输入他们的姓名、密码等等。当他们点击提交按钮时,实际上是点击一个链接将邮件发送到您的服务器。您已经保存了其他信息,因此该消息只包括一个令牌,指示这是哪个帐户。

8
如何给刚刚输入的电子邮件地址发送确认邮件,其中包含您网站上确认URL的链接,这样您就知道他们已经收到了消息?任何没有点击确认收到电子邮件的人可能已经错误地输入了他们的电子邮件地址。虽然不是完美的解决方案,但这只是一些想法。

4
我目前有这个实现。问题在于用户认为他们没有收到电子邮件是因为我们出现了错误,因为他们检查了他们认为输入的电子邮件地址,但他们没有收到电子邮件。此外,当他们尝试重新注册时,他们使用的用户名现在不可用,因为它与那个不正确的电子邮件地址绑定在一起。 - justinl
然后,也许可以添加一些工作流程/代码,每天运行清理未经确认的用户名,例如2天。 - Colin
1
谢谢你的评论。我的想法是,如果你在一个网站上尝试创建账户,然后发现用户名已被使用,你会在两天后再回去试一次吗?我认为大多数人可能不会这样做。要么你当天就用一个不同的用户名创建了新账户,要么你根本没有再回去因为你没能弄清楚如何注册,而且觉得这个网站“太复杂”。 - justinl
8
继续Colin所说的,您可以假设当某人尝试使用相同的用户名和不同的电子邮件地址重新注册,并且他们没有回应确认消息时,可能可以让他们这样做。您可能会发现,有些人在电子邮件中正确输入了域名,但拼错了用户名,可以利用这一点进一步确定是否有人犯了错误? - Richard Lucas
1
我非常喜欢允许尚未确认其帐户信息的用户重新注册的想法。我认为这种设计解决方案比我最初提出的技术解决方案更好。听到其他人说更改此默认浏览器功能是个坏主意是我需要听到的,以找到更好的解决方案。 - justinl

7

你可以使用jQuery

HTML文件

<input id="email" name="email">

JQuery 代码

$('#email').bind('copy paste', function (e) {
        e.preventDefault();
    });

5

扩展@boycs的回答,我建议还使用"on"。

$('body').on('copy paste', 'input', function (e) { e.preventDefault(); });

如果您计划将脚本应用于动态添加的表单元素,则此方法非常有用。 - Matthew

5

使用VanillaJS的函数式方法

function pasteNotAllowFunc(xid){
 let myInput = document.getElementById(xid);
     myInput.onpaste = (e) => e.preventDefault();
}

function copyNotAllowFunc(xid){
 let myInput = document.getElementById(xid);
     myInput.oncopy = (e) => e.preventDefault();
}


copyNotAllowFunc('copyInput')

pasteNotAllowFunc('pasteInput')
Copy
<input id="copyInput" value="copy not allow" />
<hr/>
Paste
<input id="pasteInput" value="paste not allow"/>
<hr/>
Textarea
<textarea id="test" value="Paste here"></textarea>


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