https://lestoitsdumonde.ca/wp-content/plugins/hbook/front-end/js/jquery.form-validator.js?ver=2.0.12
1(function (root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 // AMD. Register as an anonymous module unless amdModuleId is set 4 define(["jquery"], function (a0) { 5 return (factory(a0)); 6 }); 7 } else if (typeof module === 'object' && module.exports) { 8 // Node. Does not work with strict CommonJS, but 9 // only CommonJS-like environments that support module.exports, 10 // like Node. 11 module.exports = factory(require("jquery")); 12 } else { 13 factory(root["jQuery"]); 14 } 15}(this, function (jQuery) { 16 17/** File generated by Grunt -- do not modify 18 * JQUERY-FORM-VALIDATOR 19 * 20 * @version 2.3.79 21 * @website http://formvalidator.net/ 22 * @author Victor Jonsson, http://victorjonsson.se 23 * @license MIT 24 */ 25/** 26 */ 27(function ($, window, undefined) { 28 29 var disableFormSubmit = function () { 30 return false; 31 }, 32 lastFormEvent = null, 33 HaltManager = { 34 numHalted: 0, 35 haltValidation: function($form) { 36 this.numHalted++; 37 $.formUtils.haltValidation = true; 38 $form 39 .unbind('submit', disableFormSubmit) 40 .bind('submit', disableFormSubmit) 41 .find('*[type="submit"]') 42 .addClass('disabled') 43 .attr('disabled', 'disabled'); 44 }, 45 unHaltValidation: function($form) { 46 this.numHalted--; 47 if (this.numHalted === 0) { 48 $.formUtils.haltValidation = false; 49 $form 50 .unbind('submit', disableFormSubmit) 51 .find('*[type="submit"]') 52 .removeClass('disabled') 53 .removeAttr('disabled', 'disabled'); 54 } 55 } 56 }; 57 58 function AsyncValidation($form, $input) { 59 this.$form = $form; 60 this.$input = $input; 61 this.reset(); 62 $input.on('change paste', this.reset.bind(this)); 63 } 64 65 AsyncValidation.prototype.reset = function() { 66 this.haltedFormValidation = false; 67 this.hasRun = false; 68 this.isRunning = false; 69 this.result = undefined; 70 }; 71 72 AsyncValidation.prototype.run = function(eventContext, callback) { 73 if (eventContext === 'keyup') { 74 return null; 75 } else if (this.isRunning) { 76 lastFormEvent = eventContext; 77 if (!this.haltedFormValidation) { 78 HaltManager.haltValidation(); 79 this.haltedFormValidation = true; 80 } 81 return null; // Waiting for result 82 } else if(this.hasRun) { 83 //this.$input.one('keyup change paste', this.reset.bind(this)); 84 return this.result; 85 } else { 86 lastFormEvent = eventContext; 87 HaltManager.haltValidation(this.$form); 88 this.haltedFormValidation = true; 89 this.isRunning = true; 90 this.$input 91 .attr('disabled', 'disabled') 92 .addClass('async-validation'); 93 this.$form.addClass('async-validation'); 94 95 callback(function(result) { 96 this.done(result); 97 }.bind(this)); 98 99 return null; 100 } 101 }; 102 103 AsyncValidation.prototype.done = function(result) { 104 this.result = result; 105 this.hasRun = true; 106 this.isRunning = false; 107 this.$input 108 .removeAttr('disabled') 109 .removeClass('async-validation'); 110 this.$form.removeClass('async-validation'); 111 if (this.haltedFormValidation) { 112 HaltManager.unHaltValidation(this.$form); 113 if (lastFormEvent === 'submit') { 114 this.$form.trigger('submit'); 115 } else { 116 this.$input.trigger('validation.revalidate'); 117 } 118 } 119 }; 120 121 AsyncValidation.loadInstance = function(validatorName, $input, $form) { 122 // Return async validator attached to this input element 123 // or create a new async validator and attach it to the input 124 var asyncValidation, 125 input = $input.get(0); 126 127 if (!input.asyncValidators) { 128 input.asyncValidators = {}; 129 } 130 131 if (input.asyncValidators[validatorName]) { 132 asyncValidation = input.asyncValidators[validatorName]; 133 } else { 134 asyncValidation = new AsyncValidation($form, $input); 135 input.asyncValidators[validatorName] = asyncValidation; 136 } 137 138 return asyncValidation; 139 }; 140 141 $.formUtils = $.extend($.formUtils || {}, { 142 143 /** 144 * @deprecated 145 * @param validatorName 146 * @param $input 147 * @param $form 148 */
149 asyncValidation: function(validatorName, $input, $form) { 150 // @todo: Remove when moving up to version 3.0 151 this.warn('Use of deprecated function $.formUtils.asyncValidation, use $.formUtils.addAsyncValidator() instead'); 152 return AsyncValidation.loadInstance(validatorName, $input, $form); 153 }, 154 155 /** 156 * @param {Object} asyncValidator 157 */ 158 addAsyncValidator: function (asyncValidator) { 159 var validator = $.extend({}, asyncValidator), 160 originalValidatorFunc = validator.validatorFunction; 161 validator.async = true; 162 validator.validatorFunction = function (value, $el, config, language, $form, eventContext) { 163 var asyncValidation = AsyncValidation.loadInstance(this.name, $el, $form); 164 return asyncValidation.run(eventContext, function(done) { 165 originalValidatorFunc.apply(validator, [ 166 done, value, $el, config, language, $form, eventContext 167 ]); 168 }); 169 }; 170 this.addValidator(validator); 171 } 172 }); 173 174 // Tag elements having async validators 175 $(window).bind('validatorsLoaded formValidationSetup', function (evt, $form) { 176 if (!$form) { 177 $form = $('form'); 178 } 179 $form.find('[data-validation]').each(function () { 180 var $input = $(this); 181 $input.valAttr('async', false); 182 $.each($.split($input.attr('data-validation')), function (i, validatorName) { 183 var validator = $.formUtils.validators['validate_'+validatorName]; 184 if (validator && validator.async) { 185 $input.valAttr('async', 'yes'); 186 } 187 }); 188 }); 189 }); 190 191})(jQuery, window); 192 193/** 194 * Deprecated functions and attributes 195 * @todo: Remove in release of 3.0 196 */ 197(function ($, undefined) { 198 199 'use strict'; 200 201 /** 202 * @deprecated 203 * @param language 204 * @param conf 205 */ 206 $.fn.validateForm = function (language, conf) { 207 $.formUtils.warn('Use of deprecated function $.validateForm, use $.isValid instead'); 208 return this.isValid(language, conf, true); 209 }; 210 211 $(window) 212 .on('formValidationPluginInit', function(evt, config) { 213 convertDeprecatedLangCodeToISO6391(config); 214 addSupportForCustomErrorMessageCallback(config); 215 addSupportForElementReferenceInPositionParam(config); 216 }) 217 .on('validatorsLoaded formValidationSetup', function(evt, $form) { 218 if( !$form ) { 219 $form = $('form'); 220 } 221 addSupportForValidationDependingOnCheckedInput($form); 222 }); 223 224 225 function addSupportForCustomErrorMessageCallback(config) { 226 if (config && 227 config.errorMessagePosition === 'custom' && 228 typeof config.errorMessageCustom === 'function') { 229 230 $.formUtils.warn('Use of deprecated function errorMessageCustom, use config.submitErrorMessageCallback instead'); 231 232 config.submitErrorMessageCallback = function($form, errorMessages) { 233 config.errorMessageCustom( 234 $form, 235 config.language.errorTitle, 236 errorMessages, 237 config 238 ); 239 }; 240 } 241 } 242 243 function addSupportForElementReferenceInPositionParam(config) { 244 if (config.errorMessagePosition && typeof config.errorMessagePosition === 'object') { 245 $.formUtils.warn('Deprecated use of config parameter errorMessagePosition, use config.submitErrorMessageCallback instead'); 246 var $errorMessageContainer = config.errorMessagePosition; 247 config.errorMessagePosition = 'top'; 248 config.submitErrorMessageCallback = function() { 249 return $errorMessageContainer; 250 }; 251 } 252 } 253 254 function addSupportForValidationDependingOnCheckedInput($form) { 255 var $inputsDependingOnCheckedInputs = $form.find('[data-validation-if-checked]'); 256 if ($inputsDependingOnCheckedInputs.length) { 257 $.formUtils.warn( 258 'Detected use of attribute "data-validation-if-checked" which is '+ 259 'deprecated. Use "data-validation-depends-on" provided by module "logic"' 260 ); 261 } 262 263 $inputsDependingOnCheckedInputs 264 .on('beforeValidation', function() { 265 266 var $elem = $(this), 267 nameOfDependingInput = $elem.valAttr('if-checked'); 268 269 // Set the boolean telling us that the validation depends 270 // on another input being checked
271 var $dependingInput = $('input[name="' + nameOfDependingInput + '"]', $form), 272 dependingInputIsChecked = $dependingInput.is(':checked'), 273 valueOfDependingInput = ($.formUtils.getValue($dependingInput) || '').toString(), 274 requiredValueOfDependingInput = $elem.valAttr('if-checked-value'); 275 276 if (!dependingInputIsChecked || !( 277 !requiredValueOfDependingInput || 278 requiredValueOfDependingInput === valueOfDependingInput 279 )) { 280 $elem.valAttr('skipped', true); 281 } 282 283 }); 284 } 285 286 function convertDeprecatedLangCodeToISO6391(config) { 287 var deprecatedLangCodes = { 288 se: 'sv', 289 cz: 'cs', 290 dk: 'da' 291 }; 292 293 if (config.lang in deprecatedLangCodes) { 294 var newLangCode = deprecatedLangCodes[config.lang]; 295 $.formUtils.warn( 296 'Deprecated use of lang code "'+config.lang+'" use "'+newLangCode+'" instead' 297 ); 298 config.lang = newLangCode; 299 } 300 } 301 302})(jQuery); 303 304/** 305 * Utility methods used for displaying error messages (attached to $.formUtils) 306 */ 307(function ($) { 308 309 'use strict'; 310 311 var dialogs = { 312 313 resolveErrorMessage: function($elem, validator, validatorName, conf, language) { 314 var errorMsgAttr = conf.validationErrorMsgAttribute + '-' + validatorName.replace('validate_', ''), 315 validationErrorMsg = $elem.attr(errorMsgAttr); 316 317 if (!validationErrorMsg) { 318 validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute); 319 if (!validationErrorMsg) { 320 if (typeof validator.errorMessageKey !== 'function') { 321 validationErrorMsg = language[validator.errorMessageKey]; 322 } 323 else { 324 validationErrorMsg = language[validator.errorMessageKey(conf)]; 325 } 326 if (!validationErrorMsg) { 327 validationErrorMsg = validator.errorMessage; 328 } 329 } 330 } 331 return validationErrorMsg; 332 }, 333 getParentContainer: function ($elem) { 334 if ($elem.valAttr('error-msg-container')) { 335 return $($elem.valAttr('error-msg-container')); 336 } else { 337 var $parent = $elem.parent(); 338 if($elem.attr('type') === 'checkbox' && $elem.closest('.checkbox').length) { 339 $parent = $elem.closest('.checkbox').parent(); 340 } else if($elem.attr('type') === 'radio' && $elem.closest('.radio').length) { 341 $parent = $elem.closest('.radio').parent(); 342 } 343 if($parent.closest('.input-group').length) { 344 $parent = $parent.closest('.input-group').parent(); 345 } 346 return $parent; 347 } 348 }, 349 applyInputErrorStyling: function ($input, conf) { 350 $input 351 .addClass(conf.errorElementClass) 352 .removeClass(conf.successElementClass); 353 354 this.getParentContainer($input) 355 .addClass(conf.inputParentClassOnError) 356 .removeClass(conf.inputParentClassOnSuccess); 357 358 if (conf.borderColorOnError !== '') { 359 $input.css('border-color', conf.borderColorOnError); 360 } 361 }, 362 applyInputSuccessStyling: function($input, conf) { 363 $input.addClass(conf.successElementClass); 364 this.getParentContainer($input) 365 .addClass(conf.inputParentClassOnSuccess); 366 }, 367 removeInputStylingAndMessage: function($input, conf) { 368 369 // Reset input css 370 $input 371 .removeClass(conf.successElementClass) 372 .removeClass(conf.errorElementClass) 373 .css('border-color', ''); 374 375 var $parentContainer = dialogs.getParentContainer($input); 376 377 // Reset parent css 378 $parentContainer 379 .removeClass(conf.inputParentClassOnError) 380 .removeClass(conf.inputParentClassOnSuccess); 381 382 // Remove possible error message 383 if (typeof conf.inlineErrorMessageCallback === 'function') { 384 var $errorMessage = conf.inlineErrorMessageCallback($input, false, conf); 385 if ($errorMessage) { 386 $errorMessage.html(''); 387 } 388 } else { 389 $parentContainer 390 .find('.' + conf.errorMessageClass) 391 .remove(); 392 } 393 394 }, 395 removeAllMessagesAndStyling: function($form, conf) { 396
397 // Remove error messages in top of form 398 if (typeof conf.submitErrorMessageCallback === 'function') { 399 var $errorMessagesInTopOfForm = conf.submitErrorMessageCallback($form, false, conf); 400 if ($errorMessagesInTopOfForm) { 401 $errorMessagesInTopOfForm.html(''); 402 } 403 } else { 404 $form.find('.' + conf.errorMessageClass + '.alert').remove(); 405 } 406 407 // Remove input css/messages 408 $form.find('.' + conf.errorElementClass + ',.' + conf.successElementClass).each(function() { 409 dialogs.removeInputStylingAndMessage($(this), conf); 410 }); 411 }, 412 setInlineMessage: function ($input, errorMsg, conf) { 413 414 this.applyInputErrorStyling($input, conf); 415 416 var custom = document.getElementById($input.attr('name') + '_err_msg'), 417 $messageContainer = false, 418 setErrorMessage = function ($elem) { 419 $.formUtils.$win.trigger('validationErrorDisplay', [$input, $elem]); 420 $elem.html(errorMsg); 421 }, 422 addErrorToMessageContainer = function() { 423 var $found = false; 424 $messageContainer.find('.' + conf.errorMessageClass).each(function () { 425 if (this.inputReferer === $input[0]) { 426 $found = $(this); 427 return false; 428 } 429 }); 430 if ($found) { 431 if (!errorMsg) { 432 $found.remove(); 433 } else { 434 setErrorMessage($found); 435 } 436 } else if(errorMsg !== '') { 437 $message = $('<div class="' + conf.errorMessageClass + ' alert"></div>'); 438 setErrorMessage($message); 439 $message[0].inputReferer = $input[0]; 440 $messageContainer.prepend($message); 441 } 442 }, 443 $message; 444 445 if (custom) { 446 // Todo: remove in 3.0 447 $.formUtils.warn('Using deprecated element reference ' + custom.id); 448 $messageContainer = $(custom); 449 addErrorToMessageContainer(); 450 } else if (typeof conf.inlineErrorMessageCallback === 'function') { 451 $messageContainer = conf.inlineErrorMessageCallback($input, errorMsg, conf); 452 if (!$messageContainer) { 453 // Error display taken care of by inlineErrorMessageCallback 454 return; 455 } 456 addErrorToMessageContainer(); 457 } else { 458 var $parent = this.getParentContainer($input); 459 $message = $parent.find('.' + conf.errorMessageClass + '.help-block'); 460 if ($message.length === 0) { 461 $message = $('<span></span>').addClass('help-block').addClass(conf.errorMessageClass); 462 $message.appendTo($parent); 463 } 464 setErrorMessage($message); 465 } 466 }, 467 setMessageInTopOfForm: function ($form, errorMessages, conf, lang) { 468 var view = '<div class="{errorMessageClass} alert alert-danger">'+ 469 '<strong>{errorTitle}</strong>'+ 470 '<ul>{fields}</ul>'+ 471 '</div>', 472 $container = false; 473 474 if (typeof conf.submitErrorMessageCallback === 'function') { 475 $container = conf.submitErrorMessageCallback($form, errorMessages, conf); 476 if (!$container) { 477 // message display taken care of by callback 478 return; 479 } 480 } 481 482 var viewParams = { 483 errorTitle: lang.errorTitle, 484 fields: '', 485 errorMessageClass: conf.errorMessageClass 486 }; 487 488 $.each(errorMessages, function (i, msg) { 489 viewParams.fields += '<li>'+msg+'</li>'; 490 }); 491 492 $.each(viewParams, function(param, value) { 493 view = view.replace('{'+param+'}', value); 494 }); 495 496 if ($container) { 497 $container.html(view); 498 } else { 499 $form.children().eq(0).before($(view)); 500 } 501 } 502 }; 503 504 $.formUtils = $.extend($.formUtils || {}, { 505 dialogs: dialogs 506 }); 507 508})(jQuery); 509 510/** 511 * File declaring all methods if this plugin which is applied to $.fn. 512 */ 513(function($, window, undefined) { 514 515 'use strict'; 516 517 var _helpers = 0; 518 519 520 /** 521 * Assigns validateInputOnBlur function to elements blur event 522 * 523 * @param {Object} language Optional, will override $.formUtils.LANG 524 * @param {Object} conf Optional, will override the default settings 525 * @return {jQuery} 526 */ 527 $.fn.validateOnBlur = function (language, conf) { 528 var $form = this, 529 $elems = this.find('*[data-validation]'); 530 531 $elems.each(function(){ 532 var $this = $(this); 533 if ($this.is('[type=radio]')){ 534 var $additionals = $form.find('[type=radio][name="' + $this.attr('name') + '"]'); 535 $additionals.bind('blur.validation', function(){ 536 $this.validateInputOnBlur(language, conf, true, 'blur'); 537 }); 538 if (conf.validateCheckboxRadioOnClick) { 539 $additionals.bind('click.validation', function () { 540 $this.validateInputOnBlur(language, conf, true, 'click'); 541 }); 542 } 543 } 544 }); 545 546 $elems.bind('blur.validation', function () {
547 $(this).validateInputOnBlur(language, conf, true, 'blur'); 548 }); 549 550 if (conf.validateCheckboxRadioOnClick) { 551 // bind click event to validate on click for radio & checkboxes for nice UX 552 this.find('input[type=checkbox][data-validation],input[type=radio][data-validation]') 553 .bind('click.validation', function () { 554 $(this).validateInputOnBlur(language, conf, true, 'click'); 555 }); 556 } 557 558 return this; 559 }; 560 561 /* 562 * Assigns validateInputOnBlur function to elements custom event 563 * @param {Object} language Optional, will override $.formUtils.LANG 564 * @param {Object} settings Optional, will override the default settings 565 * * @return {jQuery} 566 */ 567 $.fn.validateOnEvent = function (language, config) { 568 if(this.length === 0) { 569 return; 570 } 571 572 var $elements = this[0].nodeName === 'FORM' ? this.find('*[data-validation-event]') : this; 573 $elements 574 .each(function () { 575 var $el = $(this), 576 etype = $el.valAttr('event'); 577 if (etype) { 578 $el 579 .unbind(etype + '.validation') 580 .bind(etype + '.validation', function (evt) { 581 if( (evt || {}).keyCode !== 9 ) { 582 $(this).validateInputOnBlur(language, config, true, etype); 583 } 584 }); 585 } 586 }); 587 return this; 588 }; 589 590 /** 591 * fade in help message when input gains focus 592 * fade out when input loses focus 593 * <input data-help="The info that I want to display for the user when input is focused" ... /> 594 * 595 * @param {String} attrName - Optional, default is data-help 596 * @return {jQuery} 597 */ 598 $.fn.showHelpOnFocus = function (attrName) { 599 if (!attrName) { 600 attrName = 'data-validation-help'; 601 } 602 603 // Add help text listeners 604 this.find('textarea,input').each(function () { 605 var $elem = $(this), 606 className = 'jquery_form_help_' + (++_helpers), 607 help = $elem.attr(attrName); 608 609 // Reset 610 $elem 611 .removeClass('has-help-text') 612 .unbind('focus.help') 613 .unbind('blur.help'); 614 615 if (help) { 616 $elem 617 .addClass('has-help-txt') 618 .bind('focus.help', function () { 619 var $help = $elem.parent().find('.' + className); 620 if ($help.length === 0) { 621 $help = $('<span />') 622 .addClass(className) 623 .addClass('help') 624 .addClass('help-block') // twitter bs 625 .text(help) 626 .hide(); 627 628 $elem.after($help); 629 } 630 $help.fadeIn(); 631 }) 632 .bind('blur.help', function () { 633 $(this) 634 .parent() 635 .find('.' + className) 636 .fadeOut('slow'); 637 }); 638 } 639 }); 640 641 return this; 642 }; 643 644 /** 645 * @param {Function} cb 646 * @param {Object} [conf] 647 * @param {Object} [lang] 648 */ 649 $.fn.validate = function(cb, conf, lang) { 650 var language = $.extend({}, $.formUtils.LANG, lang || {}); 651 this.each(function() { 652 var $elem = $(this), 653 closestFormElem = $elem.closest('form').get(0) || {}, 654 formDefaultConfig = closestFormElem.validationConfig || $.formUtils.defaultConfig(); 655 656 $elem.one('validation', function(evt, isValid) { 657 if ( typeof cb === 'function' ) { 658 cb(isValid, this, evt); 659 } 660 }); 661 662 $elem.validateInputOnBlur( 663 language, 664 $.extend({}, formDefaultConfig, conf || {}), 665 true 666 ); 667 }); 668 }; 669 670 /** 671 * Tells whether or not validation of this input will have to postpone the form submit () 672 * @returns {Boolean} 673 */ 674 $.fn.willPostponeValidation = function() { 675 return (this.valAttr('suggestion-nr') || 676 this.valAttr('postpone') || 677 this.hasClass('hasDatepicker')) && 678 !window.postponedValidation; 679 }; 680 681 /** 682 * Validate single input when it loses focus 683 * shows error message in a span element 684 * that is appended to the parent element 685 * 686 * @param {Object} [language] Optional, will override $.formUtils.LANG 687 * @param {Object} [conf] Optional, will override the default settings 688 * @param {Boolean} attachKeyupEvent Optional 689 * @param {String} eventContext 690 * @return {jQuery} 691 */ 692 $.fn.validateInputOnBlur = function (language, conf, attachKeyupEvent, eventContext) { 693 694 $.formUtils.eventType = eventContext; 695 696 if ( this.willPostponeValidation() ) { 697 // This validation has to be postponed 698 var _self = this, 699 postponeTime = this.valAttr('postpone') || 200; 700 701 window.postponedValidation = function () { 702 _self.validateInputOnBlur(language, conf, attachKeyupEvent, eventContext); 703 window.postponedValidation = false;
704 }; 705 706 setTimeout(function () { 707 if (window.postponedValidation) { 708 window.postponedValidation(); 709 } 710 }, postponeTime); 711 712 return this; 713 } 714 715 language = $.extend({}, $.formUtils.LANG, language || {}); 716 $.formUtils.dialogs.removeInputStylingAndMessage(this, conf); 717 718 var $elem = this, 719 $form = $elem.closest('form'), 720 result = $.formUtils.validateInput( 721 $elem, 722 language, 723 conf, 724 $form, 725 eventContext 726 ); 727 728 var reValidate = function() { 729 $elem.validateInputOnBlur(language, conf, false, 'blur.revalidated'); 730 }; 731 732 if (eventContext === 'blur') { 733 $elem 734 .unbind('validation.revalidate', reValidate) 735 .one('validation.revalidate', reValidate); 736 } 737 738 if (attachKeyupEvent) { 739 $elem.removeKeyUpValidation(); 740 } 741 742 if (result.shouldChangeDisplay) { 743 if (result.isValid) { 744 $.formUtils.dialogs.applyInputSuccessStyling($elem, conf); 745 } else { 746 $.formUtils.dialogs.setInlineMessage($elem, result.errorMsg, conf); 747 } 748 } 749 750 if (!result.isValid && attachKeyupEvent) { 751 $elem.validateOnKeyUp(language, conf); 752 } 753 754 return this; 755 }; 756 757 /** 758 * Validate element on keyup-event 759 */ 760 $.fn.validateOnKeyUp = function(language, conf) { 761 this.each(function() { 762 var $input = $(this); 763 if (!$input.valAttr('has-keyup-event')) { 764 $input 765 .valAttr('has-keyup-event', 'true') 766 .bind('keyup.validation', function (evt) { 767 if( evt.keyCode !== 9 ) { 768 $input.validateInputOnBlur(language, conf, false, 'keyup'); 769 } 770 }); 771 } 772 }); 773 return this; 774 }; 775 776 /** 777 * Remove validation on keyup 778 */ 779 $.fn.removeKeyUpValidation = function() { 780 this.each(function() { 781 $(this) 782 .valAttr('has-keyup-event', false) 783 .unbind('keyup.validation'); 784 }); 785 return this; 786 }; 787 788 /** 789 * Short hand for fetching/adding/removing element attributes 790 * prefixed with 'data-validation-' 791 * 792 * @param {String} name 793 * @param {String|Boolean} [val] 794 * @return {String|undefined|jQuery} 795 * @protected 796 */ 797 $.fn.valAttr = function (name, val) { 798 if (val === undefined) { 799 return this.attr('data-validation-' + name); 800 } else if (val === false || val === null) { 801 return this.removeAttr('data-validation-' + name); 802 } else { 803 name = ((name.length > 0) ? '-' + name : ''); 804 return this.attr('data-validation' + name, val); 805 } 806 }; 807 808 /** 809 * Function that validates all inputs in active form 810 * 811 * @param {Object} [language] 812 * @param {Object} [conf] 813 * @param {Boolean} [displayError] Defaults to true 814 */ 815 $.fn.isValid = function (language, conf, displayError) { 816 817 if ($.formUtils.isLoadingModules) { 818 var $self = this; 819 setTimeout(function () { 820 $self.isValid(language, conf, displayError); 821 }, 200); 822 return null; 823 } 824 825 conf = $.extend({}, $.formUtils.defaultConfig(), conf || {}); 826 language = $.extend({}, $.formUtils.LANG, language || {}); 827 displayError = displayError !== false; 828 829 if ($.formUtils.errorDisplayPreventedWhenHalted) { 830 // isValid() was called programmatically with argument displayError set 831 // to false when the validation was halted by any of the validators 832 delete $.formUtils.errorDisplayPreventedWhenHalted; 833 displayError = false; 834 } 835 836 /** 837 * Adds message to error message stack if not already in the message stack 838 * 839 * @param {String} mess 840 * @para {jQuery} $elem 841 */ 842 var addErrorMessage = function (mess, $elem) { 843 if ($.inArray(mess, errorMessages) < 0) { 844 errorMessages.push(mess); 845 } 846 errorInputs.push($elem); 847 $elem.valAttr('current-error', mess); 848 if (displayError) { 849 $.formUtils.dialogs.applyInputErrorStyling($elem, conf); 850 } 851 }, 852 853 /** Holds inputs (of type checkox or radio) already validated, to prevent recheck of mulitple checkboxes & radios */ 854 checkedInputs = [], 855 856 /** Error messages for this validation */ 857 errorMessages = [], 858
859 /** Input elements which value was not valid */ 860 errorInputs = [], 861 862 /** Form instance */ 863 $form = this, 864 865 /** 866 * Tells whether or not to validate element with this name and of this type 867 * 868 * @param {String} name 869 * @param {String} type 870 * @return {Boolean} 871 */ 872 ignoreInput = function (name, type) { 873 if (type === 'submit' || type === 'button' || type === 'reset') { 874 return true; 875 } 876 /*added by ad */ 877 if ( 878 name && 879 ( $form.find( '[name="' + name + '"]' ).attr( 'type' ) == 'text' ) && 880 ( $form.find( '[name="' + name + '"]' ).attr( 'data-validation' ) ) && 881 ( $form.find( '[name="' + name + '"]' ).attr( 'data-validation' ).indexOf( 'required' ) == -1 ) && 882 ( $form.find( '[name="' + name + '"]' ).val() == '' ) 883 ) { 884 return true; 885 } 886 /*added by ad */ 887 return $.inArray(name, conf.ignore || []) > -1; 888 }; 889 890 // Reset style and remove error class 891 if (displayError) { 892 $.formUtils.dialogs.removeAllMessagesAndStyling($form, conf); 893 } 894 895 // Validate element values 896 $form.find('input,textarea,select').filter(':not([type="submit"],[type="button"])').each(function () { 897 var $elem = $(this), 898 elementType = $elem.attr('type'), 899 isCheckboxOrRadioBtn = elementType === 'radio' || elementType === 'checkbox', 900 elementName = $elem.attr('name'); 901 902 if (!ignoreInput(elementName, elementType) && (!isCheckboxOrRadioBtn || $.inArray(elementName, checkedInputs) < 0)) { 903 // added by ad 904 $elem.val( $elem.val().trim() ); 905 906 if (isCheckboxOrRadioBtn) { 907 checkedInputs.push(elementName); 908 } 909 910 var result = $.formUtils.validateInput( 911 $elem, 912 language, 913 conf, 914 $form, 915 'submit' 916 ); 917 918 if (!result.isValid) { 919 addErrorMessage(result.errorMsg, $elem); 920 } else if (result.isValid && result.shouldChangeDisplay) { 921 $elem.valAttr('current-error', false); 922 $.formUtils.dialogs.applyInputSuccessStyling($elem, conf); 923 } 924 } 925 926 }); 927 928 // Run validation callback 929 if (typeof conf.onValidate === 'function') { 930 var errors = conf.onValidate($form); 931 if ($.isArray(errors)) { 932 $.each(errors, function (i, err) { 933 addErrorMessage(err.message, err.element); 934 }); 935 } 936 else if (errors && errors.element && errors.message) { 937 addErrorMessage(errors.message, errors.element); 938 } 939 } 940 941 // Reset form validation flag 942 $.formUtils.isValidatingEntireForm = false; 943 944 // Validation failed 945 if (errorInputs.length > 0) { 946 if (displayError) { 947 if (conf.errorMessagePosition === 'top') { 948 $.formUtils.dialogs.setMessageInTopOfForm($form, errorMessages, conf, language); 949 } else { 950 $.each(errorInputs, function (i, $input) { 951 $.formUtils.dialogs.setInlineMessage($input, $input.valAttr('current-error'), conf); 952 }); 953 } 954 if (conf.scrollToTopOnError) { 955 $.formUtils.$win.scrollTop($form.offset().top - 20); 956 } 957 } 958 } 959 960 if (!displayError && $.formUtils.haltValidation) { 961 $.formUtils.errorDisplayPreventedWhenHalted = true; 962 } 963 964 return errorInputs.length === 0 && !$.formUtils.haltValidation; 965 }; 966 967 /** 968 * Plugin for displaying input length restriction 969 */ 970 $.fn.restrictLength = function (maxLengthElement) { 971 new $.formUtils.lengthRestriction(this, maxLengthElement); 972 return this; 973 }; 974 975 /** 976 * Add suggestion dropdown to inputs having data-suggestions with a comma 977 * separated string with suggestions 978 * @param {Array} [settings] 979 * @returns {jQuery} 980 */ 981 $.fn.addSuggestions = function (settings) { 982 var sugs = false; 983 this.find('input').each(function () { 984 var $field = $(this); 985 986 sugs = $.split($field.attr('data-suggestions')); 987 988 if (sugs.length > 0 && !$field.hasClass('has-suggestions')) { 989 $.formUtils.suggest($field, sugs, settings); 990 $field.addClass('has-suggestions'); 991 } 992 }); 993 return this; 994 }; 995 996 997})(jQuery, window); 998 999/** 1000 * Utility methods used for handling loading of modules (attached to $.formUtils) 1001 */ 1002(function($) { 1003 1004 'use strict'; 1005 1006 $.formUtils = $.extend($.formUtils || {}, { 1007 1008 /** 1009 * @var {Boolean} 1010 */ 1011 isLoadingModules: false, 1012 1013 /** 1014 * @var {Object} 1015 */ 1016 loadedModules: {}, 1017 1018 /** 1019 * @param {String} name 1020 */ 1021 registerLoadedModule: function (name) { 1022 this.loadedModules[$.trim(name).toLowerCase()] = true; 1023 }, 1024 1025 /** 1026 * @param {String} name 1027 * @return {Boolean} 1028 */ 1029 hasLoadedModule: function (name) { 1030 return $.trim(name).toLowerCase() in this.loadedModules; 1031 }, 1032 1033 /** 1034 * @example
1035 * $.formUtils.loadModules('date, security.dev'); 1036 * 1037 * Will load the scripts date.js and security.dev.js from the 1038 * directory where this script resides. If you want to load 1039 * the modules from another directory you can use the 1040 * path argument. 1041 * 1042 * The script will be cached by the browser unless the module 1043 * name ends with .dev 1044 * 1045 * @param {String} modules - Comma separated string with module file names (no directory nor file extension) 1046 * @param {String} [path] - Path where the module files are located if their not in the same directory as the core modules 1047 * @param {function} [callback] - Callback invoked when all modules are loaded 1048 */ 1049 loadModules: function (modules, path, callback) { 1050 1051 if ($.formUtils.isLoadingModules) { 1052 setTimeout(function () { 1053 $.formUtils.loadModules(modules, path, callback); 1054 }, 100); 1055 return; 1056 } 1057 1058 var loadModuleScripts = function (modules, path) { 1059 1060 var moduleList = $.split(modules), 1061 numModules = moduleList.length, 1062 moduleLoadedCallback = function () { 1063 numModules--; 1064 if (numModules === 0) { 1065 $.formUtils.isLoadingModules = false; 1066 if (typeof callback === 'function') { 1067 callback(); 1068 } 1069 } 1070 }; 1071 1072 if (numModules > 0) { 1073 $.formUtils.isLoadingModules = true; 1074 } 1075 1076 var cacheSuffix = '?_=' + ( new Date().getTime() ), 1077 appendToElement = document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]; 1078 1079 $.each(moduleList, function (i, modName) { 1080 modName = $.trim(modName); 1081 if (modName.length === 0 || $.formUtils.hasLoadedModule(modName)) { 1082 moduleLoadedCallback(); 1083 } else { 1084 var scriptUrl = path + modName + (modName.slice(-3) === '.js' ? '' : '.js'), 1085 script = document.createElement('SCRIPT'); 1086 1087 if (typeof define === 'function' && define.amd) { 1088 require([scriptUrl + ( scriptUrl.slice(-7) === '.dev.js' ? cacheSuffix : '' )], moduleLoadedCallback); 1089 } else { 1090 // Load the script 1091 script.type = 'text/javascript'; 1092 script.onload = moduleLoadedCallback; 1093 script.src = scriptUrl + ( scriptUrl.slice(-7) === '.dev.js' ? cacheSuffix : '' ); 1094 script.onerror = function() { 1095 $.formUtils.warn('Unable to load form validation module '+scriptUrl, true); 1096 moduleLoadedCallback(); 1097 }; 1098 script.onreadystatechange = function () { 1099 // IE 7 fix 1100 if (this.readyState === 'complete' || this.readyState === 'loaded') { 1101 moduleLoadedCallback(); 1102 // Handle memory leak in IE 1103 this.onload = null; 1104 this.onreadystatechange = null; 1105 } 1106 }; 1107 appendToElement.appendChild(script); 1108 } 1109 } 1110 }); 1111 }; 1112 1113 if (path) { 1114 loadModuleScripts(modules, path); 1115 } else { 1116 var findScriptPathAndLoadModules = function () { 1117 var foundPath = false; 1118 $('script[src*="form-validator"]').each(function () { 1119 var isScriptFromPluginNodeModulesDirectory = this.src.split('form-validator')[1].split('node_modules').length > 1; 1120 if (!isScriptFromPluginNodeModulesDirectory) { 1121 foundPath = this.src.substr(0, this.src.lastIndexOf('/')) + '/'; 1122 if (foundPath === '/') { 1123 foundPath = ''; 1124 } 1125 return false; 1126 } 1127 }); 1128 1129 if (foundPath !== false) { 1130 loadModuleScripts(modules, foundPath); 1131 return true; 1132 } 1133 return false; 1134 }; 1135 1136 if (!findScriptPathAndLoadModules()) { 1137 $(function () { 1138 var hasLoadedModuleScripts = findScriptPathAndLoadModules(); 1139 if (!hasLoadedModuleScripts) { 1140 // The modules may have been inserted via a minified script 1141 if (typeof callback === 'function') { 1142 callback(); 1143 } 1144 } 1145 }); 1146 } 1147 } 1148 } 1149 1150 }); 1151 1152})(jQuery); 1153 1154/** 1155 * Setup function for the plugin 1156 */ 1157(function ($) { 1158 1159 'use strict'; 1160 1161 1162 /** 1163 * A bit smarter split function 1164 * delimiter can be space, comma, dash or pipe 1165 * @param {String} val 1166 * @param {Function|String} [callback] 1167 * @param {Boolean}
1167 [allowSpaceAsDelimiter] 1168 * @returns {Array|void} 1169 */ 1170 $.split = function (val, callback, allowSpaceAsDelimiter) { 1171 // default to true 1172 allowSpaceAsDelimiter = allowSpaceAsDelimiter === undefined || allowSpaceAsDelimiter === true; 1173 var pattern = '[,|'+(allowSpaceAsDelimiter ? '\\s':'')+'-]\\s*', 1174 regex = new RegExp(pattern, 'g'); 1175 if (typeof callback !== 'function') { 1176 // return array 1177 if (!val) { 1178 return []; 1179 } 1180 var values = []; 1181 $.each(val.split(callback ? callback : regex), 1182 function (i, str) { 1183 str = $.trim(str); 1184 if (str.length) { 1185 values.push(str); 1186 } 1187 } 1188 ); 1189 return values; 1190 } else if (val) { 1191 // exec callback func on each 1192 $.each(val.split(regex), 1193 function (i, str) { 1194 str = $.trim(str); 1195 if (str.length) { 1196 return callback(str, i); 1197 } 1198 } 1199 ); 1200 } 1201 }; 1202 1203 /** 1204 * Short hand function that makes the validation setup require less code 1205 * @param conf 1206 */ 1207 $.validate = function (conf) { 1208 1209 var defaultConf = $.extend($.formUtils.defaultConfig(), { 1210 form: 'form', 1211 validateOnEvent: false, 1212 validateOnBlur: true, 1213 validateCheckboxRadioOnClick: true, 1214 showHelpOnFocus: true, 1215 addSuggestions: true, 1216 modules: '', 1217 onModulesLoaded: null, 1218 language: false, 1219 onSuccess: false, 1220 onError: false, 1221 onElementValidate: false 1222 }); 1223 1224 conf = $.extend(defaultConf, conf || {}); 1225 1226 $(window).trigger('formValidationPluginInit', [conf]); 1227 1228 if( conf.lang && conf.lang !== 'en' ) { 1229 var langModule = 'lang/'+conf.lang+'.js'; 1230 conf.modules += conf.modules.length ? ','+langModule : langModule; 1231 } 1232 1233 // Add validation to forms 1234 $(conf.form).each(function (i, form) { 1235 1236 // Make a reference to the config for this form 1237 form.validationConfig = conf; 1238 1239 // Trigger jQuery event that we're about to setup validation 1240 var $form = $(form); 1241 $form.trigger('formValidationSetup', [$form, conf]); 1242 1243 // Remove classes and event handlers that might have been 1244 // added by a previous call to $.validate 1245 $form.find('.has-help-txt') 1246 .unbind('focus.validation') 1247 .unbind('blur.validation'); 1248 1249 $form 1250 .removeClass('has-validation-callback') 1251 .unbind('submit.validation') 1252 .unbind('reset.validation') 1253 .find('input[data-validation],textarea[data-validation]') 1254 .unbind('blur.validation'); 1255 1256 // Validate when submitted 1257 $form.bind('submit.validation', function (evt) { 1258 1259 var $form = $(this), 1260 stop = function() { 1261 evt.stopImmediatePropagation(); 1262 return false; 1263 }; 1264 1265 if ($.formUtils.haltValidation) { 1266 // pressing several times on submit button while validation is halted 1267 return stop(); 1268 } 1269 1270 if ($.formUtils.isLoadingModules) { 1271 setTimeout(function () { 1272 $form.trigger('submit.validation'); 1273 }, 200); 1274 return stop(); 1275 } 1276 1277 var valid = $form.isValid(conf.language, conf); 1278 if ($.formUtils.haltValidation) { 1279 // Validation got halted by one of the validators 1280 return stop(); 1281 } else { 1282 if (valid && typeof conf.onSuccess === 'function') { 1283 var callbackResponse = conf.onSuccess($form); 1284 if (callbackResponse === false) { 1285 return stop(); 1286 } 1287 } else if (!valid && typeof conf.onError === 'function') { 1288 conf.onError($form); 1289 return stop(); 1290 } else { 1291 return valid ? true : stop(); 1292 } 1293 } 1294 }) 1295 .bind('reset.validation', function () { 1296 $.formUtils.dialogs.removeAllMessagesAndStyling($form, conf); 1297 }) 1298 .addClass('has-validation-callback'); 1299 1300 if (conf.showHelpOnFocus) { 1301 $form.showHelpOnFocus(); 1302 } 1303 if (conf.addSuggestions) { 1304 $form.addSuggestions(); 1305 } 1306 if (conf.validateOnBlur) { 1307 $form.validateOnBlur(conf.language, conf); 1308 $form.bind('html5ValidationAttrsFound', function () { 1309 $form.validateOnBlur(conf.language, conf); 1310 }); 1311 } 1312 if (conf.validateOnEvent) { 1313 $form.validateOnEvent(conf.language, conf); 1314 } 1315 }); 1316 1317 if (conf.modules !== '') {
1318 $.formUtils.loadModules(conf.modules, null, function() { 1319 if (typeof conf.onModulesLoaded === 'function') { 1320 conf.onModulesLoaded(); 1321 } 1322 var $form = typeof conf.form === 'string' ? $(conf.form) : conf.form; 1323 $.formUtils.$win.trigger('validatorsLoaded', [$form, conf]); 1324 }); 1325 } 1326 }; 1327 1328})(jQuery); 1329 1330/** 1331 * Utility methods and properties attached to $.formUtils 1332 */ 1333(function($, window) { 1334 1335 'use strict'; 1336 1337 var $win = $(window); 1338 1339 $.formUtils = $.extend($.formUtils || {}, { 1340 1341 $win: $win, 1342 1343 /** 1344 * Default config for $(...).isValid(); 1345 */ 1346 defaultConfig: function () { 1347 return { 1348 ignore: [], // Names of inputs not to be validated even though `validationRuleAttribute` containing the validation rules tells us to 1349 errorElementClass: 'error', // Class that will be put on elements which value is invalid 1350 successElementClass: 'valid', // Class that will be put on elements that has been validated with success 1351 borderColorOnError: '#b94a48', // Border color of elements which value is invalid, empty string to not change border color 1352 errorMessageClass: 'form-error', // class name of div containing error messages when validation fails 1353 validationRuleAttribute: 'data-validation', // name of the attribute holding the validation rules 1354 validationErrorMsgAttribute: 'data-validation-error-msg', // define custom err msg inline with element 1355 errorMessagePosition: 'inline', // Can be either "top" or "inline" 1356 errorMessageTemplate: { 1357 container: '<div class="{errorMessageClass} alert alert-danger">{messages}</div>', 1358 messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>', 1359 field: '<li>{msg}</li>' 1360 }, 1361 scrollToTopOnError: true, 1362 dateFormat: 'yyyy-mm-dd', 1363 addValidClassOnAll: false, // whether or not to apply class="valid" even if the input wasn't validated 1364 decimalSeparator: '.', 1365 inputParentClassOnError: 'has-error', // twitter-bootstrap default class name 1366 inputParentClassOnSuccess: 'has-success', // twitter-bootstrap default class name 1367 validateHiddenInputs: false, // whether or not hidden inputs should be validated 1368 inlineErrorMessageCallback: false, 1369 submitErrorMessageCallback: false 1370 }; 1371 }, 1372 1373 /** 1374 * Available validators 1375 */ 1376 validators: {}, 1377 1378 /** 1379 * Available sanitizers 1380 */ 1381 sanitizers: {}, 1382 1383 /** 1384 * Events triggered by form validator 1385 */ 1386 _events: {load: [], valid: [], invalid: []}, 1387 1388 /** 1389 * Setting this property to true during validation will 1390 * stop further validation from taking place and form will 1391 * not be sent 1392 */ 1393 haltValidation: false, 1394 1395 /** 1396 * Function for adding a validator 1397 * @see $.formUtils.addAsyncValidator (async.js) 1398 * @param {Object} validator 1399 */ 1400 addValidator: function (validator) { 1401 // prefix with "validate_" for backward compatibility reasons 1402 var name = validator.name.indexOf('validate_') === 0 ? validator.name : 'validate_' + validator.name; 1403 if (validator.validateOnKeyUp === undefined) { 1404 validator.validateOnKeyUp = true; 1405 } 1406 this.validators[name] = validator; 1407 }, 1408 1409 /** 1410 * Function for adding a sanitizer 1411 * @param {Object} sanitizer 1412 */ 1413 addSanitizer: function (sanitizer) { 1414 this.sanitizers[sanitizer.name] = sanitizer; 1415 }, 1416 1417 /** 1418 * Warn user via the console if available 1419 */ 1420 warn: function(msg, fallbackOnAlert) { 1421 if( 'console' in window ) { 1422 if( typeof window.console.warn === 'function' ) { 1423 window.console.warn(msg); 1424 } else if( typeof window.console.log === 'function' ) { 1425 window.console.log(msg); 1426 } 1427 } else if (fallbackOnAlert) { 1428 // This is for some old IE version... 1429 alert(msg); 1430 } 1431 }, 1432 1433 /** 1434 * Same as input $.fn.val() but also supporting input of typ radio or checkbox 1435 * @example 1436 * 1437 * $.formUtils.getValue('.myRadioButtons', $('#some-form')); 1438 * $.formUtils.getValue($('#some-form').find('.check-boxes')); 1439 * 1440 * @param query 1441 * @param $parent 1442 * @returns {String|Boolean} 1443 */ 1444 getValue: function(query, $parent) {
1445 var $inputs = $parent ? $parent.find(query) : query; 1446 if ($inputs.length > 0 ) { 1447 var type = $inputs.eq(0).attr('type'); 1448 if (type === 'radio' || type === 'checkbox') { 1449 return $inputs.filter(':checked').val() || ''; 1450 } else { 1451 return $inputs.val() || ''; 1452 } 1453 } 1454 return false; 1455 }, 1456 1457 /** 1458 * Validate the value of given element according to the validation rules 1459 * found in the attribute data-validation. Will return an object representing 1460 * a validation result, having the props shouldChangeDisplay, isValid and errorMsg 1461 * @param {jQuery} $elem 1462 * @param {Object} language ($.formUtils.LANG) 1463 * @param {Object} conf 1464 * @param {jQuery} $form 1465 * @param {String} [eventContext] 1466 * @return {Object} 1467 */ 1468 validateInput: function ($elem, language, conf, $form, eventContext) { 1469 1470 conf = conf || $.formUtils.defaultConfig(); 1471 language = language || $.formUtils.LANG; 1472 1473 if (!$form.length) { 1474 $form = $elem.parent(); 1475 } 1476 1477 var value = this.getValue($elem); 1478 1479 $elem 1480 .valAttr('skipped', false) 1481 .one('beforeValidation', function() { 1482 // Skip input because its hidden or disabled 1483 // Doing this in a callback makes it possible for others to prevent the default 1484 // behaviour by binding to the same event and call evt.stopImmediatePropagation() 1485 if ($elem.attr('disabled') || (!$elem.is(':visible') && !conf.validateHiddenInputs)) { 1486 $elem.valAttr('skipped', 1); 1487 } 1488 }) 1489 .trigger('beforeValidation', [value, language, conf]); 1490 1491 var inputIsOptional = $elem.valAttr('optional') === 'true', 1492 skipBecauseItsEmpty = !value && inputIsOptional, 1493 validationRules = $elem.attr(conf.validationRuleAttribute), 1494 isValid = true, 1495 errorMsg = '', 1496 result = {isValid: true, shouldChangeDisplay:true, errorMsg:''}; 1497 1498 // For input type="number", browsers attempt to parse the entered value into a number. 1499 // If the input is not numeric, browsers handle the situation differently: 1500 // Chrome 48 simply disallows non-numeric input; FF 44 clears out the input box on blur; 1501 // Safari 5 parses the entered string to find a leading number. 1502 // If the input fails browser validation, the browser sets the input value equal to an empty string. 1503 // Therefore, we cannot distinguish (apart from hacks) between an empty input type="text" and one with a 1504 // value that can't be parsed by the browser. 1505 1506 if (!validationRules || skipBecauseItsEmpty || $elem.valAttr('skipped')) { 1507 result.shouldChangeDisplay = conf.addValidClassOnAll; 1508 return result; 1509 } 1510 1511 // Filter out specified characters 1512 var ignore = $elem.valAttr('ignore'); 1513 if (ignore) { 1514 $.each(ignore.split(''), function(i, character) { 1515 value = value.replace(new RegExp('\\'+character, 'g'), ''); 1516 }); 1517 } 1518 1519 $.split(validationRules, function (rule) { 1520 1521 if (rule.indexOf('validate_') !== 0) { 1522 rule = 'validate_' + rule; 1523 } 1524 1525 var validator = $.formUtils.validators[rule]; 1526 1527 if (validator) { 1528 1529 // special change of element for checkbox_group rule 1530 if (rule === 'validate_checkbox_group') { 1531 // set element to first in group, so error msg attr doesn't need to be set on all elements in group 1532 $elem = $form.find('[name="' + $elem.attr('name') + '"]:eq(0)'); 1533 } 1534 1535 if (eventContext !== 'keyup' || validator.validateOnKeyUp) { 1536 // A validator can prevent itself from getting triggered on keyup 1537 isValid = validator.validatorFunction(value, $elem, conf, language, $form, eventContext); 1538 } 1539 1540 if (!isValid) { 1541 if (conf.validateOnBlur) { 1542 $elem.validateOnKeyUp(language, conf); 1543 } 1544 errorMsg = $.formUtils.dialogs.resolveErrorMessage($elem, validator, rule, conf, language); 1545 return false; // break iteration 1546 } 1547 1548 } else { 1549 1550 // todo: Add some validator lookup function and tell immediately which module is missing 1551 throw new Error('Using undefined validator "' + rule + 1552 '". Maybe you have forgotten to load the module that "' + rule +'" belongs to?'); 1553 1554 } 1555 1556 }); 1557 1558 1559 if (isValid === false) { 1560 $elem.trigger('validation', false); 1561 result.errorMsg = errorMsg; 1562 result.isValid = false;
1563 result.shouldChangeDisplay = true; 1564 } else if (isValid === null) { 1565 // A validatorFunction returning null means that it's not able to validate 1566 // the input at this time. Most probably some async stuff need to gets finished 1567 // first and then the validator will re-trigger the validation. 1568 result.shouldChangeDisplay = false; 1569 } else { 1570 $elem.trigger('validation', true); 1571 result.shouldChangeDisplay = true; 1572 } 1573 1574 // Run element validation callback 1575 if (typeof conf.onElementValidate === 'function' && errorMsg !== null) { 1576 conf.onElementValidate(result.isValid, $elem, $form, errorMsg); 1577 } 1578 1579 $elem.trigger('afterValidation', [result, eventContext]); 1580 1581 return result; 1582 }, 1583 1584 /** 1585 * Is it a correct date according to given dateFormat. Will return false if not, otherwise 1586 * an array 0=>year 1=>month 2=>day 1587 * 1588 * @param {String} val 1589 * @param {String} dateFormat 1590 * @param {Boolean} [addMissingLeadingZeros] 1591 * @return {Array}|{Boolean} 1592 */ 1593 parseDate: function (val, dateFormat, addMissingLeadingZeros) { 1594 var divider = dateFormat.replace(/[a-zA-Z]/gi, '').substring(0, 1), 1595 regexp = '^', 1596 formatParts = dateFormat.split(divider || null), 1597 matches, day, month, year; 1598 1599 $.each(formatParts, function (i, part) { 1600 regexp += (i > 0 ? '\\' + divider : '') + '(\\d{' + part.length + '})'; 1601 }); 1602 1603 regexp += '$'; 1604 1605 if (addMissingLeadingZeros) { 1606 var newValueParts = []; 1607 $.each(val.split(divider), function(i, part) { 1608 if(part.length === 1) { 1609 part = '0'+part; 1610 } 1611 newValueParts.push(part); 1612 }); 1613 val = newValueParts.join(divider); 1614 } 1615 1616 matches = val.match(new RegExp(regexp)); 1617 if (matches === null) { 1618 return false; 1619 } 1620 1621 var findDateUnit = function (unit, formatParts, matches) { 1622 for (var i = 0; i < formatParts.length; i++) { 1623 if (formatParts[i].substring(0, 1) === unit) { 1624 return $.formUtils.parseDateInt(matches[i + 1]); 1625 } 1626 } 1627 return -1; 1628 }; 1629 1630 month = findDateUnit('m', formatParts, matches); 1631 day = findDateUnit('d', formatParts, matches); 1632 year = findDateUnit('y', formatParts, matches); 1633 1634 if ((month === 2 && day > 28 && (year % 4 !== 0 || year % 100 === 0 && year % 400 !== 0)) || 1635 (month === 2 && day > 29 && (year % 4 === 0 || year % 100 !== 0 && year % 400 === 0)) || 1636 month > 12 || month === 0) { 1637 return false; 1638 } 1639 if ((this.isShortMonth(month) && day > 30) || (!this.isShortMonth(month) && day > 31) || day === 0) { 1640 return false; 1641 } 1642 1643 return [year, month, day]; 1644 }, 1645 1646 /** 1647 * skum fix. är talet 05 eller lägre ger parseInt rätt int annars får man 0 när man kör parseInt? 1648 * 1649 * @param {String} val 1650 * @return {Number} 1651 */ 1652 parseDateInt: function (val) { 1653 if (val.indexOf('0') === 0) { 1654 val = val.replace('0', ''); 1655 } 1656 return parseInt(val, 10); 1657 }, 1658 1659 /** 1660 * Has month only 30 days? 1661 * 1662 * @param {Number} m 1663 * @return {Boolean} 1664 */ 1665 isShortMonth: function (m) { 1666 return (m % 2 === 0 && m < 7) || (m % 2 !== 0 && m > 7); 1667 }, 1668 1669 /** 1670 * Restrict input length 1671 * 1672 * @param {jQuery} $inputElement Jquery Html object 1673 * @param {jQuery} $maxLengthElement jQuery Html Object 1674 * @return void 1675 */ 1676 lengthRestriction: function ($inputElement, $maxLengthElement) { 1677 // read maxChars from counter display initial text value 1678 var maxChars = parseInt($maxLengthElement.text(), 10), 1679 charsLeft = 0, 1680 1681 // internal function does the counting and sets display value 1682 countCharacters = function () { 1683 var numChars = $inputElement.val().length; 1684 if (numChars > maxChars) { 1685 // get current scroll bar position 1686 var currScrollTopPos = $inputElement.scrollTop(); 1687 // trim value to max length 1688 $inputElement.val($inputElement.val().substring(0, maxChars)); 1689 $inputElement.scrollTop(currScrollTopPos); 1690 } 1691 charsLeft = maxChars - numChars; 1692 if (charsLeft < 0) { 1693 charsLeft = 0; 1694 } 1695 1696 // set counter text 1697 $maxLengthElement.text(charsLeft); 1698 }; 1699 1700 // bind events to this element 1701 // setTimeout is needed, cut or paste fires before val is available 1702 $($inputElement).bind('keydown keyup keypress focus blur', countCharacters) 1703 .bind('cut paste', function () { 1704 setTimeout(countCharacters, 100); 1705 }); 1706
1707 // count chars on pageload, if there are prefilled input-values 1708 $(document).bind('ready', countCharacters); 1709 }, 1710 1711 /** 1712 * Test numeric against allowed range 1713 * 1714 * @param $value int 1715 * @param $rangeAllowed str; (1-2, min1, max2, 10) 1716 * @return array 1717 */ 1718 numericRangeCheck: function (value, rangeAllowed) { 1719 // split by dash 1720 var range = $.split(rangeAllowed), 1721 // min or max 1722 minmax = parseInt(rangeAllowed.substr(3), 10); 1723 1724 if( range.length === 1 && rangeAllowed.indexOf('min') === -1 && rangeAllowed.indexOf('max') === -1 ) { 1725 range = [rangeAllowed, rangeAllowed]; // only a number, checking agains an exact number of characters 1726 } 1727 1728 // range ? 1729 if (range.length === 2 && (value < parseInt(range[0], 10) || value > parseInt(range[1], 10) )) { 1730 return [ 'out', range[0], range[1] ]; 1731 } // value is out of range 1732 else if (rangeAllowed.indexOf('min') === 0 && (value < minmax )) // min 1733 { 1734 return ['min', minmax]; 1735 } // value is below min 1736 else if (rangeAllowed.indexOf('max') === 0 && (value > minmax )) // max 1737 { 1738 return ['max', minmax]; 1739 } // value is above max 1740 // since no other returns executed, value is in allowed range 1741 return [ 'ok' ]; 1742 }, 1743 1744 1745 _numSuggestionElements: 0, 1746 _selectedSuggestion: null, 1747 _previousTypedVal: null, 1748 1749 /** 1750 * Utility function that can be used to create plugins that gives
1751 * suggestions when inputs is typed into 1752 * @param {jQuery} $elem 1753 * @param {Array} suggestions 1754 * @param {Object} settings - Optional 1755 * @return {jQuery} 1756 */ 1757 suggest: function ($elem, suggestions, settings) { 1758 var conf = { 1759 css: { 1760 maxHeight: '150px', 1761 background: '#FFF', 1762 lineHeight: '150%', 1763 textDecoration: 'underline', 1764 overflowX: 'hidden', 1765 overflowY: 'auto', 1766 border: '#CCC solid 1px', 1767 borderTop: 'none', 1768 cursor: 'pointer' 1769 }, 1770 activeSuggestionCSS: { 1771 background: '#E9E9E9' 1772 } 1773 }, 1774 setSuggsetionPosition = function ($suggestionContainer, $input) { 1775 var offset = $input.offset(); 1776 $suggestionContainer.css({ 1777 width: $input.outerWidth(), 1778 left: offset.left + 'px', 1779 top: (offset.top + $input.outerHeight()) + 'px' 1780 }); 1781 }; 1782 1783 if (settings) { 1784 $.extend(conf, settings); 1785 } 1786 1787 conf.css.position = 'absolute'; 1788 conf.css['z-index'] = 9999; 1789 $elem.attr('autocomplete', 'off'); 1790 1791 if (this._numSuggestionElements === 0) { 1792 // Re-position suggestion container if window size changes 1793 $win.bind('resize', function () { 1794 $('.jquery-form-suggestions').each(function () { 1795 var $container = $(this), 1796 suggestID = $container.attr('data-suggest-container'); 1797 setSuggsetionPosition($container, $('.suggestions-' + suggestID).eq(0)); 1798 }); 1799 }); 1800 } 1801 1802 this._numSuggestionElements++; 1803 1804 var onSelectSuggestion = function ($el) { 1805 var suggestionId = $el.valAttr('suggestion-nr'); 1806 $.formUtils._selectedSuggestion = null; 1807 $.formUtils._previousTypedVal = null; 1808 $('.jquery-form-suggestion-' + suggestionId).fadeOut('fast'); 1809 }; 1810 1811 $elem 1812 .data('suggestions', suggestions) 1813 .valAttr('suggestion-nr', this._numSuggestionElements) 1814 .unbind('focus.suggest') 1815 .bind('focus.suggest', function () { 1816 $(this).trigger('keyup'); 1817 $.formUtils._selectedSuggestion = null; 1818 }) 1819 .unbind('keyup.suggest') 1820 .bind('keyup.suggest', function () { 1821 var $input = $(this), 1822 foundSuggestions = [], 1823 val = $.trim($input.val()).toLocaleLowerCase(); 1824 1825 if (val === $.formUtils._previousTypedVal) { 1826 return; 1827 } 1828 else { 1829 $.formUtils._previousTypedVal = val; 1830 } 1831 1832 var hasTypedSuggestion = false, 1833 suggestionId = $input.valAttr('suggestion-nr'), 1834 $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId); 1835 1836 $suggestionContainer.scrollTop(0); 1837 1838 // Find the right suggestions 1839 if (val !== '') { 1840 var findPartial = val.length > 2; 1841 $.each($input.data('suggestions'), function (i, suggestion) { 1842 var lowerCaseVal = suggestion.toLocaleLowerCase(); 1843 if (lowerCaseVal === val) { 1844 foundSuggestions.push('<strong>' + suggestion + '</strong>'); 1845 hasTypedSuggestion = true; 1846 return false; 1847 } else if (lowerCaseVal.indexOf(val) === 0 || (findPartial && lowerCaseVal.indexOf(val) > -1)) { 1848 foundSuggestions.push(suggestion.replace(new RegExp(val, 'gi'), '<strong>$&</strong>')); 1849 } 1850 }); 1851 } 1852 1853 // Hide suggestion container 1854 if (hasTypedSuggestion || (foundSuggestions.length === 0 && $suggestionContainer.length > 0)) { 1855 $suggestionContainer.hide(); 1856 } 1857 1858 // Create suggestion container if not already exists 1859 else if (foundSuggestions.length > 0 && $suggestionContainer.length === 0) {
1860 $suggestionContainer = $('<div></div>').css(conf.css).appendTo('body'); 1861 $elem.addClass('suggestions-' + suggestionId); 1862 $suggestionContainer 1863 .attr('data-suggest-container', suggestionId) 1864 .addClass('jquery-form-suggestions') 1865 .addClass('jquery-form-suggestion-' + suggestionId); 1866 } 1867 1868 // Show hidden container 1869 else if (foundSuggestions.length > 0 && !$suggestionContainer.is(':visible')) { 1870 $suggestionContainer.show(); 1871 } 1872 1873 // add suggestions 1874 if (foundSuggestions.length > 0 && val.length !== foundSuggestions[0].length) { 1875 1876 // put container in place every time, just in case 1877 setSuggsetionPosition($suggestionContainer, $input); 1878 1879 // Add suggestions HTML to container 1880 $suggestionContainer.html(''); 1881 $.each(foundSuggestions, function (i, text) { 1882 $('<div></div>') 1883 .append(text) 1884 .css({ 1885 overflow: 'hidden', 1886 textOverflow: 'ellipsis', 1887 whiteSpace: 'nowrap', 1888 padding: '5px' 1889 }) 1890 .addClass('form-suggest-element') 1891 .appendTo($suggestionContainer) 1892 .click(function () { 1893 $input.focus(); 1894 $input.val($(this).text()); 1895 $input.trigger('change'); 1896 onSelectSuggestion($input); 1897 }); 1898 }); 1899 } 1900 }) 1901 .unbind('keydown.validation') 1902 .bind('keydown.validation', function (e) { 1903 var code = (e.keyCode ? e.keyCode : e.which), 1904 suggestionId, 1905 $suggestionContainer, 1906 $input = $(this); 1907 1908 if (code === 13 && $.formUtils._selectedSuggestion !== null) { 1909 suggestionId = $input.valAttr('suggestion-nr'); 1910 $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId); 1911 if ($suggestionContainer.length > 0) { 1912 var newText = $suggestionContainer.find('div').eq($.formUtils._selectedSuggestion).text(); 1913 $input.val(newText); 1914 $input.trigger('change'); 1915 onSelectSuggestion($input); 1916 e.preventDefault(); 1917 } 1918 } 1919 else { 1920 suggestionId = $input.valAttr('suggestion-nr'); 1921 $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId); 1922 var $suggestions = $suggestionContainer.children(); 1923 if ($suggestions.length > 0 && $.inArray(code, [38, 40]) > -1) { 1924 if (code === 38) { // key up 1925 if ($.formUtils._selectedSuggestion === null) { 1926 $.formUtils._selectedSuggestion = $suggestions.length - 1; 1927 } 1928 else{ 1929 $.formUtils._selectedSuggestion--; 1930 } 1931 if ($.formUtils._selectedSuggestion < 0) { 1932 $.formUtils._selectedSuggestion = $suggestions.length - 1; 1933 } 1934 } 1935 else if (code === 40) { // key down 1936 if ($.formUtils._selectedSuggestion === null) { 1937 $.formUtils._selectedSuggestion = 0; 1938 } 1939 else { 1940 $.formUtils._selectedSuggestion++; 1941 } 1942 if ($.formUtils._selectedSuggestion > ($suggestions.length - 1)) { 1943 $.formUtils._selectedSuggestion = 0; 1944 } 1945 } 1946 1947 // Scroll in suggestion window 1948 var containerInnerHeight = $suggestionContainer.innerHeight(), 1949 containerScrollTop = $suggestionContainer.scrollTop(), 1950 suggestionHeight = $suggestionContainer.children().eq(0).outerHeight(), 1951 activeSuggestionPosY = suggestionHeight * ($.formUtils._selectedSuggestion); 1952 1953 if (activeSuggestionPosY < containerScrollTop || activeSuggestionPosY > (containerScrollTop + containerInnerHeight)) { 1954 $suggestionContainer.scrollTop(activeSuggestionPosY); 1955 } 1956 1957 $suggestions 1958 .removeClass('active-suggestion') 1959 .css('background', 'none') 1960 .eq($.formUtils._selectedSuggestion) 1961 .addClass('active-suggestion') 1962 .css(conf.activeSuggestionCSS); 1963 1964 e.preventDefault(); 1965 return false;
1966 } 1967 } 1968 }) 1969 .unbind('blur.suggest') 1970 .bind('blur.suggest', function () { 1971 onSelectSuggestion($(this)); 1972 }); 1973 1974 return $elem; 1975 }, 1976 1977 /** 1978 * Error dialogs 1979 * 1980 * @var {Object} 1981 */ 1982 LANG: { 1983 errorTitle: 'Form submission failed!', 1984 requiredField: 'This is a required field', 1985 requiredFields: 'You have not answered all required fields', 1986 badTime: 'You have not given a correct time', 1987 badEmail: 'You have not given a correct e-mail address', 1988 badTelephone: 'You have not given a correct phone number', 1989 badSecurityAnswer: 'You have not given a correct answer to the security question', 1990 badDate: 'You have not given a correct date', 1991 lengthBadStart: 'The input value must be between ', 1992 lengthBadEnd: ' characters', 1993 lengthTooLongStart: 'The input value is longer than ', 1994 lengthTooShortStart: 'The input value is shorter than ', 1995 notConfirmed: 'Input values could not be confirmed', 1996 badDomain: 'Incorrect domain value', 1997 badUrl: 'The input value is not a correct URL', 1998 badCustomVal: 'The input value is incorrect', 1999 andSpaces: ' and spaces ', 2000 badInt: 'The input value was not a correct number', 2001 badSecurityNumber: 'Your social security number was incorrect', 2002 badUKVatAnswer: 'Incorrect UK VAT Number', 2003 badUKNin: 'Incorrect UK NIN', 2004 badUKUtr: 'Incorrect UK UTR Number', 2005 badStrength: 'The password isn\'t strong enough', 2006 badNumberOfSelectedOptionsStart: 'You have to choose at least ', 2007 badNumberOfSelectedOptionsEnd: ' answers', 2008 badAlphaNumeric: 'The input value can only contain alphanumeric characters ', 2009 badAlphaNumericExtra: ' and ', 2010 wrongFileSize: 'The file you are trying to upload is too large (max %s)', 2011 wrongFileType: 'Only files of type %s is allowed', 2012 groupCheckedRangeStart: 'Please choose between ', 2013 groupCheckedTooFewStart: 'Please choose at least ', 2014 groupCheckedTooManyStart: 'Please choose a maximum of ', 2015 groupCheckedEnd: ' item(s)', 2016 badCreditCard: 'The credit card number is not correct', 2017 badCVV: 'The CVV number was not correct', 2018 wrongFileDim : 'Incorrect image dimensions,', 2019 imageTooTall : 'the image can not be taller than', 2020 imageTooWide : 'the image can not be wider than', 2021 imageTooSmall : 'the image was too small', 2022 min : 'min', 2023 max : 'max', 2024 imageRatioNotAccepted : 'Image ratio is not be accepted', 2025 badBrazilTelephoneAnswer: 'The phone number entered is invalid', 2026 badBrazilCEPAnswer: 'The CEP entered is invalid', 2027 badBrazilCPFAnswer: 'The CPF entered is invalid', 2028 badPlPesel: 'The PESEL entered is invalid', 2029 badPlNip: 'The NIP entered is invalid', 2030 badPlRegon: 'The REGON entered is invalid', 2031 badreCaptcha: 'Please confirm that you are not a bot', 2032 passwordComplexityStart: 'Password must contain at least ', 2033 passwordComplexitySeparator: ', ', 2034 passwordComplexityUppercaseInfo: ' uppercase letter(s)', 2035 passwordComplexityLowercaseInfo: ' lowercase letter(s)', 2036 passwordComplexitySpecialCharsInfo: ' special character(s)', 2037 passwordComplexityNumericCharsInfo: ' numeric character(s)', 2038 passwordComplexityEnd: '.' 2039 } 2040 }); 2041 2042})(jQuery, window); 2043 2044/** 2045 * File declaring all default validators. 2046 */ 2047(function($) { 2048 2049 /* 2050 * Validate email 2051 */ 2052 $.formUtils.addValidator({ 2053 name: 'email', 2054 validatorFunction: function (email) { 2055 2056 var emailParts = email.toLowerCase().split('@'), 2057 localPart = emailParts[0], 2058 domain = emailParts[1]; 2059 2060 if (localPart && domain) { 2061 2062 if( localPart.indexOf('"') === 0 ) { 2063 var len = localPart.length; 2064 localPart = localPart.replace(/\"/g, ''); 2065 if( localPart.length !== (len-2) ) { 2066 return false; // It was not allowed to have more than two apostrophes 2067 } 2068 } 2069 2070 return $.formUtils.validators.validate_domain.validatorFunction(emailParts[1]) && 2071 localPart.indexOf('.') !== 0 && 2072 localPart.substring(localPart.length-1, localPart.length) !== '.' && 2073 localPart.indexOf('..') === -1 && 2074 !(/[^\w\+\.\-\#\-\_\~\!\$\&\'\(\)\*\+\,\;\=\:]/.test(localPart)); 2075 } 2076 2077 return false;
2078 }, 2079 errorMessage: '', 2080 errorMessageKey: 'badEmail' 2081 }); 2082 2083 /* 2084 * Validate domain name 2085 */ 2086 $.formUtils.addValidator({ 2087 name: 'domain', 2088 validatorFunction: function (val) { 2089 return val.length > 0 && 2090 val.length <= 253 && // Including sub domains 2091 !(/[^a-zA-Z0-9]/.test(val.slice(-2))) && !(/[^a-zA-Z0-9]/.test(val.substr(0, 1))) && !(/[^a-zA-Z0-9\.\-]/.test(val)) && 2092 val.split('..').length === 1 && 2093 val.split('.').length > 1; 2094 }, 2095 errorMessage: '', 2096 errorMessageKey: 'badDomain' 2097 }); 2098 2099 /* 2100 * Validate required 2101 */ 2102 $.formUtils.addValidator({ 2103 name: 'required', 2104 validatorFunction: function (val, $el, config, language, $form) { 2105 switch ($el.attr('type')) { 2106 case 'checkbox': 2107 return $el.is(':checked'); 2108 case 'radio': 2109 return $form.find('input[name="' + $el.attr('name') + '"]').filter(':checked').length > 0; 2110 default: 2111 return $.trim(val) !== ''; 2112 } 2113 }, 2114 errorMessage: '', 2115 errorMessageKey: function(config) { 2116 if (config.errorMessagePosition === 'top' || typeof config.errorMessagePosition === 'function') { 2117 return 'requiredFields'; 2118 } 2119 else { 2120 return 'requiredField'; 2121 } 2122 } 2123 }); 2124 2125 /* 2126 * Validate length range 2127 */ 2128 $.formUtils.addValidator({ 2129 name: 'length', 2130 validatorFunction: function (val, $el, conf, lang) { 2131 var lengthAllowed = $el.valAttr('length'), 2132 type = $el.attr('type'); 2133 2134 if (lengthAllowed === undefined) { 2135 alert('Please add attribute "data-validation-length" to ' + $el[0].nodeName + ' named ' + $el.attr('name')); 2136 return true; 2137 } 2138 2139 // check if length is above min, below max or within range. 2140 var len = type === 'file' && $el.get(0).files !== undefined ? $el.get(0).files.length : val.length, 2141 lengthCheckResults = $.formUtils.numericRangeCheck(len, lengthAllowed), 2142 checkResult; 2143 2144 switch (lengthCheckResults[0]) { // outside of allowed range 2145 case 'out': 2146 this.errorMessage = lang.lengthBadStart + lengthAllowed + lang.lengthBadEnd; 2147 checkResult = false;
2148 break; 2149 // too short 2150 case 'min': 2151 this.errorMessage = lang.lengthTooShortStart + lengthCheckResults[1] + lang.lengthBadEnd; 2152 checkResult = false; 2153 break; 2154 // too long 2155 case 'max': 2156 this.errorMessage = lang.lengthTooLongStart + lengthCheckResults[1] + lang.lengthBadEnd; 2157 checkResult = false; 2158 break; 2159 // ok 2160 default: 2161 checkResult = true; 2162 } 2163 2164 return checkResult; 2165 }, 2166 errorMessage: '', 2167 errorMessageKey: '' 2168 }); 2169 2170 /* 2171 * Validate url 2172 */ 2173 $.formUtils.addValidator({ 2174 name: 'url', 2175 validatorFunction: function (url) { 2176 // written by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 2177 // - Victor Jonsson added support for arrays in the url ?arg[]=sdfsdf 2178 // - General improvements made by Stéphane Moureau <https://github.com/TraderStf> 2179 2180 var urlFilter = /^(https?|ftp):\/\/((((\w|-|\.|~|[\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])(\w|-|\.|~|[\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])(\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|\[|\]|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i; 2181 if (urlFilter.test(url)) { 2182 var domain = url.split('://')[1], 2183 domainSlashPos = domain.indexOf('/'); 2184 2185 if (domainSlashPos > -1) { 2186 domain = domain.substr(0, domainSlashPos); 2187 } 2188 2189 return $.formUtils.validators.validate_domain.validatorFunction(domain); // todo: add support for IP-addresses 2190 } 2191 return false; 2192 }, 2193 errorMessage: '', 2194 errorMessageKey: 'badUrl' 2195 }); 2196 2197 /* 2198 * Validate number (floating or integer) 2199 */ 2200 $.formUtils.addValidator({ 2201 name: 'number', 2202 validatorFunction: function (val, $el, conf) { 2203 if (val !== '') { 2204 var allowing = $el.valAttr('allowing') || '', 2205 decimalSeparator = $el.valAttr('decimal-separator') || conf.decimalSeparator, 2206 allowsRange = false, 2207 begin, end, 2208 steps = $el.valAttr('step') || '', 2209 allowsSteps = false, 2210 sanitize = $el.attr('data-sanitize') || '', 2211 isFormattedWithNumeral = sanitize.match(/(^|[\s])numberFormat([\s]|$)/i); 2212 2213 if (isFormattedWithNumeral) { 2214 if (!window.numeral) { 2215 throw new ReferenceError('The data-sanitize value numberFormat cannot be used without the numeral' + 2216 ' library. Please see Data Validation in http://www.formvalidator.net for more information.'); 2217 } 2218 //Unformat input first, then convert back to String 2219 if (val.length) { 2220 val = String(numeral().unformat(val)); 2221 } 2222 } 2223 2224 if (allowing.indexOf('number') === -1) { 2225 allowing += ',number'; 2226 } 2227 2228 if (allowing.indexOf('negative') === -1 && val.indexOf('-') === 0) { 2229 return false; 2230 } 2231 2232 if (allowing.indexOf('range') > -1) { 2233 begin = parseFloat(allowing.substring(allowing.indexOf('[') + 1, allowing.indexOf(';'))); 2234 end = parseFloat(allowing.substring(allowing.indexOf(';') + 1, allowing.indexOf(']'))); 2235 allowsRange = true; 2236 } 2237 2238 if (steps !== '') { 2239 allowsSteps = true; 2240 } 2241 2242 if (decimalSeparator === ',') { 2243 if (val.indexOf('.') > -1) { 2244 return false;
2245 } 2246 // Fix for checking range with floats using , 2247 val = val.replace(',', '.'); 2248 } 2249 if (val.replace(/[0-9-]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) { 2250 return true; 2251 } 2252 2253 if (allowing.indexOf('float') > -1 && val.match(new RegExp('^([0-9-]+)\\.([0-9]+)$')) !== null && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) { 2254 return true; 2255 } 2256 } 2257 return false; 2258 }, 2259 errorMessage: '', 2260 errorMessageKey: 'badInt' 2261 }); 2262 2263 /* 2264 * Validate alpha numeric 2265 */ 2266 $.formUtils.addValidator({ 2267 name: 'alphanumeric', 2268 validatorFunction: function (val, $el, conf, language) { 2269 var patternStart = '^([a-zA-Z0-9', 2270 patternEnd = ']+)$', 2271 additionalChars = $el.valAttr('allowing'), 2272 pattern = '', 2273 hasSpaces = false; 2274 2275 if (additionalChars) { 2276 pattern = patternStart + additionalChars + patternEnd; 2277 var extra = additionalChars.replace(/\\/g, ''); 2278 if (extra.indexOf(' ') > -1) { 2279 hasSpaces = true; 2280 extra = extra.replace(' ', ''); 2281 extra += language.andSpaces || $.formUtils.LANG.andSpaces; 2282 } 2283 2284 if(language.badAlphaNumericAndExtraAndSpaces && language.badAlphaNumericAndExtra) { 2285 if(hasSpaces) { 2286 this.errorMessage = language.badAlphaNumericAndExtraAndSpaces + extra; 2287 } else { 2288 this.errorMessage = language.badAlphaNumericAndExtra + extra + language.badAlphaNumericExtra; 2289 } 2290 } else { 2291 this.errorMessage = language.badAlphaNumeric + language.badAlphaNumericExtra + extra; 2292 } 2293 } else { 2294 pattern = patternStart + patternEnd; 2295 this.errorMessage = language.badAlphaNumeric; 2296 } 2297 2298 return new RegExp(pattern).test(val); 2299 }, 2300 errorMessage: '', 2301 errorMessageKey: '' 2302 }); 2303 2304 /* 2305 * Validate against regexp 2306 */ 2307 $.formUtils.addValidator({ 2308 name: 'custom', 2309 validatorFunction: function (val, $el) { 2310 var regexp = new RegExp($el.valAttr('regexp')); 2311 return regexp.test(val); 2312 }, 2313 errorMessage: '', 2314 errorMessageKey: 'badCustomVal' 2315 }); 2316 2317 /* 2318 * Validate date 2319 */ 2320 $.formUtils.addValidator({ 2321 name: 'date', 2322 validatorFunction: function (date, $el, conf) { 2323 var dateFormat = $el.valAttr('format') || conf.dateFormat || 'yyyy-mm-dd', 2324 addMissingLeadingZeros = $el.valAttr('require-leading-zero') === 'false'; 2325 return $.formUtils.parseDate(date, dateFormat, addMissingLeadingZeros) !== false; 2326 }, 2327 errorMessage: '', 2328 errorMessageKey: 'badDate' 2329 }); 2330 2331 2332 /* 2333 * Validate group of checkboxes, validate qty required is checked 2334 * written by Steve Wasiura : http://stevewasiura.waztech.com 2335 * element attrs 2336 * data-validation="checkbox_group" 2337 * data-validation-qty="1-2" // min 1 max 2 2338 * data-validation-error-msg="chose min 1, max of 2 checkboxes" 2339 */ 2340 $.formUtils.addValidator({ 2341 name: 'checkbox_group', 2342 validatorFunction: function (val, $el, conf, lang, $form) { 2343 // preset return var 2344 var isValid = true, 2345 // get name of element. since it is a checkbox group, all checkboxes will have same name 2346 elname = $el.attr('name'), 2347 // get checkboxes and count the checked ones 2348 $checkBoxes = $('input[type=checkbox][name^="' + elname + '"]', $form), 2349 checkedCount = $checkBoxes.filter(':checked').length, 2350 // get el attr that specs qty required / allowed 2351 qtyAllowed = $el.valAttr('qty'); 2352 2353 if (qtyAllowed === undefined) { 2354 var elementType = $el.get(0).nodeName; 2355 alert('Attribute "data-validation-qty" is missing from ' + elementType + ' named ' + $el.attr('name')); 2356 } 2357 2358 // call Utility function to check if count is above min, below max, within range etc. 2359 var qtyCheckResults = $.formUtils.numericRangeCheck(checkedCount, qtyAllowed); 2360 2361 // results will be array, [0]=result str, [1]=qty int 2362 switch (qtyCheckResults[0]) { 2363 // outside allowed range 2364 case 'out': 2365 this.errorMessage = lang.groupCheckedRangeStart + qtyAllowed + lang.groupCheckedEnd; 2366 isValid = false;
2367 break; 2368 // below min qty 2369 case 'min': 2370 this.errorMessage = lang.groupCheckedTooFewStart + qtyCheckResults[1] + (lang.groupCheckedTooFewEnd || lang.groupCheckedEnd); 2371 isValid = false; 2372 break; 2373 // above max qty 2374 case 'max': 2375 this.errorMessage = lang.groupCheckedTooManyStart + qtyCheckResults[1] + (lang.groupCheckedTooManyEnd || lang.groupCheckedEnd); 2376 isValid = false; 2377 break; 2378 // ok 2379 default: 2380 isValid = true; 2381 } 2382 2383 if( !isValid ) { 2384 var _triggerOnBlur = function() { 2385 $checkBoxes.unbind('click', _triggerOnBlur); 2386 $checkBoxes.filter('*[data-validation]').validateInputOnBlur(lang, conf, false, 'blur'); 2387 }; 2388 $checkBoxes.bind('click', _triggerOnBlur); 2389 } 2390 2391 return isValid; 2392 } 2393 // errorMessage : '', // set above in switch statement 2394 // errorMessageKey: '' // not used 2395 }); 2396 2397})(jQuery); 2398 2399 2400}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.