Created
May 22, 2017 06:49
-
-
Save fczbkk/ef9639c82ec90ecb47b6b0e57f9242eb to your computer and use it in GitHub Desktop.
Simple extensible form validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <html> | |
| <head> | |
| <script> | |
| /** | |
| * @typedef {Object} validation_result | |
| * @property {('ok'|'fail')} status | |
| * @property {string} [message] | |
| */ | |
| /** | |
| * @typedef {Object} field_config | |
| * @property {Element} field | |
| * @property {string} validator - Validator identifier | |
| */ | |
| /** | |
| * @typedef {Object} error_data | |
| * @property {Element} field | |
| * @property {string} message | |
| */ | |
| var validators = { | |
| /** | |
| * Checks for any non-whitespace character. | |
| * @param {string} input | |
| * @returns {validation_result} | |
| */ | |
| is_not_empty: function (input) { | |
| return (/\S/g.test(input)) | |
| ? {status: 'ok'} | |
| : {status: 'fail', message: 'Field should not be empty.'}; | |
| }, | |
| /** | |
| * Checks for any non-number character. | |
| * @param {string} input | |
| * @returns {validation_result} | |
| */ | |
| is_numeric: function (input) { | |
| return (/\D/g.test(input)) | |
| ? {status: 'fail', message: 'Field should only contain numbers.'} | |
| : {status: 'ok'}; | |
| } | |
| }; | |
| /** | |
| * Routes field config to appropriate validator function. | |
| * @param {field_config} field_config | |
| * @returns {validation_result} | |
| */ | |
| function checkField (field_config) { | |
| return validators[field_config.validator](field_config.field.value); | |
| } | |
| /** | |
| * Helper to be used via Array.reduce to compile all errors produced during form validation. | |
| * @param {Array.<validation_result>} existing_errors | |
| * @param {field_config} field_config | |
| * @returns {Array.<validation_result>} | |
| */ | |
| function validateField (existing_errors, field_config) { | |
| var result = checkField(field_config); | |
| if (result.status !== 'ok') { | |
| existing_errors.push({ | |
| message: result.message, | |
| field: field_config.field | |
| }); | |
| } | |
| return existing_errors; | |
| } | |
| /** | |
| * Routes error data to reporter. | |
| * @param {Function} reporter | |
| * @param {error_data} error_data | |
| */ | |
| function reportError (reporter, error_data) { | |
| reporter( | |
| 'Validation error:', error_data.message, | |
| '\nin field:', error_data.field | |
| ); | |
| } | |
| /** | |
| * Creates field validator. Returns object with `destroy()` method for easier cleanup. | |
| * @param {Element} form_element | |
| * @param {Array.<field_config>} fields_config | |
| * @param {Function} [reporter=console.log] | |
| * @returns {{destroy: destroy}} | |
| */ | |
| function createFormValidator (form_element, fields_config, reporter) { | |
| reporter = reporter || console.log; | |
| var handleFormSubmit = function (event) { | |
| var validation_errors = fields_config.reduce(validateField, []); | |
| if (validation_errors.length > 0) { | |
| validation_errors.forEach(function (error_data) { | |
| reportError(reporter, error_data); | |
| }); | |
| event.preventDefault(); | |
| } | |
| }; | |
| form_element.addEventListener('submit', handleFormSubmit); | |
| return { | |
| destroy: function () { | |
| form_element.removeEventListener('submit', handleFormSubmit); | |
| } | |
| } | |
| } | |
| function init () { | |
| createFormValidator( | |
| document.getElementById('my_form'), | |
| [ | |
| { | |
| field: document.getElementById('non_empty_input'), | |
| validator: 'is_not_empty' | |
| }, | |
| { | |
| field: document.getElementById('numeric_input'), | |
| validator: 'is_numeric' | |
| } | |
| ] | |
| ); | |
| } | |
| window.addEventListener('load', init); | |
| </script> | |
| </head> | |
| <body> | |
| <ul> | |
| <li>If there are no errors, form will submit.</li> | |
| <li>If there are any errors, form submission will be cancelled and error messages will appear in console.</li> | |
| </ul> | |
| <form id="my_form"> | |
| <p> | |
| <label for="non_empty_input">Must not be empty</label> | |
| <input type="text" id="non_empty_input"> | |
| </p> | |
| <p> | |
| <label for="numeric_input">Must only contain numbers</label> | |
| <input type="text" id="numeric_input"> | |
| </p> | |
| <p> | |
| <input type="submit"> | |
| </p> | |
| </form> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment