jQuery验证和屏蔽输入之间的冲突

jQuery验证和屏蔽输入之间的冲突,jquery,validation,maskedinput,Jquery,Validation,Maskedinput,我有一个表单,对电话号码和美国邮政编码字段使用and 例如,对于美国邮政编码,屏蔽输入只允许输入数字,并强制使用格式“99999”或“99999-9999”(其中9可以是任何数字)。Validate规则需要相同的参数。但在某些情况下,Validate会在字段实际有效时将其标记为无效 代码细节 jQuery Validate在邮政编码字段上使用的正则表达式是^\d{5}$|^\d{5}\-\d{4}$ 我用屏蔽输入应用的屏蔽是.mask('99999?'9999') 复制步骤 当我执行以下操作时,

我有一个表单,对电话号码和美国邮政编码字段使用and

例如,对于美国邮政编码,屏蔽输入只允许输入数字,并强制使用格式“99999”或“99999-9999”(其中9可以是任何数字)。Validate规则需要相同的参数。但在某些情况下,Validate会在字段实际有效时将其标记为无效

代码细节 jQuery Validate在邮政编码字段上使用的正则表达式是
^\d{5}$|^\d{5}\-\d{4}$

我用屏蔽输入应用的屏蔽是
.mask('99999?'9999')

复制步骤 当我执行以下操作时,它们之间会产生冲突:

  • 填写无效的邮政编码(例如,三位数)
  • 选项卡远离字段。屏蔽输入会删除输入(预期行为),jQuery Validate会将其标记为无效,因为它是空的(也是预期的)
  • 返回zip字段并填写有效的5位数的zip
  • 选项卡远离字段它仍被标记为无效。这是出乎意料的
如果我填写9位数的zip,则不会发生此问题

假设 我认为这个错误是因为在5位zip的情况下,屏蔽输入临时插入了“-\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。模糊时会删除该字段,但在删除之前,该字段会被验证并失败,因为不允许使用下划线

如果表单随后被重新验证,zip字段将通过,这一事实支持了这一假设。我有两种方法:

  • 通过提交表格;单击submit按钮、zip字段通过并提交表单时,所有字段都将重新验证

  • 通过设置重新验证特定字段的
    blur
    事件。例如:

    $(“#zipcode”).blur(function(){$(this).closest('form').validate().element($(this));})

这可以作为一个黑客解决方案,但不是很令人满意,因为1)默认设置已经在模糊上重新验证,因此这是重复的,2)除了正常的验证规则外,还需要额外的代码

还有其他人遇到过这个问题吗您是否有比设置额外的模糊事件侦听器更优雅的解决方案

更新:应用黑客解决方案 即使应用上面的黑客解决方案也没有我所希望的那么好。例如,这不起作用:

$appDiv.delegate('input,select,textarea','blur',function(){
  $(this).closest('form').validate().element($(this));
});
……这也不是:

$('input,select,textarea').live('blur',function(){
  $(this).closest('form').validate().element($(this));
});
……但这确实:

$('input,select,textarea').each(function(){
  $(this).blur(function(){
    $(this).closest('form').validate().element($(this));
  });
});

由于这些元素是由AJAX加载的,
。每次加载表单节时都必须运行每个版本。

绑定的顺序是否重要?例如,两者之间有区别吗

$(function() {
  var $form = $("#myForm"), $zip = $("#zip");
  $zip.mask("99999?-9999");
  $form.validate();
});


我认为绑定应该按顺序启动。

我实际上是在寻找这个确切问题的答案。最终找到了一个更可靠的解决方法

因为我正在为zipcode定义自己的验证器方法,所以我修改了它,以便在我从值中删除占位符后,如果zipcode的长度为6,它将删除连字符

看起来是这样的:

$.validator.addMethod("zipcode", function(postalcode, element) {
            //removes placeholder from string
            postalcode = postalcode.split("_").join("");

            //Checks the length of the zipcode now that placeholder characters are removed.
            if (postalcode.length === 6) {
                //Removes hyphen
                postalcode = postalcode.replace("-", "");
            }
            //validates postalcode.
            return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
        }, "Please specify a valid zip code");
<input type="text" class="form-control" id="telefone" placeholder="(__) ____-_____" name="telefone" required>
$(document).ready(function() {
   var telefone = $('#telefone'), //THAT'S MY INPUT WITH MASK
       form = telefone.parents("form"), //THAT'S MY FORM WITH THE VALIDATE
       alteredField = false; //THAT'S A FLAG TO SSE IF THE INPUT WAS ALTERED

            // APPLY MY MASK
            telefone.mask('(99) 9999-9999?9');

            // FOCUS ON ANY INPUT
            form.find('input[type=text]').focus(function(){
                // REMOVE THE VALIDATION STATUS
                $(form).data('bootstrapValidator').updateStatus($(this).attr('name'), 'NOT_VALIDATED');
                // ENABLE THE SUBMIT BUTTON
                $(form).data('bootstrapValidator').disableSubmitButtons(false);
            });

            // FOCUS ON THE MASKED INPUT
            telefone.focus(function(){
                // DISABLE THE VALIDATE
                $(form).data('bootstrapValidator').enableFieldValidators('telefone', false);
                // ENABLE THE SUBMIT BUTTON
                $(form).data('bootstrapValidator').disableSubmitButtons(false);
            }).blur(function(){ // BLUR ON THE MASKED INPUT
                // GET THE INPUT VALUE
                var value = telefone.val();
                // ENABLE THE VALIDATE 
                $(form).data('bootstrapValidator').enableFieldValidators('telefone', true);
                // CHECK IF THE VALUE IS EMPTY
                if(value != ""){
                    // CHANGE THE STATUS OF THE INPUT TO VALID 
                    $(form).data('bootstrapValidator').updateStatus('telefone', 'VALID')
                    // ACTIVE THE FLAG
                    alteredField = true;
                }else if (alteredField) { // IF THE INPUT WAS ALTERED BEFORE AND DON'T HAVE VALUE
                    // CHANGE THE STATUS OF THE INPUT TO INVALID
                    $(form).data('bootstrapValidator').updateStatus('telefone', 'INVALID')
                };
            });

        });

因此,我正在验证的postalcode将由输入插件添加占位符,如果输入的zipcode只有5个数字(6个包括连字符),则删除连字符。因此,它将正确地验证它。

我遇到了一个类似的问题,并设法解决了它,将默认占位符字符更改为空字符串

我使用了一个
.mask('9?99')并使用简单的“数字”规则进行验证,并且存在相同类型的冲突

我将掩码声明更改为
.mask('9?99',{占位符:'})和。。。不再有冲突。:)

您的情况可能存在问题,因为邮政编码中的
-
,它总是由mask插件插入表单中。我认为您可以将regexp更改为
^\d{5}-$^\d{5}-\d{4}$
(在两种情况下都与破折号匹配),然后应该进行验证


不管怎么说,您不久前发布过,可能不再需要此功能,但它可能会帮助其他人。:)

我尝试了以下解决方案,效果很好

$(“[数据输入类型=电话],“正文”)
.面具(“(999)999 99”)
.bind(“模糊”,函数(){
//在模糊上强制重新验证。
var frm=$(此).parents(“表格”);
//如果表单有验证器
if($.data(frm[0],“验证器”)){
var validator=$(this.parents(“表单”).validate();
validator.settings.onfocusout.apply(validator[this]);
}
});
触发问题的是事件顺序。 当一个元素被屏蔽时,它由
blur
上的maskedinput插件进行验证,但同一元素由
focusout
事件(非ie浏览器上的blur包装)上的validator插件进行验证,该事件在maskedinput的blur之前调用

在这种情况下,当验证器检查值时,输入元素的值为
”(___________)
。当代码到达maskedinput的blur事件时,插件会测试并清除该值,因为它不是有效的输入

每个验证案例的验证结果可能不同。例如,
required
规则将成功通过,因为元素有一个值。非必需的
number
字段将失败,即使我们将输入留空,因为像
“999”
这样的掩码可能被测试为
12

上面的代码测试屏蔽输入的形式是否附加了验证,并调用focusout事件处理程序。由于我们的处理程序是最新的,希望它最终会被调用

警告,代码只是复制验证插件的行为。它可能会工作十年,但如果验证插件决定做与现在不同的事情,它可能会失败

真诚地
//Function to detect if a jQuery elements exists.  i.e.:
//      var $element = $(selector);
//      if($element.exists()) do something...

$.fn.exists = function () {
    return this.length !== 0;
}
<input type="text" class="form-control" id="telefone" placeholder="(__) ____-_____" name="telefone" required>
$(document).ready(function() {
   var telefone = $('#telefone'), //THAT'S MY INPUT WITH MASK
       form = telefone.parents("form"), //THAT'S MY FORM WITH THE VALIDATE
       alteredField = false; //THAT'S A FLAG TO SSE IF THE INPUT WAS ALTERED

            // APPLY MY MASK
            telefone.mask('(99) 9999-9999?9');

            // FOCUS ON ANY INPUT
            form.find('input[type=text]').focus(function(){
                // REMOVE THE VALIDATION STATUS
                $(form).data('bootstrapValidator').updateStatus($(this).attr('name'), 'NOT_VALIDATED');
                // ENABLE THE SUBMIT BUTTON
                $(form).data('bootstrapValidator').disableSubmitButtons(false);
            });

            // FOCUS ON THE MASKED INPUT
            telefone.focus(function(){
                // DISABLE THE VALIDATE
                $(form).data('bootstrapValidator').enableFieldValidators('telefone', false);
                // ENABLE THE SUBMIT BUTTON
                $(form).data('bootstrapValidator').disableSubmitButtons(false);
            }).blur(function(){ // BLUR ON THE MASKED INPUT
                // GET THE INPUT VALUE
                var value = telefone.val();
                // ENABLE THE VALIDATE 
                $(form).data('bootstrapValidator').enableFieldValidators('telefone', true);
                // CHECK IF THE VALUE IS EMPTY
                if(value != ""){
                    // CHANGE THE STATUS OF THE INPUT TO VALID 
                    $(form).data('bootstrapValidator').updateStatus('telefone', 'VALID')
                    // ACTIVE THE FLAG
                    alteredField = true;
                }else if (alteredField) { // IF THE INPUT WAS ALTERED BEFORE AND DON'T HAVE VALUE
                    // CHANGE THE STATUS OF THE INPUT TO INVALID
                    $(form).data('bootstrapValidator').updateStatus('telefone', 'INVALID')
                };
            });

        });
$.validator.addMethod("zipcode", function(postalcode, element) {
            //removes placeholder from string
            postalcode = postalcode.replace(/[^0-9]/g, "");
            //validates postalcode.
            return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
        }, "Please specify a valid zip code");
$.validator.addMethod("phone_length", function(phoneno, element) {
                //removes all special characters
                phoneno= phoneno.replace(/[^0-9]/g, "");
                return this.optional(element) || phoneno.match(/^\d{10}$|^\d{10}\-\d{9}$/);
            }, "Please enter a valid phone");