|
5 | 5 | * Documentation and issue tracking on Github <https://github.com/victorjonsson/jQuery-Form-Validator/> |
6 | 6 | * |
7 | 7 | * @license Dual licensed under the MIT or GPL Version 2 licenses |
8 | | -* @version 1.9.32 |
| 8 | +* @version 1.9.33 |
9 | 9 | */ |
10 | 10 | (function($) { |
11 | 11 |
|
|
187 | 187 | */ |
188 | 188 | $.fn.validate = function(language, config) { |
189 | 189 |
|
190 | | - language = $.extend(language || {}, $.formUtils.LANG); |
| 190 | + language = $.extend($.formUtils.LANG, language || {}); |
191 | 191 | config = $.extend($.formUtils.defaultConfig(), config || {}); |
192 | 192 |
|
193 | 193 | /** |
|
233 | 233 | var elementType = $element.attr('type'); |
234 | 234 | if (!ignoreInput($element.attr('name'), elementType)) { |
235 | 235 |
|
236 | | - // input of type radio |
237 | | - if(elementType === 'radio') { |
238 | | - var validationRule = $element.attr(config.validationRuleAttribute); |
239 | | - if (typeof validationRule != 'undefined' && validationRule === 'required') { |
240 | | - var radioButtonName = $element.attr('name'); |
241 | | - var isChecked = false; |
242 | | - $form.find('input[name="' + radioButtonName + '"]').each(function() { |
243 | | - if ($(this).is(':checked')) { |
244 | | - isChecked = true; |
245 | | - return false; |
246 | | - } |
247 | | - return true; |
248 | | - }); |
249 | | - |
250 | | - if (!isChecked) { |
251 | | - var validationErrorMsg = $element.attr(config.validationErrorMsgAttribute); |
252 | | - $element.valAttr('current-error', validationErrorMsg || language.requiredFields); |
253 | | - errorMessages.push(validationErrorMsg || language.requiredFields); |
254 | | - errorInputs.push($element); |
255 | | - } |
256 | | - } |
| 236 | + // memorize border color |
| 237 | + $.formUtils.figureOutDefaultBorderColor($element); |
| 238 | + |
| 239 | + var validation = $.formUtils.validateInput( |
| 240 | + $element, |
| 241 | + language, |
| 242 | + config, |
| 243 | + $form |
| 244 | + ); |
| 245 | + |
| 246 | + if(validation !== true) { |
| 247 | + errorInputs.push($element); |
| 248 | + addErrorMessage(validation); |
| 249 | + $element |
| 250 | + .valAttr('current-error', validation) |
| 251 | + .removeClass('valid'); |
257 | 252 | } |
258 | | - // inputs, textareas and select lists |
259 | 253 | else { |
260 | | - |
261 | | - // memorize border color |
262 | | - $.formUtils.figureOutDefaultBorderColor($element); |
263 | | - |
264 | | - var valid = $.formUtils.validateInput( |
265 | | - $element, |
266 | | - language, |
267 | | - config, |
268 | | - $form |
269 | | - ); |
270 | | - |
271 | | - if(valid !== true) { |
272 | | - errorInputs.push($element); |
273 | | - addErrorMessage(valid); |
274 | | - $element |
275 | | - .valAttr('current-error', valid) |
276 | | - .removeClass('valid'); |
277 | | - } |
278 | | - else { |
279 | | - $element |
280 | | - .valAttr('current-error', false) |
281 | | - .addClass('valid'); |
282 | | - } |
| 254 | + $element |
| 255 | + .valAttr('current-error', false) |
| 256 | + .addClass('valid'); |
283 | 257 | } |
284 | 258 | } |
285 | 259 |
|
|
406 | 380 | } |
407 | 381 | }; |
408 | 382 |
|
| 383 | + /** |
| 384 | + * Short hand function that makes the validation setup require less code |
| 385 | + * @param config |
| 386 | + */ |
| 387 | + $.setupForm = function(config) { |
| 388 | + config = $.extend({ |
| 389 | + form : 'form', |
| 390 | + validateOnBlur : true, |
| 391 | + showHelpOnFocus : true, |
| 392 | + addSuggestions : true, |
| 393 | + modules : '', |
| 394 | + onModulesLoaded : null, |
| 395 | + language : false, |
| 396 | + onSuccess : false, |
| 397 | + onError : false |
| 398 | + }, config || {}); |
| 399 | + |
| 400 | + $.split(config.form, function(formQuery) { |
| 401 | + var $form = $(formQuery); |
| 402 | + |
| 403 | + // Validate when submitted |
| 404 | + $form.bind('submit', function() { |
| 405 | + if($.formUtils.isLoadingModules) { |
| 406 | + setTimeout(function() { |
| 407 | + $form.trigger('submit'); |
| 408 | + }, 200); |
| 409 | + return false; |
| 410 | + } |
| 411 | + var valid = $(this).validate(config.language, config); |
| 412 | + if( valid && typeof config.onSuccess == 'function') { |
| 413 | + var callbackResponse = config.onSuccess($form); |
| 414 | + if( callbackResponse === false ) |
| 415 | + return false; |
| 416 | + } else if ( !valid && typeof config.onError == 'function' ) { |
| 417 | + config.onError($form); |
| 418 | + return false; |
| 419 | + } else { |
| 420 | + return valid; |
| 421 | + } |
| 422 | + }); |
| 423 | + |
| 424 | + if( config.validateOnBlur ) { |
| 425 | + $form.validateOnBlur(config.language, config); |
| 426 | + } |
| 427 | + if( config.showHelpOnFocus ) { |
| 428 | + $form.showHelpOnFocus(); |
| 429 | + } |
| 430 | + |
| 431 | + if( config.addSuggestions ) { |
| 432 | + $form.addSuggestions(); |
| 433 | + } |
| 434 | + }); |
| 435 | + |
| 436 | + if( config.modules != '' ) { |
| 437 | + if( typeof config.onModulesLoaded == 'function' ) { |
| 438 | + $.formUtils.on('load', function() { |
| 439 | + $.split(config.form, function(formQuery) { |
| 440 | + config.onModulesLoaded( $(formQuery) ); |
| 441 | + }); |
| 442 | + }); |
| 443 | + } |
| 444 | + $.formUtils.loadModules(config.modules); |
| 445 | + } |
| 446 | + }; |
| 447 | + |
| 448 | + /** |
| 449 | + * Object containing utility methods for this plugin |
| 450 | + */ |
409 | 451 | $.formUtils = { |
410 | 452 |
|
411 | 453 | /** |
|
419 | 461 | errorMessageClass : 'jquery_form_error_message', // class name of div containing error messages when validation fails |
420 | 462 | validationRuleAttribute : 'data-validation', // name of the attribute holding the validation rules |
421 | 463 | validationErrorMsgAttribute : 'data-validation-error-msg', // define custom err msg inline with element |
422 | | - errorMessagePosition : 'top', // Can be either "top" or "element" |
| 464 | + errorMessagePosition : 'element', // Can be either "top" or "element" |
423 | 465 | scrollToTopOnError : true, |
424 | 466 | dateFormat : 'yyyy-mm-dd' |
425 | 467 | } |
|
487 | 529 | }); |
488 | 530 | }, |
489 | 531 |
|
| 532 | + /** |
| 533 | + * @ {Boolean} |
| 534 | + */ |
| 535 | + isLoadingModules : false, |
| 536 | + |
490 | 537 | /** |
491 | 538 | * @example |
492 | 539 | * $.formUtils.loadModules('date, security.dev'); |
|
510 | 557 | moduleLoadedCallback = function() { |
511 | 558 | numModules--; |
512 | 559 | if( numModules == 0 ) { |
| 560 | + $.formUtils.isLoadingModules = false; |
513 | 561 | $.formUtils.trigger('load', path); |
514 | 562 | } |
515 | 563 | }; |
516 | 564 |
|
| 565 | + if( numModules > 0 ) { |
| 566 | + $.formUtils.isLoadingModules = true; |
| 567 | + } |
| 568 | + |
517 | 569 | $.each(moduleList, function(i, modName) { |
518 | 570 | modName = $.trim(modName); |
519 | 571 | if( modName.length == 0 ) { |
|
581 | 633 | */ |
582 | 634 | validateInput : function($element, language, config, $form) { |
583 | 635 |
|
584 | | - // Multiple select |
585 | | - if( $element.get(0).nodeName == 'SELECT' && $element.attr('multiple') ) { |
586 | | - return this.validateMultipleSelect($element.val(), $element, config, language); |
587 | | - } |
588 | | - |
589 | | - var value = $.trim($element.val()); |
590 | | - value = value || ''; |
| 636 | + var value = $.trim( $element.val() || '' ); |
591 | 637 | var optional = $element.valAttr('optional'); |
592 | 638 |
|
593 | 639 | // test if a checkbox forces this element to be validated |
|
660 | 706 | } |
661 | 707 | }, |
662 | 708 |
|
663 | | - /** |
664 | | - * @param {Array} values |
665 | | - * @param {jQuery} $el |
666 | | - * @param {Object} config |
667 | | - * @param {Object} language - $.formUtils.LANG |
668 | | - * @return {Boolean|String} |
669 | | - */ |
670 | | - validateMultipleSelect : function(values, $el, config, language) { |
671 | | - values = values || []; |
672 | | - var validationRules = $el.attr(config.validationRuleAttribute); |
673 | | - var validationErrorMsg = $el.attr(config.validationErrorMsgAttribute); |
674 | | - if(validationRules.indexOf('validate_num_answers') > -1) { |
675 | | - var num = this.getAttributeInteger(validationRules, 'num'); |
676 | | - if(num > values.length) { |
677 | | - return validationErrorMsg || (language.badNumberOfSelectedOptionsStart +num+ language.badNumberOfSelectedOptionsEnd); |
678 | | - } |
679 | | - } |
680 | | - return true; |
681 | | - }, |
682 | | - |
683 | 709 | /** |
684 | 710 | * <input data-validation="validate_min_length length12" /> => getAttribute($(element).attr('data-validation'), 'length') = 12 |
685 | 711 | * @param {String} attrValue |
|
769 | 795 | * @return void |
770 | 796 | */ |
771 | 797 | lengthRestriction : function($inputElement, $maxLengthElement) { |
772 | | - // read maxChars from counter display initial text value |
773 | | - var maxChars = parseInt($maxLengthElement.text(),10); |
| 798 | + // read maxChars from counter display initial text value |
| 799 | + var maxChars = parseInt($maxLengthElement.text(),10), |
| 800 | + |
| 801 | + // internal function does the counting and sets display value |
| 802 | + countCharacters = function() { |
| 803 | + var numChars = $inputElement.val().length; |
| 804 | + if(numChars > maxChars) { |
| 805 | + // get current scroll bar position |
| 806 | + var currScrollTopPos = $inputElement.scrollTop(); |
| 807 | + // trim value to max length |
| 808 | + $inputElement.val($inputElement.val().substring(0, maxChars)); |
| 809 | + $inputElement.scrollTop(currScrollTopPos); |
| 810 | + } |
| 811 | + // set counter text |
| 812 | + $maxLengthElement.text(maxChars - numChars); |
| 813 | + }; |
774 | 814 |
|
775 | 815 | // bind events to this element |
776 | 816 | // setTimeout is needed, cut or paste fires before val is available |
777 | 817 | $($inputElement).bind('keydown keyup keypress focus blur', countCharacters ) |
778 | 818 | .bind('cut paste', function(){ setTimeout(countCharacters, 100); } ) ; |
779 | 819 |
|
780 | | - // internal function does the counting and sets display value |
781 | | - function countCharacters() { |
782 | | - var numChars = $inputElement.val().length; |
783 | | - if(numChars > maxChars) { |
784 | | - // get current scroll bar position |
785 | | - var currScrollTopPos = $inputElement.scrollTop(); |
786 | | - // trim value to max length |
787 | | - $inputElement.val($inputElement.val().substring(0, maxChars)); |
788 | | - $inputElement.scrollTop(currScrollTopPos); |
789 | | - } |
790 | | - // set counter text |
791 | | - $maxLengthElement.text(maxChars - numChars); |
792 | | - } |
| 820 | + // count chars on pageload, if there are prefilled input-values |
| 821 | + $(document).bind("ready", countCharacters); |
| 822 | + |
793 | 823 | }, |
794 | 824 |
|
795 | 825 | _numSuggestionElements : 0, |
|
1056 | 1086 | name : 'validate_domain', |
1057 | 1087 | validate : function(val, $input) { |
1058 | 1088 |
|
1059 | | - // Clean up |
1060 | | - val = val.toLowerCase(); |
1061 | | - val = val.replace('ftp://', '').replace('https://', '').replace('http://', '').replace('www.', ''); |
1062 | | - if(val.substr(-1) == '/') |
1063 | | - val = val.substr(0, val.length-1); |
1064 | | - |
1065 | 1089 | var topDomains = ['.com', '.net', '.org', '.biz', '.coop', '.info', '.museum', '.name', '.pro', |
1066 | 1090 | '.edu', '.gov', '.int', '.mil', '.ac', '.ad', '.ae', '.af', '.ag', '.ai', '.al', |
1067 | 1091 | '.am', '.an', '.ao', '.aq', '.ar', '.as', '.at', '.au', '.aw', '.az', '.ba', '.bb', |
|
1209 | 1233 | validate : function(url) { |
1210 | 1234 | // written by Scott Gonzalez: http://projects.scottsplayground.com/iri/ but added support for arrays in the url ?arg[]=sdfsdf |
1211 | 1235 | var urlFilter = /^(https|http|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|\[|\]|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i; |
1212 | | - if(urlFilter.test(url)) { |
1213 | | - var domain = url.split(/^https|^http|^ftp/i)[1].replace('://', ''); |
| 1236 | + if( urlFilter.test(url) ) { |
| 1237 | + var domain = url.split('://')[1]; |
1214 | 1238 | var domainSlashPos = domain.indexOf('/'); |
1215 | 1239 | if(domainSlashPos > -1) |
1216 | 1240 | domain = domain.substr(0, domainSlashPos); |
|
0 commit comments