限制HTML输入,只允许粘贴。

6

在表单中是否可以使用HTML输入框只接受粘贴的内容?

在我们的注册流程中,终端用户需要在基本的HTML输入表单中输入一个20个字符的标识令牌。理想情况下,用户只需将标识令牌复制/粘贴到相应的字段中即可。我们不希望允许用户手动输入此内容,因为他们很可能会输错字母,并且我们没有任何可靠的手段来验证输入。

该令牌来自桌面软件,需要粘贴到已经打开的网页中(即他们从中下载软件的网页)。因此,可点击的链接并不是一种可行的选择。

有没有什么方法可以实现这一点,例如通过Javascript?谢谢。


我的解决方案,修改自SimplePi的答案:

<html>
<body>
<script type="text/javascript">
 function validate(evt) {
   var theEvent = evt || window.event;
   var key = theEvent.charCode || theEvent.which;

   if(key >= 32 && (theEvent.ctrlKey === undefined || !theEvent.ctrlKey)) {
    if(theEvent.preventDefault) theEvent.preventDefault();
    else theEvent.returnValue = false;
  }
 }
 </script>
  <span>Textbox name</span> <br />
 <input type="text" onkeypress='validate(event)' value=""/>
</body>
</html>

这段代码在某些浏览器中可以正常使用,但并非所有浏览器都支持。我发现Mac上的Firefox是唯一有问题的浏览器——Firefox通常将ctrl-v报告为与v完全相同,但在Windows上,theEvent.ctrlKey成员可以区分这两者。在Mac上执行相同操作显然需要使用按键按下/释放事件来检查是否按下cmd键。虽然这是可行的,但本代码未包含此功能,以便其他人希望使用时进行自行添加。


3
我很确定这是可能的,但这会导致非常不好的用户体验。大多数用户都会复制/粘贴令牌ID,因此为极少数用户付出额外的努力并不值得。 - stackErr
2
您需要允许键盘快捷键粘贴(这可能因操作系统而异)和右键上下文菜单粘贴。此外,有什么方法可以防止他们粘贴与您的标记完全不同的内容呢? - ajp15243
1
他们从哪里获取令牌? - Matt Burland
2
@DylanStreb 我相信这是可能的,但需要大量的投资和测试来确保它不包含任何隐藏的漏洞。为什么不让他们输入两到三次密钥以确保他们没有输入错误?如果他们像大多数人一样复制/粘贴,这将很快且不容易出错。如果他们打字不像大多数人,那么他们两到三次输错的机会比一次低得多。 - ajp15243
@DylanStreb 可以理解。如果你有时间,可以快速创建一个输入更改/按键等的原型,并查看不同情况下出现的按键和值(例如:键入、Ctrl+V/Cmd+V、右键粘贴)。这可以让你更好地了解什么是容易/可能的。但老实说,这个选项需要比多个匹配输入之类的东西花费更多的时间,且回报递减,可能会导致用户体验较差。 - ajp15243
显示剩余4条评论
3个回答

6
这里是一个更加强大的解决方案,我对上面的代码进行了扩展。可能有点过度但它可以在所有浏览器上运行。以下代码将会:
  1. 使文本框像只读一样,但会尊重tab索引并设置焦点
  2. 支持所有剪贴板功能win和mac与鼠标或键盘
  3. 允许撤消、重做和全选

$( "#your_textbox" ).keypress(function(evt) {
 // Note this could be a bit of overkill but I found some
 // problems in Firefox and decided to go the distance
 // including old windows keyboard short cut keys.
 // Enumerate all supported clipboard, undo and redo keys
 var clipboardKeys = {
  winInsert : 45,
  winDelete : 46,
  SelectAll : 97,
  macCopy : 99,
  macPaste : 118,
  macCut : 120,
  redo : 121, 
  undo : 122
 }
 // Simulate readonly but allow all clipboard, undo and redo action keys
 var charCode = evt.which;
 //alert(charCode);
 // Accept ctrl+v, ctrl+c, ctrl+z, ctrl+insert, shift+insert, shift+del and ctrl+a
 if (
  evt.ctrlKey && charCode == clipboardKeys.redo ||  /* ctrl+y redo   */
  evt.ctrlKey && charCode == clipboardKeys.undo ||  /* ctrl+z undo   */
  evt.ctrlKey && charCode == clipboardKeys.macCut ||  /* ctrl+x mac cut  */
  evt.ctrlKey && charCode == clipboardKeys.macPaste ||  /* ctrl+v mac paste  */
  evt.ctrlKey && charCode == clipboardKeys.macCopy ||  /* ctrl+c mac copy  */ 
  evt.shiftKey && evt.keyCode == clipboardKeys.winInsert || /* shift+ins windows paste */ 
  evt.shiftKey && evt.keyCode == clipboardKeys.winDelete || /* shift+del windows cut */ 
  evt.ctrlKey && evt.keyCode == clipboardKeys.winInsert  || /* ctrl+ins windows copy */ 
  evt.ctrlKey && charCode == clipboardKeys.SelectAll  /* ctrl+a select all  */
  ){ return 0; }
 // Shun all remaining keys simulating readonly textbox
 var theEvent = evt || window.event;
 var key = theEvent.keyCode || theEvent.which;
 key = String.fromCharCode(key);
 var regex = /[]|\./;
 if(!regex.test(key)) {
  theEvent.returnValue = false;
  theEvent.preventDefault();
 }
});


我最喜欢你的解决方案。跨浏览器/系统支持非常好。 - Adam
同意,这是最好的答案。 - reven

5
<script type="text/javascript">
 function validate(evt) {
   var theEvent = evt || window.event;
   var key = theEvent.keyCode || theEvent.which;
   key = String.fromCharCode(key);
  var regex = /[]|\./;
   if(!regex.test(key)) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
  }
 }
 </script>
  <span>Textbox name</span>
 <input name="ReceiveNo" type="text" class="txtbox" onkeypress='validate(event)' value=""         required tabindex="" />

这似乎只是限制文本框仅接受数字,并禁止粘贴任何文本。 - DylanStreb
@DylanStreb 我修复了数字问题。粘贴功能完全正常。在我的服务器上进行了检查。 - SimplePi
1
仅仅将key = String.fromCharCode(key);替换为key != 22,似乎正则表达式就能起作用了,因为在按ctrl-v时,键值被设置为22。右键菜单不受影响。这样做可能是解决方案,但我需要更彻底地测试一下。谢谢。 - DylanStreb
进行了更彻底的测试并进行了一些更改。我已经更新了我的原始帖子,其中大部分都是有效的修改。谢谢。 - DylanStreb

2

如果您通过电子邮件发送验证码,则为什么还要让他们将其粘贴在网站上?只需通过电子邮件将他们路由到 http://example.com/verify/{{TOKEN}} ,然后从那里开始进行剩余的注册过程。


1
抱歉,我更新了更多细节:令牌是从桌面应用程序中获取的。它是物理设备的序列号,他们需要将其应用于其用户帐户。 - DylanStreb

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