diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62e7820 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Created by .ignore support plugin (hsz.mobi) +.idea \ No newline at end of file diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..f250442 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +JavascriptFormValidator \ No newline at end of file diff --git a/.idea/JavascriptFormValidator.iml b/.idea/JavascriptFormValidator.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/JavascriptFormValidator.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..b8387eb --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..eabe228 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..c82afdc --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml new file mode 100644 index 0000000..9338ba6 --- /dev/null +++ b/.idea/watcherTasks.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/demo/index.html b/src/demo/index.html new file mode 100644 index 0000000..9f1e4e7 --- /dev/null +++ b/src/demo/index.html @@ -0,0 +1,76 @@ + + + + + + + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/src/js/formValidator.js b/src/js/formValidator.js index 5b3fd32..f5674c9 100644 --- a/src/js/formValidator.js +++ b/src/js/formValidator.js @@ -1,5 +1,4 @@ //---------------------Form New Ticket--------------------------- - var warning_font_color = '#761c19'; var warning_class = ''; var form = { @@ -21,9 +20,9 @@ var form = { elements[0].parentNode.removeChild(elements[0]); } // **********************************VALIDATE AND POPULATE****************************************** - + // ----------------------------------GENERAL VALIDATION [Input]------------------------------------- - + // Start Searching Elements for Validation. for (var i = 0; i < st_form_inputs.length; i++) { if (st_form_inputs[i].required == true) { @@ -288,14 +287,4 @@ function validate(data) { // Trigger the Validation process. function initValidation(activeForm) { return form.validate(activeForm); -} - - -var data = { - form: 'new_ticket_form', - warning_color: 'aa0000', - new_class: 'test' }; - -// Default Form Init. -validate(data); diff --git a/src/js/formValidator.min.js b/src/js/formValidator.min.js new file mode 100644 index 0000000..3f69861 --- /dev/null +++ b/src/js/formValidator.min.js @@ -0,0 +1 @@ +var jsValidator={formData:!1,onlyFilter:!1,jsForm:!1,jsSettings:!1,jsFormError:!1,formErrorList:{},validationPass:!1,init:function(e){return jsLogger.table(e),this.onlyFilter=e.onlyFilter,this.jsSettings=jsSettings.init(e),this.jsForm=jsForm.init(e),this.jsFormError=jsFormError.init(),this.check(),this.submitListener(this.jsForm.formCore,this),this},submitListener:function(e,t){!1===this.onlyFilter&&document.querySelector("#"+e).addEventListener("submit",function(e){t.check(),!1===t.validationPass&&e.preventDefault()})},check:function(){var e=this.jsForm,t=this.formErrorList;t.input=this.elemLoop("input",e.input),t.textArea=this.elemLoop("textArea",e.textArea),t.select=this.elemLoop("select",e.select),jsLogger.out("Error List",this.formErrorList),0===t.input.length&&0===t.textArea.length&&0===t.select.length&&(alert("Form Valid !"),this.validationPass=!0)},elemLoop:function(e,t){var r=[];for(var i in t){var s=t[i];r=this.checkValidation(s,r),this.applyFilters(s)}return r},applyFilters:function(e){"number"==e.type&&jsFilter.number(e),"email"==e.type&&jsFilter.email(e),(e.min||e.max)&&jsFilter.limit(e),e.getAttribute("data-allow")&&jsFilter.string(e)},checkValidation:function(e,t){return jsRuleSets.isSet(e)||t.push({empty:e}),e.min&&(jsRuleSets.min(e)||t.push({min:e})),e.max&&(jsRuleSets.max(e)||t.push({max:e})),"email"==e.type&&(jsRuleSets.email(e)||t.push({email:e})),"password"==e.type&&(jsRuleSets.compare(e)||t.push({password:e})),t}},jsFilter={number:function(e){e.addEventListener("keypress",this.isNumberKey,!1)},string:function(e){var t=e.getAttribute("data-allow");switch(t){case"onlyAlpha":e.addEventListener("keypress",this.isAlpha,!0);break;case"string":e.addEventListener("keypress",this.isAlphaNumeric,!0);break;default:e.addEventListener("keypress",this.isPatternValid,!0)}},email:function(e){e.addEventListener("keypress",jsRuleSets.email,!1)},limit:function(e){e.addEventListener("keypress",this.isInLimit,!1)},alphaNumericWith:function(){},isInLimit:function(e){var t=e.target.min,r=e.target.max;t||(t=0),r||(r=9);var i=new RegExp("^["+t+"-"+r+" ]+$"),s=String.fromCharCode(e.charCode?e.charCode:e.which);jsLogger.out("Alpha",i.test(s)),!1===i.test(s)&&e.preventDefault()},isAlpha:function(e){var t=e.target.getAttribute("data-allowSpecial");t||null!=t||(t=""),t=t.toString();var r=new RegExp("^[a-zA-Z"+t+"]+$"),i=String.fromCharCode(e.charCode?e.charCode:e.which);jsLogger.out("Alpha",r.test(i)),!1===r.test(i)&&e.preventDefault()},isAlphaNumeric:function(e){var t=e.target.getAttribute("data-allowSpecial");t||null!=t||(t=""),t=t.toString();var r=new RegExp("^[a-zA-Z0-9"+t+"]+$"),i=String.fromCharCode(e.charCode?e.charCode:e.which);jsLogger.out("Alpha",r.test(i)),!1===r.test(i)&&e.preventDefault()},isPatternValid:function(e){var t=e.target.getAttribute("data-allow"),r=new RegExp(t),i=String.fromCharCode(e.charCode?e.charCode:e.which);jsLogger.out("Alpha",r.test(i)),!1===r.test(i)&&e.preventDefault()},isNumberKey:function(e){var t=e.which?e.which:e.keyCode;return 46===t||t>31&&(48>t||t>57)?(e.preventDefault(),!1):!0}},jsSettings={errorColor:!1,followedElement:!1,errorTemplate:!1,phonePattern:!1,init:function(e){return this.errorColor=e.errorColor,this.followedElement=e.followedElement,this.errorTemplate=e.errorTemplate,this},log:function(){jsLogger.out(this.errorColor),jsLogger.out(this.followedElement),jsLogger.out(this.errorTemplate)}},jsForm={form:!1,formCore:!1,input:!1,select:!1,textArea:!1,label:!1,init:function(e){return jsLogger.out("Form",e.form),this.registerForm(e.form),this.parseForm(this.form),this.required(),this},registerForm:function(e){"undefined"==typeof e&&jsLogger.out("Form Identification","Form Identification is Missing !"),this.form=document.getElementById(e),this.formCore=e},parseForm:function(e){this.input=e.getElementsByTagName("input"),this.select=e.getElementsByTagName("select"),this.textArea=e.getElementsByTagName("textarea"),this.label=e.getElementsByTagName("label")},required:function(){this.input=jsField.required(this.input),this.select=jsField.required(this.select),this.textArea=jsField.required(this.textArea)},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){for(var t=[],r=0;re.max&&(t=!1),t},email:function(e){var t=!0,r=e.value;return r=r.toString(),r||(t=!1),/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(r)&&(t=!0),t},phone:function(e,t){var r=!0;return""===e.value&&(r=!1),r},compare:function(e,t){var r=!0;return e.value!==t.value&&e.length!==t.length&&(r=!1),r}},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(){jsLogger.out("Form Error Hit",this.errorHit)},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)}}; \ No newline at end of file diff --git a/src/js/validatorNew.es6.js b/src/js/validatorNew.es6.js new file mode 100644 index 0000000..1fdd2ce --- /dev/null +++ b/src/js/validatorNew.es6.js @@ -0,0 +1,604 @@ +/*! + * JavaScript Validator Library v0.9 + * 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-05-01 + */ + +/* + * For Managing overall Validation flow. + */ + +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 = {}; + // Overall validation status. + this.validationPass = false; + // Common Logger Instance. + this.jsFilter = false; + this.jsRuleSet = false; + } + + // Initiating the Validator. + init(option) { + var status; + + this.jsFilter = new jsFilter(); + this.jsRuleSet = new jsRuleSets(); + + jsLogger.table(option); + + // Updating the filter flag to global. + const 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 check the form elements. + status = 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) { + // Initiate listener for form submission. + document.querySelector("#" + formID).addEventListener("submit", function (e) { + + // To start form validations and authorize. + if (false === obj.check()) { + //stop form from submitting, if validation fails + e.preventDefault(); + } + }); + } + }; + + // To checking all elements from registered form. + check() { + // Loading JS Form. + var jsFormObj = this.jsForm; + // Loading JS error list. + var errorList = this.formErrorList; + // Overall validation status. + var status = false; + + // 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); + + // 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) { + alert('Form Valid !'); + // If validation pass, then update "validationPass" object. + status = true; + } + } + } + return status; + }; + + // To looping all elements for actions. + elemLoop(index, formElem) { + // Initiate empty array for keep list of errors. + var log = []; + // Looping elements. + for (var i in formElem) { + // Switch to static variable. + var activeElem = formElem[i]; + // Apply filter to element. + this.applyFilters(activeElem); + // If not only filter, then start validations. + if (false === this.onlyFilter) { + // Initiate validations and update to log. + log = this.constructor.checkValidation(activeElem, log); + } + } + return log; + }; + + // To apply filter to all relevant elements by it's attributes. + applyFilters(activeElem) { + //console.log(this.jsFilter); + //var jsFilter = new jsFilter(); + // Apply filter for Number elements. + if (activeElem.type == 'number') this.jsFilter.number(activeElem); + // Apply filter for Email elements. + if (activeElem.type == 'email') this.jsFilter.constructor.email(activeElem); + // Apply filter for Numeric elements. + if (activeElem.min || activeElem.max) this.jsFilter.limit(activeElem); + // Apply filter with string, alphaNumeric and pregMatch. + if (activeElem.getAttribute('data-allow')) this.jsFilter.string(activeElem); + }; + + // To start validation process. + static checkValidation(activeElem, log) { + var jsRuleSet = new jsRuleSets(); + // To Generally checks, the field is empty or not. + if (!jsRuleSets.isSet(activeElem))log.push({'empty': activeElem}); + // To Check the Value is less than min or not. + if (activeElem.min) if (!jsRuleSet.constructor.min(activeElem)) log.push({'min': activeElem}); + // To Check the Value is grater than max or not. + if (activeElem.max) if (!jsRuleSet.constructor.max(activeElem)) log.push({'max': activeElem}); + // To Check the Entered E-mail is Valid or Not. + if (activeElem.type == "email") if (!jsRuleSet.constructor.email(activeElem)) log.push({'email': activeElem}); + // To Compare the Password is Same or Not with Re-Password. + // TODO: Implement Simplified Comparison. + if (activeElem.type == "password")if (!jsRuleSet.constructor.compare(activeElem)) log.push({'password': activeElem}); + // Return overall log report of validation. + return log; + }; + + // Single step instance validator for Ajax form submissions. + validate() { + // Initiate form Check. + this.check(); + // Return validation status. + return this.validationPass; + } + + //}; +} + +/* + * Common Filter instances. + */ +class jsFilter { + constructor() { + + } + + // Number elements filter listener. + number(element) { + var current = this; + element.addEventListener("keypress", current.constructor.isNumberKey, false); + }; + + // String elements filter listener. + string(element) { + // Getting "data" attribute for actions. + var type = element.getAttribute('data-allow'); + var current = this; + + // Switching actions. + switch (type) { + // Allow only alphabets [a-zA-Z] not [0-9] and special characters. + case 'onlyAlpha': + element.addEventListener("keypress", current.constructor.isAlpha, false); + break; + // Allow only alpha Numeric [a-zA-Z0-9] not special characters. + case 'string': + element.addEventListener("keypress", current.constructor.isAlphaNumeric, false); + break; + // Allow based on the pattern given. + default: + element.addEventListener("keypress", current.constructor.isPatternValid, false); + break; + } + + + }; + + // Email elements filter listener. + static email(element) { + //this.jsRuleSet = new jsRuleSets(); + //element.addEventListener("keypress", this.jsRuleSet.constructor.email, false); + }; + + // Numeric with Limited elements filter listener. + limit(element) { + element.addEventListener("keypress", this.constructor.isInLimit, false); + }; + + //TODO: fix live entry issue. + // Restrict element with it's limit. + static isInLimit(event) { + var value = event.target.value; + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + + // Getting object from element. + var min = event.target.min; + var max = event.target.max; + + // Default values for Min and Max. + if (!min) min = 0; + if (!max) max = 54; + + // 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(); + } + event.target.value = event.target.value.substring(0, event.target.value.length - 1); + }; + + // Only allow alpha([a-zA-Z]). + static isAlpha(event) { + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + // Getting special characters list. + var allow_special = event.target.getAttribute('data-allowSpecial'); + // Set default values for special characters. + if (!allow_special && allow_special == null) allow_special = ''; + // Format to string. + allow_special = allow_special.toString(); + // Validate with special formed pattern. + var regex = new RegExp('^[a-zA-Z' + allow_special + ']+$'); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }; + + // Only allow alpha([a-zA-Z0-9]). + static isAlphaNumeric(event) { + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + // Getting special characters list. + var allow_special = event.target.getAttribute('data-allowSpecial'); + // Set default values for special characters. + if (!allow_special && allow_special == null) allow_special = ''; + // Format to string. + allow_special = allow_special.toString(); + // Validate with special formed pattern. + var regex = new RegExp('^[a-zA-Z0-9' + allow_special + ']+$'); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }; + + // Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). + static isPatternValid(event) { + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + // Getting special characters list. + var pattern = event.target.getAttribute('data-allow'); + // Validate with special formed pattern. + var regex = new RegExp(pattern); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }; + + // Check is numeric or not. + static isNumberKey(event) { + // To check is this action is from "windows" action or not. + if (true === 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. + */ +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; + }; + + log() { + jsLogger.out(this.errorColor); + jsLogger.out(this.followedElement); + 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; + } + + // To Initiating the "jsForm". + init(option) { + jsLogger.out('Form', option.form); + // 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 !'); + + // Fetch Form element from Document. + this.form = document.getElementById(form); + // Update Direct Form ID. + this.formCore = form; + }; + + // To Parse all Relative Form components. + parseForm(form) { + // "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() { + // Filter all required "input" elements. + this.input = jsField.required(this.input); + // Filter all required "select" elements. + this.select = jsField.required(this.select); + // Filter all required "textArea" elements. + this.textArea = jsField.required(this.textArea); + }; + + 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 { + constructor() { + + } + + // Return all required elements list. + static required(field) { + var requiredFieldsList = []; + for (var i = 0; i < field.length; i++) { + // Check and push elements. + if (field[i].required === true) { + // Pushing to required elements list. + requiredFieldsList.push(field[i]); + } + } + // Return list of required elements. + return requiredFieldsList; + } +} + +/** + * List of Validation Rules. + */ +class jsRuleSets { + constructor() { + + } + + // To Check, whether the element have value or not. + static isSet(elem) { + var status = true; + // Check length and empty or not. + if (elem.length === 0 || elem.value === '') status = false; + return status; + }; + + // To Check Element with Min Condition. + static min(elem) { + var status = true; + //TODO: Implement suitable solution for this. + //if (elem.length < elem.min && elem.length !== 0) status = false; + return status; + }; + + // To Check Element with Max Condition. + static max(elem) { + var status = true; + if (elem.value > elem.max) status = false; + return status; + }; + + // To Check Element Email is Valid or Not. + static email(elem) { + var status = true; + var email = elem.value; + // To Validate Email. + // Convert to Native String Format. + email = email.toString(); + // To Check it as String or Not. + if (!email) status = false; + if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { + // Valid Email. + status = true; + } + return status; + }; + + // To Check Element Phone Value is Valid or Not. + static phone(elem, pattern) { + var status = true; + if (elem.value === '') status = false; + return status; + }; + + // To Compare two Elements Values. + static compare(elem1) { + var elem2_id = elem1.getAttribute('data-check'); + + if (elem2_id == null) elem2_id = elem1.getAttribute('data-parent'); + + elem2_id = elem2_id.toString(); + var elem2 = document.getElementById(elem2_id); + var status = true; + if ((elem1.value !== elem2.value) && elem1.length !== elem2.length) status = false; + 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. + * + */ +var jsLogger = { + + // Simple log with "heading" and "message". + out: function (heading, message) { + console.log('======' + heading + '======'); + console.log(message); + console.log('------------------------'); + }, + + // For bulk data logging. + bulk: function (data) { + console.log(data); + }, + + // For log data with table. + table: function (data) { + console.table(data); + } +}; + +/* + * To check the keyboard action is window action or not. + */ +function isWindowAction(event) { + // Getting the event to be triggered. + var theEvent = event || window.event; + // Getting the type of event or code. + var key = theEvent.keyCode || theEvent.which; + + // Check with list of code and ignore holding. + // Tab, Space, Home, End, Up, Down, Left, Right... + if (key === 9 || key === 32 || key === 13 || key === 8 || (key >= 35 && key <= 40)) { //TAB was pressed + 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; +} \ No newline at end of file diff --git a/src/js/validatorNew.js b/src/js/validatorNew.js new file mode 100644 index 0000000..8b31a37 --- /dev/null +++ b/src/js/validatorNew.js @@ -0,0 +1,534 @@ +/*! + * JavaScript Validator Library v0.9 + * 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-05-01 + */ + +/* + * For Managing overall Validation flow. + */ +var jsValidator = { + // Holding form element data. + formData: false, + // Switch complete validation and input filter. + onlyFilter: false, + // JS form. + jsForm: false, + // JS setting. + jsSettings: false, + // JS form error. + jsFormError: false, + // Overall error list. + formErrorList: {}, + // Overall validation status. + validationPass: false, + // Initiating the Validator. + init: function (option) { + jsLogger.table(option); + + // Updating the filter flag to global. + this.onlyFilter = option.onlyFilter; + // Update "jsSettings" to global object. + this.jsSettings = jsSettings.init(option); + // Update "jsForm" to global object. + this.jsForm = jsForm.init(option); + // Initiate form error setup. + this.jsFormError = jsFormError.init(); + // 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: function (formID, obj) { + // To off submit listener, if only filter needed. + if (false === this.onlyFilter) { + // Initiate listener for form submission. + document.querySelector("#" + formID).addEventListener("submit", function (e) { + // To start form validations. + obj.check(); + // Check validation status. + if (false === obj.validationPass) { + //stop form from submitting, if validation fails + e.preventDefault(); + } + }); + } + }, + // To checking all elements from registered form. + check: function () { + // Loading JS Form. + var jsFormObj = this.jsForm; + // Loading JS error list. + var errorList = this.formErrorList; + + // 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); + + // 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) { + alert('Form Valid !'); + // If validation pass, then update "validationPass" object. + this.validationPass = true; + } + } + } + + }, + // To looping all elements for actions. + elemLoop: function (index, formElem) { + // Initiate empty array for keep list of errors. + var log = []; + // Looping elements. + for (var i in formElem) { + // Switch to static variable. + var activeElem = formElem[i]; + // Apply filter to element. + this.applyFilters(activeElem); + // If not only filter, then start validations. + if (false === this.onlyFilter) { + // Initiate validations and update to log. + log = this.checkValidation(activeElem, log); + + } + } + return log; + }, + // To apply filter to all relevant elements by it's attributes. + applyFilters: function (activeElem) { + // Apply filter for Number elements. + if (activeElem.type == 'number') jsFilter.number(activeElem); + // Apply filter for Email elements. + if (activeElem.type == 'email') jsFilter.email(activeElem); + // Apply filter for Numeric elements. + if (activeElem.min || activeElem.max) jsFilter.limit(activeElem); + // Apply filter with string, alphaNumeric and pregMatch. + if (activeElem.getAttribute('data-allow')) jsFilter.string(activeElem); + }, + // To start validation process. + checkValidation: function (activeElem, log) { + // To Generally checks, the field is empty or not. + if (!jsRuleSets.isSet(activeElem))log.push({'empty': activeElem}); + // To Check the Value is less than min or not. + if (activeElem.min) if (!jsRuleSets.min(activeElem)) log.push({'min': activeElem}); + // To Check the Value is grater than max or not. + if (activeElem.max) if (!jsRuleSets.max(activeElem)) log.push({'max': activeElem}); + // To Check the Entered E-mail is Valid or Not. + if (activeElem.type == "email") if (!jsRuleSets.email(activeElem)) log.push({'email': activeElem}); + // To Compare the Password is Same or Not with Re-Password. + // TODO: Implement Simplified Comparison. + if (activeElem.type == "password")if (!jsRuleSets.compare(activeElem)) log.push({'password': activeElem}); + // Return overall log report of validation. + return log; + }, + // Single step instance validator for Ajax form submissions. + validate: function () { + // Initiate form Check. + this.check(); + // Return validation status. + return this.validationPass; + } +}; + +/* + * Common Filter instances. + */ +var jsFilter = { + // Number elements filter listener. + number: function (element) { + element.addEventListener("keypress", this.isNumberKey, false); + }, + // String elements filter listener. + string: function (element) { + // Getting "data" attribute for actions. + var type = element.getAttribute('data-allow'); + var current = this; + + // Switching actions. + switch (type) { + // Allow only alphabets [a-zA-Z] not [0-9] and special characters. + case 'onlyAlpha': + element.addEventListener("keypress", current.isAlpha, false); + break; + // Allow only alpha Numeric [a-zA-Z0-9] not special characters. + case 'string': + element.addEventListener("keypress", current.isAlphaNumeric, false); + break; + // Allow based on the pattern given. + default: + element.addEventListener("keypress", current.isPatternValid, false); + break; + } + }, + // Email elements filter listener. + email: function (element) { + element.addEventListener("keypress", jsRuleSets.email, false); + }, + // Numeric with Limited elements filter listener. + limit: function (element) { + element.addEventListener("keypress", this.isInLimit, false); + }, + // Restrict element with it's limit. + isInLimit: function (event) { + var value = event.target.value; + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + + // Getting object from element. + var min = event.target.min; + var max = event.target.max; + + // Default values for Min and Max. + if (!min) min = 0; + if (!max) max = 54; + + // 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(); + } + event.target.value = event.target.value.substring(0, event.target.value.length - 1); + }, + // Only allow alpha([a-zA-Z]). + isAlpha: function (event) { + // To check is this action is from "windows" action or not. + //if (true === isWindowAction(event)) return true; + // Getting special characters list. + var allow_special = event.target.getAttribute('data-allowSpecial'); + // Set default values for special characters. + if (!allow_special && allow_special == null) allow_special = ''; + // Format to string. + allow_special = allow_special.toString(); + // Validate with special formed pattern. + var regex = new RegExp('^[a-zA-Z' + allow_special + ']+$'); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }, + // Only allow alpha([a-zA-Z0-9]). + isAlphaNumeric: function (event) { + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + // Getting special characters list. + var allow_special = event.target.getAttribute('data-allowSpecial'); + // Set default values for special characters. + if (!allow_special && allow_special == null) allow_special = ''; + // Format to string. + allow_special = allow_special.toString(); + // Validate with special formed pattern. + var regex = new RegExp('^[a-zA-Z0-9' + allow_special + ']+$'); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }, + // Only allow by pattern(ex. ^[a-zA-Z0-3@#$!_.]+$). + isPatternValid: function (event) { + // To check is this action is from "windows" action or not. + if (true === isWindowAction(event)) return true; + // Getting special characters list. + var pattern = event.target.getAttribute('data-allow'); + // Validate with special formed pattern. + var regex = new RegExp(pattern); + // Validation with Code. + var key = String.fromCharCode(!event.charCode ? event.which : event.charCode); + jsLogger.out('Alpha', regex.test(key)); + // Return status of the Action. + if (false === regex.test(key)) event.preventDefault(); + }, + // Check is numeric or not. + isNumberKey: function (event) { + // To check is this action is from "windows" action or not. + if (true === 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. + */ +var jsSettings = { + // Common error message color for form validation. + errorColor: false, + // Set common template for error message + errorTemplate: false, + + // To Initiate the Configurations. + 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; + }, + log: function () { + jsLogger.out(this.errorColor); + jsLogger.out(this.followedElement); + jsLogger.out(this.errorTemplate); + } +}; + +/** + * To Perform all Form based Operations. + */ +var jsForm = { + // Form element. + form: false, + // Form ID. + formCore: false, + // Form element's inputs. + input: false, + // Form element's selects. + select: false, + // Form element's textAreas. + textArea: false, + // Form element's labels. + label: false, + + // To Initiating the "jsForm". + init: function (option) { + jsLogger.out('Form', option.form); + // 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: function (form) { + // validate and Update Log. + if (typeof form == 'undefined') jsLogger.out('Form Identification', 'Form Identification is Missing !'); + + // Fetch Form element from Document. + this.form = document.getElementById(form); + // Update Direct Form ID. + this.formCore = form; + }, + + // To Parse all Relative Form components. + parseForm: function (form) { + // "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: function () { + // Filter all required "input" elements. + this.input = jsField.required(this.input); + // Filter all required "select" elements. + this.select = jsField.required(this.select); + // Filter all required "textArea" elements. + this.textArea = jsField.required(this.textArea); + }, + 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 = { + // Return all required elements list. + required: function (field) { + var requiredFieldsList = []; + for (var i = 0; i < field.length; i++) { + // Check and push elements. + if (field[i].required === true) { + // Pushing to required elements list. + requiredFieldsList.push(field[i]); + } + } + // Return list of required elements. + return requiredFieldsList; + } +}; + +/** + * List of Validation Rules. + */ +var jsRuleSets = { + // To Check, whether the element have value or not. + isSet: function (elem) { + var status = true; + // Check length and empty or not. + if (elem.length === 0 || elem.value === '') status = false; + return status; + }, + // To Check Element with Min Condition. + min: function (elem) { + var status = true; + //TODO: Implement suitable solution for this. + //if (elem.length < elem.min && elem.length !== 0) status = false; + return status; + }, + // To Check Element with Max Condition. + max: function (elem) { + var status = true; + if (elem.value > elem.max) status = false; + return status; + }, + // To Check Element Email is Valid or Not. + email: function (elem) { + var status = true; + var email = elem.value; + // To Validate Email. + // Convert to Native String Format. + email = email.toString(); + // To Check it as String or Not. + if (!email) status = false; + if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { + // Valid Email. + status = true; + } + return status; + }, + // To Check Element Phone Value is Valid or Not. + phone: function (elem, pattern) { + var status = true; + if (elem.value === '') status = false; + return status; + }, + // To Compare two Elements Values. + compare: function (elem1) { + var elem2_id = elem1.getAttribute('data-check'); + + if (elem2_id == null) elem2_id = elem1.getAttribute('data-parent'); + + elem2_id = elem2_id.toString(); + var elem2 = document.getElementById(elem2_id); + var status = true; + if ((elem1.value !== elem2.value) && elem1.length !== elem2.length) status = false; + return status; + } +}; + +/** + * To Manage JsValidator Errors. + */ +var jsFormError = { + // Global constant to specify, error happened or not. + errorHit: false, + // Error Css. + errorCss: false, + // Success Css. + successCss: false, + // Initiate overall form error handler. + 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 () { + jsLogger.out('Form Error Hit', this.errorHit); + }, + // Form error style. + style: function (css) { + this.errorCss = css.error; + this.successCss = css.success; + } +}; + +/* + * For manage overall logging with validator. + * + */ +var jsLogger = { + // Simple log with "heading" and "message". + out: function (heading, message) { + console.log('======' + heading + '======'); + console.log(message); + console.log('------------------------'); + }, + // For bulk data logging. + bulk: function (data) { + console.log(data); + }, + // For log data with table. + table: function (data) { + console.table(data); + } +}; + +/* + * To check the keyboard action is window action or not. + */ +function isWindowAction(event) { + // Getting the event to be triggered. + var theEvent = event || window.event; + // Getting the type of event or code. + var key = theEvent.keyCode || theEvent.which; + + // Check with list of code and ignore holding. + // Tab, Space, Home, End, Up, Down, Left, Right... + if (key === 9 || key === 32 || key === 13 || key === 8 || (key >= 35 && key <= 40)) { //TAB was pressed + 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; +} \ No newline at end of file