1/*! jQuery Validation Plugin - v1.10.0 - 9/7/2012 2* https://github.com/jzaefferer/jquery-validation 3* Copyright (c) 2012 Jörn Zaefferer; Licensed MIT, GPL */ 4 5(function($) { 6 7$.extend($.fn, { 8 // http://docs.jquery.com/Plugins/Validation/validate 9 validate: function( options ) { 10 11 // if nothing is selected, return nothing; can't chain anyway 12 if (!this.length) { 13 if (options && options.debug && window.console) { 14 console.warn( "nothing selected, can't validate, returning nothing" ); 15 } 16 return; 17 } 18 19 // check if a validator for this form was already created 20 var validator = $.data(this[0], 'validator'); 21 if ( validator ) { 22 return validator; 23 } 24 25 // Add novalidate tag if HTML5. 26 this.attr('novalidate', 'novalidate'); 27 28 validator = new $.validator( options, this[0] ); 29 $.data(this[0], 'validator', validator); 30 31 if ( validator.settings.onsubmit ) { 32 33 this.validateDelegate( ":submit", "click", function(ev) { 34 if ( validator.settings.submitHandler ) { 35 validator.submitButton = ev.target; 36 } 37 // allow suppressing validation by adding a cancel class to the submit button 38 if ( $(ev.target).hasClass('cancel') ) { 39 validator.cancelSubmit = true; 40 } 41 }); 42 43 // validate the form on submit 44 this.submit( function( event ) { 45 if ( validator.settings.debug ) { 46 // prevent form submit to be able to see console output 47 event.preventDefault(); 48 } 49 function handle() { 50 var hidden; 51 if ( validator.settings.submitHandler ) { 52 if (validator.submitButton) { 53 // insert a hidden input as a replacement for the missing submit button 54 hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); 55 } 56 validator.settings.submitHandler.call( validator, validator.currentForm, event ); 57 if (validator.submitButton) { 58 // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 59 hidden.remove(); 60 } 61 return false; 62 } 63 return true; 64 } 65 66 // prevent submit for invalid forms or custom submit handlers 67 if ( validator.cancelSubmit ) { 68 validator.cancelSubmit = false; 69 return handle(); 70 } 71 if ( validator.form() ) { 72 if ( validator.pendingRequest ) { 73 validator.formSubmitted = true; 74 return false; 75 } 76 return handle(); 77 } else { 78 validator.focusInvalid(); 79 return false; 80 } 81 }); 82 } 83 84 return validator; 85 }, 86 // http://docs.jquery.com/Plugins/Validation/valid 87 valid: function() { 88 if ( $(this[0]).is('form')) { 89 return this.validate().form(); 90 } else { 91 var valid = true; 92 var validator = $(this[0].form).validate(); 93 this.each(function() { 94 valid &= validator.element(this); 95 }); 96 return valid; 97 } 98 }, 99 // attributes: space seperated list of attributes to retrieve and remove 100 removeAttrs: function(attributes) { 101 var result = {}, 102 $element = this; 103 $.each(attributes.split(/\s/), function(index, value) { 104 result[value] = $element.attr(value); 105 $element.removeAttr(value); 106 }); 107 return result; 108 }, 109 // http://docs.jquery.com/Plugins/Validation/rules 110 rules: function(command, argument) { 111 var element = this[0]; 112 113 if (command) { 114 var settings = $.data(element.form, 'validator').settings; 115 var staticRules = settings.rules; 116 var existingRules = $.validator.staticRules(element); 117 switch(command) { 118 case "add": 119 $.extend(existingRules, $.validator.normalizeRule(argument)); 120 staticRules[element.name] = existingRules; 121 if (argument.messages) { 122 settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); 123 } 124 break; 125 case "remove": 126 if (!argument) { 127 delete staticRules[element.name]; 128 return existingRules; 129 } 130 var filtered = {}; 131 $.each(argument.split(/\s/), function(index, method) { 132 filtered[method] = existingRules[method]; 133 delete existingRules[method]; 134 }); 135 return filtered; 136 } 137 } 138 139 var data = $.validator.normalizeRules( 140 $.extend( 141 {}, 142 $.validator.metadataRules(element), 143 $.validator.classRules(element), 144 $.validator.attributeRules(element), 145 $.validator.staticRules(element) 146 ), element); 147 148 // make sure required is at front 149 if (data.required) { 150 var param = data.required; 151 delete data.required; 152 data = $.extend({required: param}, data); 153 } 154 155 return data; 156 } 157}); 158 159// Custom selectors 160$.extend($.expr[":"], {
161 // http://docs.jquery.com/Plugins/Validation/blank 162 blank: function(a) {return !$.trim("" + a.value);}, 163 // http://docs.jquery.com/Plugins/Validation/filled 164 filled: function(a) {return !!$.trim("" + a.value);}, 165 // http://docs.jquery.com/Plugins/Validation/unchecked 166 unchecked: function(a) {return !a.checked;} 167}); 168 169// constructor for validator 170$.validator = function( options, form ) { 171 this.settings = $.extend( true, {}, $.validator.defaults, options ); 172 this.currentForm = form; 173 this.init(); 174}; 175 176$.validator.format = function(source, params) { 177 if ( arguments.length === 1 ) { 178 return function() { 179 var args = $.makeArray(arguments); 180 args.unshift(source); 181 return $.validator.format.apply( this, args ); 182 }; 183 } 184 if ( arguments.length > 2 && params.constructor !== Array ) { 185 params = $.makeArray(arguments).slice(1); 186 } 187 if ( params.constructor !== Array ) { 188 params = [ params ]; 189 } 190 $.each(params, function(i, n) { 191 source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); 192 }); 193 return source; 194}; 195 196$.extend($.validator, { 197 198 defaults: { 199 messages: {}, 200 groups: {}, 201 rules: {}, 202 errorClass: "error", 203 validClass: "valid", 204 errorElement: "label", 205 focusInvalid: true, 206 errorContainer: $( [] ), 207 errorLabelContainer: $( [] ), 208 onsubmit: true, 209 ignore: ":hidden", 210 ignoreTitle: false, 211 onfocusin: function(element, event) { 212 this.lastActive = element; 213 214 // hide error label and remove error class on focus if enabled 215 if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { 216 if ( this.settings.unhighlight ) { 217 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 218 } 219 this.addWrapper(this.errorsFor(element)).hide(); 220 } 221 }, 222 onfocusout: function(element, event) { 223 if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { 224 this.element(element); 225 } 226 }, 227 onkeyup: function(element, event) { 228 if ( event.which === 9 && this.elementValue(element) === '' ) { 229 return; 230 } else if ( element.name in this.submitted || element === this.lastActive ) { 231 this.element(element); 232 } 233 }, 234 onclick: function(element, event) { 235 // click on selects, radiobuttons and checkboxes 236 if ( element.name in this.submitted ) { 237 this.element(element); 238 } 239 // or option elements, check parent select in that case 240 else if (element.parentNode.name in this.submitted) { 241 this.element(element.parentNode); 242 } 243 }, 244 highlight: function(element, errorClass, validClass) { 245 if (element.type === 'radio') { 246 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 247 } else { 248 $(element).addClass(errorClass).removeClass(validClass); 249 } 250 }, 251 unhighlight: function(element, errorClass, validClass) { 252 if (element.type === 'radio') { 253 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 254 } else { 255 $(element).removeClass(errorClass).addClass(validClass); 256 } 257 } 258 }, 259 260 // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults 261 setDefaults: function(settings) { 262 $.extend( $.validator.defaults, settings ); 263 }, 264 265 messages: { 266 required: "This field is required.", 267 remote: "Please fix this field.", 268 email: "Please enter a valid email address.", 269 url: "Please enter a valid URL.", 270 date: "Please enter a valid date.", 271 dateISO: "Please enter a valid date (ISO).", 272 number: "Please enter a valid number.", 273 digits: "Please enter only digits.", 274 creditcard: "Please enter a valid credit card number.", 275 equalTo: "Please enter the same value again.", 276 maxlength: $.validator.format("Please enter no more than {0} characters."), 277 minlength: $.validator.format("Please enter at least {0} characters."), 278 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 279 range: $.validator.format("Please enter a value between {0} and {1}."), 280 max: $.validator.format("Please enter a value less than or equal to {0}."), 281 min: $.validator.format("Please enter a value greater than or equal to {0}.") 282 }, 283 284 autoCreateRanges: false, 285 286 prototype: { 287 288 init: function() { 289 this.labelContainer = $(this.settings.errorLabelContainer); 290 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 291 this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); 292 this.submitted = {}; 293 this.valueCache = {}; 294 this.pendingRequest = 0; 295 this.pending = {}; 296 this.invalid = {}; 297 this.reset(); 298 299 var groups = (this.groups = {}); 300 $.each(this.settings.groups, function(key, value) { 301 $.each(value.split(/\s/), function(index, name) { 302 groups[name] = key; 303 }); 304 }); 305 var rules = this.settings.rules; 306 $.each(rules, function(key, value) { 307 rules[key] = $.validator.normalizeRule(value); 308 }); 309 310 function delegate(event) {
311 var validator = $.data(this[0].form, "validator"), 312 eventType = "on" + event.type.replace(/^validate/, ""); 313 if (validator.settings[eventType]) { 314 validator.settings[eventType].call(validator, this[0], event); 315 } 316 } 317 $(this.currentForm) 318 .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " + 319 "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + 320 "[type='email'], [type='datetime'], [type='date'], [type='month'], " + 321 "[type='week'], [type='time'], [type='datetime-local'], " + 322 "[type='range'], [type='color'] ", 323 "focusin focusout keyup", delegate) 324 .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); 325 326 if (this.settings.invalidHandler) { 327 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 328 } 329 }, 330 331 // http://docs.jquery.com/Plugins/Validation/Validator/form 332 form: function() { 333 this.checkForm(); 334 $.extend(this.submitted, this.errorMap); 335 this.invalid = $.extend({}, this.errorMap); 336 if (!this.valid()) { 337 $(this.currentForm).triggerHandler("invalid-form", [this]); 338 } 339 this.showErrors(); 340 return this.valid(); 341 }, 342 343 checkForm: function() { 344 this.prepareForm(); 345 for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { 346 this.check( elements[i] ); 347 } 348 return this.valid(); 349 }, 350 351 // http://docs.jquery.com/Plugins/Validation/Validator/element 352 element: function( element ) { 353 element = this.validationTargetFor( this.clean( element ) ); 354 this.lastElement = element; 355 this.prepareElement( element ); 356 this.currentElements = $(element); 357 var result = this.check( element ) !== false; 358 if (result) { 359 delete this.invalid[element.name]; 360 } else { 361 this.invalid[element.name] = true; 362 } 363 if ( !this.numberOfInvalids() ) { 364 // Hide error containers on last error 365 this.toHide = this.toHide.add( this.containers ); 366 } 367 this.showErrors(); 368 return result; 369 }, 370 371 // http://docs.jquery.com/Plugins/Validation/Validator/showErrors 372 showErrors: function(errors) { 373 if(errors) { 374 // add items to error list and map 375 $.extend( this.errorMap, errors ); 376 this.errorList = []; 377 for ( var name in errors ) { 378 this.errorList.push({ 379 message: errors[name], 380 element: this.findByName(name)[0] 381 }); 382 } 383 // remove items from success list 384 this.successList = $.grep( this.successList, function(element) { 385 return !(element.name in errors); 386 }); 387 } 388 if (this.settings.showErrors) { 389 this.settings.showErrors.call( this, this.errorMap, this.errorList ); 390 } else { 391 this.defaultShowErrors(); 392 } 393 }, 394 395 // http://docs.jquery.com/Plugins/Validation/Validator/resetForm 396 resetForm: function() { 397 if ( $.fn.resetForm ) { 398 $( this.currentForm ).resetForm(); 399 } 400 this.submitted = {}; 401 this.lastElement = null; 402 this.prepareForm(); 403 this.hideErrors(); 404 this.elements().removeClass( this.settings.errorClass ).removeData( "previousValue" ); 405 }, 406 407 numberOfInvalids: function() { 408 return this.objectLength(this.invalid); 409 }, 410 411 objectLength: function( obj ) { 412 var count = 0; 413 for ( var i in obj ) { 414 count++; 415 } 416 return count; 417 }, 418 419 hideErrors: function() { 420 this.addWrapper( this.toHide ).hide(); 421 }, 422 423 valid: function() { 424 return this.size() === 0; 425 }, 426 427 size: function() { 428 return this.errorList.length; 429 }, 430 431 focusInvalid: function() { 432 if( this.settings.focusInvalid ) { 433 try { 434 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 435 .filter(":visible") 436 .focus() 437 // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 438 .trigger("focusin"); 439 } catch(e) { 440 // ignore IE throwing errors when focusing hidden elements 441 } 442 } 443 }, 444 445 findLastActive: function() { 446 var lastActive = this.lastActive; 447 return lastActive && $.grep(this.errorList, function(n) { 448 return n.element.name === lastActive.name; 449 }).length === 1 && lastActive; 450 }, 451 452 elements: function() {
453 var validator = this, 454 rulesCache = {}; 455 456 // select all valid inputs inside the form (no submit or reset buttons) 457 return $(this.currentForm) 458 .find("input, select, textarea") 459 .not(":submit, :reset, :image, [disabled]") 460 .not( this.settings.ignore ) 461 .filter(function() { 462 if ( !this.name && validator.settings.debug && window.console ) { 463 console.error( "%o has no name assigned", this); 464 } 465 466 // select only the first element for each name, and only those with rules specified 467 if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) { 468 return false; 469 } 470 471 rulesCache[this.name] = true; 472 return true; 473 }); 474 }, 475 476 clean: function( selector ) { 477 return $( selector )[0]; 478 }, 479 480 errors: function() { 481 var errorClass = this.settings.errorClass.replace(' ', '.'); 482 return $( this.settings.errorElement + "." + errorClass, this.errorContext ); 483 }, 484 485 reset: function() { 486 this.successList = []; 487 this.errorList = []; 488 this.errorMap = {}; 489 this.toShow = $([]); 490 this.toHide = $([]); 491 this.currentElements = $([]); 492 }, 493 494 prepareForm: function() { 495 this.reset(); 496 this.toHide = this.errors().add( this.containers ); 497 }, 498 499 prepareElement: function( element ) { 500 this.reset(); 501 this.toHide = this.errorsFor(element); 502 }, 503 504 elementValue: function( element ) { 505 var type = $(element).attr('type'), 506 val = $(element).val(); 507 508 if ( type === 'radio' || type === 'checkbox' ) { 509 return $('input[name="' + $(element).attr('name') + '"]:checked').val(); 510 } 511 512 if ( typeof val === 'string' ) { 513 return val.replace(/\r/g, ""); 514 } 515 return val; 516 }, 517 518 check: function( element ) { 519 element = this.validationTargetFor( this.clean( element ) ); 520 521 var rules = $(element).rules(); 522 var dependencyMismatch = false; 523 var val = this.elementValue(element); 524 var result; 525 526 for (var method in rules ) { 527 var rule = { method: method, parameters: rules[method] }; 528 try { 529 530 result = $.validator.methods[method].call( this, val, element, rule.parameters ); 531 532 // if a method indicates that the field is optional and therefore valid, 533 // don't mark it as valid when there are no other rules 534 if ( result === "dependency-mismatch" ) { 535 dependencyMismatch = true; 536 continue; 537 } 538 dependencyMismatch = false; 539 540 if ( result === "pending" ) { 541 this.toHide = this.toHide.not( this.errorsFor(element) ); 542 return; 543 } 544 545 if( !result ) { 546 this.formatAndAdd( element, rule ); 547 return false; 548 } 549 } catch(e) { 550 if ( this.settings.debug && window.console ) { 551 console.log("exception occured when checking element " + element.id + ", check the '" + rule.method + "' method", e); 552 } 553 throw e; 554 } 555 } 556 if (dependencyMismatch) { 557 return; 558 } 559 if ( this.objectLength(rules) ) { 560 this.successList.push(element); 561 } 562 return true; 563 }, 564 565 // return the custom message for the given element and validation method 566 // specified in the element's "messages" metadata 567 customMetaMessage: function(element, method) { 568 if (!$.metadata) { 569 return; 570 } 571 var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata(); 572 return meta && meta.messages && meta.messages[method]; 573 }, 574 575 // return the custom message for the given element and validation method 576 // specified in the element's HTML5 data attribute 577 customDataMessage: function(element, method) { 578 return $(element).data('msg-' + method.toLowerCase()) || (element.attributes && $(element).attr('data-msg-' + method.toLowerCase())); 579 }, 580 581 // return the custom message for the given element name and validation method 582 customMessage: function( name, method ) { 583 var m = this.settings.messages[name]; 584 return m && (m.constructor === String ? m : m[method]); 585 }, 586 587 // return the first defined argument, allowing empty strings 588 findDefined: function() { 589 for(var i = 0; i < arguments.length; i++) { 590 if (arguments[i] !== undefined) { 591 return arguments[i]; 592 } 593 } 594 return undefined; 595 }, 596 597 defaultMessage: function( element, method) { 598 return this.findDefined( 599 this.customMessage( element.name, method ), 600 this.customDataMessage( element, method ), 601 this.customMetaMessage( element, method ), 602 // title is never undefined, so handle empty string as undefined 603 !this.settings.ignoreTitle && element.title || undefined, 604 $.validator.messages[method], 605 "<strong>Warning: No message defined for " + element.name + "</strong>" 606 ); 607 }, 608 609 formatAndAdd: function( element, rule ) { 610 var message = this.defaultMessage( element, rule.method ), 611 theregex = /\$?\{(\d+)\}/g; 612 if ( typeof message === "function" ) { 613 message = message.call(this, rule.parameters, element); 614 } else if (theregex.test(message)) { 615 message = $.validator.format(message.replace(theregex, '{$1}'), rule.parameters); 616 } 617 this.errorList.push({ 618 message: message, 619 element: element 620 }); 621 622 this.errorMap[element.name] = message; 623 this.submitted[element.name] = message; 624 }, 625 626 addWrapper: function(toToggle) { 627 if ( this.settings.wrapper ) { 628 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 629 } 630 return toToggle; 631 }, 632 633 defaultShowErrors: function() { 634 var i, elements; 635 for ( i = 0; this.errorList[i]; i++ ) { 636 var error = this.errorList[i]; 637 if ( this.settings.highlight ) { 638 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.val
638idClass ); 639 } 640 this.showLabel( error.element, error.message ); 641 } 642 if( this.errorList.length ) { 643 this.toShow = this.toShow.add( this.containers ); 644 } 645 if (this.settings.success) { 646 for ( i = 0; this.successList[i]; i++ ) { 647 this.showLabel( this.successList[i] ); 648 } 649 } 650 if (this.settings.unhighlight) { 651 for ( i = 0, elements = this.validElements(); elements[i]; i++ ) { 652 this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); 653 } 654 } 655 this.toHide = this.toHide.not( this.toShow ); 656 this.hideErrors(); 657 this.addWrapper( this.toShow ).show(); 658 }, 659 660 validElements: function() { 661 return this.currentElements.not(this.invalidElements()); 662 }, 663 664 invalidElements: function() { 665 return $(this.errorList).map(function() { 666 return this.element; 667 }); 668 }, 669 670 showLabel: function(element, message) { 671 var label = this.errorsFor( element ); 672 if ( label.length ) { 673 // refresh error/success class 674 label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 675 676 // check if we have a generated label, replace the message then 677 if ( label.attr("generated") ) { 678 label.html(message); 679 } 680 } else { 681 // create label 682 label = $("<" + this.settings.errorElement + "/>") 683 .attr({"for": this.idOrName(element), generated: true}) 684 .addClass(this.settings.errorClass) 685 .html(message || ""); 686 if ( this.settings.wrapper ) { 687 // make sure the element is visible, even in IE 688 // actually showing the wrapped element is handled elsewhere 689 label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 690 } 691 if ( !this.labelContainer.append(label).length ) { 692 if ( this.settings.errorPlacement ) { 693 this.settings.errorPlacement(label, $(element) ); 694 } else { 695 label.insertAfter(element); 696 } 697 } 698 } 699 if ( !message && this.settings.success ) { 700 label.text(""); 701 if ( typeof this.settings.success === "string" ) { 702 label.addClass( this.settings.success ); 703 } else { 704 this.settings.success( label, element ); 705 } 706 } 707 this.toShow = this.toShow.add(label); 708 }, 709 710 errorsFor: function(element) { 711 var name = this.idOrName(element); 712 return this.errors().filter(function() { 713 return $(this).attr('for') === name; 714 }); 715 }, 716 717 idOrName: function(element) { 718 return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); 719 }, 720 721 validationTargetFor: function(element) { 722 // if radio/checkbox, validate first element in group instead 723 if (this.checkable(element)) { 724 element = this.findByName( element.name ).not(this.settings.ignore)[0]; 725 } 726 return element; 727 }, 728 729 checkable: function( element ) { 730 return (/radio|checkbox/i).test(element.type); 731 }, 732 733 findByName: function( name ) { 734 return $(this.currentForm).find('[name="' + name + '"]'); 735 }, 736 737 getLength: function(value, element) { 738 switch( element.nodeName.toLowerCase() ) { 739 case 'select': 740 return $("option:selected", element).length; 741 case 'input': 742 if( this.checkable( element) ) { 743 return this.findByName(element.name).filter(':checked').length; 744 } 745 } 746 return value.length; 747 }, 748 749 depend: function(param, element) { 750 return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; 751 }, 752 753 dependTypes: { 754 "boolean": function(param, element) { 755 return param; 756 }, 757 "string": function(param, element) { 758 return !!$(param, element.form).length; 759 }, 760 "function": function(param, element) { 761 return param(element); 762 } 763 }, 764 765 optional: function(element) { 766 var val = this.elementValue(element); 767 return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; 768 }, 769 770 startRequest: function(element) { 771 if (!this.pending[element.name]) { 772 this.pendingRequest++; 773 this.pending[element.name] = true; 774 } 775 }, 776 777 stopRequest: function(element, valid) { 778 this.pendingRequest--; 779 // sometimes synchronization fails, make sure pendingRequest is never < 0 780 if (this.pendingRequest < 0) { 781 this.pendingRequest = 0; 782 } 783 delete this.pending[element.name]; 784 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { 785 $(this.currentForm).submit(); 786 this.formSubmitted = false;
787 } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { 788 $(this.currentForm).triggerHandler("invalid-form", [this]); 789 this.formSubmitted = false; 790 } 791 }, 792 793 previousValue: function(element) { 794 return $.data(element, "previousValue") || $.data(element, "previousValue", { 795 old: null, 796 valid: true, 797 message: this.defaultMessage( element, "remote" ) 798 }); 799 } 800 801 }, 802 803 classRuleSettings: { 804 required: {required: true}, 805 email: {email: true}, 806 url: {url: true}, 807 date: {date: true}, 808 dateISO: {dateISO: true}, 809 number: {number: true}, 810 digits: {digits: true}, 811 creditcard: {creditcard: true} 812 }, 813 814 addClassRules: function(className, rules) { 815 if ( className.constructor === String ) { 816 this.classRuleSettings[className] = rules; 817 } else { 818 $.extend(this.classRuleSettings, className); 819 } 820 }, 821 822 classRules: function(element) { 823 var rules = {}; 824 var classes = $(element).attr('class'); 825 if ( classes ) { 826 $.each(classes.split(' '), function() { 827 if (this in $.validator.classRuleSettings) { 828 $.extend(rules, $.validator.classRuleSettings[this]); 829 } 830 }); 831 } 832 return rules; 833 }, 834 835 attributeRules: function(element) { 836 var rules = {}; 837 var $element = $(element); 838 839 for (var method in $.validator.methods) { 840 var value; 841 842 // support for <input required> in both html5 and older browsers 843 if (method === 'required') { 844 value = $element.get(0).getAttribute(method); 845 // Some browsers return an empty string for the required attribute 846 // and non-HTML5 browsers might have required="" markup 847 if (value === "") { 848 value = true; 849 } 850 // force non-HTML5 browsers to return bool 851 value = !!value; 852 } else { 853 value = $element.attr(method); 854 } 855 856 if (value) { 857 rules[method] = value; 858 } else if ($element[0].getAttribute("type") === method) { 859 rules[method] = true; 860 } 861 } 862 863 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 864 if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { 865 delete rules.maxlength; 866 } 867 868 return rules; 869 }, 870 871 metadataRules: function(element) { 872 if (!$.metadata) { 873 return {}; 874 } 875 876 var meta = $.data(element.form, 'validator').settings.meta; 877 return meta ? 878 $(element).metadata()[meta] : 879 $(element).metadata(); 880 }, 881 882 staticRules: function(element) { 883 var rules = {}; 884 var validator = $.data(element.form, 'validator'); 885 if (validator.settings.rules) { 886 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 887 } 888 return rules; 889 }, 890 891 normalizeRules: function(rules, element) { 892 // handle dependency check 893 $.each(rules, function(prop, val) { 894 // ignore rule when param is explicitly false, eg. required:false 895 if (val === false) { 896 delete rules[prop]; 897 return; 898 } 899 if (val.param || val.depends) { 900 var keepRule = true; 901 switch (typeof val.depends) { 902 case "string": 903 keepRule = !!$(val.depends, element.form).length; 904 break; 905 case "function": 906 keepRule = val.depends.call(element, element); 907 break; 908 } 909 if (keepRule) { 910 rules[prop] = val.param !== undefined ? val.param : true; 911 } else { 912 delete rules[prop]; 913 } 914 } 915 }); 916 917 // evaluate parameters 918 $.each(rules, function(rule, parameter) { 919 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 920 }); 921 922 // clean number parameters 923 $.each(['minlength', 'maxlength', 'min', 'max'], function() { 924 if (rules[this]) { 925 rules[this] = Number(rules[this]); 926 } 927 }); 928 $.each(['rangelength', 'range'], function() { 929 if (rules[this]) { 930 rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; 931 } 932 }); 933 934 if ($.validator.autoCreateRanges) { 935 // auto-create ranges 936 if (rules.min && rules.max) { 937 rules.range = [rules.min, rules.max]; 938 delete rules.min; 939 delete rules.max; 940 } 941 if (rules.minlength && rules.maxlength) { 942 rules.rangelength = [rules.minlength, rules.maxlength]; 943 delete rules.minlength; 944 delete rules.maxlength; 945 } 946 } 947 948 // To support custom messages in metadata ignore rule methods titled "messages" 949 if (rules.messages) { 950 delete rules.messages; 951 } 952 953 return rules; 954 }, 955
956 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 957 normalizeRule: function(data) { 958 if( typeof data === "string" ) { 959 var transformed = {}; 960 $.each(data.split(/\s/), function() { 961 transformed[this] = true; 962 }); 963 data = transformed; 964 } 965 return data; 966 }, 967 968 // http://docs.jquery.com/Plugins/Validation/Validator/addMethod 969 addMethod: function(name, method, message) { 970 $.validator.methods[name] = method; 971 $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; 972 if (method.length < 3) { 973 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 974 } 975 }, 976 977 methods: { 978 979 // http://docs.jquery.com/Plugins/Validation/Methods/required 980 required: function(value, element, param) { 981 // check if dependency is met 982 if ( !this.depend(param, element) ) { 983 return "dependency-mismatch"; 984 } 985 if ( element.nodeName.toLowerCase() === "select" ) { 986 // could be an array for select-multiple or a string, both are fine this way 987 var val = $(element).val(); 988 return val && val.length > 0; 989 } 990 if ( this.checkable(element) ) { 991 return this.getLength(value, element) > 0; 992 } 993 return $.trim(value).length > 0; 994 }, 995 996 // http://docs.jquery.com/Plugins/Validation/Methods/remote 997 remote: function(value, element, param) { 998 if ( this.optional(element) ) { 999 return "dependency-mismatch"; 1000 } 1001 1002 var previous = this.previousValue(element); 1003 if (!this.settings.messages[element.name] ) { 1004 this.settings.messages[element.name] = {}; 1005 } 1006 previous.originalMessage = this.settings.messages[element.name].remote; 1007 this.settings.messages[element.name].remote = previous.message; 1008 1009 param = typeof param === "string" && {url:param} || param; 1010 1011 if ( this.pending[element.name] ) { 1012 return "pending"; 1013 } 1014 if ( previous.old === value ) { 1015 return previous.valid; 1016 } 1017 1018 previous.old = value; 1019 var validator = this; 1020 this.startRequest(element); 1021 var data = {}; 1022 data[element.name] = value; 1023 $.ajax($.extend(true, { 1024 url: param, 1025 mode: "abort", 1026 port: "validate" + element.name, 1027 dataType: "json", 1028 data: data, 1029 success: function(response) { 1030 validator.settings.messages[element.name].remote = previous.originalMessage; 1031 var valid = response === true || response === "true"; 1032 if ( valid ) { 1033 var submitted = validator.formSubmitted; 1034 validator.prepareElement(element); 1035 validator.formSubmitted = submitted; 1036 validator.successList.push(element); 1037 delete validator.invalid[element.name]; 1038 validator.showErrors(); 1039 } else { 1040 var errors = {}; 1041 var message = response || validator.defaultMessage( element, "remote" ); 1042 errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 1043 validator.invalid[element.name] = true; 1044 validator.showErrors(errors); 1045 } 1046 previous.valid = valid; 1047 validator.stopRequest(element, valid); 1048 } 1049 }, param)); 1050 return "pending"; 1051 }, 1052 1053 // http://docs.jquery.com/Plugins/Validation/Methods/minlength 1054 minlength: function(value, element, param) { 1055 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1056 return this.optional(element) || length >= param; 1057 }, 1058 1059 // http://docs.jquery.com/Plugins/Validation/Methods/maxlength 1060 maxlength: function(value, element, param) { 1061 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1062 return this.optional(element) || length <= param; 1063 }, 1064 1065 // http://docs.jquery.com/Plugins/Validation/Methods/rangelength 1066 rangelength: function(value, element, param) { 1067 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1068 return this.optional(element) || ( length >= param[0] && length <= param[1] ); 1069 }, 1070 1071 // http://docs.jquery.com/Plugins/Validation/Methods/min 1072 min: function( value, element, param ) { 1073 return this.optional(element) || value >= param; 1074 }, 1075 1076 // http://docs.jquery.com/Plugins/Validation/Methods/max 1077 max: function( value, element, param ) { 1078 return this.optional(element) || value <= param; 1079 }, 1080 1081 // http://docs.jquery.com/Plugins/Validation/Methods/range 1082 range: function( value, element, param ) { 1083 return this.optional(element) || ( value >= param[0] && value <= param[1] ); 1084 }, 1085 1086 // http://docs.jquery.com/Plugins/Validation/Methods/email 1087 email: function(value, element) { 1088 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ 1089 return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value); 1090 }, 1091 1092 // http://docs.jquery.com/Plugins/Validation/Methods/url 1093 url: function(value, element) { 1094 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 1095 return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 1096 }, 1097 1098 // http://docs.jquery.com/Plugins/Validation/Methods/date 1099 date: function(value, element) { 1100 return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); 1101 }, 1102 1103 // http://docs.jquery.com/Plugins/Validation/Methods/dateISO 1104 dateISO: function(value, element) { 1105 return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value); 1106 }, 1107 1108 // http://docs.jquery.com/Plugins/Validation/Methods/number 1109 number: function(value, element) { 1110 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); 1111 }, 1112 1113 // http://docs.jquery.com/Plugins/Validation/Methods/digits 1114 digits: function(value, element) { 1115 return this.optional(element) || /^\d+$/.test(value); 1116 }, 1117 1118 // http://docs.jquery.com/Plugins/Validation/Methods/creditcard 1119 // based on http://en.wikipedia.org/wiki/Luhn 1120 creditcard: function(value, element) { 1121 if ( this.optional(element) ) { 1122 return "dependency-mismatch"; 1123 } 1124 // accept only spaces, digits and dashes 1125 if (/[^0-9 \-]+/.test(value)) { 1126 return false;
1127 } 1128 var nCheck = 0, 1129 nDigit = 0, 1130 bEven = false; 1131 1132 value = value.replace(/\D/g, ""); 1133 1134 for (var n = value.length - 1; n >= 0; n--) { 1135 var cDigit = value.charAt(n); 1136 nDigit = parseInt(cDigit, 10); 1137 if (bEven) { 1138 if ((nDigit *= 2) > 9) { 1139 nDigit -= 9; 1140 } 1141 } 1142 nCheck += nDigit; 1143 bEven = !bEven; 1144 } 1145 1146 return (nCheck % 10) === 0; 1147 }, 1148 1149 // http://docs.jquery.com/Plugins/Validation/Methods/equalTo 1150 equalTo: function(value, element, param) { 1151 // bind to the blur event of the target in order to revalidate whenever the target field is updated 1152 // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 1153 var target = $(param); 1154 if (this.settings.onfocusout) { 1155 target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 1156 $(element).valid(); 1157 }); 1158 } 1159 return value === target.val(); 1160 } 1161 1162 } 1163 1164}); 1165 1166// deprecated, use $.validator.format instead 1167$.format = $.validator.format; 1168 1169}(jQuery)); 1170 1171// ajax mode: abort 1172// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 1173// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 1174(function($) { 1175 var pendingRequests = {}; 1176 // Use a prefilter if available (1.5+) 1177 if ( $.ajaxPrefilter ) { 1178 $.ajaxPrefilter(function(settings, _, xhr) { 1179 var port = settings.port; 1180 if (settings.mode === "abort") { 1181 if ( pendingRequests[port] ) { 1182 pendingRequests[port].abort(); 1183 } 1184 pendingRequests[port] = xhr; 1185 } 1186 }); 1187 } else { 1188 // Proxy ajax 1189 var ajax = $.ajax; 1190 $.ajax = function(settings) { 1191 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 1192 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 1193 if (mode === "abort") { 1194 if ( pendingRequests[port] ) { 1195 pendingRequests[port].abort(); 1196 } 1197 return (pendingRequests[port] = ajax.apply(this, arguments)); 1198 } 1199 return ajax.apply(this, arguments); 1200 }; 1201 } 1202}(jQuery)); 1203 1204// provides cross-browser focusin and focusout events 1205// IE has native support, in other browsers, use event caputuring (neither bubbles) 1206 1207// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 1208// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 1209(function($) { 1210 // only implement if not provided by jQuery core (since 1.4) 1211 // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs 1212 if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { 1213 $.each({ 1214 focus: 'focusin', 1215 blur: 'focusout' 1216 }, function( original, fix ){ 1217 $.event.special[fix] = { 1218 setup:function() { 1219 this.addEventListener( original, handler, true ); 1220 }, 1221 teardown:function() { 1222 this.removeEventListener( original, handler, true ); 1223 }, 1224 handler: function(e) { 1225 var args = arguments; 1226 args[0] = $.event.fix(e); 1227 args[0].type = fix; 1228 return $.event.handle.apply(this, args); 1229 } 1230 }; 1231 function handler(e) { 1232 e = $.event.fix(e); 1233 e.type = fix; 1234 return $.event.handle.call(this, e); 1235 } 1236 }); 1237 } 1238 $.extend($.fn, { 1239 validateDelegate: function(delegate, type, handler) { 1240 return this.bind(type, function(event) { 1241 var target = $(event.target); 1242 if (target.is(delegate)) { 1243 return handler.apply(target, arguments); 1244 } 1245 }); 1246 } 1247 }); 1248}(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.