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