|
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