diff --git a/src/demo/index.html b/src/demo/index.html index cae8b59..9bad52f 100644 --- a/src/demo/index.html +++ b/src/demo/index.html @@ -1,86 +1,129 @@ - - + + - - Demo 1 | Javascript Validator + Demo 2 | Javascript Validator -
-
-
-
-
- - + +
+

Input Client Information

+ + +
+
+ +
-
- - + +






+ +
+ + +
-
- - + +






+ +
+ +
-
- - + +







+ +
+ +
-
- - + +








+ + + + +
+ +
-
- - + +






+ + + +
+ +
-
- + +












+ + + +
+ +
+












- + +
- + +
+ +












+ + + + +









+
+
+ +
- +






+
+ + +
+






+
+ - - - diff --git a/src/demo/index2.html b/src/demo/index2.html deleted file mode 100644 index 02924e9..0000000 --- a/src/demo/index2.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - Demo 2 | Javascript Validator - - - -
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-
- - - - - - diff --git a/src/demo/index3.html b/src/demo/index3.html deleted file mode 100644 index 1123857..0000000 --- a/src/demo/index3.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Demo 2 | Javascript Validator - - - -
-

Input Client Information

-
- -
-
- - -
- -






- -
- - - -
- -






- -
- - -
- -







- -
- - -
- -








- - - - -
- - -
- -






- - - -
- - -
- -












- - - -
- - -
- -












- - - - -









-
-
- - -
-






-
- - -
-






- -
-
- - - - - diff --git a/src/js/formValidator.es6.js b/src/js/formValidator.es6.js index 7a6f659..5af1008 100644 --- a/src/js/formValidator.es6.js +++ b/src/js/formValidator.es6.js @@ -1,10 +1,10 @@ /*! - * JavaScript Validator Library v1.0 + * JavaScript Validator Library v2.0 * To perform effective validation and filter with form elements. * * Author : Shankar Thiyagaraajan * Email : shankarthiyagaraajan@gmail.com - * Github : https://github.com/shankarThiyagaraajan + * GitHub : https://github.com/shankarThiyagaraajan * * Source * https://github.com/global-source/javascript_form_validator @@ -17,17 +17,20 @@ * Released under the MIT license * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE * - * Date: 2017-05-01 + * Date: 2017-08-03 */ -/** + +/* * For Managing overall Validation flow. */ +let __err_id_suffix_rand_hash = '_new1_1_1xv_resp'; +let __status_log = false; +/** + * Core Js Validator. + */ class jsValidator { - /* - * jsValidator's Constructor. - */ constructor() { // Holding form element data. this.formData = false; @@ -41,8 +44,6 @@ class jsValidator { this.jsFormError = false; // Overall error list. this.formErrorList = {}; - // Common Logger Instance. - this.jsFilter = false; // To Filter non-required fields. this.forceFilter = false; // To Filter the First load. @@ -51,30 +52,31 @@ class jsValidator { this.option = false; // To apply global validator. this.onChange = false; + this.validateResponse = false; } /* * Initiating the Validator. */ init(option) { - this.jsFilter = new jsFilter(option.forceFilter); - - jsLogger.table(option); - + // Update overall log status. + __status_log = option.log; // To Update global options. this.option = option; + jsLogger.table(option); // Updating the filter flag to global. - // this.onlyFilter = option.onlyFilter; + this.onlyFilter = option.onlyFilter; // To Enable/Disable global validator. this.onChange = option.onChange; + // Update default response "class". + if ('undefined' === typeof option.errorClass) option.errorClass = 'js-error-cop'; + this.validateResponse = new validationResponse(); // Update "jsSettings" to global object. this.jsSettings = new jsSettings().init(option); // Update "jsForm" to global object. this.jsForm = new jsForm().init(option); // Initiate form error setup. this.jsFormError = new jsFormError().init(); - // Initiate Rule Sets. - this.jsRuleSets = new jsRuleSets(); // Update Force Field status. this.forceFilter = option.forceFilter; // To check the form elements. @@ -83,64 +85,61 @@ class jsValidator { this.submitListener(this.jsForm.formCore, this); // Send back "this". return this; - } + }; /* * To make listen on submit action of the form. */ submitListener(formID, obj) { // To off submit listener, if only filter needed. - if (false === this.onlyFilter || typeof(this.onlyFilter) === 'undefined') { + if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { // Initiate listener for form submission. - document.querySelector("#" + formID).addEventListener("submit", function (e) { - - // To start form validations and authorize. + document.querySelector('#' + formID).addEventListener('submit', function (e) { + // To start form validations. + // Check validation status. if (false === obj.check()) { //stop form from submitting, if validation fails e.preventDefault(); } }); } - } + }; /* - * To update the DOM to make action listener. + * To Refresh the DOM and enable Dynamic-Elements to Access. */ update() { - // To Update global options. let option = this.option; + // Updating the filter flag to global. + this.onlyFilter = option.onlyFilter; // Update "jsSettings" to global object. this.jsSettings = new jsSettings().init(option); // Update "jsForm" to global object. this.jsForm = new jsForm().init(option); // Initiate form error setup. this.jsFormError = new jsFormError().init(); - } + }; /* * To checking all elements from registered form. */ check() { + let status = false; // Loading JS Form. let jsFormObj = this.jsForm; // Loading JS error list. let errorList = this.formErrorList; - // Overall validation status. - let status = false; - let option = []; - // Looping the "input" elements for validation and filter implementation. errorList.input = this.elemLoop('input', jsFormObj.input); // Looping the "textArea" elements fro validation filter implementation. errorList.textArea = this.elemLoop('textArea', jsFormObj.textArea); // Looping the "select" elements fro validation filter implementation. errorList.select = this.elemLoop('select', jsFormObj.select); - - option.push({'errorElem': errorList}); - - jsLogger.out('Error List', option); - + jsLogger.out('Error List', this.formErrorList); + option.push({ + 'errorElem': errorList + }); // To Update global Validation Status. // If, Input elements have no errors. if (errorList.input.length === 0) { @@ -148,17 +147,16 @@ class jsValidator { if (errorList.textArea.length === 0) { // If, Select elements have no errors. if (errorList.select.length === 0) { - // If validation pass, then update "validationPass" object. + // If validation pass, then update "status" object. status = true; } } } - if (false == this.initialLoad) validationResponse.init(errorList, this.option); - + if (false == this.initialLoad) this.validateResponse.init(errorList, this.option); this.initialLoad = false; - + helper.scrollToError(this.validateResponse); return status; - } + }; /* * To looping all elements for actions. @@ -166,13 +164,13 @@ class jsValidator { elemLoop(index, formElem) { // Initiate empty array for keep list of errors. let log = []; + // Sanity check with "formElem". if (formElem === null || typeof formElem === 'undefined') return false; - // To Reverse the loop to start notify from first element. formElem = formElem.reverse(); // Looping elements. for (let i in formElem) { if (formElem[i]) { - // Switch to static variable. + // Switch to static letiable. let activeElem = formElem[i]; // Apply filter to element. this.applyFilters(activeElem); @@ -180,52 +178,55 @@ class jsValidator { if (true == this.onChange) { this.applyGlobalListener(activeElem); } + //jsLogger.out('Only Filter', this.onlyFilter); // If not only filter, then start validations. - if (false === this.onlyFilter || 'undefined' === this.onlyFilter) { + if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { // Initiate validations and update to log. - log = this.jsRuleSets.constructor.checkValidation(activeElem, log); + log = new jsRuleSets().checkValidation(activeElem, log); } } } + // jsLogger.out('Log', log); return log; - } + }; /* * To apply filter to all relevant elements by it's attributes. */ applyFilters(activeElem) { // Apply filter for Number elements. - if (activeElem.type == 'number') this.jsFilter.number(activeElem); + if (activeElem.type == 'number') new jsFilter().number(activeElem); // Apply filter for Email elements. - if (activeElem.type == 'email') this.jsFilter.constructor.email(activeElem); + if (activeElem.type == 'email') new jsFilter().email(activeElem); // Apply filter for Numeric elements. - // if (activeElem.min || activeElem.max) this.jsFilter.limit(activeElem); + if ('' !== activeElem.min || '' !== activeElem.max || activeElem.getAttribute('data-maxlength') || -1 !== activeElem.maxLength) new jsFilter().limit(activeElem); + // Apply filter File elements. + if (activeElem.type == 'file') new jsFilter().file(activeElem); // Apply filter with string, alphaNumeric and pregMatch. - if (activeElem.getAttribute('data-allow')) this.jsFilter.string(activeElem); + if (activeElem.getAttribute('data-allow')) new jsFilter().string(activeElem); // Apply filter with pattern. - if (activeElem.getAttribute('pattern')) jsFilter.pattern(activeElem); - } + if (activeElem.getAttribute('pattern')) new jsFilter().pattern(activeElem); + }; /* * To make it active to listen changes of those error fields. */ applyGlobalListener(element) { - var current = this; - element.addEventListener("change", current.constructor.quickValidation, false); - } + element.addEventListener('change', this.quickValidation, false); + }; /* * To perform quick validation to respond those fields. */ - static quickValidation(event) { - jsLogger.out('Quick', event); - var log = []; - var target = event.target; - jsLogger.out('Target', target); - log = new jsRuleSets().constructor.checkValidation(target, log); - jsLogger.out('Quick Out', log); - validationResponse.process(log); - } + quickValidation(event) { + // jsLogger.out('Quick', event); + let log = []; + let target = event.target; + // To check the validation of an element. + log = new jsRuleSets().checkValidation(target, log); + // jsLogger.out('Quick Out', log); + new validationResponse().process(log); + }; /* * Single step instance validator for Ajax form submissions. @@ -233,35 +234,29 @@ class jsValidator { validate() { // Initiate form Check. return this.check(); - } + }; } - /** * Common Filter instances. */ class jsFilter { - /* - * jsFilter's Constructor. - */ - constructor(forceFilter) { - this.forceFilter = forceFilter; - } - - /* - * Number elements filter listener. - */ - number(element) { - let current = this; - let status = true; - if (false === this.forceFilter) { + checkStatus(elem) { + let status; + status = true; + if (false === new jsValidator().forceFilter) { status = false; - if (true === element.required) { + if (true === elem.required) { status = true; } } - if (true === status) element.addEventListener("keypress", current.constructor.isNumberKey, false); + return status; + }; - } + // Number elements filter listener. + number(element) { + let status = this.checkStatus(element); + if (true === status) element.addEventListener('keypress', this.isNumberKey, false); + }; /* * String elements filter listener. @@ -270,167 +265,187 @@ class jsFilter { // Getting "data" attribute for actions. let type = element.getAttribute('data-allow'); let current = this; - let status = true; - - if (false == this.forceFilter) { - status = false; - if (true === element.required) { - status = true; - } - } + let status = this.checkStatus(element); // Switching actions. switch (type) { // Allow only alphabets [a-zA-Z] not [0-9] and special characters. case 'onlyAlpha': - if (true === status) element.addEventListener("keypress", current.constructor.isAlpha, false); + if (true === status) element.addEventListener('keypress', current.isAlpha, false); break; // Allow only alpha Numeric [a-zA-Z0-9] not special characters. case 'string': - if (true === status) element.addEventListener("keypress", current.constructor.isAlphaNumeric, false); - break; - // Allow only alpha Numeric [a-zA-Z0-9] not special characters. - case 'password': - if (true === status) element.addEventListener("keypress", current.constructor.isValidPassword, false); + if (true === status) element.addEventListener('keypress', current.isAlphaNumeric, false); break; // Allow based on the pattern given. default: - if (true === status) element.addEventListener("keypress", current.constructor.isPatternValid, false); + if (true === status) element.addEventListener('keypress', current.isPatternValid, false); break; } - } + }; /* * Pattern based filter and listener. */ - static pattern(element) { - var current = this; - - var status = true; - if (false === this.forceFilter) { - status = false; - if (true === element.required) { - status = true; - } - } - - if (true === status) element.addEventListener("keypress", current.isPatternValid, false); - - } + pattern(element) { + let current = this; + let status = this.checkStatus(element); + if (true === status) element.addEventListener('keypress', current.isPatternValid, false); + }; /* * Email elements filter listener. */ - static email(element) { - //this.jsRuleSet = new jsRuleSets(); - //element.addEventListener("keypress", this.jsRuleSet.constructor.email, false); - } + email(element) { + let status = this.checkStatus(element); + if (true === status) element.addEventListener('keypress', jsRuleSets.email, false); + }; + + file(element) { + let status = this.checkStatus(element); + if (true === status) element.addEventListener('change', jsRuleSets.file, false); + }; /* * Numeric with Limited elements filter listener. */ limit(element) { - let status = true; - if (false === this.forceFilter) { - status = false; - if (true === element.required) { - status = true; - } - } - if (true === status) element.addEventListener("keypress", this.constructor.isInLimit, false); - - } + let current = this; + let status = this.checkStatus(element); + if (true === status) element.addEventListener('change', current.isInLimit, false); + }; - //TODO: fix live entry issue. /* * Restrict element with it's limit. */ - static isInLimit(event) { + isInLimit(event) { + + // Load the element value. let value = event.target.value; + // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; + // Getting target element. + let target = event.target; + + // Final value to load back. + let final_value = value; + // Getting object from element. let min = event.target.min; let max = event.target.max; - // Default values for Min and Max. - if (!min) min = 0; - if (!max) max = 54; + // Get max-length attribute from element. + let max_length = event.target.getAttribute('data-maxlength') ? event.target.getAttribute('data-maxlength') : 0; + max_length = parseInt(max_length); + let num = value; - // Forming pattern for Restriction. - let regex = new RegExp('^[0-9]+$'); - // Validation with Code. - let key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + // if "max_length" is "0", then its don't have limit letiables. + if (0 === max_length) { - // jsLogger.out('Limit', regex.test(key) + ' | min |' + min + ' | max | ' + max); - // jsLogger.out('Regex', regex.test(key)); - // Return status of the Action. - if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { - event.preventDefault(); + // Default values for Min and Max. + if (!min) min = 1; + if (!max) max = 100; + + // Forming pattern for Restriction. + let regex = new RegExp('^[0-9]+$'); + + // Validation with Code. + let key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + + // Return status of the Action. + if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { + event.preventDefault(); + } + + // Parse to INT. + num = parseInt(num, 10); + + // // converts value to a Number. + if (isNaN(num)) { + target.value = ""; + return; + } + + // Check value is greater than "max", then replace "max". + if (parseInt(num) > max) final_value = max; + + // Check value is greater than "min", then replace "min". + if (parseInt(num) < min) final_value = min; + + } else { + //TODO: Min length later. + // Validate the length of the string. + if ((num.length > max_length) && 0 < max_length) { + // If length is more, then cutoff the remaining letters. + final_value = num.substr(0, max_length); + } } - // Updating the value. - event.target.value = (event.target.value > max) ? max : event.target.value; - } + + // Revert value back to an element. + this.value = final_value; + }; /* * Only allow alpha([a-zA-Z]). */ - static isAlpha(event) { + isAlpha(event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; - let status = pattern.validate(event, 'a-zA-Z'); - console.log(status); + // Managing the Pattern. + let status = new pattern().validate(event, 'a-zA-Z'); // Return status of the Action. if (false === status) event.preventDefault(); - } + }; /* * Only allow alpha([a-zA-Z0-9]). */ - static isAlphaNumeric(event) { + isAlphaNumeric(event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - let status = pattern.validate(event, 'a-zA-Z0-9'); + let status = new pattern().validate(event, 'a-zA-Z0-9'); // Return status of the Action. if (false === status) event.preventDefault(); - } + }; /* * To check password is valid or not. */ - static isValidPassword(event) { + isValidPassword(event) { // Prevent using "space". let charCode = (event.which) ? event.which : event.keyCode; + // If event is "space" then prevent to enter. if (charCode === 32) { event.preventDefault(); return false; - } - // To check is this action is from "windows" action or not. + } // To check is this action is from "windows" action or not. + if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - let status = pattern.validate(event, 'a-zA-Z0-9'); + let status = new pattern().validate(event, 'a-zA-Z0-9'); // Return status of the Action. if (false === status) event.preventDefault(); - } + }; /* * Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). */ - static isPatternValid(event) { + isPatternValid(event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - let status = pattern.validate(event, 'a-zA-Z0-9'); + let status = new pattern().validate(event, 'a-zA-Z0-4'); // Return status of the Action. if (false === status) event.preventDefault(); - } + }; /* * Check is numeric or not. */ - static isNumberKey(event) { + isNumberKey(event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Validation with Code. @@ -438,19 +453,16 @@ class jsFilter { if (charCode === 46 || charCode > 31 && (charCode < 48 || charCode > 57)) { event.preventDefault(); return false; - } - // Return status of the Action. + } // Return status of the Action. + return true; - } + }; } /** * To Update overall JsValidator Settings. */ class jsSettings { - /* - * jsSetting's Constructor. - */ constructor() { // Common error message color for form validation. this.errorColor = false; @@ -468,27 +480,21 @@ class jsSettings { this.errorTemplate = option.errorTemplate; // Return "this" object. return this; - } + }; /* * General Log. */ log() { jsLogger.out(this.errorColor); - jsLogger.out(this.followedElement); jsLogger.out(this.errorTemplate); - } + }; } - /** * To Perform all Form based Operations. */ class jsForm { - /* - * jsForm's Constructor. - */ constructor() { - this.options = false; // Form element. this.form = false; // Form ID. @@ -509,7 +515,7 @@ class jsForm { * To Initiating the "jsForm". */ init(option) { - // jsLogger.out('Form', option.form); + jsLogger.out('Form', option.form); // Update Global Option. this.options = option; // Enable/Disable Force Filter. @@ -520,9 +526,8 @@ class jsForm { this.parseForm(this.form); // To Filter Required Elements. this.required(); - return this; - } + }; /* * To Register Active Form to Global Object. @@ -530,25 +535,20 @@ class jsForm { registerForm(form) { // validate and Update Log. if (typeof form === 'undefined') jsLogger.out('Form Identification', 'Form Identification is Missing !'); - // Form should not be an ID. if (null === form) return false; - // Fetch Form element from Document. this.form = document.getElementById(form); if (null === this.form) jsLogger.out('Status 503', 'Failed to Proceed !'); // Update Direct Form ID. this.formCore = form; - } + }; /* * To Parse all Relative Form components. */ parseForm(form) { - - // Form should not be an ID. - if (null === form) return false; - + if (form === null) return false; // "Input" elements like "text, date, time..." this.input = form.getElementsByTagName('input'); // "Select" element. @@ -557,7 +557,7 @@ class jsForm { this.textArea = form.getElementsByTagName('textarea'); // "Label" element. this.label = form.getElementsByTagName('label'); - } + }; /* * To set fields are required. @@ -565,13 +565,14 @@ class jsForm { required() { // let jsField = new jsField().init(this.options); let forceFilter = this.forceFilter; + let jsField_obj = new jsField(); // Filter all required "input" elements. - this.input = jsField.required(this.input, forceFilter); + this.input = jsField_obj.required(this.input, forceFilter); // Filter all required "select" elements. - this.select = jsField.required(this.select, forceFilter); + this.select = jsField_obj.required(this.select, forceFilter); // Filter all required "textArea" elements. - this.textArea = jsField.required(this.textArea, forceFilter); - } + this.textArea = jsField_obj.required(this.textArea, forceFilter); + }; /* * General Log. @@ -582,151 +583,131 @@ class jsForm { jsLogger.out('select', this.select); jsLogger.out('textarea', this.textArea); jsLogger.out('labels', this.label); - } + }; } - /** * Perform Operations in Field level. */ class jsField { - - /* - * jsField's Constructor. - */ - constructor() { - this.forceFilter = false; - } - - /* - * To Initializing jsField. - */ - init(option) { - this.forceFilter = option.forceFilter; - } - /* * Return all required elements list. */ - static required(field, forceFilter) { + required(field, forceFilter) { let requiredFieldsList = []; + // Looping fields to filter. for (let i = 0; i < field.length; i++) { // Check and push elements. - // if (field[i].required === true) { - if ((field[i].required === true) || true === forceFilter) { + if (field[i].required === true || true === forceFilter) { // Pushing to required elements list. requiredFieldsList.push(field[i]); } - } - // Return list of required elements. + } // Return list of required elements. + return requiredFieldsList; - } + }; } - /** * List of Validation Rules. */ class jsRuleSets { - /* - * jsRuleSets's Constructor. - */ - constructor() { - - } - /* * To start validation process. */ - static checkValidation(activeElem, log) { + checkValidation(activeElem, log) { + //jsLogger.out('Active Elem', activeElem); let validElem = true; - let firstErrorHit = false; + let jsRuleSets_obj = new jsRuleSets(); // To Generally checks, the field is empty or not. - if (!jsRuleSets.isSet(activeElem)) { + if (!jsRuleSets_obj.isSet(activeElem)) { log.push({ 'el': activeElem, 'type': 'required', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; - } // To Check the Value is less than min or not. + validElem = false; + } + // To Check the Value is less than minimum or not. if (activeElem.min) { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.min(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.min(activeElem)) { log.push({ 'el': activeElem, 'type': 'min', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } - } // To Check the Value is grater than max or not. + } + // To Check the Value is grater than max or not. if (activeElem.max) { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.max(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.max(activeElem)) { log.push({ 'el': activeElem, 'type': 'max', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } - } // To Check the Entered E-mail is Valid or Not. + } + // To Check the Entered E-mail is Valid or Not. if (activeElem.type == 'email') { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.email(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.email(activeElem)) { log.push({ 'el': activeElem, 'type': 'email', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } - } // To Compare the Password is Same or Not with Re-Password. - // TODO: Implement Simplified Comparison. + } + // To Compare the Password is Same or Not with Re-Password. + // TODO: Implement Simplified Comparison. if (activeElem.type == 'password') { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.compare(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.compare(activeElem)) { log.push({ 'el': activeElem, 'type': 'password', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } } // If valid, then reset validation message. if (true === validElem) { - jsLogger.out('Valid Elem', activeElem); + //jsLogger.out('Valid Elem', activeElem); if (activeElem.name !== '') { - let elem = document.getElementById(activeElem.name + '_new1_1_1xv_resp'); + let elem = document.getElementById(activeElem.name + __err_id_suffix_rand_hash); if (typeof (elem) !== 'undefined' && elem !== null) { - elem.innerHTML = ''; + // Remove element to avoid un-necessary buffer. + elem.remove(); } } } // If error occurred, then locate that error - if (false !== firstErrorHit) { - helper.scrollToItem(firstErrorHit); + if (false !== validElem) { + // } + // Return overall log report of validation. + return log; - } + }; /* * To Check, whether the element have value or not. */ - static isSet(elem) { + isSet(elem) { // If field is not required, then return "true". if (false === elem.required) return true; let status = true; @@ -734,45 +715,45 @@ class jsRuleSets { //TODO: Implement suitable solution for this. if (value.length === 0 || value === '' || value === ' ' || value === '[]') status = false; return status; - } + }; /* * To Check Element with Min Condition. */ - static min(elem) { + min(elem) { // If field is not required, then return "true". if (false === elem.required) return true; let status = true; let value = elem.value; let min = elem.min; //TODO: Implement suitable solution for this. - if (value.length < min) status = false; + if (value.length < min && value.length != 0) status = false; return status; - } + }; /* * To Check Element with Max Condition. */ - static max(elem) { + max(elem) { // If field is not required, then return "true". if (false === elem.required) return true; let status = true; let value = elem.value; let max = elem.max; //TODO: Implement suitable solution for this. - if (value.length > max) status = false; + if (value.length > max && value.length != 0) status = false; return status; - } + }; /* * To Check Element Email is Valid or Not. */ - static email(elem) { + email(elem) { // If field is not required, then return "true". if (false === elem.required) return true; - let status = false; let email = elem.value; + if (typeof email === 'undefined') return false; // To Validate Email. // Convert to Native String Format. email = email.toString(); @@ -781,60 +762,72 @@ class jsRuleSets { // Valid Email. status = true; } - if (!email) status = false; - return status; - } + }; + + file(elem) { + let list_to_allow = elem.target.getAttribute('data-extensions'); + let target = elem.target; + let list_to_allow_array; + let file_response; + if ('' === list_to_allow) return true; + // Slit into array of extensions. + if (-1 === list_to_allow.indexOf(',')) { + list_to_allow_array = [list_to_allow]; + } else { + list_to_allow_array = list_to_allow.split(','); + } + // Get file name. + let fileName = target.value; + // Convert to lower case for native validation. + fileName = fileName.toLowerCase(); + file_response = (new RegExp('(' + list_to_allow_array.join('|').replace(/\./g, '\\.') + ')$')).test(fileName); + if (false === file_response) { + alert('Allowed file types are "' + list_to_allow + '" !'); + // Reset file type. + elem.target.value = ''; + return false; + } + return true; + }; /* * To Check Element Phone Value is Valid or Not. */ - static phone(elem, pattern) { + phone(elem, pattern) { // If field is not required, then return "true". if (false === elem.required) return true; let status = true; if (elem.value === '') status = false; return status; - } + }; /* * To Compare two Elements Values. */ - static compare(elem1) { + compare(elem1) { let status = false; - // If field is not required, then return "true". if (false === elem1.required) status = true; - let elem2_id = elem1.getAttribute('data-check'); - if (typeof elem2_id == 'undefined' || elem2_id == null) status = false; - if (elem2_id === null) elem2_id = elem1.getAttribute('data-parent'); if (elem2_id === null) { status = false; } else { elem2_id = elem2_id.toString(); - let elem2 = document.getElementById(elem2_id); - if (elem1.value === elem2.value) status = true; } - - jsLogger.out('Compare Status', status); + //jsLogger.out('Compare Status', status); return status; - } + }; } - - /** * To Manage JsValidator Errors. */ class jsFormError { - /* - * jsFormError's constructor. - */ constructor() { // Global constant to specify, error happened or not. this.errorHit = false; @@ -851,15 +844,14 @@ class jsFormError { this.errorHit = false; this.errorCss = 'border-color: red;border-radius: 5px;color: red;'; this.successCss = 'border-color: green;border-radius: 5px;color: green;'; - - } + }; /* * Form error log. */ log() { // jsLogger.out('Form Error Hit', this.errorHit); - } + }; /* * Form error style. @@ -867,17 +859,22 @@ class jsFormError { style(css) { this.errorCss = css.error; this.successCss = css.success; - } + }; } - /** * For manage overall logging with validator. */ let jsLogger = { + status: function () { + // return jsValidator.option.log; + return __status_log; + }, /* * Simple log with "heading" and "message". */ out: function (heading, message) { + + if (true !== this.status()) return false; console.log('======' + heading + '======'); console.log(message); console.log('------------------------'); @@ -886,17 +883,19 @@ let jsLogger = { * For bulk data logging. */ bulk: function (data) { + if (true !== this.status()) return false; console.log(data); }, /* * For log data with table. */ table: function (data) { + if (true !== this.status()) return false; console.table(data); } }; /** - * General Helping methods. + * General Helping methods.jsField_obj */ let helper = { /* @@ -919,44 +918,73 @@ let helper = { // Finally return "false" for general keys. return false; }, + /* + * To Scroll Up / Down to notify the item that have validation message. + */ + scrollToError: function (validateResponse) { + let dummy_id = '__header_error_target_temp'; + let active_class = validateResponse.getClass(); + + if (false === active_class) { + jsLogger.out('Active Class Error', 'ACTIVE CLASS NOT DEFINED, GET :' + active_class); + return false; + } + + if (0 === document.getElementsByClassName(active_class).length) return false; + // Getting current ID of the element. + let active_id = document.getElementsByClassName(active_class)[0].id; + // Update first element with dummy index ID. + document.getElementsByClassName(active_class)[0].setAttribute('id', dummy_id); + // Forming ID. + let id = document.getElementsByClassName(active_class)[0].id; + // Retrieve the element name. + let elem_name = active_id.replace(__err_id_suffix_rand_hash, ''); + // Taking active element to navigate. + let top = document.getElementsByName(elem_name)[0].offsetTop; + // Format as ID. + id = '#' + id; + // Navigate to ID. + // window.location.href = id; + // Scroll to error element as close as possible. + window.scroll(0, parseInt(top) - 15); + // Restore with actual ID. + document.getElementsByClassName(active_class)[0].setAttribute('id', active_id); + // Remove the navigated value. + this.removeHash(id); + }, /* * To Scroll Up / Down to notify the item that have validation message. */ scrollToItem: function (item) { - // alert(item); - location.href = '#' + item; - // // Update by Tag Name. - // let elem_name = item.nodeName; - // // If Element is not valid, then return false. - // if (!elem_name) return false; - // if (null == elem_name) return false; - // // Re-Fetching elements by its Name. - // item = document.getElementsByName(elem_name); - // - // let diff = (item.offsetTop - window.scrollY) / 20; - // if (!window._lastDiff) { - // window._lastDiff = 0; - // } - // if (Math.abs(diff) > 2) { - // window.scrollTo(0, (window.scrollY + diff)); - // clearTimeout(window._TO); - // if (diff !== window._lastDiff) { - // window._lastDiff = diff; - // window._TO = setTimeout(this.scrollToItem, 100, item); - // } - // } else { - // window.scrollTo(0, item.offsetTop) - // } + // Form hash value. + let hash = item; + // If "#" is missing, then add back to the ID. + if (-1 === hash.indexOf('#')) hash = '#' + hash; + // Navigate with the hash value. + window.location.href = hash; + // Remove the navigated value. + this.removeHash(hash); + }, + /* + * To remove the hash value from the URL. + */ + removeHash: function (hash) { + // Getting the actual URL. + let path = window.location.href; + // Replacing the URL with specific hash value. + path = path.replace(hash, ''); + // Update to url history. + window.history.pushState('', 'Title', path); } }; /** * Simple library for Pattern. */ -let pattern = { +class pattern { /* * To generate pattern from element attribute. */ - getDefault: function (event, originalPattern) { + getDefault(event, originalPattern) { if (typeof originalPattern == 'undefined') originalPattern = ''; // Getting special characters list. let allow_special = event.target.getAttribute('data-allowSpecial'); @@ -973,11 +1001,12 @@ let pattern = { defaultPattern = '^[' + originalPattern + allow_special + ']+$'; } return defaultPattern; - }, + }; + /* * To validate event with the pattern. */ - validate: function (event, pattern) { + validate(event, pattern) { // Managing the Pattern. let defaultPattern = this.getDefault(event, pattern); // Validate with special formed pattern. @@ -985,46 +1014,70 @@ let pattern = { // Validation with Code. let key = String.fromCharCode(!event.charCode ? event.which : event.charCode); return regex.test(key); - } -}; + }; +} /** * To Manage all kind of error response. */ -let validationResponse = { +class validationResponse { + constructor() { + this.active_class = false; + } + /* * Initiating the Response handler. */ - init: function (errorList, option) { + init(errorList, option) { this.errorMessage = option.message; + // Updating the class. + this.active_class = option.errorClass; // let errorElements = option.errorElem; // jsLogger.out('Errors', errorList); this.input(errorList.input); this.select(errorList.select); this.textArea(errorList.textArea); - }, + + }; + /* * To handle the "input" element. */ - input: function (elem) { + input(elem) { + // Initiate process for Input. this.process(elem); - }, + }; + /* * To handle the "select" element. */ - select: function (elem) { + select(elem) { + // Initiate process for Select. this.process(elem); - }, + }; + + /* + * To return active class for validation response style. + */ + getClass() { + return this.active_class; + }; + /* * To handle the "textArea" element. */ - textArea: function (elem) { + textArea(elem) { + // Initiate process for TextArea. this.process(elem); - }, + }; + /* * To process all handlers. */ - process: function (elem) { + process(elem) { + // Process with initial response. let elementDefaultResponse = ''; + // Get active class for error response element + let active_class = this.getClass(); for (let i in elem) { // jsLogger.out('Element', document.getElementById(elem[i].id)); if (elem[i].el && true === elem[i].el.required) { @@ -1040,33 +1093,36 @@ let validationResponse = { // jsLogger.out('Element Found', false); spanTag = document.createElement('span'); spanTag.setAttribute('id', activeElem.id); + spanTag.setAttribute('class', active_class); spanTag.innerHTML = elementDefaultResponse; } else { // Re-use Existing response Message SPAN. spanTag.innerHTML = elementDefaultResponse; - // jsLogger.out('Element Found', true); - } // jsLogger.out('Error Elem', activeElem.el); + } // Append HTML response to the Element. - activeElem.el.parentNode.insertBefore(spanTag, activeElem.el.nextSibling); } } - }, + }; + /* * Perform template creation and update. */ - template: function (activeElem, errorType) { - jsLogger.out('error Type 0', errorType); + template(activeElem, errorType) { + //jsLogger.out('error Type 0', errorType); let errorIndex = ''; let activeError = ''; + // Getting error response message from elemnet. let elementDefaultResponse = activeElem.el.getAttribute('data-message'); if (typeof elementDefaultResponse === 'undefined' || elementDefaultResponse === '' || elementDefaultResponse === null) { // Sanity check with error message object. if (typeof this.errorMessage !== 'undefined' && typeof this.errorMessage[errorType] !== 'undefined') { + // Getting error type. [ex. Required, Min, Max...] errorType = this.errorMessage[errorType]; - activeElem.el.getAttribute('data-message'); + + // activeElem.el.getAttribute('data-message'); if (errorType) { - jsLogger.out('errorType', errorType); + //jsLogger.out('errorType', errorType); activeError = errorType; // If error type is Min or Max, then it will proceed responsive. if (activeElem.type == 'min' || activeElem.type == 'max') { @@ -1081,22 +1137,25 @@ let validationResponse = { elementDefaultResponse = activeError; } return elementDefaultResponse; - }, + }; + /* * Default error handling messages. * If user not specify the messages, * then it will be replaces. */ - default: function (errorType) { + default(errorType) { + let active_class = this.getClass(); let errorMessages = { - required: 'This field is required', - min: 'This field length is too low.', - max: 'This field length is exceeds the limit', - password: 'Password does not match.', - email: 'Email is not valid' + required: 'This field is required.', + min: 'This field length is too low.', + max: 'This field length is exceeds the limit.', + password: 'Password does not match.', + email: 'Email is not valid.', + file: 'This file is not allowed.' }; if (typeof errorType !== 'string') return false; if (typeof errorMessages[errorType] === 'undefined') return false; return errorMessages[errorType]; - } -}; + }; +} \ No newline at end of file diff --git a/src/js/formValidator.es6.min.js b/src/js/formValidator.es6.min.js index bc5c94b..23455c4 100644 --- a/src/js/formValidator.es6.min.js +++ b/src/js/formValidator.es6.min.js @@ -1,4 +1,63 @@ -/** - * Created by shankar on 12/5/17. +/*! + * JavaScript Validator Library v2.0 + * To perform effective validation and filter with form elements. + * + * Author : Shankar Thiyagaraajan + * Email : shankarthiyagaraajan@gmail.com + * GitHub : https://github.com/shankarThiyagaraajan + * + * Source + * https://github.com/global-source/javascript_form_validator + * + * Site + * https://global-source.github.io/javascript_form_validator/ + * + * Copyright 2017 + * + * Released under the MIT license + * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE + * + * Date: 2017-08-03 */ -class jsValidator{constructor(){this.formData=!1,this.onlyFilter=!1,this.jsForm=!1,this.jsSettings=!1,this.jsFormError=!1,this.formErrorList={},this.jsFilter=!1,this.forceFilter=!1,this.initialLoad=!0,this.option=!1,this.onChange=!1}init(a){return this.jsFilter=new jsFilter(a.forceFilter),jsLogger.table(a),this.option=a,this.onChange=a.onChange,this.jsSettings=(new jsSettings).init(a),this.jsForm=(new jsForm).init(a),this.jsFormError=(new jsFormError).init(),this.jsRuleSets=new jsRuleSets,this.forceFilter=a.forceFilter,this.check(),this.submitListener(this.jsForm.formCore,this),this}submitListener(a,b){!1!==this.onlyFilter&&void 0!==this.onlyFilter||document.querySelector("#"+a).addEventListener("submit",function(a){!1===b.check()&&a.preventDefault()})}update(){let a=this.option;this.jsSettings=(new jsSettings).init(a),this.jsForm=(new jsForm).init(a),this.jsFormError=(new jsFormError).init()}check(){let a=this.jsForm,b=this.formErrorList,c=!1,d=[];return b.input=this.elemLoop("input",a.input),b.textArea=this.elemLoop("textArea",a.textArea),b.select=this.elemLoop("select",a.select),d.push({errorElem:b}),jsLogger.out("Error List",d),0===b.input.length&&0===b.textArea.length&&0===b.select.length&&(alert("Form Valid !"),c=!0),0==this.initialLoad&&validationResponse.init(b,this.option),this.initialLoad=!1,c}elemLoop(a,b){let c=[];if(null===b||void 0===b)return!1;for(let a in b)if(b[a]){let d=b[a];this.applyFilters(d),1==this.onChange&&this.applyGlobalListener(d),!1!==this.onlyFilter&&"undefined"!==this.onlyFilter||(c=this.jsRuleSets.constructor.checkValidation(d,c))}return c}applyFilters(a){"number"==a.type&&this.jsFilter.number(a),"email"==a.type&&this.jsFilter.constructor.email(a),a.getAttribute("data-allow")&&this.jsFilter.string(a),a.getAttribute("pattern")&&jsFilter.pattern(a)}applyGlobalListener(a){var b=this;a.addEventListener("change",b.constructor.quickValidation,!1)}static quickValidation(a){jsLogger.out("Quick",a);var b=[],c=a.target;jsLogger.out("Target",c),b=(new jsRuleSets).constructor.checkValidation(c,b),jsLogger.out("Quick Out",b),validationResponse.process(b)}validate(){return this.check()}}class jsFilter{constructor(a){this.forceFilter=a}number(a){let b=this,c=!0;!1===this.forceFilter&&(c=!1,!0===a.required&&(c=!0)),!0===c&&a.addEventListener("keypress",b.constructor.isNumberKey,!1)}string(a){let b=a.getAttribute("data-allow"),c=this,d=!0;switch(0==this.forceFilter&&(d=!1,!0===a.required&&(d=!0)),b){case"onlyAlpha":!0===d&&a.addEventListener("keypress",c.constructor.isAlpha,!1);break;case"string":!0===d&&a.addEventListener("keypress",c.constructor.isAlphaNumeric,!1);break;case"password":!0===d&&a.addEventListener("keypress",c.constructor.isValidPassword,!1);break;default:!0===d&&a.addEventListener("keypress",c.constructor.isPatternValid,!1)}}static pattern(a){var b=this,c=!0;!1===this.forceFilter&&(c=!1,!0===a.required&&(c=!0)),!0===c&&a.addEventListener("keypress",b.isPatternValid,!1)}static email(a){}limit(a){let b=!0;!1===this.forceFilter&&(b=!1,!0===a.required&&(b=!0)),!0===b&&a.addEventListener("keypress",this.constructor.isInLimit,!1)}static isInLimit(a){let b=a.target.value;if(!0===helper.isWindowAction(a))return!0;let c=a.target.min,d=a.target.max;c||(c=0),d||(d=54);let e=new RegExp("^[0-9]+$"),f=String.fromCharCode(a.charCode?a.charCode:a.which);(!1===e.test(f)||parseInt(b)>d||parseInt(b)d?d:a.target.value}static isAlpha(a){if(!0===helper.isWindowAction(a))return!0;let b=pattern.validate(a,"a-zA-Z");console.log(b),!1===b&&a.preventDefault()}static isAlphaNumeric(a){if(!0===helper.isWindowAction(a))return!0;!1===pattern.validate(a,"a-zA-Z0-9")&&a.preventDefault()}static isValidPassword(a){return 32===(a.which?a.which:a.keyCode)?(a.preventDefault(),!1):!0===helper.isWindowAction(a)||void(!1===pattern.validate(a,"a-zA-Z0-9")&&a.preventDefault())}static isPatternValid(a){if(!0===helper.isWindowAction(a))return!0;!1===pattern.validate(a,"a-zA-Z0-9")&&a.preventDefault()}static isNumberKey(a){if(!0===helper.isWindowAction(a))return!0;let b=a.which?a.which:a.keyCode;return!(46===b||b>31&&(b<48||b>57))||(a.preventDefault(),!1)}}class jsSettings{constructor(){this.errorColor=!1,this.errorTemplate=!1}init(a){return this.errorColor=a.errorColor,this.errorTemplate=a.errorTemplate,this}log(){jsLogger.out(this.errorColor),jsLogger.out(this.followedElement),jsLogger.out(this.errorTemplate)}}class jsForm{constructor(){this.options=!1,this.form=!1,this.formCore=!1,this.input=!1,this.select=!1,this.textArea=!1,this.label=!1,this.forceFilter=!1}init(a){return this.options=a,this.forceFilter=a.forceFilter,this.registerForm(a.form),this.parseForm(this.form),this.required(),this}registerForm(a){if(void 0===a&&jsLogger.out("Form Identification","Form Identification is Missing !"),null===a)return!1;this.form=document.getElementById(a),null===this.form&&jsLogger.out("Status 503","Failed to Proceed !"),this.formCore=a}parseForm(a){if(null===a)return!1;this.input=a.getElementsByTagName("input"),this.select=a.getElementsByTagName("select"),this.textArea=a.getElementsByTagName("textarea"),this.label=a.getElementsByTagName("label")}required(){let a=this.forceFilter;this.input=jsField.required(this.input,a),this.select=jsField.required(this.select,a),this.textArea=jsField.required(this.textArea,a)}log(){jsLogger.out("Form",this.form),jsLogger.out("input",this.input),jsLogger.out("select",this.select),jsLogger.out("textarea",this.textArea),jsLogger.out("labels",this.label)}}class jsField{constructor(){this.forceFilter=!1}init(a){this.forceFilter=a.forceFilter}static required(a,b){let c=[];for(let d=0;dd&&(b=!1),b}static email(a){if(!1===a.required)return!0;var b=!1,c=a.value;return c=c.toString(),/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(c)&&(b=!0),c||(b=!1),b}static phone(a,b){if(!1===a.required)return!0;let c=!0;return""===a.value&&(c=!1),c}static compare(a){let b=!1;!1===a.required&&(b=!0);let c=a.getAttribute("data-check");if(void 0!==c&&null!=c||(b=!1),null===c&&(c=a.getAttribute("data-parent")),null===c)b=!1;else{c=c.toString();let d=document.getElementById(c);a.value===d.value&&(b=!0)}return jsLogger.out("Compare Status",b),b}}class jsFormError{constructor(){this.errorHit=!1,this.errorCss=!1,this.successCss=!1}init(){this.errorHit=!1,this.errorCss="border-color: red;border-radius: 5px;color: red;",this.successCss="border-color: green;border-radius: 5px;color: green;"}log(){}style(a){this.errorCss=a.error,this.successCss=a.success}}let jsLogger={out:function(a,b){console.log("======"+a+"======"),console.log(b),console.log("------------------------")},bulk:function(a){console.log(a)},table:function(a){console.table(a)}},helper={isWindowAction:function(a){let b=a||window.event,c=b.shiftKey||b.which;return 9===c||0===c||8===c||32===c||13===c||8===c||c>=35&&c<=40||(c=String.fromCharCode(c),0===c.length)},scrollToItem:function(a){let b=a.nodeName;if(!b)return!1;if(null==b)return!1;a=document.getElementsByName(b);var c=(a.offsetTop-window.scrollY)/20;window._lastDiff||(window._lastDiff=0),Math.abs(c)>2?(window.scrollTo(0,window.scrollY+c),clearTimeout(window._TO),c!==window._lastDiff&&(window._lastDiff=c,window._TO=setTimeout(this.scrollToItem,100,a))):window.scrollTo(0,a.offsetTop)}},pattern={getDefault:function(a,b){void 0===b&&(b="");let c=a.target.getAttribute("data-allowSpecial"),d=a.target.pattern;console.log(d.length);return c||null!==c||(c=""),c=c.toString(),""!==d&&d.length>0&&null!==d?d:"^["+b+c+"]+$"},validate:function(a,b){let c=this.getDefault(a,b),d=new RegExp(c),e=String.fromCharCode(a.charCode?a.charCode:a.which);return d.test(e)}},validationResponse={init:function(a,b){this.errorMessage=b.message,this.input(a.input),this.select(a.select),this.textArea(a.textArea)},input:function(a){this.process(a)},select:function(a){this.process(a)},textArea:function(a){this.process(a)},process:function(a){let b="";for(let c in a)if(a[c].el&&!0===a[c].el.required){let d=a[c],e=a[c].type;b=this.template(d,e);let f=document.getElementById(d.id);void 0===f||null===f?(f=document.createElement("span"),f.setAttribute("id",d.id),f.innerHTML=b):f.innerHTML=b,d.el.parentNode.insertBefore(f,d.el.nextSibling)}},template:function(a,b){jsLogger.out("error Type 0",b);let c="",d="",e=a.el.getAttribute("data-message");return void 0!==e&&""!==e&&null!==e||(void 0!==this.errorMessage&&void 0!==this.errorMessage[b]?(b=this.errorMessage[b],a.el.getAttribute("data-message"),b&&(jsLogger.out("errorType",b),d=b,"min"!=a.type&&"max"!=a.type||("min"==a.type&&(c=a.el.min),"max"==a.type&&(c=a.el.max),d=d.replace("[INDEX]",c)))):d=this.default(b),e=d),e},default:function(a){let b={required:"This field is required",min:"This field length is too low.",max:"This field length is exceeds the limit",password:"Password does not match.",email:"Email is not valid"};return"string"==typeof a&&(void 0!==b[a]&&b[a])}}; \ No newline at end of file + +let __err_id_suffix_rand_hash='_new1_1_1xv_resp';let __status_log=!1;class jsValidator{constructor(){this.formData=!1;this.onlyFilter=!1;this.jsForm=!1;this.jsSettings=!1;this.jsFormError=!1;this.formErrorList={};this.forceFilter=!1;this.initialLoad=!0;this.option=!1;this.onChange=!1;this.validateResponse=!1} + init(option){__status_log=option.log;this.option=option;jsLogger.table(option);this.onlyFilter=option.onlyFilter;this.onChange=option.onChange;if('undefined'===typeof option.errorClass)option.errorClass='js-error-cop';this.validateResponse=new validationResponse();this.jsSettings=new jsSettings().init(option);this.jsForm=new jsForm().init(option);this.jsFormError=new jsFormError().init();this.forceFilter=option.forceFilter;this.check();this.submitListener(this.jsForm.formCore,this);return this};submitListener(formID,obj){if(!1===this.onlyFilter||typeof(this.onlyFilter)==='undefined'){document.querySelector('#'+formID).addEventListener('submit',function(e){if(!1===obj.check()){e.preventDefault()}})}};update(){let option=this.option;this.onlyFilter=option.onlyFilter;this.jsSettings=new jsSettings().init(option);this.jsForm=new jsForm().init(option);this.jsFormError=new jsFormError().init()};check(){let status=!1;let jsFormObj=this.jsForm;let errorList=this.formErrorList;let option=[];errorList.input=this.elemLoop('input',jsFormObj.input);errorList.textArea=this.elemLoop('textArea',jsFormObj.textArea);errorList.select=this.elemLoop('select',jsFormObj.select);jsLogger.out('Error List',this.formErrorList);option.push({'errorElem':errorList});if(errorList.input.length===0){if(errorList.textArea.length===0){if(errorList.select.length===0){status=!0}}} + if(!1==this.initialLoad)this.validateResponse.init(errorList,this.option);this.initialLoad=!1;helper.scrollToError(this.validateResponse);return status};elemLoop(index,formElem){let log=[];if(formElem===null||typeof formElem==='undefined')return!1;formElem=formElem.reverse();for(let i in formElem){if(formElem[i]){let activeElem=formElem[i];this.applyFilters(activeElem);if(!0==this.onChange){this.applyGlobalListener(activeElem)} + if(!1===this.onlyFilter||typeof(this.onlyFilter)==='undefined'){log=new jsRuleSets().checkValidation(activeElem,log)}}} + return log};applyFilters(activeElem){if(activeElem.type=='number')new jsFilter().number(activeElem);if(activeElem.type=='email')new jsFilter().email(activeElem);if(''!==activeElem.min||''!==activeElem.max||activeElem.getAttribute('data-maxlength')||-1!==activeElem.maxLength)new jsFilter().limit(activeElem);if(activeElem.type=='file')new jsFilter().file(activeElem);if(activeElem.getAttribute('data-allow'))new jsFilter().string(activeElem);if(activeElem.getAttribute('pattern'))new jsFilter().pattern(activeElem)};applyGlobalListener(element){element.addEventListener('change',this.quickValidation,!1)};quickValidation(event){let log=[];let target=event.target;log=new jsRuleSets().checkValidation(target,log);new validationResponse().process(log)};validate(){return this.check()}} +class jsFilter{checkStatus(elem){let status;status=!0;if(!1===new jsValidator().forceFilter){status=!1;if(!0===elem.required){status=!0}} + return status};number(element){let status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',this.isNumberKey,!1)};string(element){let type=element.getAttribute('data-allow');let current=this;let status=this.checkStatus(element);switch(type){case 'onlyAlpha':if(!0===status)element.addEventListener('keypress',current.isAlpha,!1);break;case 'string':if(!0===status)element.addEventListener('keypress',current.isAlphaNumeric,!1);break;default:if(!0===status)element.addEventListener('keypress',current.isPatternValid,!1);break}};pattern(element){let current=this;let status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',current.isPatternValid,!1)};email(element){let status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',jsRuleSets.email,!1)};file(element){let status=this.checkStatus(element);if(!0===status)element.addEventListener('change',jsRuleSets.file,!1)};limit(element){let current=this;let status=this.checkStatus(element);if(!0===status)element.addEventListener('change',current.isInLimit,!1)};isInLimit(event){let value=event.target.value;if(!0===helper.isWindowAction(event))return!0;let target=event.target;let final_value=value;let min=event.target.min;let max=event.target.max;let max_length=event.target.getAttribute('data-maxlength')?event.target.getAttribute('data-maxlength'):0;max_length=parseInt(max_length);let num=value;if(0===max_length){if(!min)min=1;if(!max)max=100;let regex=new RegExp('^[0-9]+$');let key=String.fromCharCode(!event.charCode?event.which:event.charCode);if(!1===regex.test(key)||parseInt(value)>max||parseInt(value)max)final_value=max;if(parseInt(num)max_length)&&031&&(charCode<48||charCode>57)){event.preventDefault();return!1} + return!0}} +class jsSettings{constructor(){this.errorColor=!1;this.errorTemplate=!1} + init(option){this.errorColor=option.errorColor;this.errorTemplate=option.errorTemplate;return this};log(){jsLogger.out(this.errorColor);jsLogger.out(this.errorTemplate)}} +class jsForm{constructor(){this.form=!1;this.formCore=!1;this.input=!1;this.select=!1;this.textArea=!1;this.label=!1;this.forceFilter=!1} + init(option){jsLogger.out('Form',option.form);this.options=option;this.forceFilter=option.forceFilter;this.registerForm(option.form);this.parseForm(this.form);this.required();return this};registerForm(form){if(typeof form==='undefined')jsLogger.out('Form Identification','Form Identification is Missing !');if(null===form)return!1;this.form=document.getElementById(form);if(null===this.form)jsLogger.out('Status 503','Failed to Proceed !');this.formCore=form};parseForm(form){if(form===null)return!1;this.input=form.getElementsByTagName('input');this.select=form.getElementsByTagName('select');this.textArea=form.getElementsByTagName('textarea');this.label=form.getElementsByTagName('label')};required(){let forceFilter=this.forceFilter;let jsField_obj=new jsField();this.input=jsField_obj.required(this.input,forceFilter);this.select=jsField_obj.required(this.select,forceFilter);this.textArea=jsField_obj.required(this.textArea,forceFilter)};log(){jsLogger.out('Form',this.form);jsLogger.out('input',this.input);jsLogger.out('select',this.select);jsLogger.out('textarea',this.textArea);jsLogger.out('labels',this.label)}} +class jsField{required(field,forceFilter){let requiredFieldsList=[];for(let i=0;imax&&value.length!=0)status=!1;return status};email(elem){if(!1===elem.required)return!0;let status=!1;let email=elem.value;if(typeof email==='undefined')return!1;email=email.toString();if(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)){status=!0} + if(!email)status=!1;return status};file(elem){let list_to_allow=elem.target.getAttribute('data-extensions');let target=elem.target;let list_to_allow_array;let file_response;if(''===list_to_allow)return!0;if(-1===list_to_allow.indexOf(',')){list_to_allow_array=[list_to_allow]}else{list_to_allow_array=list_to_allow.split(',')} + let fileName=target.value;fileName=fileName.toLowerCase();file_response=(new RegExp('('+list_to_allow_array.join('|').replace(/\./g,'\\.')+')$')).test(fileName);if(!1===file_response){alert('Allowed file types are "'+list_to_allow+'" !');elem.target.value='';return!1} + return!0};phone(elem,pattern){if(!1===elem.required)return!0;let status=!0;if(elem.value==='')status=!1;return status};compare(elem1){let status=!1;if(!1===elem1.required)status=!0;let elem2_id=elem1.getAttribute('data-check');if(typeof elem2_id=='undefined'||elem2_id==null)status=!1;if(elem2_id===null)elem2_id=elem1.getAttribute('data-parent');if(elem2_id===null){status=!1}else{elem2_id=elem2_id.toString();let elem2=document.getElementById(elem2_id);if(elem1.value===elem2.value)status=!0} + return status}} +class jsFormError{constructor(){this.errorHit=!1;this.errorCss=!1;this.successCss=!1} + init(){this.errorHit=!1;this.errorCss='border-color: red;border-radius: 5px;color: red;';this.successCss='border-color: green;border-radius: 5px;color: green;'};log(){};style(css){this.errorCss=css.error;this.successCss=css.success}} +let jsLogger={status:function(){return __status_log},out:function(heading,message){if(!0!==this.status())return!1;console.log('======'+heading+'======');console.log(message);console.log('------------------------')},bulk:function(data){if(!0!==this.status())return!1;console.log(data)},table:function(data){if(!0!==this.status())return!1;console.table(data)}};let helper={isWindowAction:function(event){let theEvent=event||window.event;let key=theEvent.shiftKey||theEvent.which;if(key===9||key===0||key===8||key===32||key===13||key===8||(key>=35&&key<=40)){return!0} + key=String.fromCharCode(key);if(key.length===0)return!0;return!1},scrollToError:function(validateResponse){let dummy_id='__header_error_target_temp';let active_class=validateResponse.getClass();if(!1===active_class){jsLogger.out('Active Class Error','ACTIVE CLASS NOT DEFINED, GET :'+active_class);return!1} + if(0===document.getElementsByClassName(active_class).length)return!1;let active_id=document.getElementsByClassName(active_class)[0].id;document.getElementsByClassName(active_class)[0].setAttribute('id',dummy_id);let id=document.getElementsByClassName(active_class)[0].id;let elem_name=active_id.replace(__err_id_suffix_rand_hash,'');let top=document.getElementsByName(elem_name)[0].offsetTop;id='#'+id;window.scroll(0,parseInt(top)-15);document.getElementsByClassName(active_class)[0].setAttribute('id',active_id);this.removeHash(id)},scrollToItem:function(item){let hash=item;if(-1===hash.indexOf('#'))hash='#'+hash;window.location.href=hash;this.removeHash(hash)},removeHash:function(hash){let path=window.location.href;path=path.replace(hash,'');window.history.pushState('','Title',path)}};class pattern{getDefault(event,originalPattern){if(typeof originalPattern=='undefined')originalPattern='';let allow_special=event.target.getAttribute('data-allowSpecial');let pattern=event.target.pattern;console.log(pattern.length);let defaultPattern;if(!allow_special&&allow_special===null)allow_special='';allow_special=allow_special.toString();if(pattern!==''&&pattern.length>0&&pattern!==null){defaultPattern=pattern}else{defaultPattern='^['+originalPattern+allow_special+']+$'} + return defaultPattern};validate(event,pattern){let defaultPattern=this.getDefault(event,pattern);let regex=new RegExp(defaultPattern);let key=String.fromCharCode(!event.charCode?event.which:event.charCode);return regex.test(key)}} +class validationResponse{constructor(){this.active_class=!1} + init(errorList,option){this.errorMessage=option.message;this.active_class=option.errorClass;this.input(errorList.input);this.select(errorList.select);this.textArea(errorList.textArea)};input(elem){this.process(elem)};select(elem){this.process(elem)};getClass(){return this.active_class};textArea(elem){this.process(elem)};process(elem){let elementDefaultResponse='';let active_class=this.getClass();for(let i in elem){if(elem[i].el&&!0===elem[i].el.required){let activeElem=elem[i];let errorType=elem[i].type;elementDefaultResponse=this.template(activeElem,errorType);let spanTag=document.getElementById(activeElem.id);if(typeof spanTag==='undefined'||spanTag==='undefined'||spanTag===null){spanTag=document.createElement('span');spanTag.setAttribute('id',activeElem.id);spanTag.setAttribute('class',active_class);spanTag.innerHTML=elementDefaultResponse}else{spanTag.innerHTML=elementDefaultResponse} + activeElem.el.parentNode.insertBefore(spanTag,activeElem.el.nextSibling)}}};template(activeElem,errorType){let errorIndex='';let activeError='';let elementDefaultResponse=activeElem.el.getAttribute('data-message');if(typeof elementDefaultResponse==='undefined'||elementDefaultResponse===''||elementDefaultResponse===null){if(typeof this.errorMessage!=='undefined'&&typeof this.errorMessage[errorType]!=='undefined'){errorType=this.errorMessage[errorType];if(errorType){activeError=errorType;if(activeElem.type=='min'||activeElem.type=='max'){if('min'==activeElem.type)errorIndex=activeElem.el.min;if('max'==activeElem.type)errorIndex=activeElem.el.max;activeError=activeError.replace('[INDEX]',errorIndex)}}}else{activeError=this.default(errorType)} + elementDefaultResponse=activeError} + return elementDefaultResponse};default(errorType){let active_class=this.getClass();let errorMessages={required:'This field is required.',min:'This field length is too low.',max:'This field length is exceeds the limit.',password:'Password does not match.',email:'Email is not valid.',file:'This file is not allowed.'};if(typeof errorType!=='string')return!1;if(typeof errorMessages[errorType]==='undefined')return!1;return errorMessages[errorType]}} \ No newline at end of file diff --git a/src/js/formValidator.js b/src/js/formValidator.js index d4563ee..8a94c78 100644 --- a/src/js/formValidator.js +++ b/src/js/formValidator.js @@ -1,10 +1,10 @@ /*! - * JavaScript Validator Library v1.0 + * JavaScript Validator Library v2.0 * To perform effective validation and filter with form elements. * * Author : Shankar Thiyagaraajan * Email : shankarthiyagaraajan@gmail.com - * Github : https://github.com/shankarThiyagaraajan + * GitHub : https://github.com/shankarThiyagaraajan * * Source * https://github.com/global-source/javascript_form_validator @@ -17,41 +17,45 @@ * Released under the MIT license * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE * - * Date: 2017-07-21 + * Date: 2017-08-03 */ /* * For Managing overall Validation flow. */ -var firstErrorHit = false; +var __err_id_suffix_rand_hash = '_new1_1_1xv_resp'; +var __status_log = false; /** * Core Js Validator. */ -var jsValidator = { +function jsValidator() { // Holding form element data. - formData: false, + this.formData = false; // Switch complete validation and input filter. - onlyFilter: false, + this.onlyFilter = false; // JS form. - jsForm: false, + this.jsForm = false; // JS setting. - jsSettings: false, + this.jsSettings = false; // JS form error. - jsFormError: false, + this.jsFormError = false; // Overall error list. - formErrorList: {}, + this.formErrorList = {}; // To Filter non-required fields. - forceFilter: false, + this.forceFilter = false; // To Filter the First load. - initialLoad: true, + this.initialLoad = true; // Global options. - option: false, + this.option = false; // To apply global validator. - onChange: false, + this.onChange = false; + this.validateResponse = false; /* * Initiating the Validator. */ - init: function (option) { + this.init = function (option) { + // Update overall log status. + __status_log = option.log; // To Update global options. this.option = option; jsLogger.table(option); @@ -61,12 +65,13 @@ var jsValidator = { this.onChange = option.onChange; // Update default response "class". if ('undefined' === typeof option.errorClass) option.errorClass = 'js-error-cop'; + this.validateResponse = new validationResponse(); // Update "jsSettings" to global object. - this.jsSettings = jsSettings.init(option); + this.jsSettings = new jsSettings().init(option); // Update "jsForm" to global object. - this.jsForm = jsForm.init(option); + this.jsForm = new jsForm().init(option); // Initiate form error setup. - this.jsFormError = jsFormError.init(); + this.jsFormError = new jsFormError().init(); // Update Force Field status. this.forceFilter = option.forceFilter; // To check the form elements. @@ -75,11 +80,11 @@ var jsValidator = { this.submitListener(this.jsForm.formCore, this); // Send back "this". return this; - }, + }; /* * To make listen on submit action of the form. */ - submitListener: function (formID, obj) { + this.submitListener = function (formID, obj) { // To off submit listener, if only filter needed. if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { // Initiate listener for form submission. @@ -92,25 +97,25 @@ var jsValidator = { } }); } - }, + }; /* * To Refresh the DOM and enable Dynamic-Elements to Access. */ - update: function () { + this.update = function () { var option = this.option; // Updating the filter flag to global. this.onlyFilter = option.onlyFilter; // Update "jsSettings" to global object. - this.jsSettings = jsSettings.init(option); + this.jsSettings = new jsSettings().init(option); // Update "jsForm" to global object. - this.jsForm = jsForm.init(option); + this.jsForm = new jsForm().init(option); // Initiate form error setup. - this.jsFormError = jsFormError.init(); - }, + this.jsFormError = new jsFormError().init(); + }; /* * To checking all elements from registered form. */ - check: function () { + this.check = function () { var status = false; // Loading JS Form. var jsFormObj = this.jsForm; @@ -139,15 +144,15 @@ var jsValidator = { } } } - if (false == this.initialLoad) validationResponse.init(errorList, this.option); + if (false == this.initialLoad) this.validateResponse.init(errorList, this.option); this.initialLoad = false; - helper.scrollToError(); + helper.scrollToError(this.validateResponse); return status; - }, + }; /* * To looping all elements for actions. */ - elemLoop: function (index, formElem) { + this.elemLoop = function (index, formElem) { // Initiate empty array for keep list of errors. var log = []; // Sanity check with "formElem". @@ -168,79 +173,80 @@ var jsValidator = { // If not only filter, then start validations. if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { // Initiate validations and update to log. - log = jsRuleSets.checkValidation(activeElem, log); + log = new jsRuleSets().checkValidation(activeElem, log); } } } // jsLogger.out('Log', log); return log; - }, + }; /* * To apply filter to all relevant elements by it's attributes. */ - applyFilters: function (activeElem) { + this.applyFilters = function (activeElem) { // Apply filter for Number elements. - if (activeElem.type == 'number') jsFilter.number(activeElem); + if (activeElem.type == 'number') new jsFilter().number(activeElem); // Apply filter for Email elements. - if (activeElem.type == 'email') jsFilter.email(activeElem); + if (activeElem.type == 'email') new jsFilter().email(activeElem); // Apply filter for Numeric elements. - if (activeElem.min || activeElem.max || activeElem.minLength || activeElem.maxLength) jsFilter.limit(activeElem); + if ('' !== activeElem.min || '' !== activeElem.max || activeElem.getAttribute('data-maxlength') || -1 !== activeElem.maxLength) new jsFilter().limit(activeElem); // Apply filter File elements. - if (activeElem.type == 'file') jsFilter.file(activeElem); + if (activeElem.type == 'file') new jsFilter().file(activeElem); // Apply filter with string, alphaNumeric and pregMatch. - if (activeElem.getAttribute('data-allow')) jsFilter.string(activeElem); + if (activeElem.getAttribute('data-allow')) new jsFilter().string(activeElem); // Apply filter with pattern. - if (activeElem.getAttribute('pattern')) jsFilter.pattern(activeElem); - }, + if (activeElem.getAttribute('pattern')) new jsFilter().pattern(activeElem); + }; /* * To make it active to listen changes of those error fields. */ - applyGlobalListener: function (element) { + this.applyGlobalListener = function (element) { element.addEventListener('change', this.quickValidation, false); - }, + }; /* * To perform quick validation to respond those fields. */ - quickValidation: function (event) { + this.quickValidation = function (event) { // jsLogger.out('Quick', event); var log = []; var target = event.target; - log = jsRuleSets.checkValidation(target, log); + // To check the validation of an element. + log = new jsRuleSets().checkValidation(target, log); // jsLogger.out('Quick Out', log); - validationResponse.process(log); - }, + new validationResponse().process(log); + }; /* * Single step instance validator for Ajax form submissions. */ - validate: function () { + this.validate = function () { // Initiate form Check. return this.check(); - } -}; + }; +} /** * Common Filter instances. */ -var jsFilter = { - checkStatus: function (elem) { +function jsFilter() { + this.checkStatus = function (elem) { var status; status = true; - if (false === jsValidator.forceFilter) { + if (false === new jsValidator().forceFilter) { status = false; if (true === elem.required) { status = true; } } return status; - }, + }; // Number elements filter listener. - number: function (element) { + this.number = function (element) { var status = this.checkStatus(element); if (true === status) element.addEventListener('keypress', this.isNumberKey, false); - }, + }; /* * String elements filter listener. */ - string: function (element) { + this.string = function (element) { // Getting "data" attribute for actions. var type = element.getAttribute('data-allow'); var current = this; @@ -261,89 +267,129 @@ var jsFilter = { if (true === status) element.addEventListener('keypress', current.isPatternValid, false); break; } - }, + }; /* * Pattern based filter and listener. */ - pattern: function (element) { + this.pattern = function (element) { var current = this; var status = this.checkStatus(element); if (true === status) element.addEventListener('keypress', current.isPatternValid, false); - }, + }; /* * Email elements filter listener. */ - email: function (element) { + this.email = function (element) { var status = this.checkStatus(element); if (true === status) element.addEventListener('keypress', jsRuleSets.email, false); - }, - file: function (element) { + }; + this.file = function (element) { var status = this.checkStatus(element); if (true === status) element.addEventListener('change', jsRuleSets.file, false); - }, + }; /* * Numeric with Limited elements filter listener. */ - limit: function (element) { + this.limit = function (element) { var status = this.checkStatus(element); - if (true === status) element.addEventListener('input', this.isInLimit, false); - }, + if (true === status) element.addEventListener('change', this.isInLimit, false); + }; /* * Restrict element with it's limit. */ - isInLimit: function (event) { + this.isInLimit = function (event) { + // Load the element value. var value = event.target.value; + // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; + + // Getting target element. + var target = event.target; + + // Final value to load back. + var final_value = value; + // Getting object from element. var min = event.target.min; var max = event.target.max; - // Default values for Min and Max. - if (!min) min = 1; - if (!max) max = 31; - // Forming pattern for Restriction. - var regex = new RegExp('^[0-9]+$'); - // Validation with Code. - var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); - //jsLogger.out('Limit', regex.test(key) + ' | min |' + min + ' | max | ' + max); - //jsLogger.out('Regex', regex.test(key)); - // Return status of the Action. - if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { - event.preventDefault(); - } - var num = +this.value; //converts value to a Number - if (!this.value.length) return false; //allows empty field - this.value = isNaN(num) ? min : num > max ? max : num < min ? min : num; + // Get max-length attribute from element. + var max_length = event.target.getAttribute('data-maxlength') ? event.target.getAttribute('data-maxlength') : 0; + max_length = parseInt(max_length); + var num = value; - event.target.value = event.target.value.substring(0, event.target.value.length - 1); - }, + // if "max_length" is "0", then its don't have limit variables. + if (0 === max_length) { + + // Default values for Min and Max. + if (!min) min = 1; + if (!max) max = 100; + + // Forming pattern for Restriction. + var regex = new RegExp('^[0-9]+$'); + + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + + // Return status of the Action. + if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { + event.preventDefault(); + } + + // Parse to INT. + num = parseInt(num, 10); + + // // converts value to a Number. + if (isNaN(num)) { + target.value = ""; + return; + } + + // Check value is greater than "max", then replace "max". + if (parseInt(num) > max) final_value = max; + + // Check value is greater than "min", then replace "min". + if (parseInt(num) < min) final_value = min; + + } else { + //TODO: Min length later. + // Validate the length of the string. + if ((num.length > max_length) && 0 < max_length) { + // If length is more, then cutoff the remaining letters. + final_value = num.substr(0, max_length); + } + } + + // Revert value back to an element. + this.value = final_value; + }; /* * Only allow alpha([a-zA-Z]). */ - isAlpha: function (event) { + this.isAlpha = function (event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - var status = pattern.validate(event, 'a-zA-Z'); + var status = new pattern().validate(event, 'a-zA-Z'); // Return status of the Action. if (false === status) event.preventDefault(); - }, + }; /* * Only allow alpha([a-zA-Z0-9]). */ - isAlphaNumeric: function (event) { + this.isAlphaNumeric = function (event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - var status = pattern.validate(event, 'a-zA-Z0-9'); + var status = new pattern().validate(event, 'a-zA-Z0-9'); // Return status of the Action. if (false === status) event.preventDefault(); - }, + }; /* * To check password is valid or not. */ - isValidPassword: function (event) { + this.isValidPassword = function (event) { // Prevent using "space". var charCode = (event.which) ? event.which : event.keyCode; // If event is "space" then prevent to enter. @@ -354,25 +400,25 @@ var jsFilter = { if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - var status = pattern.validate(event, 'a-zA-Z0-9'); + var status = new pattern().validate(event, 'a-zA-Z0-9'); // Return status of the Action. if (false === status) event.preventDefault(); - }, + }; /* * Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). */ - isPatternValid: function (event) { + this.isPatternValid = function (event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Managing the Pattern. - var status = pattern.validate(event, 'a-zA-Z0-4'); + var status = new pattern().validate(event, 'a-zA-Z0-4'); // Return status of the Action. if (false === status) event.preventDefault(); - }, + }; /* * Check is numeric or not. */ - isNumberKey: function (event) { + this.isNumberKey = function (event) { // To check is this action is from "windows" action or not. if (true === helper.isWindowAction(event)) return true; // Validation with Code. @@ -383,57 +429,58 @@ var jsFilter = { } // Return status of the Action. return true; - } -}; + }; +} + /** * To Update overall JsValidator Settings. */ -var jsSettings = { +function jsSettings() { // Common error message color for form validation. - errorColor: false, + this.errorColor = false; // Set common template for error message - errorTemplate: false, + this.errorTemplate = false; /* * To Initiate the Configurations. */ - init: function (option) { + this.init = function (option) { // To update error message color to global object. this.errorColor = option.errorColor; // To update error template to handle error message. this.errorTemplate = option.errorTemplate; // Return "this" object. return this; - }, + }; /* * General Log. */ - log: function () { + this.log = function () { jsLogger.out(this.errorColor); jsLogger.out(this.errorTemplate); - } -}; + }; +} /** * To Perform all Form based Operations. */ -var jsForm = { +function jsForm() { // Form element. - form: false, + this.form = false; // Form ID. - formCore: false, + this.formCore = false; // Form element's inputs. - input: false, + this.input = false; // Form element's selects. - select: false, + this.select = false; // Form element's textAreas. - textArea: false, + this.textArea = false; // Form element's labels. - label: false, + this.label = false; // Perform Force Filter on Elements. - forceFilter: false, + this.forceFilter = false; /* * To Initiating the "jsForm". */ - init: function (option) { + this.init = function (option) { jsLogger.out('Form', option.form); // Update Global Option. this.options = option; @@ -446,11 +493,11 @@ var jsForm = { // To Filter Required Elements. this.required(); return this; - }, + }; /* * To Register Active Form to Global Object. */ - registerForm: function (form) { + this.registerForm = function (form) { // validate and Update Log. if (typeof form === 'undefined') jsLogger.out('Form Identification', 'Form Identification is Missing !'); // Form should not be an ID. @@ -460,11 +507,11 @@ var jsForm = { if (null === this.form) jsLogger.out('Status 503', 'Failed to Proceed !'); // Update Direct Form ID. this.formCore = form; - }, + }; /* * To Parse all Relative Form components. */ - parseForm: function (form) { + this.parseForm = function (form) { if (form === null) return false; // "Input" elements like "text, date, time..." this.input = form.getElementsByTagName('input'); @@ -474,39 +521,40 @@ var jsForm = { this.textArea = form.getElementsByTagName('textarea'); // "Label" element. this.label = form.getElementsByTagName('label'); - }, + }; /* * To set fields are required. */ - required: function () { + this.required = function () { // var jsField = new jsField().init(this.options); var forceFilter = this.forceFilter; + var jsField_obj = new jsField(); // Filter all required "input" elements. - this.input = jsField.required(this.input, forceFilter); + this.input = jsField_obj.required(this.input, forceFilter); // Filter all required "select" elements. - this.select = jsField.required(this.select, forceFilter); + this.select = jsField_obj.required(this.select, forceFilter); // Filter all required "textArea" elements. - this.textArea = jsField.required(this.textArea, forceFilter); - }, + this.textArea = jsField_obj.required(this.textArea, forceFilter); + }; /* * General Log. */ - log: function () { + this.log = function () { jsLogger.out('Form', this.form); jsLogger.out('input', this.input); jsLogger.out('select', this.select); jsLogger.out('textarea', this.textArea); jsLogger.out('labels', this.label); - } -}; + }; +} /** * Perform Operations in Field level. */ -var jsField = { +function jsField() { /* * Return all required elements list. */ - required: function (field, forceFilter) { + this.required = function (field, forceFilter) { var requiredFieldsList = []; // Looping fields to filter. for (var i = 0; i < field.length; i++) { @@ -518,38 +566,38 @@ var jsField = { } // Return list of required elements. return requiredFieldsList; - } -}; + }; +} /** * List of Validation Rules. */ -var jsRuleSets = { +function jsRuleSets() { /* * To start validation process. */ - checkValidation: function (activeElem, log) { + this.checkValidation = function (activeElem, log) { //jsLogger.out('Active Elem', activeElem); var validElem = true; + var jsRuleSets_obj = new jsRuleSets(); // To Generally checks, the field is empty or not. - if (!jsRuleSets.isSet(activeElem)) { + if (!jsRuleSets_obj.isSet(activeElem)) { log.push({ 'el': activeElem, 'type': 'required', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; + validElem = false; } // To Check the Value is less than minimum or not. if (activeElem.min) { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.min(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.min(activeElem)) { log.push({ 'el': activeElem, 'type': 'min', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } @@ -557,14 +605,13 @@ var jsRuleSets = { // To Check the Value is grater than max or not. if (activeElem.max) { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.max(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.max(activeElem)) { log.push({ 'el': activeElem, 'type': 'max', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } @@ -572,14 +619,13 @@ var jsRuleSets = { // To Check the Entered E-mail is Valid or Not. if (activeElem.type == 'email') { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.email(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.email(activeElem)) { log.push({ 'el': activeElem, 'type': 'email', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } @@ -588,14 +634,13 @@ var jsRuleSets = { // To Compare the Password is Same or Not with Re-Password. // TODO: Implement Simplified Comparison. if (activeElem.type == 'password') { - if (jsRuleSets.isSet(activeElem)) { - if (!jsRuleSets.compare(activeElem)) { + if (jsRuleSets_obj.isSet(activeElem)) { + if (!jsRuleSets_obj.compare(activeElem)) { log.push({ 'el': activeElem, 'type': 'password', - 'id': activeElem.name + '_new1_1_1xv_resp' + 'id': activeElem.name + __err_id_suffix_rand_hash }); - firstErrorHit = activeElem.name + '_new1_1_1xv_resp'; validElem = false; } } @@ -604,26 +649,26 @@ var jsRuleSets = { if (true === validElem) { //jsLogger.out('Valid Elem', activeElem); if (activeElem.name !== '') { - var elem = document.getElementById(activeElem.name + '_new1_1_1xv_resp'); + var elem = document.getElementById(activeElem.name + __err_id_suffix_rand_hash); if (typeof (elem) !== 'undefined' && elem !== null) { // Remove element to avoid un-necessary buffer. elem.remove(); } } } + // If error occurred, then locate that error - if (false !== firstErrorHit) { - //helper.scrollToItem(firstErrorHit); + if (false !== validElem) { + // } - // } - // Return overall log report of validation. + // Return overall log report of validation. return log; - }, + } /* * To Check, whether the element have value or not. */ - isSet: function (elem) { + this.isSet = function (elem) { // If field is not required, then return "true". if (false === elem.required) return true; var status = true; @@ -631,11 +676,11 @@ var jsRuleSets = { //TODO: Implement suitable solution for this. if (value.length === 0 || value === '' || value === ' ' || value === '[]') status = false; return status; - }, + }; /* * To Check Element with Min Condition. */ - min: function (elem) { + this.min = function (elem) { // If field is not required, then return "true". if (false === elem.required) return true; var status = true; @@ -644,11 +689,11 @@ var jsRuleSets = { //TODO: Implement suitable solution for this. if (value.length < min && value.length != 0) status = false; return status; - }, + }; /* * To Check Element with Max Condition. */ - max: function (elem) { + this.max = function (elem) { // If field is not required, then return "true". if (false === elem.required) return true; var status = true; @@ -657,11 +702,11 @@ var jsRuleSets = { //TODO: Implement suitable solution for this. if (value.length > max && value.length != 0) status = false; return status; - }, + }; /* * To Check Element Email is Valid or Not. */ - email: function (elem) { + this.email = function (elem) { // If field is not required, then return "true". if (false === elem.required) return true; var status = false; @@ -677,8 +722,11 @@ var jsRuleSets = { } if (!email) status = false; return status; - }, - file: function (elem) { + }; + /* + * To Check Element's file is valid or not. + */ + this.file = function (elem) { var list_to_allow = elem.target.getAttribute('data-extensions'); var target = elem.target; var list_to_allow_array; @@ -702,21 +750,21 @@ var jsRuleSets = { return false; } return true; - }, + }; /* * To Check Element Phone Value is Valid or Not. */ - phone: function (elem, pattern) { + this.phone = function (elem, pattern) { // If field is not required, then return "true". if (false === elem.required) return true; var status = true; if (elem.value === '') status = false; return status; - }, + }; /* * To Compare two Elements Values. */ - compare: function (elem1) { + this.compare = function (elem1) { var status = false; // If field is not required, then return "true". if (false === elem1.required) status = true; @@ -730,48 +778,52 @@ var jsRuleSets = { var elem2 = document.getElementById(elem2_id); if (elem1.value === elem2.value) status = true; } - //jsLogger.out('Compare Status', status); + // Hardly remove the error message. + // document.getElementById(elem1.name + __err_id_suffix_rand_hash).remove(); + // document.getElementById(elem2.name + __err_id_suffix_rand_hash).remove(); + return status; - } -}; + }; +} /** * To Manage JsValidator Errors. */ -var jsFormError = { +function jsFormError() { // Global constant to specify, error happened or not. - errorHit: false, + this.errorHit = false; // Error Css. - errorCss: false, + this.errorCss = false; // Success Css. - successCss: false, + this.successCss = false; /* * Initiate overall form error handler. */ - init: function () { + this.init = function () { this.errorHit = false; this.errorCss = 'border-color: red;border-radius: 5px;color: red;'; this.successCss = 'border-color: green;border-radius: 5px;color: green;'; - }, + }; /* * Form error log. */ - log: function () { + this.log = function () { // jsLogger.out('Form Error Hit', this.errorHit); - }, + }; /* * Form error style. */ - style: function (css) { + this.style = function (css) { this.errorCss = css.error; this.successCss = css.success; - } -}; + }; +} /** * For manage overall logging with validator. */ var jsLogger = { status: function () { - return jsValidator.option.log + // return jsValidator.option.log; + return __status_log; }, /* * Simple log with "heading" and "message". @@ -799,7 +851,7 @@ var jsLogger = { } }; /** - * General Helping methods. + * General Helping methods.jsField_obj */ var helper = { /* @@ -825,18 +877,32 @@ var helper = { /* * To Scroll Up / Down to notify the item that have validation message. */ - scrollToError: function () { + scrollToError: function (validateResponse) { var dummy_id = '__header_error_target_temp'; - var active_class = validationResponse.getClass(); + var active_class = validateResponse.getClass(); + + if (false === active_class) { + jsLogger.out('Active Class Error', 'ACTIVE CLASS NOT DEFINED, GET :' + active_class); + return false; + } + if (0 === document.getElementsByClassName(active_class).length) return false; // Getting current ID of the element. var active_id = document.getElementsByClassName(active_class)[0].id; - // Update first element with dummy indec ID. + // Update first element with dummy index ID. document.getElementsByClassName(active_class)[0].setAttribute('id', dummy_id); // Forming ID. - var id = '#' + document.getElementsByClassName(active_class)[0].id; + var id = document.getElementsByClassName(active_class)[0].id; + // Retrieve the element name. + var elem_name = active_id.replace(__err_id_suffix_rand_hash, ''); + // Taking active element to navigate. + var top = document.getElementsByName(elem_name)[0].offsetTop; + // Format as ID. + id = '#' + id; // Navigate to ID. - window.location.href = id; + // window.location.href = id; + // Scroll to error element as close as possible. + window.scroll(0, parseInt(top) - 15); // Restore with actual ID. document.getElementsByClassName(active_class)[0].setAttribute('id', active_id); // Remove the navigated value. @@ -870,11 +936,11 @@ var helper = { /** * Simple library for Pattern. */ -var pattern = { +function pattern() { /* * To generate pattern from element attribute. */ - getDefault: function (event, originalPattern) { + this.getDefault = function (event, originalPattern) { if (typeof originalPattern == 'undefined') originalPattern = ''; // Getting special characters list. var allow_special = event.target.getAttribute('data-allowSpecial'); @@ -891,11 +957,11 @@ var pattern = { defaultPattern = '^[' + originalPattern + allow_special + ']+$'; } return defaultPattern; - }, + }; /* * To validate event with the pattern. */ - validate: function (event, pattern) { + this.validate = function (event, pattern) { // Managing the Pattern. var defaultPattern = this.getDefault(event, pattern); // Validate with special formed pattern. @@ -903,17 +969,17 @@ var pattern = { // Validation with Code. var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); return regex.test(key); - } -}; + }; +} /** * To Manage all kind of error response. */ -var validationResponse = { - active_class: false, +function validationResponse() { + this.active_class = false; /* * Initiating the Response handler. */ - init: function (errorList, option) { + this.init = function (errorList, option) { this.errorMessage = option.message; // Updating the class. this.active_class = option.errorClass; @@ -923,35 +989,38 @@ var validationResponse = { this.select(errorList.select); this.textArea(errorList.textArea); - }, + }; /* * To handle the "input" element. */ - input: function (elem) { + this.input = function (elem) { // Initiate process for Input. this.process(elem); - }, + }; /* * To handle the "select" element. */ - select: function (elem) { + this.select = function (elem) { // Initiate process for Select. this.process(elem); - }, - getClass: function () { + }; + /* + * To return active class for validation response style. + */ + this.getClass = function () { return this.active_class; - }, + }; /* * To handle the "textArea" element. */ - textArea: function (elem) { + this.textArea = function (elem) { // Initiate process for TextArea. this.process(elem); - }, + }; /* * To process all handlers. */ - process: function (elem) { + this.process = function (elem) { // Process with initial response. var elementDefaultResponse = ''; // Get active class for error response element @@ -981,11 +1050,11 @@ var validationResponse = { activeElem.el.parentNode.insertBefore(spanTag, activeElem.el.nextSibling); } } - }, + }; /* * Perform template creation and update. */ - template: function (activeElem, errorType) { + this.template = function (activeElem, errorType) { //jsLogger.out('error Type 0', errorType); var errorIndex = ''; var activeError = ''; @@ -1014,13 +1083,13 @@ var validationResponse = { elementDefaultResponse = activeError; } return elementDefaultResponse; - }, + }; /* * Default error handling messages. * If user not specify the messages, * then it will be replaces. */ - default: function (errorType) { + this.default = function (errorType) { var active_class = this.getClass(); var errorMessages = { required: 'This field is required.', @@ -1033,5 +1102,5 @@ var validationResponse = { if (typeof errorType !== 'string') return false; if (typeof errorMessages[errorType] === 'undefined') return false; return errorMessages[errorType]; - } -}; \ No newline at end of file + }; +} \ No newline at end of file diff --git a/src/js/formValidator.min.js b/src/js/formValidator.min.js index 105edcd..9ae653b 100644 --- a/src/js/formValidator.min.js +++ b/src/js/formValidator.min.js @@ -1,10 +1,10 @@ /*! - * JavaScript Validator Library v1.0 + * JavaScript Validator Library v2.0 * To perform effective validation and filter with form elements. * * Author : Shankar Thiyagaraajan * Email : shankarthiyagaraajan@gmail.com - * Github : https://github.com/shankarThiyagaraajan + * GitHub : https://github.com/shankarThiyagaraajan * * Source * https://github.com/global-source/javascript_form_validator @@ -17,7 +17,43 @@ * Released under the MIT license * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE * - * Date: 2017-07-21 + * Date: 2017-08-03 */ -var firstErrorHit=!1,jsValidator={formData:!1,onlyFilter:!1,jsForm:!1,jsSettings:!1,jsFormError:!1,formErrorList:{},forceFilter:!1,initialLoad:!0,option:!1,onChange:!1,init:function(e){return jsLogger.table(e),this.option=e,this.onlyFilter=e.onlyFilter,this.onChange=e.onChange,"undefined"==typeof e.errorClass&&(e.errorClass="js-error-cop"),this.jsSettings=jsSettings.init(e),this.jsForm=jsForm.init(e),this.jsFormError=jsFormError.init(),this.forceFilter=e.forceFilter,this.check(),this.submitListener(this.jsForm.formCore,this),this},submitListener:function(e,t){(!1===this.onlyFilter||"undefined"==typeof this.onlyFilter)&&document.querySelector("#"+e).addEventListener("submit",function(e){!1===t.check()&&e.preventDefault()})},update:function(){var e=this.option;this.onlyFilter=e.onlyFilter,this.jsSettings=jsSettings.init(e),this.jsForm=jsForm.init(e),this.jsFormError=jsFormError.init()},check:function(){var e=!1,t=this.jsForm,r=this.formErrorList,i=[];return r.input=this.elemLoop("input",t.input),r.textArea=this.elemLoop("textArea",t.textArea),r.select=this.elemLoop("select",t.select),jsLogger.out("Error List",this.formErrorList),i.push({errorElem:r}),0===r.input.length&&0===r.textArea.length&&0===r.select.length&&(e=!0),0==this.initialLoad&&validationResponse.init(r,this.option),this.initialLoad=!1,helper.scrollToError(),e},elemLoop:function(e,t){var r=[];if(null===t||"undefined"==typeof t)return!1;t=t.reverse();for(var i in t)if(t[i]){var n=t[i];this.applyFilters(n),1==this.onChange&&this.applyGlobalListener(n),(!1===this.onlyFilter||"undefined"==typeof this.onlyFilter)&&(r=jsRuleSets.checkValidation(n,r))}return r},applyFilters:function(e){"number"==e.type&&jsFilter.number(e),"email"==e.type&&jsFilter.email(e),"file"==e.type&&jsFilter.file(e),e.getAttribute("data-allow")&&jsFilter.string(e),e.getAttribute("pattern")&&jsFilter.pattern(e)},applyGlobalListener:function(e){e.addEventListener("change",this.quickValidation,!1)},quickValidation:function(e){var t=[],r=e.target;t=jsRuleSets.checkValidation(r,t),validationResponse.process(t)},validate:function(){return this.check()}},jsFilter={checkStatus:function(e){var t;return t=!0,!1===jsValidator.forceFilter&&(t=!1,!0===e.required&&(t=!0)),t},number:function(e){var t=this.checkStatus(e);!0===t&&e.addEventListener("keypress",this.isNumberKey,!1)},string:function(e){var t=e.getAttribute("data-allow"),r=this,i=this.checkStatus(e);switch(t){case"onlyAlpha":!0===i&&e.addEventListener("keypress",r.isAlpha,!1);break;case"string":!0===i&&e.addEventListener("keypress",r.isAlphaNumeric,!1);break;default:!0===i&&e.addEventListener("keypress",r.isPatternValid,!1)}},pattern:function(e){var t=this,r=this.checkStatus(e);!0===r&&e.addEventListener("keypress",t.isPatternValid,!1)},email:function(e){var t=this.checkStatus(e);!0===t&&e.addEventListener("keypress",jsRuleSets.email,!1)},file:function(e){var t=this.checkStatus(e);!0===t&&e.addEventListener("change",jsRuleSets.file,!1)},limit:function(e){var t=this.checkStatus(e);!0===t&&e.addEventListener("input",this.isInLimit,!1)},isInLimit:function(e){var t=e.target.value;if(!0===helper.isWindowAction(e))return!0;var r=e.target.min,i=e.target.max;r||(r=1),i||(i=31);var n=new RegExp("^[0-9]+$"),s=String.fromCharCode(e.charCode?e.charCode:e.which);(!1===n.test(s)||parseInt(t)>i||parseInt(t)i?i:r>o?r:o,void(e.target.value=e.target.value.substring(0,e.target.value.length-1))):!1},isAlpha:function(e){if(!0===helper.isWindowAction(e))return!0;var t=pattern.validate(e,"a-zA-Z");!1===t&&e.preventDefault()},isAlphaNumeric:function(e){if(!0===helper.isWindowAction(e))return!0;var t=pattern.validate(e,"a-zA-Z0-9");!1===t&&e.preventDefault()},isValidPassword:function(e){var t=e.which?e.which:e.keyCode;if(32===t)return e.preventDefault(),!1;if(!0===helper.isWindowAction(e))return!0;var r=pattern.validate(e,"a-zA-Z0-9");!1===r&&e.preventDefault()},isPatternValid:function(e){if(!0===helper.isWindowAction(e))return!0;var t=pattern.validate(e,"a-zA-Z0-4");!1===t&&e.preventDefault()},isNumberKey:function(e){if(!0===helper.isWindowAction(e))return!0;var t=e.which?e.which:e.keyCode;return 46===t||t>31&&(48>t||t>57)?(e.preventDefault(),!1):!0}},jsSettings={errorColor:!1,errorTemplate:!1,init:function(e){return this.errorColor=e.errorColor,this.errorTemplate=e.errorTemplate,this},log:function(){jsLogger.out(this.errorColor),jsLogger.out(this.errorTemplate)}},jsForm={form:!1,formCore:!1,input:!1,select:!1,textArea:!1,label:!1,forceFilter:!1,init:function(e){return jsLogger.out("Form",e.form),this.options=e,this.forceFilter=e.forceFilter,this.registerForm(e.form),this.parseForm(this.form),this.required(),this},registerForm:function(e){return"undefined"==typeof e&&jsLogger.out("Form Identification","Form Identification is Missing !"),null===e?!1:(this.form=document.getElementById(e),null===this.form&&jsLogger.out("Status 503","Failed to Proceed !"),void(this.formCore=e))},parseForm:function(e){return null===e?!1:(this.input=e.getElementsByTagName("input"),this.select=e.getElementsByTagName("select"),this.textArea=e.getElementsByTagName("textarea"),void(this.label=e.getElementsByTagName("label")))},required:function(){var e=this.forceFilter;this.input=jsField.required(this.input,e),this.select=jsField.required(this.select,e),this.textArea=jsField.required(this.textArea,e)},log:function(){jsLogger.out("Form",this.form),jsLogger.out("input",this.input),jsLogger.out("select",this.select),jsLogger.out("textarea",this.textArea),jsLogger.out("labels",this.label)}},jsField={required:function(e,t){for(var r=[],i=0;ii&&0!=r.length&&(t=!1),t},email:function(e){if(!1===e.required)return!0;var t=!1,r=e.value;return"undefined"==typeof r?!1:(r=r.toString(),/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(r)&&(t=!0),r||(t=!1),t)},file:function(e){var t,r,i=e.target.getAttribute("data-extensions"),n=e.target;if(""===i)return!0;t=-1===i.indexOf(",")?[i]:i.split(",");var s=n.value;return s=s.toLowerCase(),r=new RegExp("("+t.join("|").replace(/\./g,"\\.")+")$").test(s),!1===r?(alert('Allowed file types are "'+i+'" !'),e.target.value="",!1):!0},phone:function(e,t){if(!1===e.required)return!0;var r=!0;return""===e.value&&(r=!1),r},compare:function(e){var t=!1;!1===e.required&&(t=!0);var r=e.getAttribute("data-check");if(("undefined"==typeof r||null==r)&&(t=!1),null===r&&(r=e.getAttribute("data-parent")),null===r)t=!1;else{r=r.toString();var i=document.getElementById(r);e.value===i.value&&(t=!0)}return t}},jsFormError={errorHit:!1,errorCss:!1,successCss:!1,init:function(){this.errorHit=!1,this.errorCss="border-color: red;border-radius: 5px;color: red;",this.successCss="border-color: green;border-radius: 5px;color: green;"},log:function(){},style:function(e){this.errorCss=e.error,this.successCss=e.success}},jsLogger={out:function(e,t){console.log("======"+e+"======"),console.log(t),console.log("------------------------")},bulk:function(e){console.log(e)},table:function(e){console.table(e)}},helper={isWindowAction:function(e){var t=e||window.event,r=t.shiftKey||t.which;return 9===r||0===r||8===r||32===r||13===r||8===r||r>=35&&40>=r?!0:(r=String.fromCharCode(r),0===r.length?!0:!1)},scrollToError:function(){var e=validationResponse.getClass();if(0===document.getElementsByClassName(e).length)return!1;document.getElementsByClassName(e)[0].setAttribute("id","__header_error_target_temp");var t="#"+document.getElementsByClassName(e)[0].id;window.location.href=t,document.getElementsByClassName(e)[0].removeAttribute("id"),this.removeHash(t)},scrollToItem:function(e){var t=e;-1===t.indexOf("#")&&(t="#"+t),window.location.href=t,this.removeHash(t)},removeHash:function(e){var t=window.location.href;t=t.replace(e,""),window.history.pushState("","Title",t)}},pattern={getDefault:function(e,t){"undefined"==typeof t&&(t="");var r=e.target.getAttribute("data-allowSpecial"),i=e.target.pattern;console.log(i.length);var n;return r||null!==r||(r=""),r=r.toString(),n=""!==i&&i.length>0&&null!==i?i:"^["+t+r+"]+$"},validate:function(e,t){var r=this.getDefault(e,t),i=new RegExp(r),n=String.fromCharCode(e.charCode?e.charCode:e.which);return i.test(n)}},validationResponse={active_class:!1,init:function(e,t){this.errorMessage=t.message,this.active_class=t.errorClass,this.input(e.input),this.select(e.select),this.textArea(e.textArea)},input:function(e){this.process(e)},select:function(e){this.process(e)},getClass:function(){return this.active_class},textArea:function(e){this.process(e)},process:function(e){var t="",r=this.getClass();for(var i in e)if(e[i].el&&!0===e[i].el.required){var n=e[i],s=e[i].type;t=this.template(n,s);var o=document.getElementById(n.id);"undefined"==typeof o||"undefined"===o||null===o?(o=document.createElement("span"),o.setAttribute("id",n.id),o.setAttribute("class",r),o.innerHTML=t):o.innerHTML=t,n.el.parentNode.insertBefore(o,n.el.nextSibling)}},template:function(e,t){var r="",i="",n=e.el.getAttribute("data-message");return("undefined"==typeof n||""===n||null===n)&&("undefined"!=typeof this.errorMessage&&"undefined"!=typeof this.errorMessage[t]?(t=this.errorMessage[t],e.el.getAttribute("data-message"),t&&(i=t,("min"==e.type||"max"==e.type)&&("min"==e.type&&(r=e.el.min),"max"==e.type&&(r=e.el.max),i=i.replace("[INDEX]",r)))):i=this["default"](t),n=i),n},"default":function(e){var t=this.getClass(),r={required:'This field is required.',min:'This field length is too low.',max:'This field length is exceeds the limit.',password:'Password does not match.',email:'Email is not valid.',file:'This file is not allowed.'};return"string"!=typeof e?!1:"undefined"==typeof r[e]?!1:r[e]}}; \ No newline at end of file +var __err_id_suffix_rand_hash='_new1_1_1xv_resp';var __status_log=!1;function jsValidator(){this.formData=!1;this.onlyFilter=!1;this.jsForm=!1;this.jsSettings=!1;this.jsFormError=!1;this.formErrorList={};this.forceFilter=!1;this.initialLoad=!0;this.option=!1;this.onChange=!1;this.validateResponse=!1;this.init=function(option){__status_log=option.log;this.option=option;jsLogger.table(option);this.onlyFilter=option.onlyFilter;this.onChange=option.onChange;if('undefined'===typeof option.errorClass)option.errorClass='js-error-cop';this.validateResponse=new validationResponse();this.jsSettings=new jsSettings().init(option);this.jsForm=new jsForm().init(option);this.jsFormError=new jsFormError().init();this.forceFilter=option.forceFilter;this.check();this.submitListener(this.jsForm.formCore,this);return this};this.submitListener=function(formID,obj){if(!1===this.onlyFilter||typeof(this.onlyFilter)==='undefined'){document.querySelector('#'+formID).addEventListener('submit',function(e){if(!1===obj.check()){e.preventDefault()}})}};this.update=function(){var option=this.option;this.onlyFilter=option.onlyFilter;this.jsSettings=new jsSettings().init(option);this.jsForm=new jsForm().init(option);this.jsFormError=new jsFormError().init()};this.check=function(){var status=!1;var jsFormObj=this.jsForm;var errorList=this.formErrorList;var option=[];errorList.input=this.elemLoop('input',jsFormObj.input);errorList.textArea=this.elemLoop('textArea',jsFormObj.textArea);errorList.select=this.elemLoop('select',jsFormObj.select);jsLogger.out('Error List',this.formErrorList);option.push({'errorElem':errorList});if(errorList.input.length===0){if(errorList.textArea.length===0){if(errorList.select.length===0){status=!0}}} + if(!1==this.initialLoad)this.validateResponse.init(errorList,this.option);this.initialLoad=!1;helper.scrollToError(this.validateResponse);return status};this.elemLoop=function(index,formElem){var log=[];if(formElem===null||typeof formElem==='undefined')return!1;formElem=formElem.reverse();for(var i in formElem){if(formElem[i]){var activeElem=formElem[i];this.applyFilters(activeElem);if(!0==this.onChange){this.applyGlobalListener(activeElem)} + if(!1===this.onlyFilter||typeof(this.onlyFilter)==='undefined'){log=new jsRuleSets().checkValidation(activeElem,log)}}} + return log};this.applyFilters=function(activeElem){if(activeElem.type=='number')new jsFilter().number(activeElem);if(activeElem.type=='email')new jsFilter().email(activeElem);if(''!==activeElem.min||''!==activeElem.max||activeElem.getAttribute('data-maxlength')||-1!==activeElem.maxLength)new jsFilter().limit(activeElem);if(activeElem.type=='file')new jsFilter().file(activeElem);if(activeElem.getAttribute('data-allow'))new jsFilter().string(activeElem);if(activeElem.getAttribute('pattern'))new jsFilter().pattern(activeElem)};this.applyGlobalListener=function(element){element.addEventListener('change',this.quickValidation,!1)};this.quickValidation=function(event){var log=[];var target=event.target;log=new jsRuleSets().checkValidation(target,log);new validationResponse().process(log)};this.validate=function(){return this.check()}} +function jsFilter(){this.checkStatus=function(elem){var status;status=!0;if(!1===new jsValidator().forceFilter){status=!1;if(!0===elem.required){status=!0}} + return status};this.number=function(element){var status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',this.isNumberKey,!1)};this.string=function(element){var type=element.getAttribute('data-allow');var current=this;var status=this.checkStatus(element);switch(type){case 'onlyAlpha':if(!0===status)element.addEventListener('keypress',current.isAlpha,!1);break;case 'string':if(!0===status)element.addEventListener('keypress',current.isAlphaNumeric,!1);break;default:if(!0===status)element.addEventListener('keypress',current.isPatternValid,!1);break}};this.pattern=function(element){var current=this;var status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',current.isPatternValid,!1)};this.email=function(element){var status=this.checkStatus(element);if(!0===status)element.addEventListener('keypress',jsRuleSets.email,!1)};this.file=function(element){var status=this.checkStatus(element);if(!0===status)element.addEventListener('change',jsRuleSets.file,!1)};this.limit=function(element){var status=this.checkStatus(element);if(!0===status)element.addEventListener('change',this.isInLimit,!1)};this.isInLimit=function(event){var value=event.target.value;if(!0===helper.isWindowAction(event))return!0;var target=event.target;var final_value=value;var min=event.target.min;var max=event.target.max;var max_length=event.target.getAttribute('data-maxlength')?event.target.getAttribute('data-maxlength'):0;max_length=parseInt(max_length);var num=value;if(0===max_length){if(!min)min=1;if(!max)max=100;var regex=new RegExp('^[0-9]+$');var key=String.fromCharCode(!event.charCode?event.which:event.charCode);if(!1===regex.test(key)||parseInt(value)>max||parseInt(value)max)final_value=max;if(parseInt(num)max_length)&&031&&(charCode<48||charCode>57)){event.preventDefault();return!1} + return!0}} +function jsSettings(){this.errorColor=!1;this.errorTemplate=!1;this.init=function(option){this.errorColor=option.errorColor;this.errorTemplate=option.errorTemplate;return this};this.log=function(){jsLogger.out(this.errorColor);jsLogger.out(this.errorTemplate)}} +function jsForm(){this.form=!1;this.formCore=!1;this.input=!1;this.select=!1;this.textArea=!1;this.label=!1;this.forceFilter=!1;this.init=function(option){jsLogger.out('Form',option.form);this.options=option;this.forceFilter=option.forceFilter;this.registerForm(option.form);this.parseForm(this.form);this.required();return this};this.registerForm=function(form){if(typeof form==='undefined')jsLogger.out('Form Identification','Form Identification is Missing !');if(null===form)return!1;this.form=document.getElementById(form);if(null===this.form)jsLogger.out('Status 503','Failed to Proceed !');this.formCore=form};this.parseForm=function(form){if(form===null)return!1;this.input=form.getElementsByTagName('input');this.select=form.getElementsByTagName('select');this.textArea=form.getElementsByTagName('textarea');this.label=form.getElementsByTagName('label')};this.required=function(){var forceFilter=this.forceFilter;var jsField_obj=new jsField();this.input=jsField_obj.required(this.input,forceFilter);this.select=jsField_obj.required(this.select,forceFilter);this.textArea=jsField_obj.required(this.textArea,forceFilter)};this.log=function(){jsLogger.out('Form',this.form);jsLogger.out('input',this.input);jsLogger.out('select',this.select);jsLogger.out('textarea',this.textArea);jsLogger.out('labels',this.label)}} +function jsField(){this.required=function(field,forceFilter){var requiredFieldsList=[];for(var i=0;imax&&value.length!=0)status=!1;return status};this.email=function(elem){if(!1===elem.required)return!0;var status=!1;var email=elem.value;if(typeof email==='undefined')return!1;email=email.toString();if(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)){status=!0} + if(!email)status=!1;return status};this.file=function(elem){var list_to_allow=elem.target.getAttribute('data-extensions');var target=elem.target;var list_to_allow_array;var file_response;if(''===list_to_allow)return!0;if(-1===list_to_allow.indexOf(',')){list_to_allow_array=[list_to_allow]}else{list_to_allow_array=list_to_allow.split(',')} + var fileName=target.value;fileName=fileName.toLowerCase();file_response=(new RegExp('('+list_to_allow_array.join('|').replace(/\./g,'\\.')+')$')).test(fileName);if(!1===file_response){alert('Allowed file types are "'+list_to_allow+'" !');elem.target.value='';return!1} + return!0};this.phone=function(elem,pattern){if(!1===elem.required)return!0;var status=!0;if(elem.value==='')status=!1;return status};this.compare=function(elem1){var status=!1;if(!1===elem1.required)status=!0;var elem2_id=elem1.getAttribute('data-check');if(typeof elem2_id=='undefined'||elem2_id==null)status=!1;if(elem2_id===null)elem2_id=elem1.getAttribute('data-parent');if(elem2_id===null){status=!1}else{elem2_id=elem2_id.toString();var elem2=document.getElementById(elem2_id);if(elem1.value===elem2.value)status=!0} + return status}} +function jsFormError(){this.errorHit=!1;this.errorCss=!1;this.successCss=!1;this.init=function(){this.errorHit=!1;this.errorCss='border-color: red;border-radius: 5px;color: red;';this.successCss='border-color: green;border-radius: 5px;color: green;'};this.log=function(){};this.style=function(css){this.errorCss=css.error;this.successCss=css.success}} +var jsLogger={status:function(){return __status_log},out:function(heading,message){if(!0!==this.status())return!1;console.log('======'+heading+'======');console.log(message);console.log('------------------------')},bulk:function(data){if(!0!==this.status())return!1;console.log(data)},table:function(data){if(!0!==this.status())return!1;console.table(data)}};var helper={isWindowAction:function(event){var theEvent=event||window.event;var key=theEvent.shiftKey||theEvent.which;if(key===9||key===0||key===8||key===32||key===13||key===8||(key>=35&&key<=40)){return!0} + key=String.fromCharCode(key);if(key.length===0)return!0;return!1},scrollToError:function(validateResponse){var dummy_id='__header_error_target_temp';var active_class=validateResponse.getClass();if(!1===active_class){jsLogger.out('Active Class Error','ACTIVE CLASS NOT DEFINED, GET :'+active_class);return!1} + if(0===document.getElementsByClassName(active_class).length)return!1;var active_id=document.getElementsByClassName(active_class)[0].id;document.getElementsByClassName(active_class)[0].setAttribute('id',dummy_id);var id=document.getElementsByClassName(active_class)[0].id;var elem_name=active_id.replace(__err_id_suffix_rand_hash,'');var top=document.getElementsByName(elem_name)[0].offsetTop;id='#'+id;window.scroll(0,parseInt(top)-15);document.getElementsByClassName(active_class)[0].setAttribute('id',active_id);this.removeHash(id)},scrollToItem:function(item){var hash=item;if(-1===hash.indexOf('#'))hash='#'+hash;window.location.href=hash;this.removeHash(hash)},removeHash:function(hash){var path=window.location.href;path=path.replace(hash,'');window.history.pushState('','Title',path)}};function pattern(){this.getDefault=function(event,originalPattern){if(typeof originalPattern=='undefined')originalPattern='';var allow_special=event.target.getAttribute('data-allowSpecial');var pattern=event.target.pattern;console.log(pattern.length);var defaultPattern;if(!allow_special&&allow_special===null)allow_special='';allow_special=allow_special.toString();if(pattern!==''&&pattern.length>0&&pattern!==null){defaultPattern=pattern}else{defaultPattern='^['+originalPattern+allow_special+']+$'} + return defaultPattern};this.validate=function(event,pattern){var defaultPattern=this.getDefault(event,pattern);var regex=new RegExp(defaultPattern);var key=String.fromCharCode(!event.charCode?event.which:event.charCode);return regex.test(key)}} +function validationResponse(){this.active_class=!1;this.init=function(errorList,option){this.errorMessage=option.message;this.active_class=option.errorClass;this.input(errorList.input);this.select(errorList.select);this.textArea(errorList.textArea)};this.input=function(elem){this.process(elem)};this.select=function(elem){this.process(elem)};this.getClass=function(){return this.active_class};this.textArea=function(elem){this.process(elem)};this.process=function(elem){var elementDefaultResponse='';var active_class=this.getClass();for(var i in elem){if(elem[i].el&&!0===elem[i].el.required){var activeElem=elem[i];var errorType=elem[i].type;elementDefaultResponse=this.template(activeElem,errorType);var spanTag=document.getElementById(activeElem.id);if(typeof spanTag==='undefined'||spanTag==='undefined'||spanTag===null){spanTag=document.createElement('span');spanTag.setAttribute('id',activeElem.id);spanTag.setAttribute('class',active_class);spanTag.innerHTML=elementDefaultResponse}else{spanTag.innerHTML=elementDefaultResponse} + activeElem.el.parentNode.insertBefore(spanTag,activeElem.el.nextSibling)}}};this.template=function(activeElem,errorType){var errorIndex='';var activeError='';var elementDefaultResponse=activeElem.el.getAttribute('data-message');if(typeof elementDefaultResponse==='undefined'||elementDefaultResponse===''||elementDefaultResponse===null){if(typeof this.errorMessage!=='undefined'&&typeof this.errorMessage[errorType]!=='undefined'){errorType=this.errorMessage[errorType];if(errorType){activeError=errorType;if(activeElem.type=='min'||activeElem.type=='max'){if('min'==activeElem.type)errorIndex=activeElem.el.min;if('max'==activeElem.type)errorIndex=activeElem.el.max;activeError=activeError.replace('[INDEX]',errorIndex)}}}else{activeError=this.default(errorType)} + elementDefaultResponse=activeError} + return elementDefaultResponse};this.default=function(errorType){var active_class=this.getClass();var errorMessages={required:'This field is required.',min:'This field length is too low.',max:'This field length is exceeds the limit.',password:'Password does not match.',email:'Email is not valid.',file:'This file is not allowed.'};if(typeof errorType!=='string')return!1;if(typeof errorMessages[errorType]==='undefined')return!1;return errorMessages[errorType]}} \ No newline at end of file diff --git a/src/js/multi_formValidator.es6.js b/src/js/multi_formValidator.es6.js deleted file mode 100644 index 4601cd7..0000000 --- a/src/js/multi_formValidator.es6.js +++ /dev/null @@ -1,1162 +0,0 @@ -/*! - * JavaScript Validator Library v1.0 - * To perform effective validation and filter with form elements. - * - * Author : Shankar Thiyagaraajan - * Email : shankarthiyagaraajan@gmail.com - * GitHub : https://github.com/shankarThiyagaraajan - * - * Source - * https://github.com/global-source/javascript_form_validator - * - * Site - * https://global-source.github.io/javascript_form_validator/ - * - * Copyright 2017 - * - * Released under the MIT license - * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE - * - * Date: 2017-07-21 - */ - -/* - * For Managing overall Validation flow. - */ -let firstErrorHit = false; -let __err_id_suffix_rand_hash = '_new1_1_1xv_resp'; - -/** - * Core Js Validator. - */ -class jsValidator { - constructor() { - // Holding form element data. - this.formData = false; - // Switch complete validation and input filter. - this.onlyFilter = false; - // JS form. - this.jsForm = false; - // JS setting. - this.jsSettings = false; - // JS form error. - this.jsFormError = false; - // Overall error list. - this.formErrorList = {}; - // To Filter non-required fields. - this.forceFilter = false; - // To Filter the First load. - this.initialLoad = true; - // Global options. - this.option = false; - // To apply global validator. - this.onChange = false; - this.validateResponse = false; - } - - /* - * Initiating the Validator. - */ - init(option) { - // To Update global options. - this.option = option; - jsLogger.table(option); - // Updating the filter flag to global. - this.onlyFilter = option.onlyFilter; - // To Enable/Disable global validator. - this.onChange = option.onChange; - // Update default response "class". - if ('undefined' === typeof option.errorClass) option.errorClass = 'js-error-cop'; - this.validateResponse = new validationResponse(); - // Update "jsSettings" to global object. - this.jsSettings = new jsSettings().init(option); - // Update "jsForm" to global object. - this.jsForm = new jsForm().init(option); - // Initiate form error setup. - this.jsFormError = new jsFormError().init(); - // Update Force Field status. - this.forceFilter = option.forceFilter; - // To check the form elements. - this.check(); - // To register the listener. - this.submitListener(this.jsForm.formCore, this); - // Send back "this". - return this; - }; - - /* - * To make listen on submit action of the form. - */ - submitListener(formID, obj) { - // To off submit listener, if only filter needed. - if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { - // Initiate listener for form submission. - document.querySelector('#' + formID).addEventListener('submit', function (e) { - // To start form validations. - // Check validation status. - if (false === obj.check()) { - //stop form from submitting, if validation fails - e.preventDefault(); - } - }); - } - }; - - /* - * To Refresh the DOM and enable Dynamic-Elements to Access. - */ - update() { - let option = this.option; - // Updating the filter flag to global. - this.onlyFilter = option.onlyFilter; - // Update "jsSettings" to global object. - this.jsSettings = new jsSettings().init(option); - // Update "jsForm" to global object. - this.jsForm = new jsForm().init(option); - // Initiate form error setup. - this.jsFormError = new jsFormError().init(); - }; - - /* - * To checking all elements from registered form. - */ - check() { - let status = false; - // Loading JS Form. - let jsFormObj = this.jsForm; - // Loading JS error list. - let errorList = this.formErrorList; - let option = []; - // Looping the "input" elements for validation and filter implementation. - errorList.input = this.elemLoop('input', jsFormObj.input); - // Looping the "textArea" elements fro validation filter implementation. - errorList.textArea = this.elemLoop('textArea', jsFormObj.textArea); - // Looping the "select" elements fro validation filter implementation. - errorList.select = this.elemLoop('select', jsFormObj.select); - jsLogger.out('Error List', this.formErrorList); - option.push({ - 'errorElem': errorList - }); - // To Update global Validation Status. - // If, Input elements have no errors. - if (errorList.input.length === 0) { - // If, Text Area elements have no errors. - if (errorList.textArea.length === 0) { - // If, Select elements have no errors. - if (errorList.select.length === 0) { - // If validation pass, then update "status" object. - status = true; - } - } - } - if (false == this.initialLoad) this.validateResponse.init(errorList, this.option); - this.initialLoad = false; - helper.scrollToError(this.validateResponse); - return status; - }; - - /* - * To looping all elements for actions. - */ - elemLoop(index, formElem) { - // Initiate empty array for keep list of errors. - let log = []; - // Sanity check with "formElem". - if (formElem === null || typeof formElem === 'undefined') return false; - formElem = formElem.reverse(); - // Looping elements. - for (let i in formElem) { - if (formElem[i]) { - // Switch to static letiable. - let activeElem = formElem[i]; - // Apply filter to element. - this.applyFilters(activeElem); - // Register the DOM with live onChange validations. - if (true == this.onChange) { - this.applyGlobalListener(activeElem); - } - //jsLogger.out('Only Filter', this.onlyFilter); - // If not only filter, then start validations. - if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { - // Initiate validations and update to log. - log = new jsRuleSets().checkValidation(activeElem, log); - } - } - } - // jsLogger.out('Log', log); - return log; - }; - - /* - * To apply filter to all relevant elements by it's attributes. - */ - applyFilters(activeElem) { - // Apply filter for Number elements. - if (activeElem.type == 'number') new jsFilter().number(activeElem); - // Apply filter for Email elements. - if (activeElem.type == 'email') new jsFilter().email(activeElem); - // Apply filter for Numeric elements. - if (activeElem.min || activeElem.max || activeElem.getAttribute('data-maxlength') || activeElem.minLength || activeElem.maxLength) new jsFilter().limit(activeElem); - // Apply filter File elements. - if (activeElem.type == 'file') new jsFilter().file(activeElem); - // Apply filter with string, alphaNumeric and pregMatch. - if (activeElem.getAttribute('data-allow')) new jsFilter().string(activeElem); - // Apply filter with pattern. - if (activeElem.getAttribute('pattern')) new jsFilter().pattern(activeElem); - }; - - /* - * To make it active to listen changes of those error fields. - */ - applyGlobalListener(element) { - element.addEventListener('change', this.quickValidation, false); - }; - - /* - * To perform quick validation to respond those fields. - */ - quickValidation(event) { - // jsLogger.out('Quick', event); - let log = []; - let target = event.target; - // To check the validation of an element. - log = new jsRuleSets().checkValidation(target, log); - // jsLogger.out('Quick Out', log); - new validationResponse().process(log); - }; - - /* - * Single step instance validator for Ajax form submissions. - */ - validate() { - // Initiate form Check. - return this.check(); - }; -} -/** - * Common Filter instances. - */ -class jsFilter { - checkStatus(elem) { - let status; - status = true; - if (false === new jsValidator().forceFilter) { - status = false; - if (true === elem.required) { - status = true; - } - } - return status; - }; - - // Number elements filter listener. - number(element) { - let status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', this.isNumberKey, false); - }; - - /* - * String elements filter listener. - */ - string(element) { - // Getting "data" attribute for actions. - let type = element.getAttribute('data-allow'); - let current = this; - let status = this.checkStatus(element); - - // Switching actions. - switch (type) { - // Allow only alphabets [a-zA-Z] not [0-9] and special characters. - case 'onlyAlpha': - if (true === status) element.addEventListener('keypress', current.isAlpha, false); - break; - // Allow only alpha Numeric [a-zA-Z0-9] not special characters. - case 'string': - if (true === status) element.addEventListener('keypress', current.isAlphaNumeric, false); - break; - // Allow based on the pattern given. - default: - if (true === status) element.addEventListener('keypress', current.isPatternValid, false); - break; - } - }; - - /* - * Pattern based filter and listener. - */ - pattern(element) { - let current = this; - let status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', current.isPatternValid, false); - }; - - /* - * Email elements filter listener. - */ - email(element) { - let status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', jsRuleSets.email, false); - }; - - file(element) { - let status = this.checkStatus(element); - if (true === status) element.addEventListener('change', jsRuleSets.file, false); - }; - - /* - * Numeric with Limited elements filter listener. - */ - limit(element) { - let current = this; - let status = this.checkStatus(element); - if (true === status) element.addEventListener('change', current.isInLimit, false); - }; - - /* - * Restrict element with it's limit. - */ - isInLimit(event) { - - // Load the element value. - let value = event.target.value; - - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - - // Getting target element. - let target = event.target; - - // Final value to load back. - let final_value = value; - - // Getting object from element. - let min = event.target.min; - let max = event.target.max; - - // Get max-length attribute from element. - let max_length = event.target.getAttribute('data-maxlength') ? event.target.getAttribute('data-maxlength') : 0; - max_length = parseInt(max_length); - let num = value; - - // if "max_length" is "0", then its don't have limit letiables. - if (0 === max_length) { - - // Default values for Min and Max. - if (!min) min = 1; - if (!max) max = 31; - - // Forming pattern for Restriction. - let regex = new RegExp('^[0-9]+$'); - - // Validation with Code. - let key = String.fromCharCode(!event.charCode ? event.which : event.charCode); - - // Return status of the Action. - if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { - event.preventDefault(); - } - - // Parse to INT. - num = parseInt(num, 10); - - // // converts value to a Number. - if (isNaN(num)) { - target.value = ""; - return; - } - - // Check value is greater than "max", then replace "max". - if (parseInt(num) > max) final_value = max; - - // Check value is greater than "min", then replace "min". - if (parseInt(num) < min) final_value = min; - - } else { - //TODO: Min length later. - // Validate the length of the string. - if ((num.length > max_length) && 0 < max_length) { - // If length is more, then cutoff the remaining letters. - final_value = num.substr(0, max_length); - } - } - - // Revert value back to an element. - this.value = final_value; - }; - - /* - * Only allow alpha([a-zA-Z]). - */ - isAlpha(event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - let status = new pattern().validate(event, 'a-zA-Z'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - - /* - * Only allow alpha([a-zA-Z0-9]). - */ - isAlphaNumeric(event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - let status = new pattern().validate(event, 'a-zA-Z0-9'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - - /* - * To check password is valid or not. - */ - isValidPassword(event) { - // Prevent using "space". - let charCode = (event.which) ? event.which : event.keyCode; - // If event is "space" then prevent to enter. - if (charCode === 32) { - event.preventDefault(); - return false; - } // To check is this action is from "windows" action or not. - - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - let status = new pattern().validate(event, 'a-zA-Z0-9'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - - /* - * Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). - */ - isPatternValid(event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - let status = new pattern().validate(event, 'a-zA-Z0-4'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - - /* - * Check is numeric or not. - */ - isNumberKey(event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Validation with Code. - let charCode = (event.which) ? event.which : event.keyCode; - if (charCode === 46 || charCode > 31 && (charCode < 48 || charCode > 57)) { - event.preventDefault(); - return false; - } // Return status of the Action. - - return true; - }; -} - -/** - * To Update overall JsValidator Settings. - */ -class jsSettings { - constructor() { - // Common error message color for form validation. - this.errorColor = false; - // Set common template for error message - this.errorTemplate = false; - } - - /* - * To Initiate the Configurations. - */ - init(option) { - // To update error message color to global object. - this.errorColor = option.errorColor; - // To update error template to handle error message. - this.errorTemplate = option.errorTemplate; - // Return "this" object. - return this; - }; - - /* - * General Log. - */ - log() { - jsLogger.out(this.errorColor); - jsLogger.out(this.errorTemplate); - }; -} -/** - * To Perform all Form based Operations. - */ -class jsForm { - constructor() { - // Form element. - this.form = false; - // Form ID. - this.formCore = false; - // Form element's inputs. - this.input = false; - // Form element's selects. - this.select = false; - // Form element's textAreas. - this.textArea = false; - // Form element's labels. - this.label = false; - // Perform Force Filter on Elements. - this.forceFilter = false; - } - - /* - * To Initiating the "jsForm". - */ - init(option) { - jsLogger.out('Form', option.form); - // Update Global Option. - this.options = option; - // Enable/Disable Force Filter. - this.forceFilter = option.forceFilter; - // To Register Form. - this.registerForm(option.form); - // To Parsing the Form. - this.parseForm(this.form); - // To Filter Required Elements. - this.required(); - return this; - }; - - /* - * To Register Active Form to Global Object. - */ - registerForm(form) { - // validate and Update Log. - if (typeof form === 'undefined') jsLogger.out('Form Identification', 'Form Identification is Missing !'); - // Form should not be an ID. - if (null === form) return false; - // Fetch Form element from Document. - this.form = document.getElementById(form); - if (null === this.form) jsLogger.out('Status 503', 'Failed to Proceed !'); - // Update Direct Form ID. - this.formCore = form; - }; - - /* - * To Parse all Relative Form components. - */ - parseForm(form) { - if (form === null) return false; - // "Input" elements like "text, date, time..." - this.input = form.getElementsByTagName('input'); - // "Select" element. - this.select = form.getElementsByTagName('select'); - // "TextArea" element. - this.textArea = form.getElementsByTagName('textarea'); - // "Label" element. - this.label = form.getElementsByTagName('label'); - }; - - /* - * To set fields are required. - */ - required() { - // let jsField = new jsField().init(this.options); - let forceFilter = this.forceFilter; - let jsField_obj = new jsField(); - // Filter all required "input" elements. - this.input = jsField_obj.required(this.input, forceFilter); - // Filter all required "select" elements. - this.select = jsField_obj.required(this.select, forceFilter); - // Filter all required "textArea" elements. - this.textArea = jsField_obj.required(this.textArea, forceFilter); - }; - - /* - * General Log. - */ - log() { - jsLogger.out('Form', this.form); - jsLogger.out('input', this.input); - jsLogger.out('select', this.select); - jsLogger.out('textarea', this.textArea); - jsLogger.out('labels', this.label); - }; -} -/** - * Perform Operations in Field level. - */ -class jsField { - /* - * Return all required elements list. - */ - required(field, forceFilter) { - let requiredFieldsList = []; - // Looping fields to filter. - for (let i = 0; i < field.length; i++) { - // Check and push elements. - if (field[i].required === true || true === forceFilter) { - // Pushing to required elements list. - requiredFieldsList.push(field[i]); - } - } // Return list of required elements. - - return requiredFieldsList; - }; -} -/** - * List of Validation Rules. - */ -class jsRuleSets { - /* - * To start validation process. - */ - checkValidation(activeElem, log) { - //jsLogger.out('Active Elem', activeElem); - let validElem = true; - let jsRuleSets_obj = new jsRuleSets(); - // To Generally checks, the field is empty or not. - if (!jsRuleSets_obj.isSet(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'required', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - } - - // To Check the Value is less than minimum or not. - if (activeElem.min) { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.min(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'min', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Check the Value is grater than max or not. - if (activeElem.max) { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.max(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'max', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Check the Entered E-mail is Valid or Not. - if (activeElem.type == 'email') { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.email(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'email', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Compare the Password is Same or Not with Re-Password. - // TODO: Implement Simplified Comparison. - if (activeElem.type == 'password') { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.compare(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'password', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } // If valid, then reset validation message. - - if (true === validElem) { - //jsLogger.out('Valid Elem', activeElem); - if (activeElem.name !== '') { - let elem = document.getElementById(activeElem.name + __err_id_suffix_rand_hash); - if (typeof (elem) !== 'undefined' && elem !== null) { - // Remove element to avoid un-necessary buffer. - elem.remove(); - } - } - } - // If error occurred, then locate that error - if (false !== firstErrorHit) { - //helper.scrollToItem(firstErrorHit); - } - // } - // Return overall log report of validation. - - return log; - }; - - /* - * To Check, whether the element have value or not. - */ - isSet(elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - let status = true; - let value = elem.value; - //TODO: Implement suitable solution for this. - if (value.length === 0 || value === '' || value === ' ' || value === '[]') status = false; - return status; - }; - - /* - * To Check Element with Min Condition. - */ - min(elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - let status = true; - let value = elem.value; - let min = elem.min; - //TODO: Implement suitable solution for this. - if (value.length < min && value.length != 0) status = false; - return status; - }; - - /* - * To Check Element with Max Condition. - */ - max(elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - let status = true; - let value = elem.value; - let max = elem.max; - //TODO: Implement suitable solution for this. - if (value.length > max && value.length != 0) status = false; - return status; - }; - - /* - * To Check Element Email is Valid or Not. - */ - email(elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - let status = false; - let email = elem.value; - if (typeof email === 'undefined') return false; - // To Validate Email. - // Convert to Native String Format. - email = email.toString(); - // To Check it as String or Not. - if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { - // Valid Email. - status = true; - } - if (!email) status = false; - return status; - }; - - file(elem) { - let list_to_allow = elem.target.getAttribute('data-extensions'); - let target = elem.target; - let list_to_allow_array; - let file_response; - if ('' === list_to_allow) return true; - // Slit into array of extensions. - if (-1 === list_to_allow.indexOf(',')) { - list_to_allow_array = [list_to_allow]; - } else { - list_to_allow_array = list_to_allow.split(','); - } - // Get file name. - let fileName = target.value; - // Convert to lower case for native validation. - fileName = fileName.toLowerCase(); - file_response = (new RegExp('(' + list_to_allow_array.join('|').replace(/\./g, '\\.') + ')$')).test(fileName); - if (false === file_response) { - alert('Allowed file types are "' + list_to_allow + '" !'); - // Reset file type. - elem.target.value = ''; - return false; - } - return true; - }; - - /* - * To Check Element Phone Value is Valid or Not. - */ - phone(elem, pattern) { - // If field is not required, then return "true". - if (false === elem.required) return true; - let status = true; - if (elem.value === '') status = false; - return status; - }; - - /* - * To Compare two Elements Values. - */ - compare(elem1) { - let status = false; - // If field is not required, then return "true". - if (false === elem1.required) status = true; - let elem2_id = elem1.getAttribute('data-check'); - if (typeof elem2_id == 'undefined' || elem2_id == null) status = false; - if (elem2_id === null) elem2_id = elem1.getAttribute('data-parent'); - if (elem2_id === null) { - status = false; - } else { - elem2_id = elem2_id.toString(); - let elem2 = document.getElementById(elem2_id); - if (elem1.value === elem2.value) status = true; - } - //jsLogger.out('Compare Status', status); - return status; - }; -} -/** - * To Manage JsValidator Errors. - */ -class jsFormError { - constructor() { - // Global constant to specify, error happened or not. - this.errorHit = false; - // Error Css. - this.errorCss = false; - // Success Css. - this.successCss = false; - } - - /* - * Initiate overall form error handler. - */ - init() { - this.errorHit = false; - this.errorCss = 'border-color: red;border-radius: 5px;color: red;'; - this.successCss = 'border-color: green;border-radius: 5px;color: green;'; - }; - - /* - * Form error log. - */ - log() { - // jsLogger.out('Form Error Hit', this.errorHit); - }; - - /* - * Form error style. - */ - style(css) { - this.errorCss = css.error; - this.successCss = css.success; - }; -} -/** - * For manage overall logging with validator. - */ -let jsLogger = { - status: function () { - // return jsValidator.option.log; - return '[]'; - }, - /* - * Simple log with "heading" and "message". - */ - out: function (heading, message) { - - if (true !== this.status()) return false; - console.log('======' + heading + '======'); - console.log(message); - console.log('------------------------'); - }, - /* - * For bulk data logging. - */ - bulk: function (data) { - if (true !== this.status()) return false; - console.log(data); - }, - /* - * For log data with table. - */ - table: function (data) { - if (true !== this.status()) return false; - console.table(data); - } -}; -/** - * General Helping methods.jsField_obj - */ -let helper = { - /* - * To check the keyboard action is window action or not. - */ - isWindowAction: function (event) { - // Getting the event to be triggered. - let theEvent = event || window.event; - // Getting the type of event or code. - let key = theEvent.shiftKey || theEvent.which; - // Check with list of code and ignore holding. - // Tab, Space, Home, End, Up, Down, Left, Right... - if (key === 9 || key === 0 || key === 8 || key === 32 || key === 13 || key === 8 || (key >= 35 && key <= 40)) { - return true; - } // If not in list then check return with corresponding data. - - key = String.fromCharCode(key); - // Return also if length is 0. - if (key.length === 0) return true; - // Finally return "false" for general keys. - return false; - }, - /* - * To Scroll Up / Down to notify the item that have validation message. - */ - scrollToError: function (validateResponse) { - let dummy_id = '__header_error_target_temp'; - let active_class = validateResponse.getClass(); - - if (false === active_class) { - jsLogger.out('Active Class Error', 'ACTIVE CLASS NOT DEFINED, GET :' + active_class); - return false; - } - - if (0 === document.getElementsByClassName(active_class).length) return false; - // Getting current ID of the element. - let active_id = document.getElementsByClassName(active_class)[0].id; - // Update first element with dummy index ID. - document.getElementsByClassName(active_class)[0].setAttribute('id', dummy_id); - // Forming ID. - let id = document.getElementsByClassName(active_class)[0].id; - // Retrieve the element name. - let elem_name = active_id.replace(__err_id_suffix_rand_hash, ''); - // Taking active element to navigate. - let top = document.getElementsByName(elem_name)[0].offsetTop; - // Format as ID. - id = '#' + id; - // Navigate to ID. - // window.location.href = id; - // Scroll to error element as close as possible. - window.scroll(0, parseInt(top) - 15); - // Restore with actual ID. - document.getElementsByClassName(active_class)[0].setAttribute('id', active_id); - // Remove the navigated value. - this.removeHash(id); - }, - /* - * To Scroll Up / Down to notify the item that have validation message. - */ - scrollToItem: function (item) { - // Form hash value. - let hash = item; - // If "#" is missing, then add back to the ID. - if (-1 === hash.indexOf('#')) hash = '#' + hash; - // Navigate with the hash value. - window.location.href = hash; - // Remove the navigated value. - this.removeHash(hash); - }, - /* - * To remove the hash value from the URL. - */ - removeHash: function (hash) { - // Getting the actual URL. - let path = window.location.href; - // Replacing the URL with specific hash value. - path = path.replace(hash, ''); - // Update to url history. - window.history.pushState('', 'Title', path); - } -}; -/** - * Simple library for Pattern. - */ -class pattern { - /* - * To generate pattern from element attribute. - */ - getDefault(event, originalPattern) { - if (typeof originalPattern == 'undefined') originalPattern = ''; - // Getting special characters list. - let allow_special = event.target.getAttribute('data-allowSpecial'); - let pattern = event.target.pattern; - console.log(pattern.length); - let defaultPattern; - // Set default values for special characters. - if (!allow_special && allow_special === null) allow_special = ''; - // Format to string. - allow_special = allow_special.toString(); - if (pattern !== '' && pattern.length > 0 && pattern !== null) { - defaultPattern = pattern; - } else { - defaultPattern = '^[' + originalPattern + allow_special + ']+$'; - } - return defaultPattern; - }; - - /* - * To validate event with the pattern. - */ - validate(event, pattern) { - // Managing the Pattern. - let defaultPattern = this.getDefault(event, pattern); - // Validate with special formed pattern. - let regex = new RegExp(defaultPattern); - // Validation with Code. - let key = String.fromCharCode(!event.charCode ? event.which : event.charCode); - return regex.test(key); - }; -} -/** - * To Manage all kind of error response. - */ -class validationResponse { - constructor() { - this.active_class = false; - } - - /* - * Initiating the Response handler. - */ - init(errorList, option) { - this.errorMessage = option.message; - // Updating the class. - this.active_class = option.errorClass; - // let errorElements = option.errorElem; - // jsLogger.out('Errors', errorList); - this.input(errorList.input); - this.select(errorList.select); - this.textArea(errorList.textArea); - - }; - - /* - * To handle the "input" element. - */ - input(elem) { - // Initiate process for Input. - this.process(elem); - }; - - /* - * To handle the "select" element. - */ - select(elem) { - // Initiate process for Select. - this.process(elem); - }; - - /* - * To return active class for validation response style. - */ - getClass() { - return this.active_class; - }; - - /* - * To handle the "textArea" element. - */ - textArea(elem) { - // Initiate process for TextArea. - this.process(elem); - }; - - /* - * To process all handlers. - */ - process(elem) { - // Process with initial response. - let elementDefaultResponse = ''; - // Get active class for error response element - let active_class = this.getClass(); - for (let i in elem) { - // jsLogger.out('Element', document.getElementById(elem[i].id)); - if (elem[i].el && true === elem[i].el.required) { - // Manage active element. - let activeElem = elem[i]; - let errorType = elem[i].type; - // Fetch from Element's direct message. - elementDefaultResponse = this.template(activeElem, errorType); - let spanTag = document.getElementById(activeElem.id); - // jsLogger.out('Element Hit', errorType); - // Create new response Message SPAN. - if (typeof spanTag === 'undefined' || spanTag === 'undefined' || spanTag === null) { - // jsLogger.out('Element Found', false); - spanTag = document.createElement('span'); - spanTag.setAttribute('id', activeElem.id); - spanTag.setAttribute('class', active_class); - spanTag.innerHTML = elementDefaultResponse; - } else { - // Re-use Existing response Message SPAN. - spanTag.innerHTML = elementDefaultResponse; - } - // Append HTML response to the Element. - activeElem.el.parentNode.insertBefore(spanTag, activeElem.el.nextSibling); - } - } - }; - - /* - * Perform template creation and update. - */ - template(activeElem, errorType) { - //jsLogger.out('error Type 0', errorType); - let errorIndex = ''; - let activeError = ''; - // Getting error response message from elemnet. - let elementDefaultResponse = activeElem.el.getAttribute('data-message'); - if (typeof elementDefaultResponse === 'undefined' || elementDefaultResponse === '' || elementDefaultResponse === null) { - // Sanity check with error message object. - if (typeof this.errorMessage !== 'undefined' && typeof this.errorMessage[errorType] !== 'undefined') { - // Getting error type. [ex. Required, Min, Max...] - errorType = this.errorMessage[errorType]; - - // activeElem.el.getAttribute('data-message'); - if (errorType) { - //jsLogger.out('errorType', errorType); - activeError = errorType; - // If error type is Min or Max, then it will proceed responsive. - if (activeElem.type == 'min' || activeElem.type == 'max') { - if ('min' == activeElem.type) errorIndex = activeElem.el.min; - if ('max' == activeElem.type) errorIndex = activeElem.el.max; - activeError = activeError.replace('[INDEX]', errorIndex); - } - } - } else { - activeError = this.default(errorType); - } - elementDefaultResponse = activeError; - } - return elementDefaultResponse; - }; - - /* - * Default error handling messages. - * If user not specify the messages, - * then it will be replaces. - */ - default(errorType) { - let active_class = this.getClass(); - let errorMessages = { - required: 'This field is required.', - min: 'This field length is too low.', - max: 'This field length is exceeds the limit.', - password: 'Password does not match.', - email: 'Email is not valid.', - file: 'This file is not allowed.' - }; - if (typeof errorType !== 'string') return false; - if (typeof errorMessages[errorType] === 'undefined') return false; - return errorMessages[errorType]; - }; -} \ No newline at end of file diff --git a/src/js/multi_formValidator.js b/src/js/multi_formValidator.js deleted file mode 100644 index 0cfa1d9..0000000 --- a/src/js/multi_formValidator.js +++ /dev/null @@ -1,1105 +0,0 @@ -/*! - * JavaScript Validator Library v1.0 - * To perform effective validation and filter with form elements. - * - * Author : Shankar Thiyagaraajan - * Email : shankarthiyagaraajan@gmail.com - * GitHub : https://github.com/shankarThiyagaraajan - * - * Source - * https://github.com/global-source/javascript_form_validator - * - * Site - * https://global-source.github.io/javascript_form_validator/ - * - * Copyright 2017 - * - * Released under the MIT license - * https://github.com/global-source/javascript_form_validator/blob/master/LICENSE - * - * Date: 2017-07-21 - */ - -/* - * For Managing overall Validation flow. - */ -var firstErrorHit = false; -var __err_id_suffix_rand_hash = '_new1_1_1xv_resp'; -/** - * Core Js Validator. - */ -function jsValidator() { - // Holding form element data. - this.formData = false; - // Switch complete validation and input filter. - this.onlyFilter = false; - // JS form. - this.jsForm = false; - // JS setting. - this.jsSettings = false; - // JS form error. - this.jsFormError = false; - // Overall error list. - this.formErrorList = {}; - // To Filter non-required fields. - this.forceFilter = false; - // To Filter the First load. - this.initialLoad = true; - // Global options. - this.option = false; - // To apply global validator. - this.onChange = false; - this.validateResponse = false; - /* - * Initiating the Validator. - */ - this.init = function (option) { - // To Update global options. - this.option = option; - jsLogger.table(option); - // Updating the filter flag to global. - this.onlyFilter = option.onlyFilter; - // To Enable/Disable global validator. - this.onChange = option.onChange; - // Update default response "class". - if ('undefined' === typeof option.errorClass) option.errorClass = 'js-error-cop'; - this.validateResponse = new validationResponse(); - // Update "jsSettings" to global object. - this.jsSettings = new jsSettings().init(option); - // Update "jsForm" to global object. - this.jsForm = new jsForm().init(option); - // Initiate form error setup. - this.jsFormError = new jsFormError().init(); - // Update Force Field status. - this.forceFilter = option.forceFilter; - // To check the form elements. - this.check(); - // To register the listener. - this.submitListener(this.jsForm.formCore, this); - // Send back "this". - return this; - }; - /* - * To make listen on submit action of the form. - */ - this.submitListener = function (formID, obj) { - // To off submit listener, if only filter needed. - if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { - // Initiate listener for form submission. - document.querySelector('#' + formID).addEventListener('submit', function (e) { - // To start form validations. - // Check validation status. - if (false === obj.check()) { - //stop form from submitting, if validation fails - e.preventDefault(); - } - }); - } - }; - /* - * To Refresh the DOM and enable Dynamic-Elements to Access. - */ - this.update = function () { - var option = this.option; - // Updating the filter flag to global. - this.onlyFilter = option.onlyFilter; - // Update "jsSettings" to global object. - this.jsSettings = new jsSettings().init(option); - // Update "jsForm" to global object. - this.jsForm = new jsForm().init(option); - // Initiate form error setup. - this.jsFormError = new jsFormError().init(); - }; - /* - * To checking all elements from registered form. - */ - this.check = function () { - var status = false; - // Loading JS Form. - var jsFormObj = this.jsForm; - // Loading JS error list. - var errorList = this.formErrorList; - var option = []; - // Looping the "input" elements for validation and filter implementation. - errorList.input = this.elemLoop('input', jsFormObj.input); - // Looping the "textArea" elements fro validation filter implementation. - errorList.textArea = this.elemLoop('textArea', jsFormObj.textArea); - // Looping the "select" elements fro validation filter implementation. - errorList.select = this.elemLoop('select', jsFormObj.select); - jsLogger.out('Error List', this.formErrorList); - option.push({ - 'errorElem': errorList - }); - // To Update global Validation Status. - // If, Input elements have no errors. - if (errorList.input.length === 0) { - // If, Text Area elements have no errors. - if (errorList.textArea.length === 0) { - // If, Select elements have no errors. - if (errorList.select.length === 0) { - // If validation pass, then update "status" object. - status = true; - } - } - } - if (false == this.initialLoad) this.validateResponse.init(errorList, this.option); - this.initialLoad = false; - helper.scrollToError(this.validateResponse); - return status; - }; - /* - * To looping all elements for actions. - */ - this.elemLoop = function (index, formElem) { - // Initiate empty array for keep list of errors. - var log = []; - // Sanity check with "formElem". - if (formElem === null || typeof formElem === 'undefined') return false; - formElem = formElem.reverse(); - // Looping elements. - for (var i in formElem) { - if (formElem[i]) { - // Switch to static variable. - var activeElem = formElem[i]; - // Apply filter to element. - this.applyFilters(activeElem); - // Register the DOM with live onChange validations. - if (true == this.onChange) { - this.applyGlobalListener(activeElem); - } - //jsLogger.out('Only Filter', this.onlyFilter); - // If not only filter, then start validations. - if (false === this.onlyFilter || typeof (this.onlyFilter) === 'undefined') { - // Initiate validations and update to log. - log = new jsRuleSets().checkValidation(activeElem, log); - } - } - } - // jsLogger.out('Log', log); - return log; - }; - /* - * To apply filter to all relevant elements by it's attributes. - */ - this.applyFilters = function (activeElem) { - // Apply filter for Number elements. - if (activeElem.type == 'number') new jsFilter().number(activeElem); - // Apply filter for Email elements. - if (activeElem.type == 'email') new jsFilter().email(activeElem); - // Apply filter for Numeric elements. - if (activeElem.min || activeElem.max || activeElem.getAttribute('data-maxlength') || activeElem.minLength || activeElem.maxLength) new jsFilter().limit(activeElem); - // Apply filter File elements. - if (activeElem.type == 'file') new jsFilter().file(activeElem); - // Apply filter with string, alphaNumeric and pregMatch. - if (activeElem.getAttribute('data-allow')) new jsFilter().string(activeElem); - // Apply filter with pattern. - if (activeElem.getAttribute('pattern')) new jsFilter().pattern(activeElem); - }; - /* - * To make it active to listen changes of those error fields. - */ - this.applyGlobalListener = function (element) { - element.addEventListener('change', this.quickValidation, false); - }; - /* - * To perform quick validation to respond those fields. - */ - this.quickValidation = function (event) { - // jsLogger.out('Quick', event); - var log = []; - var target = event.target; - // To check the validation of an element. - log = new jsRuleSets().checkValidation(target, log); - // jsLogger.out('Quick Out', log); - new validationResponse().process(log); - }; - /* - * Single step instance validator for Ajax form submissions. - */ - this.validate = function () { - // Initiate form Check. - return this.check(); - }; -} -/** - * Common Filter instances. - */ -function jsFilter() { - this.checkStatus = function (elem) { - var status; - status = true; - if (false === new jsValidator().forceFilter) { - status = false; - if (true === elem.required) { - status = true; - } - } - return status; - }; - // Number elements filter listener. - this.number = function (element) { - var status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', this.isNumberKey, false); - }; - /* - * String elements filter listener. - */ - this.string = function (element) { - // Getting "data" attribute for actions. - var type = element.getAttribute('data-allow'); - var current = this; - var status = this.checkStatus(element); - - // Switching actions. - switch (type) { - // Allow only alphabets [a-zA-Z] not [0-9] and special characters. - case 'onlyAlpha': - if (true === status) element.addEventListener('keypress', current.isAlpha, false); - break; - // Allow only alpha Numeric [a-zA-Z0-9] not special characters. - case 'string': - if (true === status) element.addEventListener('keypress', current.isAlphaNumeric, false); - break; - // Allow based on the pattern given. - default: - if (true === status) element.addEventListener('keypress', current.isPatternValid, false); - break; - } - }; - /* - * Pattern based filter and listener. - */ - this.pattern = function (element) { - var current = this; - var status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', current.isPatternValid, false); - }; - /* - * Email elements filter listener. - */ - this.email = function (element) { - var status = this.checkStatus(element); - if (true === status) element.addEventListener('keypress', jsRuleSets.email, false); - }; - this.file = function (element) { - var status = this.checkStatus(element); - if (true === status) element.addEventListener('change', jsRuleSets.file, false); - }; - /* - * Numeric with Limited elements filter listener. - */ - this.limit = function (element) { - var status = this.checkStatus(element); - if (true === status) element.addEventListener('change', this.isInLimit, false); - }; - /* - * Restrict element with it's limit. - */ - this.isInLimit = function (event) { - // Load the element value. - var value = event.target.value; - - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - - // Getting target element. - var target = event.target; - - // Final value to load back. - var final_value = value; - - // Getting object from element. - var min = event.target.min; - var max = event.target.max; - - // Get max-length attribute from element. - var max_length = event.target.getAttribute('data-maxlength') ? event.target.getAttribute('data-maxlength') : 0; - max_length = parseInt(max_length); - var num = value; - - // if "max_length" is "0", then its don't have limit variables. - if (0 === max_length) { - - // Default values for Min and Max. - if (!min) min = 1; - if (!max) max = 31; - - // Forming pattern for Restriction. - var regex = new RegExp('^[0-9]+$'); - - // Validation with Code. - var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); - - // Return status of the Action. - if (false === regex.test(key) || parseInt(value) > max || parseInt(value) < min) { - event.preventDefault(); - } - - // Parse to INT. - num = parseInt(num, 10); - - // // converts value to a Number. - if (isNaN(num)) { - target.value = ""; - return; - } - - // Check value is greater than "max", then replace "max". - if (parseInt(num) > max) final_value = max; - - // Check value is greater than "min", then replace "min". - if (parseInt(num) < min) final_value = min; - - } else { - //TODO: Min length later. - // Validate the length of the string. - if ((num.length > max_length) && 0 < max_length) { - // If length is more, then cutoff the remaining letters. - final_value = num.substr(0, max_length); - } - } - - // Revert value back to an element. - this.value = final_value; - }; - /* - * Only allow alpha([a-zA-Z]). - */ - this.isAlpha = function (event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - var status = new pattern().validate(event, 'a-zA-Z'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - /* - * Only allow alpha([a-zA-Z0-9]). - */ - this.isAlphaNumeric = function (event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - var status = new pattern().validate(event, 'a-zA-Z0-9'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - /* - * To check password is valid or not. - */ - this.isValidPassword = function (event) { - // Prevent using "space". - var charCode = (event.which) ? event.which : event.keyCode; - // If event is "space" then prevent to enter. - if (charCode === 32) { - event.preventDefault(); - return false; - } // To check is this action is from "windows" action or not. - - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - var status = new pattern().validate(event, 'a-zA-Z0-9'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - /* - * Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). - */ - this.isPatternValid = function (event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Managing the Pattern. - var status = new pattern().validate(event, 'a-zA-Z0-4'); - // Return status of the Action. - if (false === status) event.preventDefault(); - }; - /* - * Check is numeric or not. - */ - this.isNumberKey = function (event) { - // To check is this action is from "windows" action or not. - if (true === helper.isWindowAction(event)) return true; - // Validation with Code. - var charCode = (event.which) ? event.which : event.keyCode; - if (charCode === 46 || charCode > 31 && (charCode < 48 || charCode > 57)) { - event.preventDefault(); - return false; - } // Return status of the Action. - - return true; - }; -} - -/** - * To Update overall JsValidator Settings. - */ -function jsSettings() { - // Common error message color for form validation. - this.errorColor = false; - // Set common template for error message - this.errorTemplate = false; - /* - * To Initiate the Configurations. - */ - this.init = function (option) { - // To update error message color to global object. - this.errorColor = option.errorColor; - // To update error template to handle error message. - this.errorTemplate = option.errorTemplate; - // Return "this" object. - return this; - }; - /* - * General Log. - */ - this.log = function () { - jsLogger.out(this.errorColor); - jsLogger.out(this.errorTemplate); - }; -} -/** - * To Perform all Form based Operations. - */ -function jsForm() { - // Form element. - this.form = false; - // Form ID. - this.formCore = false; - // Form element's inputs. - this.input = false; - // Form element's selects. - this.select = false; - // Form element's textAreas. - this.textArea = false; - // Form element's labels. - this.label = false; - // Perform Force Filter on Elements. - this.forceFilter = false; - /* - * To Initiating the "jsForm". - */ - this.init = function (option) { - jsLogger.out('Form', option.form); - // Update Global Option. - this.options = option; - // Enable/Disable Force Filter. - this.forceFilter = option.forceFilter; - // To Register Form. - this.registerForm(option.form); - // To Parsing the Form. - this.parseForm(this.form); - // To Filter Required Elements. - this.required(); - return this; - }; - /* - * To Register Active Form to Global Object. - */ - this.registerForm = function (form) { - // validate and Update Log. - if (typeof form === 'undefined') jsLogger.out('Form Identification', 'Form Identification is Missing !'); - // Form should not be an ID. - if (null === form) return false; - // Fetch Form element from Document. - this.form = document.getElementById(form); - if (null === this.form) jsLogger.out('Status 503', 'Failed to Proceed !'); - // Update Direct Form ID. - this.formCore = form; - }; - /* - * To Parse all Relative Form components. - */ - this.parseForm = function (form) { - if (form === null) return false; - // "Input" elements like "text, date, time..." - this.input = form.getElementsByTagName('input'); - // "Select" element. - this.select = form.getElementsByTagName('select'); - // "TextArea" element. - this.textArea = form.getElementsByTagName('textarea'); - // "Label" element. - this.label = form.getElementsByTagName('label'); - }; - /* - * To set fields are required. - */ - this.required = function () { - // var jsField = new jsField().init(this.options); - var forceFilter = this.forceFilter; - var jsField_obj = new jsField(); - // Filter all required "input" elements. - this.input = jsField_obj.required(this.input, forceFilter); - // Filter all required "select" elements. - this.select = jsField_obj.required(this.select, forceFilter); - // Filter all required "textArea" elements. - this.textArea = jsField_obj.required(this.textArea, forceFilter); - }; - /* - * General Log. - */ - this.log = function () { - jsLogger.out('Form', this.form); - jsLogger.out('input', this.input); - jsLogger.out('select', this.select); - jsLogger.out('textarea', this.textArea); - jsLogger.out('labels', this.label); - }; -} -/** - * Perform Operations in Field level. - */ -function jsField() { - /* - * Return all required elements list. - */ - this.required = function (field, forceFilter) { - var requiredFieldsList = []; - // Looping fields to filter. - for (var i = 0; i < field.length; i++) { - // Check and push elements. - if (field[i].required === true || true === forceFilter) { - // Pushing to required elements list. - requiredFieldsList.push(field[i]); - } - } // Return list of required elements. - - return requiredFieldsList; - }; -} -/** - * List of Validation Rules. - */ -function jsRuleSets() { - /* - * To start validation process. - */ - this.checkValidation = function (activeElem, log) { - //jsLogger.out('Active Elem', activeElem); - var validElem = true; - var jsRuleSets_obj = new jsRuleSets(); - // To Generally checks, the field is empty or not. - if (!jsRuleSets_obj.isSet(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'required', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - } - - // To Check the Value is less than minimum or not. - if (activeElem.min) { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.min(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'min', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Check the Value is grater than max or not. - if (activeElem.max) { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.max(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'max', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Check the Entered E-mail is Valid or Not. - if (activeElem.type == 'email') { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.email(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'email', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } - - // To Compare the Password is Same or Not with Re-Password. - // TODO: Implement Simplified Comparison. - if (activeElem.type == 'password') { - if (jsRuleSets_obj.isSet(activeElem)) { - if (!jsRuleSets_obj.compare(activeElem)) { - log.push({ - 'el': activeElem, - 'type': 'password', - 'id': activeElem.name + __err_id_suffix_rand_hash - }); - firstErrorHit = activeElem.name + __err_id_suffix_rand_hash; - validElem = false; - } - } - } // If valid, then reset validation message. - - if (true === validElem) { - //jsLogger.out('Valid Elem', activeElem); - if (activeElem.name !== '') { - var elem = document.getElementById(activeElem.name + __err_id_suffix_rand_hash); - if (typeof (elem) !== 'undefined' && elem !== null) { - // Remove element to avoid un-necessary buffer. - elem.remove(); - } - } - } - // If error occurred, then locate that error - if (false !== firstErrorHit) { - //helper.scrollToItem(firstErrorHit); - } - // } - // Return overall log report of validation. - - return log; - }; - /* - * To Check, whether the element have value or not. - */ - this.isSet = function (elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - var status = true; - var value = elem.value; - //TODO: Implement suitable solution for this. - if (value.length === 0 || value === '' || value === ' ' || value === '[]') status = false; - return status; - }; - /* - * To Check Element with Min Condition. - */ - this.min = function (elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - var status = true; - var value = elem.value; - var min = elem.min; - //TODO: Implement suitable solution for this. - if (value.length < min && value.length != 0) status = false; - return status; - }; - /* - * To Check Element with Max Condition. - */ - this.max = function (elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - var status = true; - var value = elem.value; - var max = elem.max; - //TODO: Implement suitable solution for this. - if (value.length > max && value.length != 0) status = false; - return status; - }; - /* - * To Check Element Email is Valid or Not. - */ - this.email = function (elem) { - // If field is not required, then return "true". - if (false === elem.required) return true; - var status = false; - var email = elem.value; - if (typeof email === 'undefined') return false; - // To Validate Email. - // Convert to Native String Format. - email = email.toString(); - // To Check it as String or Not. - if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { - // Valid Email. - status = true; - } - if (!email) status = false; - return status; - }; - /* - * To Check Element's file is valid or not. - */ - this.file = function (elem) { - var list_to_allow = elem.target.getAttribute('data-extensions'); - var target = elem.target; - var list_to_allow_array; - var file_response; - if ('' === list_to_allow) return true; - // Slit into array of extensions. - if (-1 === list_to_allow.indexOf(',')) { - list_to_allow_array = [list_to_allow]; - } else { - list_to_allow_array = list_to_allow.split(','); - } - // Get file name. - var fileName = target.value; - // Convert to lower case for native validation. - fileName = fileName.toLowerCase(); - file_response = (new RegExp('(' + list_to_allow_array.join('|').replace(/\./g, '\\.') + ')$')).test(fileName); - if (false === file_response) { - alert('Allowed file types are "' + list_to_allow + '" !'); - // Reset file type. - elem.target.value = ''; - return false; - } - return true; - }; - /* - * To Check Element Phone Value is Valid or Not. - */ - this.phone = function (elem, pattern) { - // If field is not required, then return "true". - if (false === elem.required) return true; - var status = true; - if (elem.value === '') status = false; - return status; - }; - /* - * To Compare two Elements Values. - */ - this.compare = function (elem1) { - var status = false; - // If field is not required, then return "true". - if (false === elem1.required) status = true; - var elem2_id = elem1.getAttribute('data-check'); - if (typeof elem2_id == 'undefined' || elem2_id == null) status = false; - if (elem2_id === null) elem2_id = elem1.getAttribute('data-parent'); - if (elem2_id === null) { - status = false; - } else { - elem2_id = elem2_id.toString(); - var elem2 = document.getElementById(elem2_id); - if (elem1.value === elem2.value) status = true; - } - //jsLogger.out('Compare Status', status); - return status; - }; -} -/** - * To Manage JsValidator Errors. - */ -function jsFormError() { - // Global constant to specify, error happened or not. - this.errorHit = false; - // Error Css. - this.errorCss = false; - // Success Css. - this.successCss = false; - /* - * Initiate overall form error handler. - */ - this.init = function () { - this.errorHit = false; - this.errorCss = 'border-color: red;border-radius: 5px;color: red;'; - this.successCss = 'border-color: green;border-radius: 5px;color: green;'; - }; - /* - * Form error log. - */ - this.log = function () { - // jsLogger.out('Form Error Hit', this.errorHit); - }; - /* - * Form error style. - */ - this.style = function (css) { - this.errorCss = css.error; - this.successCss = css.success; - }; -} -/** - * For manage overall logging with validator. - */ -var jsLogger = { - status: function () { - // return jsValidator.option.log; - return '[]'; - }, - /* - * Simple log with "heading" and "message". - */ - out: function (heading, message) { - - if (true !== this.status()) return false; - console.log('======' + heading + '======'); - console.log(message); - console.log('------------------------'); - }, - /* - * For bulk data logging. - */ - bulk: function (data) { - if (true !== this.status()) return false; - console.log(data); - }, - /* - * For log data with table. - */ - table: function (data) { - if (true !== this.status()) return false; - console.table(data); - } -}; -/** - * General Helping methods.jsField_obj - */ -var helper = { - /* - * To check the keyboard action is window action or not. - */ - isWindowAction: function (event) { - // Getting the event to be triggered. - var theEvent = event || window.event; - // Getting the type of event or code. - var key = theEvent.shiftKey || theEvent.which; - // Check with list of code and ignore holding. - // Tab, Space, Home, End, Up, Down, Left, Right... - if (key === 9 || key === 0 || key === 8 || key === 32 || key === 13 || key === 8 || (key >= 35 && key <= 40)) { - return true; - } // If not in list then check return with corresponding data. - - key = String.fromCharCode(key); - // Return also if length is 0. - if (key.length === 0) return true; - // Finally return "false" for general keys. - return false; - }, - /* - * To Scroll Up / Down to notify the item that have validation message. - */ - scrollToError: function (validateResponse) { - var dummy_id = '__header_error_target_temp'; - var active_class = validateResponse.getClass(); - - if (false === active_class) { - jsLogger.out('Active Class Error', 'ACTIVE CLASS NOT DEFINED, GET :' + active_class); - return false; - } - - if (0 === document.getElementsByClassName(active_class).length) return false; - // Getting current ID of the element. - var active_id = document.getElementsByClassName(active_class)[0].id; - // Update first element with dummy index ID. - document.getElementsByClassName(active_class)[0].setAttribute('id', dummy_id); - // Forming ID. - var id = document.getElementsByClassName(active_class)[0].id; - // Retrieve the element name. - var elem_name = active_id.replace(__err_id_suffix_rand_hash, ''); - // Taking active element to navigate. - var top = document.getElementsByName(elem_name)[0].offsetTop; - // Format as ID. - id = '#' + id; - // Navigate to ID. - // window.location.href = id; - // Scroll to error element as close as possible. - window.scroll(0, parseInt(top) - 15); - // Restore with actual ID. - document.getElementsByClassName(active_class)[0].setAttribute('id', active_id); - // Remove the navigated value. - this.removeHash(id); - }, - /* - * To Scroll Up / Down to notify the item that have validation message. - */ - scrollToItem: function (item) { - // Form hash value. - var hash = item; - // If "#" is missing, then add back to the ID. - if (-1 === hash.indexOf('#')) hash = '#' + hash; - // Navigate with the hash value. - window.location.href = hash; - // Remove the navigated value. - this.removeHash(hash); - }, - /* - * To remove the hash value from the URL. - */ - removeHash: function (hash) { - // Getting the actual URL. - var path = window.location.href; - // Replacing the URL with specific hash value. - path = path.replace(hash, ''); - // Update to url history. - window.history.pushState('', 'Title', path); - } -}; -/** - * Simple library for Pattern. - */ -function pattern() { - /* - * To generate pattern from element attribute. - */ - this.getDefault = function (event, originalPattern) { - if (typeof originalPattern == 'undefined') originalPattern = ''; - // Getting special characters list. - var allow_special = event.target.getAttribute('data-allowSpecial'); - var pattern = event.target.pattern; - console.log(pattern.length); - var defaultPattern; - // Set default values for special characters. - if (!allow_special && allow_special === null) allow_special = ''; - // Format to string. - allow_special = allow_special.toString(); - if (pattern !== '' && pattern.length > 0 && pattern !== null) { - defaultPattern = pattern; - } else { - defaultPattern = '^[' + originalPattern + allow_special + ']+$'; - } - return defaultPattern; - }; - /* - * To validate event with the pattern. - */ - this.validate = function (event, pattern) { - // Managing the Pattern. - var defaultPattern = this.getDefault(event, pattern); - // Validate with special formed pattern. - var regex = new RegExp(defaultPattern); - // Validation with Code. - var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); - return regex.test(key); - }; -} -/** - * To Manage all kind of error response. - */ -function validationResponse() { - this.active_class = false; - /* - * Initiating the Response handler. - */ - this.init = function (errorList, option) { - this.errorMessage = option.message; - // Updating the class. - this.active_class = option.errorClass; - // var errorElements = option.errorElem; - // jsLogger.out('Errors', errorList); - this.input(errorList.input); - this.select(errorList.select); - this.textArea(errorList.textArea); - - }; - /* - * To handle the "input" element. - */ - this.input = function (elem) { - // Initiate process for Input. - this.process(elem); - }; - /* - * To handle the "select" element. - */ - this.select = function (elem) { - // Initiate process for Select. - this.process(elem); - }; - /* - * To return active class for validation response style. - */ - this.getClass = function () { - return this.active_class; - }; - /* - * To handle the "textArea" element. - */ - this.textArea = function (elem) { - // Initiate process for TextArea. - this.process(elem); - }; - /* - * To process all handlers. - */ - this.process = function (elem) { - // Process with initial response. - var elementDefaultResponse = ''; - // Get active class for error response element - var active_class = this.getClass(); - for (var i in elem) { - // jsLogger.out('Element', document.getElementById(elem[i].id)); - if (elem[i].el && true === elem[i].el.required) { - // Manage active element. - var activeElem = elem[i]; - var errorType = elem[i].type; - // Fetch from Element's direct message. - elementDefaultResponse = this.template(activeElem, errorType); - var spanTag = document.getElementById(activeElem.id); - // jsLogger.out('Element Hit', errorType); - // Create new response Message SPAN. - if (typeof spanTag === 'undefined' || spanTag === 'undefined' || spanTag === null) { - // jsLogger.out('Element Found', false); - spanTag = document.createElement('span'); - spanTag.setAttribute('id', activeElem.id); - spanTag.setAttribute('class', active_class); - spanTag.innerHTML = elementDefaultResponse; - } else { - // Re-use Existing response Message SPAN. - spanTag.innerHTML = elementDefaultResponse; - } - // Append HTML response to the Element. - activeElem.el.parentNode.insertBefore(spanTag, activeElem.el.nextSibling); - } - } - }; - /* - * Perform template creation and update. - */ - this.template = function (activeElem, errorType) { - //jsLogger.out('error Type 0', errorType); - var errorIndex = ''; - var activeError = ''; - // Getting error response message from elemnet. - var elementDefaultResponse = activeElem.el.getAttribute('data-message'); - if (typeof elementDefaultResponse === 'undefined' || elementDefaultResponse === '' || elementDefaultResponse === null) { - // Sanity check with error message object. - if (typeof this.errorMessage !== 'undefined' && typeof this.errorMessage[errorType] !== 'undefined') { - // Getting error type. [ex. Required, Min, Max...] - errorType = this.errorMessage[errorType]; - - // activeElem.el.getAttribute('data-message'); - if (errorType) { - //jsLogger.out('errorType', errorType); - activeError = errorType; - // If error type is Min or Max, then it will proceed responsive. - if (activeElem.type == 'min' || activeElem.type == 'max') { - if ('min' == activeElem.type) errorIndex = activeElem.el.min; - if ('max' == activeElem.type) errorIndex = activeElem.el.max; - activeError = activeError.replace('[INDEX]', errorIndex); - } - } - } else { - activeError = this.default(errorType); - } - elementDefaultResponse = activeError; - } - return elementDefaultResponse; - }; - /* - * Default error handling messages. - * If user not specify the messages, - * then it will be replaces. - */ - this.default = function (errorType) { - var active_class = this.getClass(); - var errorMessages = { - required: 'This field is required.', - min: 'This field length is too low.', - max: 'This field length is exceeds the limit.', - password: 'Password does not match.', - email: 'Email is not valid.', - file: 'This file is not allowed.' - }; - if (typeof errorType !== 'string') return false; - if (typeof errorMessages[errorType] === 'undefined') return false; - return errorMessages[errorType]; - }; -} \ No newline at end of file