Author: | Laurent G. |
---|---|
Views Total: | 1,916 views |
Official Page: | Go to website |
Last Update: | January 14, 2018 |
License: | MIT |
Preview:

Description:
A small form validation script that automatically highlights invalid form fields and displays custom error messages using HTML5 validation attributes.
How to use it:
Add required and error message to the form fields using the following data
attributes:
<form class="form" action="#_"> <fieldset> <legend>My informations:</legend> <p class="requirement"><em>Fields followed by (*) are required</em></p> <div class="form-field"> <label id="optional-label" for="optional">Optional field:</label> <input id="optional" name="optional" type="text" placeholder="optional"> </div> <div class="form-field"> <label id="lastname-label" for="lastname">Lastname: <span aria-hidden="true">(*)</span></label> <input id="lastname" name="lastname" type="text" placeholder="Dupond" required pattern="[a-zA-Zçàéèëìîïòõôûùñ '-]+" title="Lettres uniquement" aria-labelledby="lastname-label" data-msg-required="The Lastname field is required." data-msg-error="The Lastname field should contain only letters."> </div> <div class="form-field"> <label id="firstname-label" for="firstname">Firstname: <span aria-hidden="true">(*)</span></label> <input id="firstname" name="firstname" type="text" placeholder="Jean" required pattern="[a-zA-Zçàéèëìîïòõôûùñ' -]+" title="Lettres uniquement" aria-labelledby="firstname-label" data-msg-required="The Firstname field is required." data-msg-error="The Firstname field should contain only letters."> </div> <div class="form-field"> <label id="email-label" for="email">Email: <span aria-hidden="true">(*)</span></label> <input id="email" type="email" placeholder="[email protected]" required aria-labelledby="email-label" data-msg-required="The Email field is required." data-msg-error="The Email field is invalid"> </div> <div class="form-field"> <label id="phone-label" for="phone">Phone number: (0611223344 or +33611223344) <span aria-hidden="true">(*)</span></label> <input id="phone" name="phone" type="tel" placeholder="0611223344" required pattern="^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$" aria-labelledby="phone-label" data-msg-required="The Phone field is required." data-msg-error="The Phone field is invalid. It must contain only numbers and/or the sign '+'"> </div> <div class="form-field"> <label id="civility-label" for="civility">Civility: <span aria-hidden="true">(*)</span></label> <select id="civility" name="civility" required aria-labelledby="civility-label" data-msg-required="The Civility field is required."> <option value="" disabled selected>Select an option</option> <option value="1">Mrs.</option> <option value="2">Mr.</option> </select> </div> <div class="form-field"> <label id="password-label" for="password">Password: (<abbr tabindex="0" title="required">*</abbr>) <span class="input-help">Password must be 8+ characters and include letters (at least one Uppercase) AND number(s)</span></label> <input id="password" name="password" type="password" required pattern="(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$" aria-labelledby="password-label" data-msg-required="The Password field is required." data-msg-error="Password field is invalid. It must be 8+ characters and include letters (at least one Uppercase) AND number(s)"> </div> <div class="form-field"> <label id="radio-label" for="radio"> <input type="radio" id="radio" name="radio" required aria-labelledby="radio-label" data-msg-required="The Password field is required."> Radio </div> <div class="form-submit"> <input type="reset"> <input type="submit"> </div> </fieldset> </form>
The main JavaScript to activate the custom HTML5 form validator.
"use strict"; const inputs = document.querySelectorAll('input[required],select[required],textarea[required]'), oForm = document.querySelector('.form'), defaultRequiredMsg = "This field is required.", defaultErrorMsg = "This field is invalid."; function formCheck(input){ const inputParent = input.closest('.form-field'), inputId = input.id; let errorMsg = input.getAttribute('data-msg-error'), requireMsg = input.getAttribute('data-msg-required'); let label_error; input.setAttribute("aria-invalid", !input.checkValidity()); if(!input.checkValidity()) { if(!document.querySelector('#'+inputId+"-error")){ label_error = document.createElement('p'); label_error.setAttribute("id", inputId+"-error"); label_error.setAttribute('class','msg-form-error'); inputParent.insertBefore(label_error, input.nextSibling); } else { label_error = document.querySelector('#'+inputId+"-error"); } if (input.value === ''){ requireMsg ? requireMsg = requireMsg : requireMsg = defaultRequiredMsg; label_error.innerHTML = requireMsg; }else{ errorMsg ? errorMsg = errorMsg : errorMsg = defaultErrorMsg; label_error.innerHTML = errorMsg; } inputParent.classList.add('is-invalid'); inputParent.classList.remove('is-valid'); input.setAttribute('aria-describedby',inputId+'-error'); } else { if(document.querySelector('#'+inputId+"-error")){ label_error = document.querySelector('#'+inputId+"-error"); label_error.parentNode.removeChild(label_error); } inputParent.classList.remove('is-invalid'); inputParent.classList.add('is-valid'); input.removeAttribute('aria-describedby'); } } // On BLUR : check the input blured inputs.forEach(input => { input.addEventListener( "blur", event => { formCheck(input); }, false ); }); // On SUBMIT : oForm.querySelector('[type="submit"]').addEventListener("click", function(e){ oForm.classList.add('is-submited'); const iLength = inputs.length; inputs.forEach((input,index) => { formCheck(input); if(index >= iLength-1){ const invalidInputs = oForm.querySelectorAll(".is-invalid input, .is-invalid select"); if(invalidInputs.length > 0){ invalidInputs[0].focus(); } } input.addEventListener( "invalid", event => { event.preventDefault(); }, false ); }); }); // On RESET : oForm.querySelector('[type="reset"]').addEventListener("click", function(e){ oForm.classList.remove('is-submited'); inputs.forEach(input => { let inputParent = input.closest('.form-field'); //inputs[0].focus(); inputParent.classList.remove('is-valid'); inputParent.classList.remove('is-invalid'); }); let msgErrors = document.querySelectorAll('.msg-form-error'); msgErrors.forEach(msgError => { msgError.parentNode.removeChild(msgError); }); });