├── .gitignore ├── LICENSE ├── package.json ├── dist ├── jquery.form-validation.min.js └── jquery.form-validation.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .idea/ 4 | package-lock.json 5 | local-test -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Bassam Nabriss 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-form-validation", 3 | "title": "jQuery form validation", 4 | "main": "dist/jquery.form-validation.js", 5 | "description": "jQuery library to validate html forms. complitable with bootstrap v4 and bootstrap v3", 6 | "version": "1.0.4", 7 | "homepage": "https://github.com/bnabriss/jquery-form-validation/", 8 | "author": { 9 | "name": "Bassam Nabriss", 10 | "url": "https://github.com/bnabriss" 11 | }, 12 | "contributors": [ 13 | { 14 | "name": "Bassam Nabriss", 15 | "url": "https://github.com/bnabriss" 16 | } 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/bnabriss/jquery-form-validation" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/bnabriss/jquery-form-validation/issues" 24 | }, 25 | "files": [ 26 | "dist/*.js" 27 | ], 28 | "license": "MIT", 29 | "dependencies": { 30 | "jquery": ">=1.8" 31 | }, 32 | "keywords": [ 33 | "jquery", 34 | "form", 35 | "validation", 36 | "validator", 37 | "bootstrap 4", 38 | "bootstrap 3", 39 | "input pattern", 40 | "laravel" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /dist/jquery.form-validation.min.js: -------------------------------------------------------------------------------- 1 | var Validator=function(){function t(t,e){e=void 0===e?{}:e,e=$.extend({parentSelector:".form-group",feedbackSelector:".form-control-feedback",inputSuccessClass:"is-valid",inputErrorClass:"is-invalid",feedbackSuccessClass:"valid-feedback",feedbackErrorClass:"invalid-feedback",parentErrorClass:"has-error",parentWarningClass:"has-warning",parentSuccessClass:"has-success",rules:"",validatorNameAttr:"validator-label"},e),this.language=$.extend(this.language,e.language),this.options=e,this.$input=t,this.$parent=this.$input.closest(e.parentSelector),this.$feedback=this.$parent.find(e.feedbackSelector),this.$form=this.getForm(this.$input),this.resetStyle(),this.val=this.$input.val(),this.name=this.$input.attr("name"),this.label=this.getLabelByName(this.name)?this.getLabelByName(this.name):this.$input.data("validator-label"),this.otherName=null,this.rules=this.first_element(e.rules,this.$input.data("validator")),this.rulesObject=this.first_element(this.getRules(),{}),this.warnings=this.first_element("",this.$input.data("validator-warnings")).split("|");var a=this.getFirstError();a?(this.showError(a),this.$feedback.removeClass(this.options.feedbackSuccessClass).addClass(this.options.feedbackErrorClass),this.$input.removeClass(this.options.inputSuccessClass).addClass(this.options.inputErrorClass),a&&this.contains(this.warnings,a)?this.setStatus("warning"):this.setStatus("error")):(this.$parent.addClass(this.options.parentSuccessClass),this.$feedback.removeClass(this.options.feedbackErrorClass).addClass(this.options.feedbackSuccessClass),this.$input.removeClass(this.options.inputErrorClass).addClass(this.options.inputSuccessClass))}return t.prototype.getLabelByName=function(t){t=t||this.otherName;var e=this.getInput(this.$form,'[name="'+t+'"]').data(this.options.validatorNameAttr);return e?e.trim():null},t.prototype.showMessage=function(t){void 0!==this.$feedback.data("html")&&this.$feedback.data("html",this.$feedback.html()),this.$feedback.html(t)},t.prototype.showError=function(t){var e=this.rulesObject[t];if(this.label){var a={label:this.label};this.otherName&&(a.otherLabel=this.getLabelByName());for(var r=0,i=e.length;r=t&&a<=e},t.prototype.max_numeric=function(t){return this.getFloat(this.val)<=this.getFloat(t)},t.prototype.min_numeric=function(t){return this.getFloat(this.val)>=this.getFloat(t)},t.prototype.size_numeric=function(t){return this.getFloat(this.val)===this.getFloat(t)},t.prototype.between=function(t,e){var a=this.valLength();return t=this.getInt(t),e=this.getInt(e),a>=t&&a<=e},t.prototype.max=function(t){return this.valLength()<=this.getInt(t)},t.prototype.min=function(t){return this.valLength()>=this.getInt(t)},t.prototype.size=function(t){return this.valLength()===this.getInt(t)},t.prototype.date=function(){return!isNaN(new Date(this.val).getTime())},t.prototype.before=function(t){return new Date(this.val).getTime()this.getDateTimestamp(t)},t.prototype.after_or_equal=function(t){return new Date(this.val).getTime()>=this.getDateTimestamp(t)},t.prototype.age=function(t){t=this.getFloat(t);var e=new Date,a=new Date(e.getFullYear()-t,e.getMonth(),e.getDate());return a=a.getTime(),this.getDateTimestamp(this.val)<=a},t.prototype.email=function(){return/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(this.val)},t.prototype.in=function(){return this.contains(arguments,this.val)},t.prototype.not_in=function(){return!this.contains(arguments,this.val)},t.prototype.regex=function(t){return new RegExp(t).test(this.val)},t.prototype.different=function(t){this.otherName=t,this.triggerOtherName(t);var e=this.serializeArrayKv(this.$form)[t];return this.val!==e},t.prototype.required_if=function(t){return this.otherName=t,this.triggerOtherName(t),!this.serializeArrayKv(this.$form)[t]||this.required()},t.prototype.required_if_val=function(t,e){this.otherName=t,this.triggerOtherName(t);var a=this.serializeArrayKv(this.$form)[t];return!this.valLength(e)||a!==e||this.required()},t.prototype.same=function(t){return this.otherName=t,this.triggerOtherName(t),!this.different(t)},t.prototype.url=function(){return new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+&:]*)*(\\?[;&a-z\\d%_.,~+&:=-]*)?(\\#[-a-z\\d_]*)?$","i").test(this.val)},t.prototype.triggerOtherName=function(t){var e=this;e.getInput(this.$form,'[name="'+t+'"]').off("change.validator").on("change.validator",function(){e.$input.trigger("blur")})},t.prototype.first_element=function(){for(var t=0,e=arguments.length;t 17 | ``` 18 | 19 | ### How to use 20 | 21 | #### Simple usage 22 | ![image](http://bntracking.com/15Cb5IPsKL.gif) 23 | ###### html 24 | ```html 25 |
26 |
27 | 28 |
29 |
30 | ``` 31 | ###### javascript 32 | ```javascript 33 | $(document).on('blur', '[data-validator]', function () { 34 | new Validator($(this)); 35 | }); 36 | ``` 37 | 38 | #### Add feedback message 39 | Update your HTML to add element with selector `.form-control-feedback`, this element should belong to the parent `.form-group` (or your parent selector), you should also set the input label, this label will be visble in the error message, by adding the attribute `data-validator-label` to input itself. 40 | ```html 41 |
42 |
43 | 44 | 45 |
46 |
47 | ``` 48 | 49 | #### Customize options 50 | You can pass your custom options as a second parameter to the constructor. 51 | ```javascript 52 | $(document).on('blur', '[data-validator]', function () { 53 | new Validator($(this), {/* your options here*/}); 54 | }); 55 | ``` 56 | And here is a table of available options 57 | 58 | | Tables | default |description | 59 | | ------------- | :------:|------| 60 | | parentSelector | `'.form-group'` | you can set the parent selector for input, this used to set error/success classes and to search in it when search for feedback messages | 61 | | feedbackSelector | `'.form-control-feedback'` | this selector used to specify when the error message should appear when error occurs, this should be inside the specified parent | 62 | | inputSuccessClass | `'is-valid'` | the class that should be given to the input when the input is valid | 63 | | inputErrorClass | `'is-invalid'` | the class that should be given to the input when the input is invalid | 64 | | feedbackSuccessClass | `'valid-feedback'` | the class that should be given to feedback element when the input is valid | 65 | | feedbackErrorClass | `'invalid-feedback'` | the class that should be given to feedback element when the input is invalid | 66 | | parentErrorClass | `'has-error'` | the class that should be given to the parent element when the input is invalid | 67 | | parentWarningClass | `'has-warning'` | the class that should be given to the parent element when the input is invalid when the rule specified as warning rule | 68 | | parentSuccessClass | `'has-success'` | the class that should be given to the parent element when the input is valid | 69 | | rules | the `data-validator` value | this option will override the `data-validator` attribute value | 70 | | validatorNameAttr | `validator-label` | specify the label attribute of the input | 71 | 72 | 73 | #### warning errors 74 | you can specify some rules as warning errors, this completable with bootstrap 3 (or your custom options) since it has `has-warning` class for the parent `.form-group` 75 | ```html 76 |
77 |
78 | 79 |
80 |
81 | ``` 82 | > Note that you should keep min in `data-validator`. 83 | 84 | ### Available Validation Rules 85 | 86 | | Rule | example | description | 87 | | ------------- | :------:|------| 88 | | required | `required` | The field under validation must be present in the input data and not empty | 89 | | numeric | `numeric` | The field under validation must be numeric | 90 | | integer | `integer` | The field under validation must be an integer | 91 | | between_numeric | `between_numeric:10,40` | The numeric field under validation must be between the given two values | 92 | | max_numeric | `max_numeric:60` | The numeric field under validation must less than or equal the given value | 93 | | min_numeric | `min_numeric:10` | The numeric field under validation must greater than or equal the given value | 94 | | size_numeric | `size_numeric:10` | The numeric field under validation must exactly equal the given value | 95 | | between | `between:2,10` | The field length must between the two given values | 96 | | max | `max:10` | The field length must less than or equal the given value | 97 | | min | `min:2` | The field length must greater than or equal the given value | 98 | | size | `size:6` | The field length must exactly equal the given value | 99 | | date | `date` | The field must be valid date syntax (`new Date()`) | 100 | | before | `before:2015-01-01` | The date value must be older than the given value | 101 | | before_or_equal | `before_or_equal:2018-12-01 14:00:00` | The date value must be older than or equal the given value | 102 | | after | `after:2015-01-01` | The date value must be newer than the given value | 103 | | after_or_equal | `after_or_equal:2018-12-01 14:00:00` | The date value must be newer than or equal the given value | 104 | | email | `email` | The field under validation must be formatted as an e-mail address | 105 | | in | `in:male,female,...` | The field under validation must be included in the given list of values | 106 | | not_in | `not_in:foo,bar,...` | The field under validation must not be included any of the given list of values | 107 | | regex | `regex:[A-Z0-9]{6}` | The field under validation must match the given regular expression | 108 | | different | `different:old_password` | The field under validation must have a different value than field with the given field `name` (attribute) | 109 | | same | `same:password` | The field under validation must exactly the same value of the field with the given field `name` (attribute) | 110 | | required_if | `required_if:old_password` | The field under validation must have a value if the field with the given `name` (attribute) is entered | 111 | | required_if_val | `required_if_val:password,123456` | The field under validation must have a value if the field with the given `name` (attribute) has exactly the given value | 112 | | url | `url` | The field under validation must be a valid URL | 113 | 114 | #### Custom errors 115 | You can bind the `Validator` object with your custom validator function. 116 | ```javascript 117 | Validator.prototype.valid_user_name = function (customLength) { 118 | if (this.val && customLength /*...*/){ 119 | // ... 120 | return true; 121 | } 122 | return false; 123 | }; 124 | ``` 125 | And to use it in your forms 126 | ```html 127 |
128 |
129 | 130 |
131 |
132 | ``` 133 | 134 | ### Existing error messages 135 | The previous listed errors already has it's errors messages (English) 136 | ```javascript 137 | Validator.prototype.language = { 138 | numeric: 'The {label} must be a number.', 139 | integer: 'The {label} must be an integer.', 140 | between_numeric: 'The {label} must be between {param0} and {param1}.', 141 | max_numeric: 'The {label} may not be greater than {param0}.', 142 | min_numeric: 'The {label} must be at least {param0}.', 143 | size_numeric: 'The {label} must be {param0}.', 144 | between: 'The {label} must be between {param0} and {param1} characters.', 145 | max: 'The {label} may not be greater than {param0} characters.', 146 | min: 'The {label} must be at least {param0} characters.', 147 | size: 'The {label} must be {param0} characters.', 148 | date: 'The {label} must be a date after {param0}.', 149 | before: 'The {label} must be a date before {param0}.', 150 | before_or_equal: 'The {label} must be a date before or equal to {param0}.', 151 | after: 'The {label} must be a date after {param0}.', 152 | after_or_equal: 'The {label} must be a date after or equal to {param0}.', 153 | age: 'The age should be more than {param0}.', 154 | email: 'The {label} must be a valid email address.', 155 | in: 'The selected {label} is invalid.', 156 | not_in: 'The selected {label} is invalid.', 157 | different: 'The {label} and {otherLabel} must be different.', 158 | required: 'The {label} field is required..', 159 | required_if: 'The {label} field is required when {otherLabel} is filled.', 160 | required_if_val: 'The {label} field is required when {otherLabel} is {param0}', 161 | same: 'The {label} and {otherLabel} must match.', 162 | url: 'The {label} format is invalid.', 163 | regex: 'The {label} format is invalid.' 164 | } 165 | ``` 166 | #### Bind error message 167 | you can simply override the given messages using prototype object, and note that the key of the message is exactly the same of the function name, so when you add your custom validator you should add the suitable key language if you want to show the error, you can also use the syntax `'{label}'` in your message to be replaced with your `[data-validator-label]` that you have added to the input, you can also the syntax `{param0}` to bind the first parameter in the error your message. 168 | ```javascript 169 | Validator.prototype.language = {/* your custom error messages */} 170 | ``` 171 | Or you can merge exiting errors with additional messages using options parameter in the constructor 172 | ```javascript 173 | $(document).on('blur', '[data-validator]', function () { 174 | new Validator($(this), { 175 | language : { 176 | valid_user_name : 'The {label} should have a valid user name with length of {param0}' 177 | } 178 | }); 179 | }); 180 | ``` 181 | -------------------------------------------------------------------------------- /dist/jquery.form-validation.js: -------------------------------------------------------------------------------- 1 | /* global $, jQuery */ 2 | var Validator = function () { 3 | function Validator($selector, options) { 4 | options = options === undefined ? {} : options; 5 | options = $.extend({ 6 | parentSelector: '.form-group', 7 | feedbackSelector: '.form-control-feedback', 8 | 9 | inputSuccessClass: 'is-valid', 10 | inputErrorClass: 'is-invalid', 11 | 12 | feedbackSuccessClass: 'valid-feedback', 13 | feedbackErrorClass: 'invalid-feedback', 14 | 15 | parentErrorClass: 'has-error', 16 | parentWarningClass: 'has-warning', 17 | parentSuccessClass: 'has-success', 18 | 19 | rules: '', 20 | 21 | validatorNameAttr: 'validator-label' 22 | }, options); 23 | this.language = $.extend(this.language, options.language ); 24 | 25 | this.options = options; 26 | 27 | this.$input = $selector; 28 | this.$parent = this.$input.closest(options.parentSelector); 29 | this.$feedback = this.$parent.find(options.feedbackSelector); 30 | this.$form = this.getForm(this.$input); 31 | 32 | this.resetStyle(); 33 | this.val = this.$input.val(); 34 | this.name = this.$input.attr('name'); 35 | this.label = this.getLabelByName(this.name) ? this.getLabelByName(this.name) : this.$input.data('validator-label'); 36 | this.otherName = null; 37 | this.rules = this.first_element(options.rules, this.$input.data('validator')); 38 | 39 | this.rulesObject = this.first_element(this.getRules(), {}); 40 | this.warnings = this.first_element('', this.$input.data('validator-warnings')).split('|'); 41 | 42 | var firstError = this.getFirstError(); 43 | if (firstError){ 44 | this.showError(firstError); 45 | this.$feedback.removeClass(this.options.feedbackSuccessClass).addClass(this.options.feedbackErrorClass); 46 | this.$input.removeClass(this.options.inputSuccessClass).addClass(this.options.inputErrorClass); 47 | if (firstError && this.contains(this.warnings, firstError)) { 48 | // warning 49 | this.setStatus('warning'); 50 | } else { 51 | this.setStatus('error'); 52 | } 53 | }else{ 54 | this.$parent.addClass(this.options.parentSuccessClass); 55 | 56 | this.$feedback.removeClass(this.options.feedbackErrorClass).addClass(this.options.feedbackSuccessClass); 57 | this.$input.removeClass(this.options.inputErrorClass).addClass(this.options.inputSuccessClass); 58 | } 59 | 60 | } 61 | 62 | Validator.prototype.getLabelByName = function (name) { 63 | name = name ? name : this.otherName; 64 | var $input = this.getInput(this.$form, '[name="' + name + '"]'); 65 | var label = $input.data(this.options.validatorNameAttr); 66 | return label ? label.trim() : null; 67 | }; 68 | 69 | Validator.prototype.showMessage = function (message) { 70 | if (this.$feedback.data('html') !== undefined) { 71 | this.$feedback.data('html', this.$feedback.html()); 72 | } 73 | this.$feedback.html(message); 74 | }; 75 | Validator.prototype.showError = function (errorKey) { 76 | var params = this.rulesObject[errorKey]; 77 | if (this.label) { 78 | var items = { 'label': this.label }; 79 | if (this.otherName) { 80 | items['otherLabel'] = this.getLabelByName(); 81 | } 82 | for (var i = 0, max = params.length; i < max; i++) { 83 | items['param' + i] = params[i]; 84 | } 85 | var message = this.getValidator(errorKey, items); 86 | this.showMessage(message); 87 | } 88 | }; 89 | Validator.prototype.setStatus = function (type) { 90 | this.$parent.removeClass('has-warning'); 91 | this.$parent.removeClass('has-error'); 92 | this.$parent.removeClass('has-success'); 93 | this.$parent.removeClass('has-loading'); 94 | if (type) { 95 | this.$parent.addClass('has-' + type); 96 | } 97 | }; 98 | Validator.prototype.resetStyle = function () { 99 | this.$feedback.html(this.$feedback.data('html') ? this.$feedback.data('html') : '' ); 100 | this.setStatus(); 101 | }; 102 | 103 | Validator.prototype.getRules = function () { 104 | var rulesObject = {}; 105 | var exploded = this.rules.split('|'); 106 | $.each(exploded, function () { 107 | var fncAndParm = this; 108 | var funcName = fncAndParm.split(':')[0]; 109 | var paramStr = fncAndParm.split(':')[1]; 110 | rulesObject[funcName] = paramStr ? paramStr.split(',') : []; 111 | }); 112 | return rulesObject; 113 | }; 114 | Validator.prototype.getFirstError = function () { 115 | var that = this; 116 | 117 | if (!this.required() && !this.rulesObject.hasOwnProperty('required')) { 118 | // require failed and not needed 119 | if (this.rulesObject.hasOwnProperty('required_if') && !this['required_if'].apply(that, this.rulesObject['required_if'])) { 120 | return 'required_if'; 121 | } 122 | return null; 123 | } 124 | var firstError = null; 125 | $.each(this.rulesObject, function (fncName, params) { 126 | if (!that[fncName].apply(that, params)) { 127 | firstError = fncName; 128 | return false; 129 | } 130 | }); 131 | return firstError; 132 | }; 133 | 134 | Validator.prototype.valLength = function (customVal) { 135 | var val = customVal ? customVal : this.val; 136 | if (typeof val === 'string') { 137 | return val.length; 138 | } 139 | return 0; 140 | }; 141 | Validator.prototype.getDateTimestamp = function (date) { 142 | var now = new Date(date ? date : null); 143 | var startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate()); 144 | return startOfDay.getTime(); 145 | }; 146 | 147 | /**** Start rules ****/ 148 | Validator.prototype.required = function () { 149 | return this.valLength() !== 0; 150 | }; 151 | Validator.prototype.numeric = function () { 152 | return parseFloat(this.val) === this.getFloat(this.val); 153 | }; 154 | Validator.prototype.integer = function () { 155 | console.log(this.val); 156 | return parseInt(this.val) === this.getFloat(this.val); 157 | }; 158 | Validator.prototype.between_numeric = function (min, max) { 159 | var val = this.getFloat(this.val); 160 | min = this.getFloat(min); 161 | max = this.getFloat(max); 162 | return val >= min && val <= max; 163 | }; 164 | Validator.prototype.max_numeric = function (max) { 165 | return this.getFloat(this.val) <= this.getFloat(max); 166 | }; 167 | Validator.prototype.min_numeric = function (min) { 168 | return this.getFloat(this.val) >= this.getFloat(min); 169 | }; 170 | Validator.prototype.size_numeric = function (siz) { 171 | return this.getFloat(this.val) === this.getFloat(siz); 172 | }; 173 | 174 | Validator.prototype.between = function (min, max) { 175 | var val = this.valLength(); 176 | min = this.getInt(min); 177 | max = this.getInt(max); 178 | return val >= min && val <= max; 179 | }; 180 | Validator.prototype.max = function (max) { 181 | return this.valLength() <= this.getInt(max); 182 | }; 183 | Validator.prototype.min = function (min) { 184 | return this.valLength() >= this.getInt(min); 185 | }; 186 | Validator.prototype.size = function (siz) { 187 | return this.valLength() === this.getInt(siz); 188 | }; 189 | Validator.prototype.date = function () { 190 | return !isNaN(new Date(this.val).getTime()); 191 | }; 192 | Validator.prototype.before = function (date) { 193 | var inpStamp = new Date(this.val).getTime(); 194 | return inpStamp < this.getDateTimestamp(date); 195 | }; 196 | Validator.prototype.before_or_equal = function (date) { 197 | var inpStamp = new Date(this.val).getTime(); 198 | return inpStamp <= this.getDateTimestamp(date); 199 | }; 200 | Validator.prototype.after = function (date) { 201 | var inpStamp = new Date(this.val).getTime(); 202 | return inpStamp > this.getDateTimestamp(date); 203 | }; 204 | Validator.prototype.after_or_equal = function (date) { 205 | var inpStamp = new Date(this.val).getTime(); 206 | return inpStamp >= this.getDateTimestamp(date); 207 | }; 208 | Validator.prototype.age = function (age) { 209 | age = this.getFloat(age); 210 | var now = new Date(); 211 | var ageStamp = new Date(now.getFullYear() - age, now.getMonth(), now.getDate()); 212 | ageStamp = ageStamp.getTime(); 213 | var inpStamp = this.getDateTimestamp(this.val); 214 | return inpStamp <= ageStamp; 215 | }; 216 | Validator.prototype.email = function () { 217 | var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 218 | return re.test(this.val); 219 | }; 220 | Validator.prototype.in = function () { 221 | return this.contains(arguments, this.val); 222 | }; 223 | Validator.prototype.not_in = function () { 224 | return !this.contains(arguments, this.val); 225 | }; 226 | Validator.prototype.regex = function (rex) { 227 | var re = new RegExp(rex); 228 | return re.test(this.val); 229 | }; 230 | Validator.prototype.different = function (otherName) { 231 | this.otherName = otherName; 232 | this.triggerOtherName(otherName); 233 | var otherValue = this.serializeArrayKv(this.$form)[otherName]; 234 | return this.val !== otherValue; 235 | }; 236 | Validator.prototype.required_if = function (otherName) { 237 | this.otherName = otherName; 238 | this.triggerOtherName(otherName); 239 | var otherValue = this.serializeArrayKv(this.$form)[otherName]; 240 | return otherValue ? this.required() : true; 241 | }; 242 | Validator.prototype.required_if_val = function (otherName, specificValue) { 243 | this.otherName = otherName; 244 | this.triggerOtherName(otherName); 245 | var otherValue = this.serializeArrayKv(this.$form)[otherName]; 246 | if (this.valLength(specificValue) && otherValue === specificValue) { 247 | // checked value === other value 248 | return this.required(); 249 | } 250 | return true; 251 | }; 252 | Validator.prototype.same = function (otherName) { 253 | this.otherName = otherName; 254 | this.triggerOtherName(otherName); 255 | return !this.different(otherName); 256 | }; 257 | 258 | Validator.prototype.url = function () { 259 | var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol 260 | '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name and extension 261 | '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address 262 | '(\\:\\d+)?' + // port 263 | '(\\/[-a-z\\d%_.~+&:]*)*' + // path 264 | '(\\?[;&a-z\\d%_.,~+&:=-]*)?' + // query string 265 | '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator 266 | return pattern.test(this.val); 267 | }; 268 | Validator.prototype.triggerOtherName = function (otherName) { 269 | var that = this; 270 | 271 | function triggerEvent() { 272 | that.$input.trigger('blur'); 273 | } 274 | 275 | that.getInput(this.$form, '[name="' + otherName + '"]').off('change.validator').on('change.validator', triggerEvent); 276 | }; 277 | 278 | Validator.prototype.first_element = function () { 279 | for (var i = 0, max = arguments.length; i < max; i++) { 280 | var item = arguments[i]; 281 | if (!(item instanceof jQuery && item.length === 0) && item !== null && item !== '' && typeof item !== 'undefined') return item; 282 | } 283 | return arguments[0]; 284 | }; 285 | Validator.prototype.getInt = function (obj) { 286 | var parsed = parseInt(obj); 287 | return isNaN(parsed) ? 0 : parsed; 288 | }; 289 | Validator.prototype.getFloat = function (obj) { 290 | var parsed = parseFloat(obj); 291 | return isNaN(parsed) ? 0 : parsed; 292 | }; 293 | Validator.prototype.getInput = function ($obj, selector) { 294 | var id = $obj.attr('id'); 295 | return this.first_element($(selector + '[form="' + id + '"]'), $obj.find(selector)); 296 | }; 297 | 298 | Validator.prototype.getForm = function ($obj) { 299 | if ($obj.attr('form')) { 300 | return $('form#' + $obj.attr('form')); 301 | } 302 | return $obj.closest('form'); 303 | }; 304 | 305 | Validator.prototype.contains = function (array, search) { 306 | return array.indexOf(search) !== -1; 307 | }; 308 | 309 | Validator.prototype.replaceAll = function (target, search, replacement) { 310 | return target.replace(new RegExp(search, 'g'), replacement); 311 | }; 312 | 313 | Validator.prototype.getValidator = function (msgKey, items) { 314 | msgKey = String(msgKey); 315 | var message = this.language[msgKey]; 316 | return this.parseData(message, items); 317 | }; 318 | Validator.prototype.parseData = function (message, data) { 319 | var that = this; 320 | $.each(data ? data : {}, function (i, v) { 321 | message = that.replaceAll(message, '{' + i + '}', v); 322 | }); 323 | return message; 324 | }; 325 | Validator.prototype.serializeArrayKv = function ($form) { 326 | var arr = $form.serializeArray(), obj = {}; 327 | for (var i = 0; i < arr.length; ++i) 328 | obj[arr[i].name] = arr[i].value; 329 | return obj; 330 | }; 331 | Validator.prototype.language = { 332 | numeric: 'The {label} must be a number.', 333 | integer: 'The {label} must be an integer.', 334 | between_numeric: 'The {label} must be between {param0} and {param1}.', 335 | max_numeric: 'The {label} may not be greater than {param0}.', 336 | min_numeric: 'The {label} must be at least {param0}.', 337 | size_numeric: 'The {label} must be {param0}.', 338 | between: 'The {label} must be between {param0} and {param1} characters.', 339 | max: 'The {label} may not be greater than {param0} characters.', 340 | min: 'The {label} must be at least {param0} characters.', 341 | size: 'The {label} must be {param0} characters.', 342 | date: 'The {label} must be a date after {param0}.', 343 | before: 'The {label} must be a date before {param0}.', 344 | before_or_equal: 'The {label} must be a date before or equal to {param0}.', 345 | after: 'The {label} must be a date after {param0}.', 346 | after_or_equal: 'The {label} must be a date after or equal to {param0}.', 347 | age: 'The age should be more than {param0}.', 348 | email: 'The {label} must be a valid email address.', 349 | in: 'The selected {label} is invalid.', 350 | not_in: 'The selected {label} is invalid.', 351 | different: 'The {label} and {otherLabel} must be different.', 352 | required: 'The {label} field is required.', 353 | required_if: 'The {label} field is required when {otherLabel} is filled.', 354 | required_if_val: 'The {label} field is required when {otherLabel} is {param0}', 355 | same: 'The {label} and {otherLabel} must match.', 356 | url: 'The {label} format is invalid.', 357 | regex: 'The {label} format is invalid.' 358 | }; 359 | 360 | return Validator; 361 | }(); 362 | --------------------------------------------------------------------------------