在回答a question asking for a way of validating an <input type="file">
against its accept
attribute时(原生行为将与生成的文件对话框一起使用,默认情况下会显示过滤器,但不会强制执行),我想看看有哪些选项可用于将此自定义验证集成到HTML5的脚本Constraint validation。
我对API的初步略读使我覆盖了本机checkValidity
方法,相信只要浏览器认为适合验证代码(jsFiddle),就会默认调用它。 :
void function enhanceFileInputTypeValidityCheck(){
var inputPrototype = document.createElement( 'input' ).constructor.prototype;
var nativeCheckValidity = inputPrototype.checkValidity;
// This is my custom validation function
function validateFileInputType( input ){
var MIMEtype = new RegExp( input.accept.replace( '*', '.\*' ) );
return Array.prototype.every.call( input.files, function passesAcceptedFormat( file ){
return MIMEtype.test( file.type );
} );
}
// My attempt at getting the behaviour to happen
inputPrototype.checkValidity = function enhancedCheckValidity(){
if( this.type === 'file' && this.accept && this.files && this.files.length ){
if( !validateFileInputType( this ) ){
this.setCustomValidity( 'Please only submit files of type ' + this.accept );
return false;
}
}
return nativeCheckValidity.apply( this );
}
}();
这有效地增强了checkValidity
在我的条件未满足时返回false
,并且如果属于,则属于原生行为,但setCustomValidity
未按预期工作:不会抛出任何异常,但也不会显示任何错误消息。至关重要的是,我return false
checkValidity
并不会阻止表单提交。
经过一番摆弄后,我最终得到了这个事件处理程序,它与上面发布的代码一起最终达到了预期目标 - 即根据自定义标准阻止提交并反馈给用户(jsFiddle):
$( 'input' ).on( 'change input', function( event ){
this.checkValidity();
} );
我对如何发生这种情况感到困惑:根据记录事件类型,change
将执行checkValidity
,但不会显示消息;同时注册提交表单 实现我的setCustomValidity
,但不会记录事件类型:但是暗示这是一个input
事件,因为那是唯一的处理程序正在侦听的其他事件 - 但是(这是真正怪异的地方),从change
取消绑定(无论如何都没有工作)只留下input
触发我的强制回调doesn't prevent submission at all anymore。
我仍然对将自定义验证绑定到本机验证流程的'正确'方式感到茫然,因为绑定到change
和event
以触发这些事件都没有发生时的预期行为实际上发生的事情实际上似乎太过于苛刻而无法用作。
用于解释以下任何内容的奖励积分:
console.log
时,为什么我的自定义验证checkValidity
没有得到任何反馈?console.log
&amp;&amp;的事件处理程序中的input
得到任何反馈? change
?change
事件的回调不会触发setCustomValidity
?input
- 实际上是在触发我的setCustomValidity
?checkValidity
的情况下生成相同的所需最终结果?答案 0 :(得分:3)
据我所知,checkValidity方法调用浏览器的内部验证,而不是浏览器的内部验证调用。因此,如果您覆盖它,浏览器将不会注意到或关心。
根据我的经验,实现自定义有效性所需的一切是绑定到change事件,然后使用正确的值调用setCustomValidity。例如,
myinput.addEventListener('change', function(e) {
if ( ! myCustomValidityCheck() )
this.setCustomValidity( 'Uh oh, that didn\'t work!' );
else
this.setCustomValidity( '' );
})
答案 1 :(得分:0)
以下是您的问题的解决方案http://jsfiddle.net/trixta/E7VtD/
这是使setCustomValidity更简单的简单方法:
//setCustomValidity is stupid so we improve by adding setCustomValidityRule
$.fn.setCustomValidityRule = function (type, rule) {
var testRule = function () {
//only if it's valid or we have set the message our own
if ($(this).is(':valid') || $.data(this, 'customErrorType' + type)) {
var message = rule(this);
this.setCustomValidity(message);
if (message) {
$.data(this, 'customErrorType' + type, message)
} else {
$.removeData(this, 'customErrorType' + type);
}
}
};
return this
//invoke initially
.each(testRule)
//and on every change
.on('customchange.customerror' + type + ' change.customerror' + type, testRule);
};
这是一种使reportValidity在当前浏览器中工作的方法:
$.fn.reportValidity = function () {
return this.each(function () {
var form;
if (this.reportValidity) {
this.reportValidity();
} else {
form = $($.prop(this, 'form')).add(this).filter('form');
//checkvalidity is obtrusive sometimes so we use :invalid
if($(':invalid', form).length){
$('<input type="submit" />')
.css({
position: 'absolute',
left: '-99999px'
})
.appendTo(form)
.click()
.remove();
}
}
});
};
答案 2 :(得分:0)
我会尝试总结一下我的经历:
setCustomValidity
和checkValidity
方法。input
事件侦听器,该侦听器在输入字段上调用setCustomValidity
。在setCustomValidity
的参数中,您调用一个合适的检查函数,如果用户输入有效则返回空字符串,否则返回约束违规消息。checkValidity
,并仅在返回true
时继续提交。另请参阅my answer to a similar SO question或try my example solution。