1/* 2 * Inline Form Validation Engine 2.6.2, jQuery plugin 3 * 4 * Copyright(c) 2010, Cedric Dugas 5 * http://www.position-absolute.com 6 * 7 * 2.0 Rewrite by Olivier Refalo 8 * http://www.crionics.com 9 * 10 * Form validation engine allowing custom regex rules to be added. 11 * Licensed under the MIT License 12 */ 13 (function($) { 14 15 "use strict"; 16 17 var methods = { 18 19 /** 20 * Kind of the constructor, called before any action 21 * @param {Map} user options 22 */ 23 init: function(options) { 24 var form = this; 25 if (!form.data('jqv') || form.data('jqv') == null ) { 26 options = methods._saveOptions(form, options); 27 // bind all formError elements to close on click 28 $(document).on("click", ".formError", function() { 29 $(this).fadeOut(150, function() { 30 // remove prompt once invisible 31 $(this).closest('.formError').remove(); 32 }); 33 }); 34 } 35 return this; 36 }, 37 /** 38 * Attachs jQuery.validationEngine to form.submit and field.blur events 39 * Takes an optional params: a list of options 40 * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"}); 41 */ 42 attach: function(userOptions) { 43 44 var form = this; 45 var options; 46 47 if(userOptions) 48 options = methods._saveOptions(form, userOptions); 49 else 50 options = form.data('jqv'); 51 52 options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class"; 53 if (options.binded) { 54 55 // delegate fields 56 form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent); 57 form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent); 58 form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent); 59 } 60 if (options.autoPositionUpdate) { 61 $(window).bind("resize", { 62 "noAnimation": true, 63 "formElem": form 64 }, methods.updatePromptsPosition); 65 } 66 form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick); 67 form.removeData('jqv_submitButton'); 68 69 // bind form.submit 70 form.on("submit", methods._onSubmitEvent); 71 return this; 72 }, 73 /** 74 * Unregisters any bindings that may point to jQuery.validaitonEngine 75 */ 76 detach: function() { 77 78 var form = this; 79 var options = form.data('jqv'); 80 81 // unbind fields 82 form.off(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent); 83 form.off("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent); 84 form.off(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", methods._onFieldEvent); 85 86 // unbind form.submit 87 form.off("submit", methods._onSubmitEvent); 88 form.removeData('jqv'); 89 90 form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick); 91 form.removeData('jqv_submitButton'); 92 93 if (options.autoPositionUpdate) 94 $(window).off("resize", methods.updatePromptsPosition); 95 96 return this; 97 }, 98 /** 99 * Validates either a form or a list of fields, shows prompts accordingly. 100 * Note: There is no ajax form validation with this method, only field ajax validation are evaluated 101 * 102 * @return true if the form validates, false if it fails 103 */ 104 validate: function(userOptions) { 105 var element = $(this); 106 var valid = null; 107 var options; 108
109 if (element.is("form") || element.hasClass("validationEngineContainer")) { 110 if (element.hasClass('validating')) { 111 // form is already validating. 112 // Should abort old validation and start new one. I don't know how to implement it. 113 return false; 114 } else { 115 element.addClass('validating'); 116 if(userOptions) 117 options = methods._saveOptions(element, userOptions); 118 else 119 options = element.data('jqv'); 120 var valid = methods._validateFields(this); 121 122 // If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again 123 setTimeout(function(){ 124 element.removeClass('validating'); 125 }, 100); 126 if (valid && options.onSuccess) { 127 options.onSuccess(); 128 } else if (!valid && options.onFailure) { 129 options.onFailure(); 130 } 131 } 132 } else if (element.is('form') || element.hasClass('validationEngineContainer')) { 133 element.removeClass('validating'); 134 } else { 135 // field validation 136 var form = element.closest('form, .validationEngineContainer'); 137 options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults; 138 valid = methods._validateField(element, options); 139 140 if (valid && options.onFieldSuccess) 141 options.onFieldSuccess(); 142 else if (options.onFieldFailure && options.InvalidFields.length > 0) { 143 options.onFieldFailure(); 144 } 145 146 return !valid; 147 } 148 if(options.onValidationComplete) { 149 // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing 150 return !!options.onValidationComplete(form, valid); 151 } 152 return valid; 153 }, 154 /** 155 * Redraw prompts position, useful when you change the DOM state when validating 156 */ 157 updatePromptsPosition: function(event) { 158 159 if (event && this == window) { 160 var form = event.data.formElem; 161 var noAnimation = event.data.noAnimation; 162 } 163 else 164 var form = $(this.closest('form, .validationEngineContainer')); 165 166 var options = form.data('jqv'); 167 // No option, take default one 168 if (!options) 169 options = methods._saveOptions(form, options); 170 form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){ 171 var field = $(this); 172 if (options.prettySelect && field.is(":hidden")) 173 field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix); 174 var prompt = methods._getPrompt(field); 175 var promptText = $(prompt).find(".formErrorContent").html(); 176 177 if(prompt) 178 methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation); 179 }); 180 return this; 181 }, 182 /** 183 * Displays a prompt on a element. 184 * Note that the element needs an id! 185 * 186 * @param {String} promptText html text to display type 187 * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) 188 * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight 189 */ 190 showPrompt: function(promptText, type, promptPosition, showArrow) { 191 var form = this.closest('form, .validationEngineContainer'); 192 var options = form.data('jqv'); 193 // No option, take default one 194 if(!options) 195 options = methods._saveOptions(this, options); 196 if(promptPosition) 197 options.promptPosition=promptPosition; 198 options.showArrow = showArrow==true; 199 200 methods._showPrompt(this, promptText, type, false, options); 201 return this; 202 }, 203 /** 204 * Closes form error prompts, CAN be invidual 205 */ 206 hide: function() { 207 var form = $(this).closest('form, .validationEngineContainer'); 208 var options = form.data('jqv'); 209 // No option, take default one 210 if (!options) 211 options = methods._saveOptions(form, options); 212 var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3; 213 var closingtag; 214
215 if(form.is("form") || form.hasClass("validationEngineContainer")) { 216 closingtag = "parentForm"+methods._getClassName($(form).attr("id")); 217 } else { 218 closingtag = methods._getClassName($(form).attr("id")) +"formError"; 219 } 220 $('.'+closingtag).fadeTo(fadeDuration, 0, function() { 221 $(this).closest('.formError').remove(); 222 }); 223 return this; 224 }, 225 /** 226 * Closes all error prompts on the page 227 */ 228 hideAll: function() { 229 var form = this; 230 var options = form.data('jqv'); 231 var duration = options ? options.fadeDuration:300; 232 $('.formError').fadeTo(duration, 0, function() { 233 $(this).closest('.formError').remove(); 234 }); 235 return this; 236 }, 237 /** 238 * Typically called when user exists a field using tab or a mouse click, triggers a field 239 * validation 240 */ 241 _onFieldEvent: function(event) { 242 var field = $(this); 243 var form = field.closest('form, .validationEngineContainer'); 244 var options = form.data('jqv'); 245 // No option, take default one 246 if (!options) 247 options = methods._saveOptions(form, options); 248 options.eventTrigger = "field"; 249 250 if (options.notEmpty == true){ 251 252 if(field.val().length > 0){ 253 // validate the current field 254 window.setTimeout(function() { 255 methods._validateField(field, options); 256 }, (event.data) ? event.data.delay : 0); 257 258 } 259 260 }else{ 261 262 // validate the current field 263 window.setTimeout(function() { 264 methods._validateField(field, options); 265 }, (event.data) ? event.data.delay : 0); 266 267 } 268 269 270 271 272 }, 273 /** 274 * Called when the form is submited, shows prompts accordingly 275 * 276 * @param {jqObject} 277 * form 278 * @return false if form submission needs to be cancelled 279 */ 280 _onSubmitEvent: function() { 281 var form = $(this); 282 var options = form.data('jqv'); 283 284 //check if it is trigger from skipped button 285 if (form.data("jqv_submitButton")){ 286 var submitButton = $("#" + form.data("jqv_submitButton")); 287 if (submitButton){ 288 if (submitButton.length > 0){
289 if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true") 290 return true; 291 } 292 } 293 } 294 295 options.eventTrigger = "submit"; 296 297 // validate each field 298 // (- skip field ajax validation, not necessary IF we will perform an ajax form validation) 299 var r=methods._validateFields(form); 300 301 if (r && options.ajaxFormValidation) { 302 methods._validateFormWithAjax(form, options); 303 // cancel form auto-submission - process with async call onAjaxFormComplete 304 return false; 305 } 306 307 if(options.onValidationComplete) { 308 // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing 309 return !!options.onValidationComplete(form, r); 310 } 311 return r; 312 }, 313 /** 314 * Return true if the ajax field validations passed so far 315 * @param {Object} options 316 * @return true, is all ajax validation passed so far (remember ajax is async) 317 */ 318 _checkAjaxStatus: function(options) { 319 var status = true; 320 $.each(options.ajaxValidCache, function(key, value) { 321 if (!value) { 322 status = false; 323 // break the each 324 return false; 325 } 326 }); 327 return status; 328 }, 329 330 /** 331 * Return true if the ajax field is validated 332 * @param {String} fieldid 333 * @param {Object} options 334 * @return true, if validation passed, false if false or doesn't exist 335 */ 336 _checkAjaxFieldStatus: function(fieldid, options) { 337 return options.ajaxValidCache[fieldid] == true; 338 }, 339 /** 340 * Validates form fields, shows prompts accordingly 341 * 342 * @param {jqObject} 343 * form 344 * @param {skipAjaxFieldValidation} 345 * boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked 346 * 347 * @return true if form is valid, false if not, undefined if ajax form validation is done 348 */ 349 _validateFields: function(form) { 350 var options = form.data('jqv'); 351 352 // this variable is set to true if an error is found 353 var errorFound = false; 354 355 // Trigger hook, start validation 356 form.trigger("jqv.form.validating"); 357 // first, evaluate status of non ajax fields 358 var first_err=null; 359 form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() { 360 var field = $(this); 361 var names = []; 362 if ($.inArray(field.attr('name'), names) < 0) { 363 errorFound |= methods._validateField(field, options); 364 if (errorFound && first_err==null) 365 if (field.is(":hidden") && options.prettySelect) 366 first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix); 367 else { 368 369 //Check if we need to adjust what element to show the prompt on 370 //and and such scroll to instead 371 if(field.data('jqv-prompt-at') instanceof jQuery ){ 372 field = field.data('jqv-prompt-at'); 373 } else if(field.data('jqv-prompt-at')) { 374 field = $(field.data('jqv-prompt-at')); 375 } 376 first_err=field; 377 } 378 if (options.doNotShowAllErrosOnSubmit) 379 return false; 380 names.push(field.attr('name')); 381 382 //if option set, stop checking validation rules after one error is found 383 if(options.showOneMessage == true && errorFound){ 384 return false; 385 } 386 } 387 }); 388 389 // second, check to see if all ajax calls completed ok 390 // errorFound |= !methods._checkAjaxStatus(options); 391 392 // third, check status and scroll the container accordingly 393 form.trigger("jqv.form.result", [errorFound]); 394 395 if (errorFound) { 396 if (options.scroll) { 397 var destination=first_err.offset().top; 398 var fixleft = first_err.offset().left; 399 400 //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10) 401 var positionType=options.promptPosition; 402 if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1) 403 positionType=positionType.substring(0,positionType.indexOf(":")); 404 405 if (positionType!="bottomRight" && positionType!="bottomLeft") { 406 var prompt_err= methods._getPrompt(first_err); 407 if (prompt_err) { 408 destination=prompt_err.offset().top; 409 } 410 } 411 412 // Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page 413 if (options.scrollOffset) { 414 destination -= options.scrollOffset; 415 } 416 417 // get the position of the first error, there should be at least one, no need to check this 418 //var destination = form.find(".formError:not('.greenPopup'):first").offset().top; 419 /*if (options.isOverflown) { 420 var overflowDIV = $(options.overflownDIV); 421 if(!overflowDIV.length) return false;
422 var scrollContainerScroll = overflowDIV.scrollTop(); 423 var scrollContainerPos = -parseInt(overflowDIV.offset().top); 424 425 destination += scrollContainerScroll + scrollContainerPos - 5; 426 var scrollContainer = $(options.overflownDIV).filter(":not(:animated)"); 427 428 scrollContainer.animate({ scrollTop: destination }, 1100, function(){ 429 if(options.focusFirstField) first_err.focus(); 430 }); 431 432 } else { 433 $("html, body").animate({ 434 scrollTop: destination 435 }, 1100, function(){ 436 if(options.focusFirstField) first_err.focus(); 437 }); 438 $("html, body").animate({scrollLeft: fixleft},1100) 439 }*/ 440 441 } else if(options.focusFirstField) 442 first_err.focus(); 443 return false; 444 } 445 return true; 446 }, 447 /** 448 * This method is called to perform an ajax form validation. 449 * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true 450 * 451 * @param {jqObject} form 452 * @param {Map} options 453 */ 454 _validateFormWithAjax: function(form, options) { 455 456 var data = form.serialize(); 457 var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET"; 458 var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action"); 459 var dataType = (options.dataType) ? options.dataType : "json"; 460 $.ajax({ 461 type: type, 462 url: url, 463 cache: false, 464 dataType: dataType, 465 data: data, 466 form: form, 467 methods: methods, 468 options: options, 469 beforeSend: function() { 470 return options.onBeforeAjaxFormValidation(form, options); 471 }, 472 error: function(data, transport) { 473 if (options.onFailure) { 474 options.onFailure(data, transport); 475 } else { 476 methods._ajaxError(data, transport); 477 } 478 }, 479 success: function(json) { 480 if ((dataType == "json") && (json !== true)) { 481 // getting to this case doesn't necessary means that the form is invalid 482 // the server may return green or closing prompt actions 483 // this flag helps figuring it out 484 var errorInForm=false; 485 for (var i = 0; i < json.length; i++) { 486 var value = json[i]; 487 488 var errorFieldId = value[0]; 489 var errorField = $($("#" + errorFieldId)[0]); 490 491 // make sure we found the element 492 if (errorField.length == 1) { 493 494 // promptText or selector 495 var msg = value[2]; 496 // if the field is valid 497 if (value[1] == true) { 498 499 if (msg == "" || !msg){ 500 // if for some reason, status==true and error="", just close the prompt 501 methods._closePrompt(errorField); 502 } else { 503 // the field is valid, but we are displaying a green prompt 504 if (options.allrules[msg]) { 505 var txt = options.allrules[msg].alertTextOk; 506 if (txt) 507 msg = txt; 508 } 509 if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true); 510 } 511 } else { 512 // the field is invalid, show the red error prompt 513 errorInForm|=true; 514 if (options.allrules[msg]) { 515 var txt = options.allrules[msg].alertText; 516 if (txt) 517 msg = txt; 518 } 519 if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true); 520 } 521 } 522 } 523 options.onAjaxFormComplete(!errorInForm, form, json, options); 524 } else 525 options.onAjaxFormComplete(true, form, json, options); 526 527 } 528 }); 529 530 }, 531 /** 532 * Validates field, shows prompts accordingly 533 * 534 * @param {jqObject} 535 * field 536 * @param {Array[String]} 537 * field's validation rules 538 * @param {Map} 539 * user options 540 * @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.) 541 */ 542 _validateField: function(field, options, skipAjaxValidation) { 543 if (!field.attr("id")) { 544 field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter); 545 ++$.validationEngine.fieldIdCounter; 546 } 547 548 if(field.hasClass(options.ignoreFieldsWithClass)) 549 return false;
550 551 if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden"))) 552 return false; 553 554 var rulesParsing = field.attr(options.validateAttribute); 555 var getRules = /validate\[(.*)\]/.exec(rulesParsing); 556 557 if (!getRules) 558 return false; 559 var str = getRules[1]; 560 var rules = str.split(/\[|,|\]/); 561 562 // true if we ran the ajax validation, tells the logic to stop messing with prompts 563 var isAjaxValidator = false; 564 var fieldName = field.attr("name"); 565 var promptText = ""; 566 var promptType = ""; 567 var required = false; 568 var limitErrors = false; 569 options.isError = false; 570 options.showArrow = true; 571 572 // If the programmer wants to limit the amount of error messages per field, 573 if (options.maxErrorsPerField > 0) { 574 limitErrors = true; 575 } 576 577 var form = $(field.closest("form, .validationEngineContainer")); 578 // Fix for adding spaces in the rules 579 for (var i = 0; i < rules.length; i++) { 580 rules[i] = rules[i].toString().replace(" ", "");//.toString to worked on IE8 581 // Remove any parsing errors 582 if (rules[i] === '') { 583 delete rules[i]; 584 } 585 } 586 587 for (var i = 0, field_errors = 0; i < rules.length; i++) { 588 589 // If we are limiting errors, and have hit the max, break 590 if (limitErrors && field_errors >= options.maxErrorsPerField) { 591 // If we haven't hit a required yet, check to see if there is one in the validation rules for this 592 // field and that it's index is greater or equal to our current index 593 if (!required) { 594 var have_required = $.inArray('required', rules); 595 required = (have_required != -1 && have_required >= i); 596 } 597 break; 598 } 599 600 601 var errorMsg = undefined; 602 switch (rules[i]) { 603 604 case "required": 605 required = true; 606 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required); 607 break; 608 case "custom": 609 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom); 610 break; 611 case "groupRequired": 612 // Check is its the first of group, if not, reload validation with first field 613 // AND continue normal validation on present field 614 var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]"; 615 var firstOfGroup = form.find(classGroup).eq(0); 616 if(firstOfGroup[0] != field[0]){ 617 618 methods._validateField(firstOfGroup, options, skipAjaxValidation); 619 options.showArrow = true; 620 621 } 622 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired); 623 if(errorMsg) required = true; 624 options.showArrow = false; 625 break; 626 case "ajax": 627 // AJAX defaults to returning it's loading message 628 errorMsg = methods._ajax(field, rules, i, options); 629 if (errorMsg) { 630 promptType = "load"; 631 } 632 break; 633 case "minSize": 634 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize); 635 break; 636 case "maxSize": 637 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize); 638 break; 639 case "min": 640 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min); 641 break; 642 case "max": 643 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max); 644 break; 645 case "past": 646 errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past); 647 break; 648 case "future": 649 errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future); 650 break; 651 case "dateRange": 652 var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]"; 653 options.firstOfGroup = form.find(classGroup).eq(0); 654 options.secondOfGroup = form.find(classGroup).eq(1); 655 656 //if one entry out of the pair has value then proceed to run through validation 657 if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) { 658 errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange); 659 } 660 if (errorMsg) required = true; 661 options.showArrow = false;
662 break; 663 664 case "dateTimeRange": 665 var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]"; 666 options.firstOfGroup = form.find(classGroup).eq(0); 667 options.secondOfGroup = form.find(classGroup).eq(1); 668 669 //if one entry out of the pair has value then proceed to run through validation 670 if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) { 671 errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange); 672 } 673 if (errorMsg) required = true; 674 options.showArrow = false; 675 break; 676 case "maxCheckbox": 677 field = $(form.find("input[name='" + fieldName + "']")); 678 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox); 679 break; 680 case "minCheckbox": 681 field = $(form.find("input[name='" + fieldName + "']")); 682 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox); 683 break; 684 case "equals": 685 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals); 686 break; 687 case "funcCall": 688 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall); 689 break; 690 case "creditCard": 691 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard); 692 break; 693 case "condRequired": 694 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired); 695 if (errorMsg !== undefined) { 696 required = true; 697 } 698 break; 699 case "funcCallRequired": 700 errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCallRequired); 701 if (errorMsg !== undefined) { 702 required = true; 703 } 704 break; 705 case "checkDuplicate": 706 errorMsg = methods._checkDuplicate(field, rules, i, options); 707 break; 708 709 default: 710 } 711 712 var end_validation = false; 713 714 // If we were passed back an message object, check what the status was to determine what to do 715 if (typeof errorMsg == "object") { 716 switch (errorMsg.status) { 717 case "_break": 718 end_validation = true; 719 break; 720 // If we have an error message, set errorMsg to the error message 721 case "_error": 722 errorMsg = errorMsg.message; 723 break; 724 // If we want to throw an error, but not show a prompt, return early with true 725 case "_error_no_prompt": 726 return true; 727 break; 728 // Anything else we continue on 729 default: 730 break; 731 } 732 } 733 734 //funcCallRequired, first in rules, and has error, skip anything else 735 if( i==0 && str.indexOf('funcCallRequired')==0 && errorMsg !== undefined ){ 736 promptText += errorMsg + "<br/>"; 737 options.isError=true; 738 field_errors++; 739 end_validation=true; 740 } 741 742 // If it has been specified that validation should end now, break 743 if (end_validation) { 744 break; 745 } 746 747 // If we have a string, that means that we have an error, so add it to the error message. 748 if (typeof errorMsg == 'string') { 749 promptText += errorMsg + "<br/>"; 750 options.isError = true; 751 field_errors++; 752 } 753 } 754 // If the rules required is not added, an empty field is not validated 755 //the 3rd condition is added so that even empty password fields should be equal 756 //otherwise if one is filled and another left empty, the "equal" condition would fail 757 //which does not make any sense 758 if(!required && !(field.val()) && field.val().length < 1 && $.inArray('equals', rules) < 0) options.isError = false; 759 760 // Hack for radio/checkbox group button, the validation go into the 761 // first radio/checkbox of the group 762 var fieldType = field.prop("type"); 763 var positionType=field.data("promptPosition") || options.promptPosition; 764 765 if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) { 766 if(positionType === 'inline') { 767 field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last")); 768 } else { 769 field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first")); 770 } 771 options.showArrow = options.showArrowOnRadioAndCheckbox; 772 } 773 774 if(field.is(":hidden") && options.prettySelect) { 775 field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix); 776 } 777 778 if (options.isError && options.showPrompts){ 779 methods._showPrompt(field, promptText, promptType, false, options); 780 }else{ 781 if (!isAjaxValidator) methods._closePrompt(field); 782 } 783 784 if (!isAjaxValidator) { 785 field.trigger("jqv.field.result", [field, options.isError, promptText]); 786 } 787 788 /* Record error */ 789 var errindex = $.inArray(field[0], options.InvalidFields); 790 if (errindex == -1) { 791 if (options.isError) 792 options.InvalidFields.push(field[0]); 793 } else if (!options.isError) { 794 options.InvalidFields.splice(errindex, 1); 795 } 796
797 methods._handleStatusCssClasses(field, options); 798 799 /* run callback function for each field */ 800 if (options.isError && options.onFieldFailure) 801 options.onFieldFailure(field); 802 803 if (!options.isError && options.onFieldSuccess) 804 options.onFieldSuccess(field); 805 806 return options.isError; 807 }, 808 /** 809 * Handling css classes of fields indicating result of validation 810 * 811 * @param {jqObject} 812 * field 813 * @param {Array[String]} 814 * field's validation rules 815 * @private 816 */ 817 _handleStatusCssClasses: function(field, options) { 818 /* remove all classes */ 819 if(options.addSuccessCssClassToField) 820 field.removeClass(options.addSuccessCssClassToField); 821 822 if(options.addFailureCssClassToField) 823 field.removeClass(options.addFailureCssClassToField); 824 825 /* Add classes */ 826 if (options.addSuccessCssClassToField && !options.isError) 827 field.addClass(options.addSuccessCssClassToField); 828 829 if (options.addFailureCssClassToField && options.isError) 830 field.addClass(options.addFailureCssClassToField); 831 }, 832 833 /******************** 834 * _getErrorMessage 835 * 836 * @param form 837 * @param field 838 * @param rule 839 * @param rules 840 * @param i 841 * @param options 842 * @param originalValidationMethod 843 * @return {*} 844 * @private 845 */ 846 _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) { 847 // If we are using the custon validation type, build the index for the rule. 848 // Otherwise if we are doing a function call, make the call and return the object 849 // that is passed back. 850 var rule_index = jQuery.inArray(rule, rules); 851 if (rule === "custom" || rule === "funcCall" || rule === "funcCallRequired") { 852 var custom_validation_type = rules[rule_index + 1]; 853 rule = rule + "[" + custom_validation_type + "]"; 854 // Delete the rule from the rules array so that it doesn't try to call the 855 // same rule over again 856 delete(rules[rule_index]); 857 } 858 // Change the rule to the composite rule, if it was different from the original 859 var alteredRule = rule; 860 861 862 var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class"); 863 var element_classes_array = element_classes.split(" "); 864 865 // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form 866 var errorMsg; 867 if (rule == "future" || rule == "past" || rule == "maxCheckbox" || rule == "minCheckbox") { 868 errorMsg = originalValidationMethod(form, field, rules, i, options); 869 } else { 870 errorMsg = originalValidationMethod(field, rules, i, options); 871 } 872 873 // If the original validation method returned an error and we have a custom error message, 874 // return the custom message instead. Otherwise return the original error message. 875 if (errorMsg != undefined) { 876 var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options); 877 if (custom_message) errorMsg = custom_message; 878 } 879 return errorMsg; 880 881 }, 882 _getCustomErrorMessage:function (field, classes, rule, options) { 883 var custom_message = false; 884 var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule]; 885 // If there is a validityProp for this rule, check to see if the field has an attribute for it 886 if (validityProp != undefined) { 887 custom_message = field.attr("data-errormessage-"+validityProp); 888 // If there was an error message for it, return the message 889 if (custom_message != undefined) 890 return custom_message; 891 } 892 custom_message = field.attr("data-errormessage"); 893 // If there is an inline custom error message, return it 894 if (custom_message != undefined) 895 return custom_message; 896 var id = '#' + field.attr("id"); 897 // If we have custom messages for the element's id, get the message for the rule from the id. 898 // Otherwise, if we have custom messages for the element's classes, use the first class message we find instead. 899 if (typeof options.custom_error_messages[id] != "undefined" && 900 typeof options.custom_error_messages[id][rule] != "undefined" ) { 901 custom_message = options.custom_error_messages[id][rule]['message']; 902 } else if (classes.length > 0) { 903 for (var i = 0; i < classes.length && classes.length > 0; i++) { 904 var element_class = "." + classes[i]; 905 if (typeof options.custom_error_messages[element_class] != "undefined" && 906 typeof options.custom_error_messages[element_class][rule] != "undefined") { 907 custom_message = options.custom_error_messages[element_class][rule]['message']; 908 break; 909 } 910 } 911 } 912 if (!custom_message && 913 typeof options.custom_error_messages[rule] != "undefined" && 914 typeof options.custom_error_messages[rule]['message'] != "undefined"){ 915 custom_message = options.custom_error_messages[rule]['message']; 916 } 917 return custom_message; 918 }, 919 _validityProp: { 920 "required": "value-missing",
921 "custom": "custom-error", 922 "groupRequired": "value-missing", 923 "ajax": "custom-error", 924 "minSize": "range-underflow", 925 "maxSize": "range-overflow", 926 "min": "range-underflow", 927 "max": "range-overflow", 928 "past": "type-mismatch", 929 "future": "type-mismatch", 930 "dateRange": "type-mismatch", 931 "dateTimeRange": "type-mismatch", 932 "maxCheckbox": "range-overflow", 933 "minCheckbox": "range-underflow", 934 "equals": "pattern-mismatch", 935 "funcCall": "custom-error", 936 "funcCallRequired": "custom-error", 937 "creditCard": "pattern-mismatch", 938 "condRequired": "value-missing" 939 }, 940 /** 941 * Required validation 942 * 943 * @param {jqObject} field 944 * @param {Array[String]} rules 945 * @param {int} i rules index 946 * @param {Map} 947 * user options 948 * @param {bool} condRequired flag when method is used for internal purpose in condRequired check 949 * @return an error string if validation failed 950 */ 951 _required: function(field, rules, i, options, condRequired) { 952 switch (field.prop("type")) { 953 case "radio": 954 case "checkbox": 955 // new validation style to only check dependent field 956 if (condRequired) { 957 if (!field.prop('checked')) { 958 return options.allrules[rules[i]].alertTextCheckboxMultiple; 959 } 960 break; 961 } 962 // old validation style 963 var form = field.closest("form, .validationEngineContainer"); 964 var name = field.attr("name"); 965 if (form.find("input[name='" + name + "']:checked").size() == 0) { 966 if (form.find("input[name='" + name + "']:visible").size() == 1) 967 return options.allrules[rules[i]].alertTextCheckboxe; 968 else 969 return options.allrules[rules[i]].alertTextCheckboxMultiple; 970 } 971 break; 972 case "text": 973 case "password": 974 case "textarea": 975 case "file": 976 case "select-one": 977 case "select-multiple": 978 default: 979 var field_val = $.trim( field.val() ); 980 var dv_placeholder = $.trim( field.attr("data-validation-placeholder") ); 981 var placeholder = $.trim( field.attr("placeholder") ); 982 if ( 983 ( !field_val ) 984 || ( dv_placeholder && field_val == dv_placeholder ) 985 || ( placeholder && field_val == placeholder ) 986 ) { 987 return options.allrules[rules[i]].alertText; 988 } 989 break; 990 } 991 }, 992 /** 993 * Validate that 1 from the group field is required 994 * 995 * @param {jqObject} field 996 * @param {Array[String]} rules 997 * @param {int} i rules index 998 * @param {Map} 999 * user options 1000 * @return an error string if validation failed 1001 */ 1002 _groupRequired: function(field, rules, i, options) { 1003 var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]"; 1004 var isValid = false; 1005 // Check all fields from the group 1006 field.closest("form, .validationEngineContainer").find(classGroup).each(function(){ 1007 if(!methods._required($(this), rules, i, options)){ 1008 isValid = true; 1009 return false; 1010 } 1011 }); 1012 1013 if(!isValid) { 1014 return options.allrules[rules[i]].alertText; 1015 } 1016 }, 1017 /** 1018 * Validate rules 1019 * 1020 * @param {jqObject} field 1021 * @param {Array[String]} rules 1022 * @param {int} i rules index 1023 * @param {Map} 1024 * user options 1025 * @return an error string if validation failed 1026 */ 1027 _checkDuplicate: function(field, rules, i, options) { 1028 var equalsField = rules[i + 1]; 1029 if (field.attr('value') == $("#" + equalsField).attr('value')) 1030 return options.allrules.checkDuplicate.alertText; 1031 }, 1032 _custom: function(field, rules, i, options) { 1033 var customRule = rules[i + 1]; 1034 var rule = options.allrules[customRule]; 1035 var fn; 1036 if(!rule) { 1037 alert("jqv:custom rule not found - "+customRule); 1038 return; 1039 } 1040 1041 if(rule["regex"]) { 1042 var ex=rule.regex; 1043 if(!ex) { 1044 alert("jqv:custom regex not found - "+customRule); 1045 return; 1046 } 1047 var pattern = new RegExp(ex); 1048 1049 if (!pattern.test(field.val())) return options.allrules[customRule].alertText; 1050 1051 } else if(rule["func"]) { 1052 fn = rule["func"]; 1053 1054 if (typeof(fn) !== "function") { 1055 alert("jqv:custom parameter 'function' is no function - "+customRule); 1056 return; 1057 } 1058 1059 if (!fn(field, rules, i, options)) 1060 return options.allrules[customRule].alertText; 1061 } else { 1062 alert("jqv:custom type not allowed "+customRule); 1063 return; 1064 } 1065 }, 1066 /** 1067 * Validate custom function outside of the engine scope 1068 * 1069 * @param {jqObject} field 1070 * @param {Array[String]} rules 1071 * @param {int} i rules index 1072 * @param {Map} 1073 * user options 1074 * @return an error string if validation failed 1075 */ 1076 _funcCall: function(field, rules, i, options) { 1077 var functionName = rules[i + 1]; 1078 var fn; 1079 if(functionName.indexOf('.') >-1) 1080 { 1081 var namespaces = functionName.split('.'); 1082 var scope = window; 1083 while(namespaces.length) 1084 { 1085 scope = scope[namespaces.shift()]; 1086 } 1087 fn = scope; 1088 } 1089 else 1090 fn = window[functionName] || options.customFunctions[functionName]; 1091 if (typeof(fn) == 'function') 1092 return fn(field, rules, i, options); 1093 1094 }, 1095 _funcCallRequired: function(field, rules, i, options) { 1096 return methods._funcCall(field,rules,i,options); 1097 }, 1098 /** 1099 * Field match 1100 * 1101 * @param {jqObject} field 1102 * @param {Array[String]} rules 1103 * @param {int} i rules index 1104 * @param {Map} 1105 * user options 1106 * @return an error string if validation failed 1107 */ 1108 _equals: function(field, rules, i, options) { 1109 var equalsField = rules[i + 1]; 1110 1111 if (field.val() != $("#" + equalsField).val()) 1112 return options.allrules.equals.alertText; 1113 }, 1114 /** 1115 * Check the maximum size (in characters) 1116 * 1117 * @param {jqObject} field 1118 * @param {Array[String]} rules 1119 * @param {int} i rules index 1120 * @param {Map} 1121 * user options 1122 * @return an error string if validation failed 1123 */ 1124 _maxSize: function(field, rules, i, options) { 1125 var max = rules[i + 1]; 1126 var len = field.val().length; 1127 1128 if (len > max) { 1129 var rule = options.allrules.maxSize; 1130 return rule.alertText + max + rule.alertText2; 1131 } 1132 }, 1133 /** 1134 * Check the minimum size (in characters) 1135 * 1136 * @param {jqObject} field 1137 * @param {Array[String]} rules 1138 * @param {int} i rules index 1139 * @param {Map} 1140 * user options 1141 * @return an error string if validation failed 1142 */ 1143 _minSize: function(field, rules, i, options) { 1144 var min = rules[i + 1]; 1145 var len = field.val().length; 1146 1147 if (len < min) { 1148 var rule = options.allrules.minSize; 1149 return rule.alertText + min + rule.alertText2; 1150 } 1151 }, 1152 /** 1153 * Check number minimum value 1154 * 1155 * @param {jqObject} field 1156 * @param {Array[String]} rules 1157 * @param {int} i rules index 1158 * @param {Map} 1159 * user options 1160 * @return an error string if validation failed 1161 */ 1162 _min: function(field, rules, i, options) { 1163 var min = parseFloat(rules[i + 1]); 1164 var len = parseFloat(field.val()); 1165 1166 if (len < min) { 1167 var rule = options.allrules.min; 1168 if (rule.alertText2) return rule.alertText + min + rule.alertText2; 1169 return rule.alertText + min; 1170 } 1171 }, 1172 /** 1173 * Check number maximum value 1174 * 1175 * @param {jqObject} field 1176 * @param {Array[String]} rules 1177 * @param {int} i rules index 1178 * @param {Map} 1179 * user options 1180 * @return an error string if validation failed 1181 */ 1182 _max: function(field, rules, i, options) { 1183 var max = parseFloat(rules[i + 1]); 1184 var len = parseFloat(field.val()); 1185 1186 if (len >max ) { 1187 var rule = options.allrules.max; 1188 if (rule.alertText2) return rule.alertText + max + rule.alertText2; 1189 //orefalo: to review, also do the translations 1190 return rule.alertText + max; 1191 } 1192 }, 1193 /** 1194 * Checks date is in the past 1195 * 1196 * @param {jqObject} field 1197 * @param {Array[String]} rules 1198 * @param {int} i rules index 1199 * @param {Map} 1200 * user options 1201 * @return an error string if validation failed 1202 */ 1203 _past: function(form, field, rules, i, options) { 1204 1205 var p=rules[i + 1]; 1206 var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']")); 1207 var pdate; 1208 1209 if (p.toLowerCase() == "now") { 1210 pdate = new Date(); 1211 } else if (undefined != fieldAlt.val()) { 1212 if (fieldAlt.is(":disabled")) 1213 return; 1214 pdate = methods._parseDate(fieldAlt.val()); 1215 } else { 1216 pdate = methods._parseDate(p); 1217 } 1218 var vdate = methods._parseDate(field.val()); 1219 1220 if (vdate > pdate ) { 1221 var rule = options.allrules.past; 1222 if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2; 1223 return rule.alertText + methods._dateToString(pdate); 1224 } 1225 }, 1226 /** 1227 * Checks date is in the future 1228 * 1229 * @param {jqObject} field 1230 * @param {Array[String]} rules 1231 * @param {int} i rules index 1232 * @param {Map} 1233 * user options 1234 * @return an error string if validation failed 1235 */ 1236 _future: function(form, field, rules, i, options) { 1237 1238 var p=rules[i + 1]; 1239 var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']")); 1240 var pdate; 1241 1242 if (p.toLowerCase() == "now") { 1243 pdate = new Date(); 1244 } else if (undefined != fieldAlt.val()) { 1245 if (fieldAlt.is(":disabled")) 1246 return; 1247 pdate = methods._parseDate(fieldAlt.val()); 1248 } else { 1249 pdate = methods._parseDate(p); 1250 } 1251 var vdate = methods._parseDate(field.val()); 1252 1253 if (vdate < pdate ) { 1254 var rule = options.allrules.future; 1255 if (rule.alertText2) 1256 return rule.alertText + methods._dateToString(pdate) + rule.alertText2; 1257 return rule.alertText + methods._dateToString(pdate); 1258 } 1259 }, 1260 /** 1261 * Checks if valid date 1262 * 1263 * @param {string} date string 1264 * @return a bool based on determination of valid date 1265 */ 1266 _isDate: function (value) { 1267 var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?
1267:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/); 1268 return dateRegEx.test(value); 1269 }, 1270 /** 1271 * Checks if valid date time 1272 * 1273 * @param {string} date string 1274 * @return a bool based on determination of valid date time 1275 */ 1276 _isDateTime: function (value){ 1277 var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/); 1278 return dateTimeRegEx.test(value); 1279 }, 1280 //Checks if the start date is before the end date 1281 //returns true if end is later than start 1282 _dateCompare: function (start, end) { 1283 return (new Date(start.toString()) < new Date(end.toString())); 1284 }, 1285 /** 1286 * Checks date range 1287 * 1288 * @param {jqObject} first field name 1289 * @param {jqObject} second field name 1290 * @return an error string if validation failed 1291 */ 1292 _dateRange: function (field, rules, i, options) { 1293 //are not both populated 1294 if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) { 1295 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1296 } 1297 1298 //are not both dates 1299 if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) { 1300 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1301 } 1302 1303 //are both dates but range is off 1304 if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) { 1305 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1306 } 1307 }, 1308 /** 1309 * Checks date time range 1310 * 1311 * @param {jqObject} first field name 1312 * @param {jqObject} second field name 1313 * @return an error string if validation failed 1314 */ 1315 _dateTimeRange: function (field, rules, i, options) { 1316 //are not both populated 1317 if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) { 1318 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1319 } 1320 //are not both dates 1321 if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) { 1322 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1323 } 1324 //are both dates but range is off 1325 if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) { 1326 return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2; 1327 } 1328 }, 1329 /** 1330 * Max number of checkbox selected 1331 * 1332 * @param {jqObject} field 1333 * @param {Array[String]} rules 1334 * @param {int} i rules index 1335 * @param {Map} 1336 * user options 1337 * @return an error string if validation failed 1338 */ 1339 _maxCheckbox: function(form, field, rules, i, options) { 1340 1341 var nbCheck = rules[i + 1]; 1342 var groupname = field.attr("name"); 1343 var groupSize = form.find("input[name='" + groupname + "']:checked").size(); 1344 if (groupSize > nbCheck) { 1345 options.showArrow = false; 1346 if (options.allrules.maxCheckbox.alertText2) 1347 return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2; 1348 return options.allrules.maxCheckbox.alertText; 1349 } 1350 }, 1351 /** 1352 * Min number of checkbox selected 1353 * 1354 * @param {jqObject} field 1355 * @param {Array[String]} rules 1356 * @param {int} i rules index 1357 * @param {Map} 1358 * user options 1359 * @return an error string if validation failed 1360 */ 1361 _minCheckbox: function(form, field, rules, i, options) { 1362 1363 var nbCheck = rules[i + 1]; 1364 var groupname = field.attr("name"); 1365 var groupSize = form.find("input[name='" + groupname + "']:checked").size(); 1366 if (groupSize < nbCheck) { 1367 options.showArrow = false;
1368 return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2; 1369 } 1370 }, 1371 /** 1372 * Checks that it is a valid credit card number according to the 1373 * Luhn checksum algorithm. 1374 * 1375 * @param {jqObject} field 1376 * @param {Array[String]} rules 1377 * @param {int} i rules index 1378 * @param {Map} 1379 * user options 1380 * @return an error string if validation failed 1381 */ 1382 _creditCard: function(field, rules, i, options) { 1383 //spaces and dashes may be valid characters, but must be stripped to calculate the checksum. 1384 var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, ''); 1385 1386 var numDigits = cardNumber.length; 1387 if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) { 1388 1389 var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String(); 1390 do { 1391 digit = parseInt(cardNumber.charAt(i)); 1392 luhn += (pos++ % 2 == 0) ? digit * 2 : digit; 1393 } while (--i >= 0) 1394 1395 for (i = 0; i < luhn.length; i++) { 1396 sum += parseInt(luhn.charAt(i)); 1397 } 1398 valid = sum % 10 == 0; 1399 } 1400 if (!valid) return options.allrules.creditCard.alertText; 1401 }, 1402 /** 1403 * Ajax field validation 1404 * 1405 * @param {jqObject} field 1406 * @param {Array[String]} rules 1407 * @param {int} i rules index 1408 * @param {Map} 1409 * user options 1410 * @return nothing! the ajax validator handles the prompts itself 1411 */ 1412 _ajax: function(field, rules, i, options) { 1413 1414 var errorSelector = rules[i + 1]; 1415 var rule = options.allrules[errorSelector]; 1416 var extraData = rule.extraData; 1417 var extraDataDynamic = rule.extraDataDynamic; 1418 var data = { 1419 "fieldId" : field.attr("id"), 1420 "fieldValue" : field.val() 1421 }; 1422 1423 if (typeof extraData === "object") { 1424 $.extend(data, extraData); 1425 } else if (typeof extraData === "string") { 1426 var tempData = extraData.split("&"); 1427 for(var i = 0; i < tempData.length; i++) { 1428 var values = tempData[i].split("="); 1429 if (values[0] && values[0]) { 1430 data[values[0]] = values[1]; 1431 } 1432 } 1433 } 1434 1435 if (extraDataDynamic) { 1436 var tmpData = []; 1437 var domIds = String(extraDataDynamic).split(","); 1438 for (var i = 0; i < domIds.length; i++) { 1439 var id = domIds[i]; 1440 if ($(id).length) { 1441 var inputValue = field.closest("form, .validationEngineContainer").find(id).val(); 1442 var keyValue = id.replace('#', '') + '=' + escape(inputValue); 1443 data[id.replace('#', '')] = inputValue; 1444 } 1445 } 1446 } 1447 1448 // If a field change event triggered this we want to clear the cache for this ID 1449 if (options.eventTrigger == "field") { 1450 delete(options.ajaxValidCache[field.attr("id")]); 1451 } 1452 1453 // If there is an error or if the the field is already validated, do not re-execute AJAX 1454 if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) { 1455 $.ajax({ 1456 type: options.ajaxFormValidationMethod, 1457 url: rule.url, 1458 cache: false, 1459 dataType: "json", 1460 data: data, 1461 field: field, 1462 rule: rule, 1463 methods: methods, 1464 options: options, 1465 beforeSend: function() {}, 1466 error: function(data, transport) { 1467 if (options.onFailure) { 1468 options.onFailure(data, transport); 1469 } else { 1470 methods._ajaxError(data, transport); 1471 } 1472 }, 1473 success: function(json) { 1474 1475 // asynchronously called on success, data is the json answer from the server 1476 var errorFieldId = json[0]; 1477 //var errorField = $($("#" + errorFieldId)[0]); 1478 var errorField = $("#"+ errorFieldId).eq(0); 1479 1480 // make sure we found the element 1481 if (errorField.length == 1) { 1482 var status = json[1]; 1483 // read the optional msg from the server 1484 var msg = json[2]; 1485 if (!status) { 1486 // Houston we got a problem - display an red prompt 1487 options.ajaxValidCache[errorFieldId] = false; 1488 options.isError = true; 1489 1490 // resolve the msg prompt 1491 if(msg) { 1492 if (options.allrules[msg]) { 1493 var txt = options.allrules[msg].alertText; 1494 if (txt) { 1495 msg = txt; 1496 } 1497 } 1498 } 1499 else 1500 msg = rule.alertText; 1501 1502 if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options); 1503 } else { 1504 options.ajaxValidCache[errorFieldId] = true; 1505 1506 // resolves the msg prompt 1507 if(msg) { 1508 if (options.allrules[msg]) { 1509 var txt = options.allrules[msg].alertTextOk; 1510 if (txt) { 1511 msg = txt; 1512 } 1513 } 1514 } 1515 else 1516 msg = rule.alertTextOk; 1517 1518 if (options.showPrompts) { 1519 // see if we should display a green prompt 1520 if (msg) 1521 methods._showPrompt(errorField, msg, "pass", true, options); 1522 else 1523 methods._closePrompt(errorField); 1524 } 1525 1526 // If a submit form triggered this, we want to re-submit the form 1527 if (options.eventTrigger == "submit") 1528 field.closest("form").submit(); 1529 } 1530 } 1531 errorField.trigger("jqv.field.result", [errorField, options.isError, msg]); 1532 } 1533 }); 1534 1535 return rule.alertTextLoad; 1536 } 1537 }, 1538 /** 1539 * Common method to handle ajax errors 1540 * 1541 * @param {Object} data 1542 * @param {Object} transport 1543 */ 1544 _ajaxError: function(data, transport) { 1545 if(data.status == 0 && transport == null) 1546 alert("The page is not served from a server! ajax call failed"); 1547 else if(typeof console != "undefined") 1548 console.log("Ajax error: " + data.status + " " + transport); 1549 }, 1550 /** 1551 * date -> string 1552 * 1553 * @param {Object} date 1554 */ 1555 _dateToString: function(date) { 1556 return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate(); 1557 }, 1558 /** 1559 * Parses an ISO date 1560 * @param {String} d 1561 */ 1562 _parseDate: function(d) { 1563 1564 var dateParts = d.split("-"); 1565 if(dateParts==d) 1566 dateParts = d.split("/"); 1567 if(dateParts==d) { 1568 dateParts = d.split("."); 1569 return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]); 1570 } 1571 return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]); 1572 }, 1573 /** 1574 * Builds or updates a prompt with the given information 1575 * 1576 * @param {jqObject} field 1577 * @param {String} promptText html text to display type 1578 * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) 1579 * @param {boolean} ajaxed - use to mark fields than being validated with ajax 1580 * @param {Map} options user options 1581 */ 1582 _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) { 1583 //Check if we need to adjust what element to show the prompt on 1584 if(field.data('jqv-prompt-at') instanceof jQuery ){ 1585 field = field.data('jqv-prompt-at'); 1586 } else if(field.data('jqv-prompt-at')) { 1587 field = $(field.data('jqv-prompt-at')); 1588 } 1589 1590 var prompt = methods._getPrompt(field); 1591 // The ajax submit errors are not see has an error in the form, 1592 // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time 1593 // Because no error was found befor submitting 1594 if(ajaxform) prompt = false;
1595 // Check that there is indded text 1596 if($.trim(promptText)){ 1597 if (prompt) 1598 methods._updatePrompt(field, prompt, promptText, type, ajaxed, options); 1599 else 1600 methods._buildPrompt(field, promptText, type, ajaxed, options); 1601 } 1602 }, 1603 /** 1604 * Builds and shades a prompt for the given field. 1605 * 1606 * @param {jqObject} field 1607 * @param {String} promptText html text to display type 1608 * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) 1609 * @param {boolean} ajaxed - use to mark fields than being validated with ajax 1610 * @param {Map} options user options 1611 */ 1612 _buildPrompt: function(field, promptText, type, ajaxed, options) { 1613 1614 // create the prompt 1615 var prompt = $('<div>'); 1616 prompt.addClass(methods._getClassName(field.attr("id")) + "formError"); 1617 // add a class name to identify the parent form of the prompt 1618 prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id"))); 1619 prompt.addClass("formError"); 1620 1621 switch (type) { 1622 case "pass": 1623 prompt.addClass("greenPopup"); 1624 break; 1625 case "load": 1626 prompt.addClass("blackPopup"); 1627 break; 1628 default: 1629 /* it has error */ 1630 //alert("unknown popup type:"+type); 1631 }
1632 if (ajaxed) 1633 prompt.addClass("ajaxed"); 1634 1635 // create the prompt content 1636 var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt); 1637 1638 // determine position type 1639 var positionType=field.data("promptPosition") || options.promptPosition; 1640 1641 // create the css arrow pointing at the field 1642 // note that there is no triangle on max-checkbox and radio 1643 if (options.showArrow) { 1644 var arrow = $('<div>').addClass("formErrorArrow"); 1645 1646 //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10) 1647 if (typeof(positionType)=='string') 1648 { 1649 var pos=positionType.indexOf(":"); 1650 if(pos!=-1) 1651 positionType=positionType.substring(0,pos); 1652 } 1653 1654 switch (positionType) { 1655 case "bottomLeft": 1656 case "bottomRight": 1657 prompt.find(".formErrorContent").before(arrow); 1658 arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>'); 1659 break; 1660 case "topLeft": 1661 case "topRight": 1662 arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>'); 1663 prompt.append(arrow); 1664 break; 1665 } 1666 } 1667 // Add custom prompt class 1668 if (options.addPromptClass) 1669 prompt.addClass(options.addPromptClass); 1670 1671 // Add custom prompt class defined in element 1672 var requiredOverride = field.attr('data-required-class'); 1673 if(requiredOverride !== undefined) { 1674 prompt.addClass(requiredOverride); 1675 } else { 1676 if(options.prettySelect) { 1677 if($('#' + field.attr('id')).next().is('select')) { 1678 var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class'); 1679 if(prettyOverrideClass !== undefined) { 1680 prompt.addClass(prettyOverrideClass); 1681 } 1682 } 1683 } 1684 } 1685 1686 prompt.css({ 1687 "opacity": 0 1688 }); 1689 if(positionType === 'inline') { 1690 prompt.addClass("inline"); 1691 if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) { 1692 prompt.appendTo($('#'+field.attr('data-prompt-target'))); 1693 } else { 1694 field.after(prompt); 1695 } 1696 } else { 1697 field.before(prompt); 1698 } 1699 1700 var pos = methods._calculatePosition(field, prompt, options); 1701 prompt.css({ 1702 'position': positionType === 'inline' ? 'relative' : 'absolute', 1703 "top": pos.callerTopPosition, 1704 "left": pos.callerleftPosition, 1705 "marginTop": pos.marginTopSize, 1706 "opacity": 0 1707 }).data("callerField", field); 1708 1709 1710 if (options.autoHidePrompt) { 1711 setTimeout(function(){ 1712 prompt.animate({ 1713 "opacity": 0 1714 },function(){ 1715 prompt.closest('.formError').remove(); 1716 }); 1717 }, options.autoHideDelay); 1718 } 1719 return prompt.animate({ 1720 "opacity": 0.87 1721 }); 1722 }, 1723 /** 1724 * Updates the prompt text field - the field for which the prompt 1725 * @param {jqObject} field 1726 * @param {String} promptText html text to display type 1727 * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) 1728 * @param {boolean} ajaxed - use to mark fields than being validated with ajax 1729 * @param {Map} options user options 1730 */ 1731 _updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) { 1732 1733 if (prompt) { 1734 if (typeof type !== "undefined") { 1735 if (type == "pass") 1736 prompt.addClass("greenPopup"); 1737 else 1738 prompt.removeClass("greenPopup"); 1739 1740 if (type == "load") 1741 prompt.addClass("blackPopup"); 1742 else 1743 prompt.removeClass("blackPopup"); 1744 } 1745 if (ajaxed) 1746 prompt.addClass("ajaxed"); 1747 else 1748 prompt.removeClass("ajaxed"); 1749 1750 prompt.find(".formErrorContent").html(promptText); 1751 1752 var pos = methods._calculatePosition(field, prompt, options); 1753 var css = {"top": pos.callerTopPosition, 1754 "left": pos.callerleftPosition, 1755 "marginTop": pos.marginTopSize, 1756 "opacity": 0.87}; 1757 1758 prompt.css({ 1759 "opacity": 0, 1760 "display": "block" 1761 }); 1762 1763 if (noAnimation) 1764 prompt.css(css); 1765 else 1766 prompt.animate(css); 1767 } 1768 }, 1769 /** 1770 * Closes the prompt associated with the given field 1771 * 1772 * @param {jqObject} 1773 * field 1774 */ 1775 _closePrompt: function(field) { 1776 var prompt = methods._getPrompt(field); 1777 if (prompt) 1778 prompt.fadeTo("fast", 0, function() { 1779 prompt.closest('.formError').remove(); 1780 }); 1781 }, 1782 closePrompt: function(field) { 1783 return methods._closePrompt(field); 1784 }, 1785 /** 1786 * Returns the error prompt matching the field if any 1787 * 1788 * @param {jqObject} 1789 * field 1790 * @return undefined or the error prompt (jqObject) 1791 */ 1792 _getPrompt: function(field) { 1793 var formId = $(field).closest('form, .validationEngineContainer').attr('id'); 1794 var className = methods._getClassName(field.attr("id")) + "formError"; 1795 var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0]; 1796 if (match) 1797 return $(match); 1798 }, 1799 /** 1800 * Returns the escapade classname 1801 * 1802 * @param {selector} 1803 * className 1804 */ 1805 _escapeExpression: function (selector) { 1806 return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1"); 1807 }, 1808 /** 1809 * returns true if we are in a RTLed document 1810 * 1811 * @param {jqObject} field 1812 */ 1813 isRTL: function(field) 1814 { 1815 var $document = $(document); 1816 var $body = $('body'); 1817 var rtl = 1818 (field && field.hasClass('rtl')) || 1819 (field && (field.attr('dir') || '').toLowerCase()==='rtl') || 1820 $document.hasClass('rtl') || 1821 ($document.attr('dir') || '').toLowerCase()==='rtl' || 1822 $body.hasClass('rtl') || 1823 ($body.attr('dir') || '').toLowerCase()==='rtl'; 1824 return Boolean(rtl); 1825 }, 1826 /** 1827 * Calculates prompt position 1828 * 1829 * @param {jqObject} 1830 * field 1831 * @param {jqObject} 1832 * the prompt 1833 * @param {Map} 1834 * options 1835 * @return positions 1836 */ 1837 _calculatePosition: function (field, promptElmt, options) { 1838 1839 var promptTopPosition, promptleftPosition, marginTopSize; 1840 var fieldWidth = field.width(); 1841 var fieldLeft = field.position().left; 1842 var fieldTop = field.position().top; 1843 var fieldHeight = field.height(); 1844 var promptHeight = promptElmt.height(); 1845 1846 1847 // is the form contained in an overflown container? 1848 promptTopPosition = promptleftPosition = 0; 1849 // compensation for the arrow 1850 marginTopSize = -promptHeight; 1851 1852 1853 //prompt positioning adjustment support
1854 //now you can adjust prompt position 1855 //usage: positionType:Xshift,Yshift 1856 //for example: 1857 // bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally 1858 // topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top 1859 //You can use +pixels, - pixels. If no sign is provided than + is default. 1860 var positionType=field.data("promptPosition") || options.promptPosition; 1861 var shift1=""; 1862 var shift2=""; 1863 var shiftX=0; 1864 var shiftY=0; 1865 if (typeof(positionType)=='string') { 1866 //do we have any position adjustments ? 1867 if (positionType.indexOf(":")!=-1) { 1868 shift1=positionType.substring(positionType.indexOf(":")+1); 1869 positionType=positionType.substring(0,positionType.indexOf(":")); 1870 1871 //if any advanced positioning will be needed (percents or something else) - parser should be added here 1872 //for now we use simple parseInt() 1873 1874 //do we have second parameter? 1875 if (shift1.indexOf(",") !=-1) { 1876 shift2=shift1.substring(shift1.indexOf(",") +1); 1877 shift1=shift1.substring(0,shift1.indexOf(",")); 1878 shiftY=parseInt(shift2); 1879 if (isNaN(shiftY)) shiftY=0; 1880 }; 1881 1882 shiftX=parseInt(shift1); 1883 if (isNaN(shift1)) shift1=0; 1884 1885 }; 1886 }; 1887 1888 1889 switch (positionType) { 1890 default: 1891 case "topRight": 1892 promptleftPosition += fieldLeft + fieldWidth - 27; 1893 promptTopPosition += fieldTop; 1894 break; 1895 1896 case "topLeft": 1897 promptTopPosition += fieldTop; 1898 promptleftPosition += fieldLeft; 1899 break; 1900 1901 case "centerRight": 1902 promptTopPosition = fieldTop+4; 1903 marginTopSize = 0; 1904 promptleftPosition= fieldLeft + field.outerWidth(true)+5; 1905 break; 1906 case "centerLeft": 1907 promptleftPosition = fieldLeft - (promptElmt.width() + 2); 1908 promptTopPosition = fieldTop+4; 1909 marginTopSize = 0; 1910 1911 break; 1912 1913 case "bottomLeft": 1914 promptTopPosition = fieldTop + field.height() + 5; 1915 marginTopSize = 0; 1916 promptleftPosition = fieldLeft; 1917 break; 1918 case "bottomRight": 1919 promptleftPosition = fieldLeft + fieldWidth - 27; 1920 promptTopPosition = fieldTop + field.height() + 5; 1921 marginTopSize = 0; 1922 break; 1923 case "inline": 1924 promptleftPosition = 0; 1925 promptTopPosition = 0; 1926 marginTopSize = 0; 1927 }; 1928 1929 1930 1931 //apply adjusments if any 1932 promptleftPosition += shiftX; 1933 promptTopPosition += shiftY; 1934 1935 return { 1936 "callerTopPosition": promptTopPosition + "px", 1937 "callerleftPosition": promptleftPosition + "px", 1938 "marginTopSize": marginTopSize + "px" 1939 }; 1940 }, 1941 /** 1942 * Saves the user options and variables in the form.data 1943 * 1944 * @param {jqObject} 1945 * form - the form where the user option should be saved 1946 * @param {Map} 1947 * options - the user options 1948 * @return the user options (extended from the defaults) 1949 */ 1950 _saveOptions: function(form, options) { 1951 1952 // is there a language localisation ? 1953 if ($.validationEngineLanguage) 1954 var allRules = $.validationEngineLanguage.allRules; 1955 else 1956 $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page"); 1957 // --- Internals DO NOT TOUCH or OVERLOAD --- 1958 // validation rules and i18 1959 $.validationEngine.defaults.allrules = allRules; 1960 1961 var userOptions = $.extend(true,{},$.validationEngine.defaults,options); 1962 1963 form.data('jqv', userOptions); 1964 return userOptions; 1965 }, 1966 1967 /** 1968 * Removes forbidden characters from class name 1969 * @param {String} className 1970 */ 1971 _getClassName: function(className) { 1972 if(className) 1973 return className.replace(/:/g, "_").replace(/\./g, "_"); 1974 }, 1975 /** 1976 * Escape special character for jQuery selector 1977 * http://totaldev.com/content/escaping-characters-get-valid-jquery-id 1978 * @param {String} selector 1979 */ 1980 _jqSelector: function(str){ 1981 return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); 1982 }, 1983 /** 1984 * Conditionally required field 1985 * 1986 * @param {jqObject} field 1987 * @param {Array[String]} rules 1988 * @param {int} i rules index 1989 * @param {Map} 1990 * user options 1991 * @return an error string if validation failed 1992 */ 1993 _condRequired: function(field, rules, i, options) { 1994 var idx, dependingField; 1995 1996 for(idx = (i + 1); idx < rules.length; idx++) { 1997 dependingField = jQuery("#" + rules[idx]).first(); 1998 1999 /* Use _required for determining wether dependingField has a value. 2000 * There is logic there for handling all field types, and default value; so we won't replicate that here 2001 * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462) 2002 */ 2003 if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) { 2004 /* We now know any of the depending fields has a value, 2005 * so we can validate this field as per normal required code 2006 */ 2007 return methods._required(field, ["required"], 0, options); 2008 } 2009 } 2010 }, 2011 2012 _submitButtonClick: function(event) { 2013 var button = $(this); 2014 var form = button.closest('form, .validationEngineContainer'); 2015 form.data("jqv_submitButton", button.attr("id")); 2016 } 2017 }; 2018 2019 /** 2020 * Plugin entry point. 2021 * You may pass an action as a parameter or a list of options. 2022 * if none, the init and attach methods are being called. 2023 * Remember: if you pass options, the attached method is NOT called automatically 2024 * 2025 * @param {String} 2026 * method (optional) action 2027 */ 2028 $.fn.validationEngine = function(method) { 2029 2030 var form = $(this); 2031 if(!form[0]) return form; // stop here if the form does not exist 2032 2033 if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) { 2034 2035 // make sure init is called once 2036 if(method != "showPrompt" && method != "hide" && method != "hideAll") 2037 methods.init.apply(form); 2038 2039 return methods[method].apply(form, Array.prototype.slice.call(arguments, 1)); 2040 } else if (typeof method == 'object' || !method) { 2041 2042 // default constructor with or without arguments 2043 methods.init.apply(form, arguments); 2044 return methods.attach.apply(form); 2045 } else { 2046 $.error('Method ' + method + ' does not exist in jQuery.validationEngine'); 2047 } 2048 }; 2049 2050 2051 2052 // LEAK GLOBAL OPTIONS 2053 $.validationEngine= {fieldIdCounter: 0,defaults:{ 2054 2055 // Name of the event triggering field validation 2056 validationEventTrigger: "blur", 2057 // Automatically scroll viewport to the first error 2058 scroll: true, 2059 // Focus on the first input 2060 focusFirstField:true, 2061 // Show prompts, set to false to disable prompts 2062 showPrompts: true, 2063 // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs) 2064 validateNonVisibleFields: false, 2065 // ignore the validation for fields with this specific class (Useful in cases of tabbed containers AND hidden fields we don't want to validate) 2066 ignoreFieldsWithClass: 'ignoreMe', 2067 // Opening box position, possible locations are: topLeft, 2068 // topRight, bottomLeft, centerRight, bottomRight, inline 2069 // inline gets inserted after the validated field or into an element specified in data-prompt-target 2070 promptPosition: "topRight", 2071 bindMethod:"bind", 2072 // internal, automatically set to true when it parse a _ajax rule
2073 inlineAjax: false, 2074 // if set to true, the form data is sent asynchronously via ajax to the form.action url (get) 2075 ajaxFormValidation: false, 2076 // The url to send the submit ajax validation (default to action) 2077 ajaxFormValidationURL: false, 2078 // HTTP method used for ajax validation 2079 ajaxFormValidationMethod: 'get', 2080 // Ajax form validation callback method: boolean onComplete(form, status, errors, options) 2081 // retuns false if the form.submit event needs to be canceled. 2082 onAjaxFormComplete: $.noop, 2083 // called right before the ajax call, may return false to cancel 2084 onBeforeAjaxFormValidation: $.noop, 2085 // Stops form from submitting and execute function assiciated with it 2086 onValidationComplete: false, 2087 2088 // Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages 2089 doNotShowAllErrosOnSubmit: false, 2090 // Object where you store custom messages to override the default error messages 2091 custom_error_messages:{}, 2092 // true if you want to validate the input fields on blur event 2093 binded: true, 2094 // set to true if you want to validate the input fields on blur only if the field it's not empty 2095 notEmpty: false, 2096 // set to true, when the prompt arrow needs to be displayed 2097 showArrow: true, 2098 // set to false, determines if the prompt arrow should be displayed when validating 2099 // checkboxes and radio buttons 2100 showArrowOnRadioAndCheckbox: false, 2101 // did one of the validation fail ? kept global to stop further ajax validations 2102 isError: false, 2103 // Limit how many displayed errors a field can have 2104 maxErrorsPerField: false, 2105 2106 // Caches field validation status, typically only bad status are created. 2107 // the array is used during ajax form validation to detect issues early and prevent an expensive submit 2108 ajaxValidCache: {}, 2109 // Auto update prompt position after window resize 2110 autoPositionUpdate: false, 2111 2112 InvalidFields: [], 2113 onFieldSuccess: false, 2114 onFieldFailure: false, 2115 onSuccess: false, 2116 onFailure: false, 2117 validateAttribute: "class", 2118 addSuccessCssClassToField: "", 2119 addFailureCssClassToField: "", 2120 2121 // Auto-hide prompt 2122 autoHidePrompt: false, 2123 // Delay before auto-hide 2124 autoHideDelay: 5000, 2125 // Fade out duration while hiding the validations 2126 fadeDuration: 300, 2127 // Use Prettify select library 2128 prettySelect: false, 2129 // Add css class on prompt 2130 addPromptClass : "", 2131 // Custom ID uses prefix 2132 usePrefix: "", 2133 // Custom ID uses suffix 2134 useSuffix: "", 2135 // Only show one message per error prompt 2136 showOneMessage: false 2137 }}; 2138 $(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"}); 2139})(jQuery);
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.