在某些浏览器上,未实现date
、time
、datetime-local
、number
等输入,而是将其视为文本输入。
我做了这些RegExp来检查这些输入值:
const RegExpYear = '(000[1-9]|00[1-9]\d|0[1-9]\d\d|100\d|10[1-9]\d|1[1-9]\d{2}|[2-9]\d{3}|[1-9]\d{4}|1\d{5}|2[0-6]\d{4}|27[0-4]\d{3}|275[0-6]\d{2}|2757[0-5]\d|275760)',
RegExpMonth ='(0[1-9]|1[012])',
RegExpDay = '(0[1-9]|[12]\d|3[01])',
RegExpHour = '(0\d|1\d|2[0-4])',
RegExpMinSec = '(0\d|[1-5]\d)',
RegExpMilli = '(00\d|0[1-9]\d|[1-9]\d{2})',
patternWeek = new RegExp('^'+RegExpYear+'-W(([1-4][0-9])|(5[0-3])|0[1-9])$'),
patternMonth = new RegExp('^'+RegExpYear + '-' + RegExpMonth + '$'),
patternDateTimeLocal = new RegExp('^' + RegExpYear + '-' + RegExpMonth + '-' + RegExpDay + 'T' + RegExpHour + ':' + RegExpMinSec + '(?::' + RegExpMinSec + ')?(?:.' + RegExpMilli + ')?$'),
patternDate = new RegExp('^' + RegExpYear + '-' + RegExpMonth + '-' + RegExpDay + '$'),
patternTime = new RegExp('^' + RegExpHour + ':' + RegExpMinSec + '(?::' + RegExpMinSec + ')?(?:.' + RegExpMilli + ')?$'),
patternNumber = new RegExp('^-?d+.?(d+)?([eE][+-]?d+)?$');
document.querySelectorAll('[type=datetime-local], [type=date], [type=time], [type=month], [type=week], [type=number]').forEach(function(a){
let type = a.type,
attrtype = a.attributes.getNamedItem('type').value,
pattern;
if (type !== attrtype) {
switch(attrtype) {
case 'number' : pattern = patternNumber; break;
case 'week' : pattern = patternWeek; break;
case 'month' : pattern = patternMonth; break;
case 'datetime-local' : pattern = patternDateTimeLocal; break;
case 'date' : pattern = patternDate; break;
case 'time' : pattern = patternTime; break;
}
a.addEventListener('input',function(e){
let test = pattern.test(this.value);
if (test) {
a.classList.add('valid')
a.classList.remove('invalid')
} else {
a.classList.add('invalid')
a.classList.remove('valid')
}
});
}
});
这样,我可以为错误的条目设置样式,但不能阻止表单提交。
是否可以添加通过ValidityState
属性的约束?
如果使用内置的DOM约束验证API,则不必在onsubmit
事件处理程序中重新验证所有输入或阻止表单提交。每个输入元素都会验证自己,并向表单报告它是否有效。特殊处理可以在onInput事件处理程序中完成。
演示:
const fruitRegx = "(?!s*[Mm]ango).*" // we don't want mango
// set patterns on all required input elements
let inpt = document.getElementById('choose');
inpt.setAttribute("pattern", fruitRegx);
// set input handlers
inpt.addEventListener('input', function(e) {
if (inpt.validity.patternMismatch) {
inpt.setCustomValidity("I said no mango!!");
// if pattern doesn't mismatch report it
// rest is taken care of automatically
inpt.reportValidity();
} else {
inpt.setCustomValidity("");
}
});
// this one has no pattern assigned, so doing validation manually
choose2.addEventListener('input', function(e) {
let val = e.target.value;
if (val.includes("banana")) {
e.target.setCustomValidity("How dare you!!");
e.target.reportValidity();
} else {
e.target.setCustomValidity("");
}
});
function send(event) {
// mimicking form submit
output.innerHTML += `Requesting ${choose.value} and ${choose2.value}...<br>`;
// just for the demo preventing form submission
event.preventDefault();
return false;
}
input:invalid {
background-color: rgb(255, 196, 196);
}
input:valid {
background-color: lightgreen;
}
<form onsubmit="send(event)" target="_self">
<label for="choose">What fruit would you prefer? Except mango!</label><br>
<input id="choose" required><br><br>
<label for="choose">This one doesn't have pattern validation. But don't enter 'banana'!</label><br>
<input id="choose2" required><br><br>
<button>Submit</button>
<pre id=output></pre>
</form>
如果您在上面的演示中键入"mango",则不会调用send
方法
还要注意<input>
是如何自动获取:valid
和:invalid
CSS伪类的。所以造型是自动处理的
如果你正在寻找防止表单提交的解决方案,那么上面的演示已经在做了。更多参考https://stackoverflow.com/a/8664680/15273968