HTML 5 验证自定义
HTML 5 Validation Customization
我想要一个表格:
- 以自定义格式而非默认样式显示验证消息。
- 一次显示所有无效字段气泡,而不是一次显示一个。
现在,我一直受困于无聊的特定于浏览器的消息外观,在更正上一个错误之前我看不到下一个错误。这是一个非常糟糕的用户体验,因此寻找一些关于如何解决这个问题的建议。
这是我当前的 JavaScript 代码:
const contactUsForm = document.querySelector('#Form');
if (contactUsForm) {
function Validate() {
validatedFields = contactUsForm.querySelectorAll('[data-validation-required],[data-validation-format]');
validatedFields.forEach(field => {
/* RegEx patterns */
const emailPattern = /^((([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
if (field.getAttribute('type') === 'email')
{
field.setAttribute('pattern', emailPattern);
}
if (field.validity.valueMissing) {
field.setCustomValidity(field.dataset.validationRequired);
}
else if (field.validity.patternMismatch) {
field.setCustomValidity(field.dataset.validationFormat);
}
else {
field.setCustomValidity('');
}
field.reportValidity();
contactUsForm.checkValidity();
/* Recheck on field value change */
field.addEventListener('change', function() {
field.setCustomValidity('');
Validate();
});
});
}
Validate();
contactUsForm.addEventListener('submit', function(e) {
e.preventDefault;
if (e.checkValidity() == false) {
return false;
}
else {
// form.submit()
}
});
}
样式验证 bubbles/tooltips 曾经是一个功能,但仅供 Chrome 使用,但已被删除。
有关它的更多信息,请访问:
How do you style the HTML5 form validation messages?
但是,您可以创建自己的工具提示或气泡来显示验证消息。通过使用 div 容器和一个跨度以及一点点 CSS,您可以创建一个几乎任何您可以想象的外观的气泡。
.ttCont {
position: relative;
display: inline-block;
}
.ttCont .ttText {
display: inline-block;
visibility: hidden;
min-width: 200px;
background-color: darkblue;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
opacity: 0;
transition: opacity 0.5s;
/* Place bubble to the right of container */
position: absolute;
z-index: 1;
top: 5px;
left: 105%;
}
.ttCont .ttText::after {
content: " ";
position: absolute;
top: 50%;
right: 100%; /* To the left of the bubble */
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent darkblue transparent transparent;
}
.ttCont .ttText.active{
visibility: visible;
opacity: 1;
}
现在使用自定义气泡意味着您可能需要使用更少的 ValidityState API,但是您仍然可以使用相同的方法验证您的字段。除了使用 field.reportValidity()
,您还可以创建一个自定义函数,在每个字段验证
时显示一个气泡
function customReportValidatity(elem, type) {
let msg = "";
///check if validity is based on required or mismatch///
switch (type) {
case 'required':
msg = $(elem).attr('data-validation-required');
///without jQuery
// msg = elem.dataset.validationRequired;
break;
case 'format':
msg = $(elem).attr('data-validation-format');
///without jQuery
// msg = elem.dataset.validationFormat;
break;
default:
break;
}
///make popup appear///
let ttText = $(elem).parent().children('.ttText');
$(ttText).text(msg);
$(ttText).addClass('active');
///without jQuery
// let ttText = elem.parentElement.querySelector('.ttText');
// ttText.innerText = msg;
// ttText.classList.add('active');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
使用该样式和自定义函数,您可以将其应用于您愿意应用的任何表单的现有代码。在这种情况下,我制作了一个示例表单,其中包含需要的姓名和电子邮件,而不需要描述。
const contactUsForm = document.querySelector('#Form');
const submitBtn = document.querySelector('#submitBtn');
if (contactUsForm) {
function customReportValidatity(elem, type) {
let msg = "";
///check if validity is based on required or mismatch///
switch (type) {
case 'required':
msg = $(elem).attr('data-validation-required');
///without jQuery
// msg = elem.dataset.validationRequired;
break;
case 'format':
msg = $(elem).attr('data-validation-format');
///without jQuery
// msg = elem.dataset.validationFormat;
break;
default:
break;
}
///make popup appear///
let ttText = $(elem).parent().children('.ttText');
$(ttText).text(msg);
$(ttText).addClass('active');
///without jQuery
// let ttText = elem.parentElement.querySelector('.ttText');
// ttText.innerText = msg;
// ttText.classList.add('active');
}
function Validate() {
let isValid = true;
/* RegEx patterns */
const emailPattern = /^((([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
let validatedFields = contactUsForm.querySelectorAll('[data-validation-required],[data-validation-format]');
validatedFields.forEach(field => {
if (field.getAttribute('type') === 'email') {
field.setAttribute('pattern', emailPattern);
}
if (field.validity.valueMissing) {
field.setCustomValidity(field.dataset.validationRequired);
customReportValidatity(field, 'required');
isValid = false;
} else if (field.validity.typeMismatch) {
//using typeMismatch instead of patternMismatch because the regex is not working for emails
field.setCustomValidity(field.dataset.validationFormat);
customReportValidatity(field, 'format');
isValid = false;
}
contactUsForm.checkValidity();
/// Recheck on field value change ///
field.addEventListener('change', function() {
$('.ttText').removeClass('active');
///without jquery
/*document.querySelectorAll('.ttText').forEach((tt)=>{
tt.classList.remove('active');
});*/
Validate();
});
});
return isValid;
}
submitBtn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (Validate()) {
// contactUsForm.submit();
//you can use this output to check if the form will submit
console.log("Form Submitted!");
} else {
return false;
}
});
}
.ttCont {
position: relative;
display: inline-block;
}
.ttCont .ttText {
display: inline-block;
visibility: hidden;
min-width: 200px;
background-color: darkblue;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
opacity: 0;
transition: opacity 0.5s;
position: absolute;
z-index: 1;
top: 5px;
left: 105%;
}
.ttCont .ttText::after {
content: " ";
position: absolute;
top: 50%;
right: 100%;
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent darkblue transparent transparent;
}
.ttCont .ttText.active {
visibility: visible;
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<form id="Form">
<div class="ttCont">
<label for="name">Name</label><br/>
<input type="text" name="name" required data-validation-required="Name is required!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<div class="ttCont">
<label for="email">Email</label><br/>
<input type="email" name="email" required data-validation-required="Email is required" data-validation-format="Email must have the format similar to example@email.com!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<div class="ttCont">
<label for="desc">Description</label><br/>
<input type="text" name="desc" data-validation-required="Description is required!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<button type="button" id="submitBtn">Submit</button>
</form>
您可以在此处详细了解如何创建和处理自定义工具提示:
我想要一个表格:
- 以自定义格式而非默认样式显示验证消息。
- 一次显示所有无效字段气泡,而不是一次显示一个。
现在,我一直受困于无聊的特定于浏览器的消息外观,在更正上一个错误之前我看不到下一个错误。这是一个非常糟糕的用户体验,因此寻找一些关于如何解决这个问题的建议。
这是我当前的 JavaScript 代码:
const contactUsForm = document.querySelector('#Form');
if (contactUsForm) {
function Validate() {
validatedFields = contactUsForm.querySelectorAll('[data-validation-required],[data-validation-format]');
validatedFields.forEach(field => {
/* RegEx patterns */
const emailPattern = /^((([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
if (field.getAttribute('type') === 'email')
{
field.setAttribute('pattern', emailPattern);
}
if (field.validity.valueMissing) {
field.setCustomValidity(field.dataset.validationRequired);
}
else if (field.validity.patternMismatch) {
field.setCustomValidity(field.dataset.validationFormat);
}
else {
field.setCustomValidity('');
}
field.reportValidity();
contactUsForm.checkValidity();
/* Recheck on field value change */
field.addEventListener('change', function() {
field.setCustomValidity('');
Validate();
});
});
}
Validate();
contactUsForm.addEventListener('submit', function(e) {
e.preventDefault;
if (e.checkValidity() == false) {
return false;
}
else {
// form.submit()
}
});
}
样式验证 bubbles/tooltips 曾经是一个功能,但仅供 Chrome 使用,但已被删除。 有关它的更多信息,请访问: How do you style the HTML5 form validation messages?
但是,您可以创建自己的工具提示或气泡来显示验证消息。通过使用 div 容器和一个跨度以及一点点 CSS,您可以创建一个几乎任何您可以想象的外观的气泡。
.ttCont {
position: relative;
display: inline-block;
}
.ttCont .ttText {
display: inline-block;
visibility: hidden;
min-width: 200px;
background-color: darkblue;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
opacity: 0;
transition: opacity 0.5s;
/* Place bubble to the right of container */
position: absolute;
z-index: 1;
top: 5px;
left: 105%;
}
.ttCont .ttText::after {
content: " ";
position: absolute;
top: 50%;
right: 100%; /* To the left of the bubble */
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent darkblue transparent transparent;
}
.ttCont .ttText.active{
visibility: visible;
opacity: 1;
}
现在使用自定义气泡意味着您可能需要使用更少的 ValidityState API,但是您仍然可以使用相同的方法验证您的字段。除了使用 field.reportValidity()
,您还可以创建一个自定义函数,在每个字段验证
function customReportValidatity(elem, type) {
let msg = "";
///check if validity is based on required or mismatch///
switch (type) {
case 'required':
msg = $(elem).attr('data-validation-required');
///without jQuery
// msg = elem.dataset.validationRequired;
break;
case 'format':
msg = $(elem).attr('data-validation-format');
///without jQuery
// msg = elem.dataset.validationFormat;
break;
default:
break;
}
///make popup appear///
let ttText = $(elem).parent().children('.ttText');
$(ttText).text(msg);
$(ttText).addClass('active');
///without jQuery
// let ttText = elem.parentElement.querySelector('.ttText');
// ttText.innerText = msg;
// ttText.classList.add('active');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
使用该样式和自定义函数,您可以将其应用于您愿意应用的任何表单的现有代码。在这种情况下,我制作了一个示例表单,其中包含需要的姓名和电子邮件,而不需要描述。
const contactUsForm = document.querySelector('#Form');
const submitBtn = document.querySelector('#submitBtn');
if (contactUsForm) {
function customReportValidatity(elem, type) {
let msg = "";
///check if validity is based on required or mismatch///
switch (type) {
case 'required':
msg = $(elem).attr('data-validation-required');
///without jQuery
// msg = elem.dataset.validationRequired;
break;
case 'format':
msg = $(elem).attr('data-validation-format');
///without jQuery
// msg = elem.dataset.validationFormat;
break;
default:
break;
}
///make popup appear///
let ttText = $(elem).parent().children('.ttText');
$(ttText).text(msg);
$(ttText).addClass('active');
///without jQuery
// let ttText = elem.parentElement.querySelector('.ttText');
// ttText.innerText = msg;
// ttText.classList.add('active');
}
function Validate() {
let isValid = true;
/* RegEx patterns */
const emailPattern = /^((([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
let validatedFields = contactUsForm.querySelectorAll('[data-validation-required],[data-validation-format]');
validatedFields.forEach(field => {
if (field.getAttribute('type') === 'email') {
field.setAttribute('pattern', emailPattern);
}
if (field.validity.valueMissing) {
field.setCustomValidity(field.dataset.validationRequired);
customReportValidatity(field, 'required');
isValid = false;
} else if (field.validity.typeMismatch) {
//using typeMismatch instead of patternMismatch because the regex is not working for emails
field.setCustomValidity(field.dataset.validationFormat);
customReportValidatity(field, 'format');
isValid = false;
}
contactUsForm.checkValidity();
/// Recheck on field value change ///
field.addEventListener('change', function() {
$('.ttText').removeClass('active');
///without jquery
/*document.querySelectorAll('.ttText').forEach((tt)=>{
tt.classList.remove('active');
});*/
Validate();
});
});
return isValid;
}
submitBtn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (Validate()) {
// contactUsForm.submit();
//you can use this output to check if the form will submit
console.log("Form Submitted!");
} else {
return false;
}
});
}
.ttCont {
position: relative;
display: inline-block;
}
.ttCont .ttText {
display: inline-block;
visibility: hidden;
min-width: 200px;
background-color: darkblue;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
opacity: 0;
transition: opacity 0.5s;
position: absolute;
z-index: 1;
top: 5px;
left: 105%;
}
.ttCont .ttText::after {
content: " ";
position: absolute;
top: 50%;
right: 100%;
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent darkblue transparent transparent;
}
.ttCont .ttText.active {
visibility: visible;
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<form id="Form">
<div class="ttCont">
<label for="name">Name</label><br/>
<input type="text" name="name" required data-validation-required="Name is required!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<div class="ttCont">
<label for="email">Email</label><br/>
<input type="email" name="email" required data-validation-required="Email is required" data-validation-format="Email must have the format similar to example@email.com!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<div class="ttCont">
<label for="desc">Description</label><br/>
<input type="text" name="desc" data-validation-required="Description is required!" /><br/>
<span class="ttText"></span>
</div>
<br/><br/>
<button type="button" id="submitBtn">Submit</button>
</form>
您可以在此处详细了解如何创建和处理自定义工具提示: