当用户输入文本时验证HTML文本输入

30
什么是验证HTML文本输入的最佳方法,当它被键入时?我所知道的所有方法都有一些缺点:
  1. 使用$.keypress 只能访问输入框的旧值,而无法访问新值。此外,某些事件(如使用鼠标剪切/粘贴)将不会被检测到。
  2. 使用$.change 仅在输入框失去焦点时起作用。
  3. 这个问题 提出了一种解决方案,其中使用轮询来监视属性更改。原则上,在回调中验证新值,如果无效,则恢复为旧值。然而,除了需要轮询外,我不确定它是否没有竞争条件。
  4. 这篇文章 建议当浏览器特定功能存在时使用它们,如果没有可用的功能,则退回到轮询。看起来是迄今为止最好的方法。
  5. [更新] 如答案中所指出的,$.keyup 可以访问更新后的值。但是,它不仅不能用于鼠标剪切/粘贴,而且如果按住键盘不放,只释放了很多输入后就会失败。或者,如果结合使用 keydown keyup 来保存/恢复旧值,则在用户输入过快时会出现问题。
以上解决方案都不是无误的或完全安全跨浏览器,是否有更好的解决方案,无论是已经准备好使用还是正在制作中?这似乎是一个常见的问题,我最近尝试回答类似的问题,例如similarquestions ,但没有成功,我也对答案感兴趣。

如果实施此验证会出现新问题,欢迎提出反对意见;不过在其他语言中这似乎很常见,所以我认为想要这样做并不是件坏事。

(如果有)

注意:请保留HTML标记。

9个回答

49
你可以使用input(适用于Firefox)和propertychange(适用于其他所有浏览器)事件来捕获所有输入形式,包括键盘和右键剪切粘贴。

http://jsfiddle.net/dFBzW/

$('input').bind('input propertychange', function() {
    $('#output').html($(this).val());
});

1
到目前为止,这是我找到的最好的答案,并且我基于它编写了此示例(http://jsfiddle.net/mgibsonbr/NJNkc/)。在FF、Chrome和Safari上运行得非常好,在IE6上有时会出现非致命性堆栈溢出,但谁在乎IE6呢?但在Opera(以及Konqueror,但我也不太关心它)上失败了。因此,我将问题保持开放状态一段时间... - mgibsonbr
@mgibsonbr - 对我来说,Opera 11.61似乎可以正常工作。这个例子具体是做什么的? - mrtsherman
它试图只允许用户输入有效的数字,但由于这是不可能的(当用户仍在输入时,值将无效),因此它也接受有效的前缀(如果整个文本无效,则显示红色边框)。因此,如果用户尝试添加或删除会使输入无效的字符,则会恢复到上次保存的值。否则,它会保存新值。(虽然不一定是我在真实系统中会做的事情-请参见nnnnnn的答案)该示例在Opera 10.63上失败,但由于它在更新版本上运行良好,所以没问题! - mgibsonbr
第二次我读到(FF),FF代表什么? - DrNio

6
如果“验证”是指“防止输入无效字符”,我认为这是一个不好的习惯。对于用户来说,这很令人困惑,他们可能没有注意到,也可能在输入时没有看着字段(例如,如果他们正在从纸上输入账户或电话号码)。实际保存/使用的值可能与他们认为输入的值略有不同。
如果“验证”是指“测试当前值并引起用户注意任何问题”,例如通过在字段旁边显示错误或更改背景颜色,则可以使用几个事件的组合,包括keyup、change、blur、paste、click,没有问题:
$("field selector").on("keyup change blur paste cut click", function() { ... });

这将在用户键入时捕获大多数常规情况,对于剪贴板或拖放情况,您至少知道在用户离开字段时仍将验证该字段。 (显然,除非所有错误都已更正,否则不允许提交。)如果您处理keyup和keydown,这将涵盖用户按住某个键的情况,因为大多数浏览器将发送重复的keydown事件。

那些是很好的观点,我会三思而后行,从现在开始不再这样做。 - mgibsonbr

5
在jQuery世界中,利用插件来完成这些验证任务是很常见的。插件通常比从头开始编写的代码更易于使用,它们的流行程度通常反映在比错误更少。
输入验证通常分为以下几类,包括: 1) 正确的输入格式/输入掩码。例如,仅限A-Z或10位数字。 2) 领域内内容的存在。例如,机场代码或邮政编码。
对于(1),您可以使用这些相对较受欢迎的插件: Digital Bush's Masked Input Plugin for Jquery。它有许多自定义选项,包括空格等: 来自Digital Bush网站:
$("#phone").mask("(999) 999-9999");

autoNumeric from decorplanit.com。他们对数字、货币、四舍五入等方面提供了良好的支持。

摘自autoNumeric网站:

$('#amountPaid').autoNumeric({aSep: '.', aDec: ','}); // eg, 9.000,00

对于第(2)点,您可以使用例如jQuery UI的自动完成,结合服务器资源数据,以JSON格式呈现。这些可能需要定制代码来锁定输入,但仍可以利用插件进行基本功能,并专注于您正在创建的特定业务逻辑。
上面的一些文本改编自其他帖子中的两个答案herehere

1
有用的参考资料加一。当涉及到剪切粘贴时,其中一些仍然表现奇怪,但对于大多数常见情况,它们确实比其他替代方案更好。 - mgibsonbr

4

您尝试过使用oninput吗?

HTML示例:

<input name="username" id="user_name" oninput="readvalue();">

JavaScript:

function readvalue() {
    var name = $('#user_name').val();
}

3

这是一种不需要 JQuery 的另一种防止特定字符的解决方案...

<input type="text" onkeypress="checkInput(event)" />

...

function checkInput(e)
{
    //only alpha-numeric characters
    var ok = /[A-Za-z0-9]/.test(String.fromCharCode(e.charCode));
    if (!ok)
        e.preventDefault();
}

我不知道这是否需要新版本的东西或只能在某些浏览器上工作,请发表评论。


等等,实际上不是这样的:Firefox 也会阻止退格键、箭头键等。看起来可以通过 || e.charCode === 0 来解决。 - phil294

3

以下是代码:

function validatephone(xxxxx) 
{
  var maintainplus = '';
  var numval = xxxxx.value
  if ( numval.charAt(0)=='+' )
  {
    var maintainplus = '';
  }
  curphonevar = numval.replace(/[\\A-Za-z!"£$%^&\-\)\(*+_={};:'@#~,.Š\/<>\" "\?|`¬\]\[]/g,'');
  xxxxx.value = maintainplus + curphonevar;
  var maintainplus = '';
  xxxxx.focus;
}
<input type="text" align="MIDDLE" size="30" maxlength="20" onkeyup="validatephone(this);" name="contact"/>


OP的问题是关于如何触发验证,而不是如何实现验证函数本身。他在问题中已经提到了keyup。 - rudolfbyker

0

这也可能会有帮助

$(".cssclass").live("input propertychange", function () {
    //Validate goes here
});

-1

function validatephone(xxxxx) 
{
  var maintainplus = '';
  var numval = xxxxx.value
  if ( numval.charAt(0)=='+' )
  {
    var maintainplus = '';
  }
  curphonevar = numval.replace(/[\\A-Za-z!"£$%^&\-\)\(*+_={};:'@#~,.Š\/<>\" "\?|`¬\]\[]/g,'');
  xxxxx.value = maintainplus + curphonevar;
  var maintainplus = '';
  xxxxx.focus;
}
<input type="text" align="MIDDLE" size="30" maxlength="20" onkeyup="validatephone(this);" name="contact"/>


1
请解释你的答案。 - Gene Sy

-3
let that=this;

$(this.element).find("input").keypress(function(e) {
               let character = String.fromCharCode(e.keyCode);

               let newValue =  this.value.substring(0,this.selectionStart) + character + this.value.substring(this.selectionEnd, String(this.value).length);


               if (!that.isFormatValid(newValue, that.getdecimalPoints())) {
                     e.preventDefault();
                     e.stopPropagation();
                     return false;
              }

              return true;
        });


        $(this.element).find("input").bind({
              paste: function() {
                     let _this = this;

                     setTimeout( function() {
                           let decimals = that.getdecimalPoints();
                           if (!that.isFormatValid($(_this).val(), decimals)) {                        
                                         $(_this).val('');                        
                           }
                     }, 0);                                                                                                  
                  }
           });

回答与代码应包括有关如何回答问题的简要说明。 - Rubén

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