1/** 2 3 * jQuery Validation Plugin 1.11.0pre 4 5 * 6 7 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 8 9 * http://docs.jquery.com/Plugins/Validation 10 11 * 12 13 * Copyright 2013 Jörn Zaefferer 14 15 * Released under the MIT license: 16 17 * http://www.opensource.org/licenses/mit-license.php 18 19 */ 20 21 22 23(function($) { 24 25 26 27$.extend($.fn, { 28 29 // http://docs.jquery.com/Plugins/Validation/validate 30 31 validate: function( options ) { 32 33 34 35 // if nothing is selected, return nothing; can't chain anyway 36 37 if ( !this.length ) { 38 39 if ( options && options.debug && window.console ) { 40 41 console.warn( "Nothing selected, can't validate, returning nothing." ); 42 43 } 44 45 return; 46 47 } 48 49 50 51 // check if a validator for this form was already created 52 53 var validator = $.data( this[0], "validator" ); 54 55 if ( validator ) { 56 57 return validator; 58 59 } 60 61 62 63 // Add novalidate tag if HTML5. 64 65 this.attr( "novalidate", "novalidate" ); 66 67 68 69 validator = new $.validator( options, this[0] ); 70 71 $.data( this[0], "validator", validator ); 72 73 74 75 if ( validator.settings.onsubmit ) { 76 77 78 79 this.validateDelegate( ":submit", "click", function( event ) { 80 81 if ( validator.settings.submitHandler ) { 82 83 validator.submitButton = event.target; 84 85 } 86 87 // allow suppressing validation by adding a cancel class to the submit button 88 89 if ( $(event.target).hasClass("cancel") ) { 90 91 validator.cancelSubmit = true; 92 93 } 94 95 }); 96 97 98 99 // validate the form on submit 100 101 this.submit( function( event ) { 102 103 if ( validator.settings.debug ) { 104 105 // prevent form submit to be able to see console output 106 107 event.preventDefault(); 108 109 } 110 111 function handle() { 112 113 var hidden; 114 115 if ( validator.settings.submitHandler ) { 116 117 if ( validator.submitButton ) { 118 119 // insert a hidden input as a replacement for the missing submit button 120 121 hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); 122 123 } 124 125 validator.settings.submitHandler.call( validator, validator.currentForm, event ); 126 127 if ( validator.submitButton ) { 128 129 // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 130 131 hidden.remove(); 132 133 } 134 135 return false; 136 137 } 138 139 return true; 140 141 } 142 143 144 145 // prevent submit for invalid forms or custom submit handlers 146 147 if ( validator.cancelSubmit ) { 148 149 validator.cancelSubmit = false; 150 151 return handle(); 152 153 } 154 155 if ( validator.form() ) { 156 157 if ( validator.pendingRequest ) { 158 159 validator.formSubmitted = true; 160 161 return false; 162 163 } 164 165 return handle(); 166 167 } else { 168 169 validator.focusInvalid(); 170 171 return false; 172 173 } 174 175 }); 176 177 } 178 179 180 181 return validator; 182 183 }, 184 185 // http://docs.jquery.com/Plugins/Validation/valid 186 187 valid: function() { 188 189 if ( $(this[0]).is("form")) { 190 191 return this.validate().form(); 192 193 } else { 194 195 var valid = true; 196 197 var validator = $(this[0].form).validate(); 198 199 this.each(function() { 200 201 valid &= validator.element(this); 202 203 }); 204 205 return valid; 206 207 } 208 209 }, 210 211 // attributes: space seperated list of attributes to retrieve and remove 212 213 removeAttrs: function( attributes ) { 214 215 var result = {}, 216 217 $element = this; 218 219 $.each(attributes.split(/\s/), function( index, value ) { 220 221 result[value] = $element.attr(value); 222 223 $element.removeAttr(value); 224 225 }); 226 227 return result; 228 229 }, 230 231 // http://docs.jquery.com/Plugins/Validation/rules 232 233 rules: function( command, argument ) { 234 235 var element = this[0]; 236 237 238 239 if ( command ) { 240 241 var settings = $.data(element.form, "validator").settings; 242 243 var staticRules = settings.rules; 244 245 var existingRules = $.validator.staticRules(element); 246 247 switch(command) { 248 249 case "add": 250 251 $.extend(existingRules, $.validator.normalizeRule(argument)); 252 253 staticRules[element.name] = existingRules; 254 255 if ( argument.messages ) { 256 257 settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); 258 259 } 260 261 break; 262 263 case "remove": 264 265 if ( !argument ) { 266 267 delete staticRules[element.name]; 268 269 return existingRules; 270 271 } 272 273 var filtered = {}; 274 275 $.each(argument.split(/\s/), function( index, method ) { 276 277 filtered[method] = existingRules[method]; 278 279 delete existingRules[method]; 280 281 }); 282 283 return filtered; 284 285 } 286 287 } 288 289 290 291 var data = $.validator.normalizeRules( 292 293 $.extend( 294 295 {}, 296 297 $.validator.classRules(element), 298 299 $.validator.attributeRules(element), 300 301 $.validator.dataRules(element), 302 303 $.validator.staticRules(element) 304 305 ), element); 306 307 308 309 // make sure required is at front 310 311 if ( data.required ) { 312 313 var param = data.required; 314 315 delete data.required; 316 317 data = $.extend({required: param}, data); 318 319 } 320 321 322 323 return data; 324 325 } 326 327}); 328 329 330 331// Custom selectors 332 333$.extend($.expr[":"], {
334 335 // http://docs.jquery.com/Plugins/Validation/blank 336 337 blank: function( a ) { return !$.trim("" + a.value); }, 338 339 // http://docs.jquery.com/Plugins/Validation/filled 340 341 filled: function( a ) { return !!$.trim("" + a.value); }, 342 343 // http://docs.jquery.com/Plugins/Validation/unchecked 344 345 unchecked: function( a ) { return !a.checked; } 346 347}); 348 349 350 351// constructor for validator 352 353$.validator = function( options, form ) { 354 355 this.settings = $.extend( true, {}, $.validator.defaults, options ); 356 357 this.currentForm = form; 358 359 this.init(); 360 361}; 362 363 364 365$.validator.format = function( source, params ) { 366 367 if ( arguments.length === 1 ) { 368 369 return function() { 370 371 var args = $.makeArray(arguments); 372 373 args.unshift(source); 374 375 return $.validator.format.apply( this, args ); 376 377 }; 378 379 } 380 381 if ( arguments.length > 2 && params.constructor !== Array ) { 382 383 params = $.makeArray(arguments).slice(1); 384 385 } 386 387 if ( params.constructor !== Array ) { 388 389 params = [ params ]; 390 391 } 392 393 $.each(params, function( i, n ) { 394 395 source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() { 396 397 return n; 398 399 }); 400 401 }); 402 403 return source; 404 405}; 406 407 408 409$.extend($.validator, { 410 411 412 413 defaults: { 414 415 messages: {}, 416 417 groups: {}, 418 419 rules: {}, 420 421 errorClass: "error", 422 423 validClass: "valid", 424 425 errorElement: "label", 426 427 focusInvalid: true, 428 429 errorContainer: $([]), 430 431 errorLabelContainer: $([]), 432 433 onsubmit: true, 434 435 ignore: ":hidden", 436 437 ignoreTitle: false, 438 439 onfocusin: function( element, event ) { 440 441 this.lastActive = element; 442 443 444 445 // hide error label and remove error class on focus if enabled 446 447 if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { 448 449 if ( this.settings.unhighlight ) { 450 451 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 452 453 } 454 455 this.addWrapper(this.errorsFor(element)).hide(); 456 457 } 458 459 }, 460 461 onfocusout: function( element, event ) { 462 463 if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { 464 465 this.element(element); 466 467 } 468 469 }, 470 471 onkeyup: function( element, event ) { 472 473 if ( event.which === 9 && this.elementValue(element) === "" ) { 474 475 return; 476 477 } else if ( element.name in this.submitted || element === this.lastElement ) { 478 479 this.element(element); 480 481 } 482 483 }, 484 485 onclick: function( element, event ) { 486 487 // click on selects, radiobuttons and checkboxes 488 489 if ( element.name in this.submitted ) { 490 491 this.element(element); 492 493 } 494 495 // or option elements, check parent select in that case 496 497 else if ( element.parentNode.name in this.submitted ) { 498 499 this.element(element.parentNode); 500 501 } 502 503 }, 504 505 highlight: function( element, errorClass, validClass ) { 506 507 if ( element.type === "radio" ) { 508 509 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 510 511 } else { 512 513 $(element).addClass(errorClass).removeClass(validClass); 514 515 } 516 517 }, 518 519 unhighlight: function( element, errorClass, validClass ) { 520 521 if ( element.type === "radio" ) { 522 523 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 524 525 } else { 526 527 $(element).removeClass(errorClass).addClass(validClass); 528 529 } 530 531 } 532 533 }, 534 535 536 537 // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults 538 539 setDefaults: function( settings ) { 540 541 $.extend( $.validator.defaults, settings ); 542 543 }, 544 545 546 547 messages: { 548 549 required: "This field is required.", 550 551 remote: "Please fix this field.", 552 553 email: "Please enter a valid email address.", 554 555 url: "Please enter a valid URL.", 556 557 date: "Please enter a valid date.", 558 559 dateISO: "Please enter a valid date (ISO).", 560 561 number: "Please enter a valid number.", 562 563 digits: "Please enter only digits.", 564 565 creditcard: "Please enter a valid credit card number.", 566 567 equalTo: "Please enter the same value again.", 568 569 maxlength: $.validator.format("Please enter no more than {0} characters."), 570 571 minlength: $.validator.format("Please enter at least {0} characters."), 572 573 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 574 575 range: $.validator.format("Please enter a value between {0} and {1}."), 576 577 max: $.validator.format("Please enter a value less than or equal to {0}."), 578 579 min: $.validator.format("Please enter a value greater than or equal to {0}.") 580 581 }, 582 583 584 585 autoCreateRanges: false, 586 587 588 589 prototype: { 590 591 592 593 init: function() { 594 595 this.labelContainer = $(this.settings.errorLabelContainer); 596 597 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 598 599 this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); 600 601 this.submitted = {}; 602 603 this.valueCache = {}; 604 605 this.pendingRequest = 0; 606 607 this.pending = {}; 608 609 this.invalid = {}; 610 611 this.reset(); 612 613 614 615 var groups = (this.groups = {}); 616 617 $.each(this.settings.groups, function( key, value ) { 618 619 if ( typeof value === "string" ) { 620 621 value = value.split(/\s/); 622 623 } 624 625 $.each(value, function( index, name ) { 626 627 groups[name] = key; 628 629 }); 630 631 }); 632 633 var rules = this.settings.rules; 634 635 $.each(rules, function( key, value ) { 636 637 rules[key] = $.validator.normalizeRule(value); 638 639 }); 640 641 642 643 function delegate(event) { 644
645 var validator = $.data(this[0].form, "validator"), 646 647 eventType = "on" + event.type.replace(/^validate/, ""); 648 649 if ( validator.settings[eventType] ) { 650 651 validator.settings[eventType].call(validator, this[0], event); 652 653 } 654 655 } 656 657 $(this.currentForm) 658 659 .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " + 660 661 "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + 662 663 "[type='email'], [type='datetime'], [type='date'], [type='month'], " + 664 665 "[type='week'], [type='time'], [type='datetime-local'], " + 666 667 "[type='range'], [type='color'] ", 668 669 "focusin focusout keyup", delegate) 670 671 .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); 672 673 674 675 if ( this.settings.invalidHandler ) { 676 677 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 678 679 } 680 681 }, 682 683 684 685 // http://docs.jquery.com/Plugins/Validation/Validator/form 686 687 form: function() { 688 689 this.checkForm(); 690 691 $.extend(this.submitted, this.errorMap); 692 693 this.invalid = $.extend({}, this.errorMap); 694 695 if ( !this.valid() ) { 696 697 $(this.currentForm).triggerHandler("invalid-form", [this]); 698 699 } 700 701 this.showErrors(); 702 703 return this.valid(); 704 705 }, 706 707 708 709 checkForm: function() { 710 711 this.prepareForm(); 712 713 for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { 714 715 this.check( elements[i] ); 716 717 } 718 719 return this.valid(); 720 721 }, 722 723 724 725 // http://docs.jquery.com/Plugins/Validation/Validator/element 726 727 element: function( element ) { 728 729 element = this.validationTargetFor( this.clean( element ) ); 730 731 this.lastElement = element; 732 733 this.prepareElement( element ); 734 735 this.currentElements = $(element); 736 737 var result = this.check( element ) !== false; 738 739 if ( result ) { 740 741 delete this.invalid[element.name]; 742 743 } else { 744 745 this.invalid[element.name] = true; 746 747 } 748 749 if ( !this.numberOfInvalids() ) { 750 751 // Hide error containers on last error 752 753 this.toHide = this.toHide.add( this.containers ); 754 755 } 756 757 this.showErrors(); 758 759 return result; 760 761 }, 762 763 764 765 // http://docs.jquery.com/Plugins/Validation/Validator/showErrors 766 767 showErrors: function( errors ) { 768 769 if ( errors ) { 770 771 // add items to error list and map 772 773 $.extend( this.errorMap, errors ); 774 775 this.errorList = []; 776 777 for ( var name in errors ) { 778 779 this.errorList.push({ 780 781 message: errors[name], 782 783 element: this.findByName(name)[0] 784 785 }); 786 787 } 788 789 // remove items from success list 790 791 this.successList = $.grep( this.successList, function( element ) { 792 793 return !(element.name in errors); 794 795 }); 796 797 } 798 799 if ( this.settings.showErrors ) { 800 801 this.settings.showErrors.call( this, this.errorMap, this.errorList ); 802 803 } else { 804 805 this.defaultShowErrors(); 806 807 } 808 809 }, 810 811 812 813 // http://docs.jquery.com/Plugins/Validation/Validator/resetForm 814 815 resetForm: function() { 816 817 if ( $.fn.resetForm ) { 818 819 $(this.currentForm).resetForm(); 820 821 } 822 823 this.submitted = {}; 824 825 this.lastElement = null; 826 827 this.prepareForm(); 828 829 this.hideErrors(); 830 831 this.elements().removeClass( this.settings.errorClass ).removeData( "previousValue" ); 832 833 }, 834 835 836 837 numberOfInvalids: function() { 838 839 return this.objectLength(this.invalid); 840 841 }, 842 843 844 845 objectLength: function( obj ) { 846 847 var count = 0; 848 849 for ( var i in obj ) { 850 851 count++; 852 853 } 854 855 return count; 856 857 }, 858 859 860 861 hideErrors: function() { 862 863 this.addWrapper( this.toHide ).hide(); 864 865 }, 866 867 868 869 valid: function() { 870 871 return this.size() === 0; 872 873 }, 874 875 876 877 size: function() { 878 879 return this.errorList.length; 880 881 }, 882 883 884 885 focusInvalid: function() { 886 887 if ( this.settings.focusInvalid ) { 888 889 try { 890 891 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 892 893 .filter(":visible") 894 895 .focus() 896 897 // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 898 899 .trigger("focusin"); 900 901 } catch(e) { 902 903 // ignore IE throwing errors when focusing hidden elements 904 905 } 906 907 } 908 909 }, 910 911 912 913 findLastActive: function() { 914 915 var lastActive = this.lastActive; 916 917 return lastActive && $.grep(this.errorList, function( n ) { 918 919 return n.element.name === lastActive.name; 920 921 }).length === 1 && lastActive; 922 923 }, 924 925 926 927 elements: function() { 928
929 var validator = this, 930 931 rulesCache = {}; 932 933 934 935 // select all valid inputs inside the form (no submit or reset buttons) 936 937 return $(this.currentForm) 938 939 .find("input, select, textarea") 940 941 .not(":submit, :reset, :image, [disabled]") 942 943 .not( this.settings.ignore ) 944 945 .filter(function() { 946 947 if ( !this.name ) { 948 949 if ( window.console ) { 950 951 console.error( "%o has no name assigned", this ); 952 953 } 954 955 throw new Error( "Failed to validate, found an element with no name assigned. See console for element reference." ); 956 957 } 958 959 960 961 // select only the first element for each name, and only those with rules specified 962 963 if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) { 964 965 return false; 966 967 } 968 969 970 971 rulesCache[this.name] = true; 972 973 return true; 974 975 }); 976 977 }, 978 979 980 981 clean: function( selector ) { 982 983 return $(selector)[0]; 984 985 }, 986 987 988 989 errors: function() { 990 991 var errorClass = this.settings.errorClass.replace(" ", "."); 992 993 return $(this.settings.errorElement + "." + errorClass, this.errorContext); 994 995 }, 996 997 998 999 reset: function() { 1000 1001 this.successList = []; 1002 1003 this.errorList = []; 1004 1005 this.errorMap = {}; 1006 1007 this.toShow = $([]); 1008 1009 this.toHide = $([]); 1010 1011 this.currentElements = $([]); 1012 1013 }, 1014 1015 1016 1017 prepareForm: function() { 1018 1019 this.reset(); 1020 1021 this.toHide = this.errors().add( this.containers ); 1022 1023 }, 1024 1025 1026 1027 prepareElement: function( element ) { 1028 1029 this.reset(); 1030 1031 this.toHide = this.errorsFor(element); 1032 1033 }, 1034 1035 1036 1037 elementValue: function( element ) { 1038 1039 var type = $(element).attr("type"), 1040 1041 val = $(element).val(); 1042 1043 1044 1045 if ( type === "radio" || type === "checkbox" ) { 1046 1047 return $("input[name='" + $(element).attr("name") + "']:checked").val(); 1048 1049 } 1050 1051 1052 1053 if ( typeof val === "string" ) { 1054 1055 return val.replace(/\r/g, ""); 1056 1057 } 1058 1059 return val; 1060 1061 }, 1062 1063 1064 1065 check: function( element ) { 1066 1067 element = this.validationTargetFor( this.clean( element ) ); 1068 1069 1070 1071 var rules = $(element).rules(); 1072 1073 var dependencyMismatch = false; 1074 1075 var val = this.elementValue(element); 1076 1077 var result; 1078 1079 1080 1081 for (var method in rules ) { 1082 1083 var rule = { method: method, parameters: rules[method] }; 1084 1085 try { 1086 1087 1088 1089 result = $.validator.methods[method].call( this, val, element, rule.parameters ); 1090 1091 1092 1093 // if a method indicates that the field is optional and therefore valid, 1094 1095 // don't mark it as valid when there are no other rules 1096 1097 if ( result === "dependency-mismatch" ) { 1098 1099 dependencyMismatch = true; 1100 1101 continue; 1102 1103 } 1104 1105 dependencyMismatch = false; 1106 1107 1108 1109 if ( result === "pending" ) { 1110 1111 this.toHide = this.toHide.not( this.errorsFor(element) ); 1112 1113 return; 1114 1115 } 1116 1117 1118 1119 if ( !result ) { 1120 1121 this.formatAndAdd( element, rule ); 1122 1123 return false; 1124 1125 } 1126 1127 } catch(e) { 1128 1129 if ( this.settings.debug && window.console ) { 1130 1131 console.log( "Exception occured when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); 1132 1133 } 1134 1135 throw e; 1136 1137 } 1138 1139 } 1140 1141 if ( dependencyMismatch ) { 1142 1143 return; 1144 1145 } 1146 1147 if ( this.objectLength(rules) ) { 1148 1149 this.successList.push(element); 1150 1151 } 1152 1153 return true; 1154 1155 }, 1156 1157 1158 1159 // return the custom message for the given element and validation method 1160 1161 // specified in the element's HTML5 data attribute 1162 1163 customDataMessage: function( element, method ) { 1164 1165 return $(element).data("msg-" + method.toLowerCase()) || (element.attributes && $(element).attr("data-msg-" + method.toLowerCase())); 1166 1167 }, 1168 1169 1170 1171 // return the custom message for the given element name and validation method 1172 1173 customMessage: function( name, method ) { 1174 1175 var m = this.settings.messages[name]; 1176 1177 return m && (m.constructor === String ? m : m[method]); 1178 1179 }, 1180 1181 1182 1183 // return the first defined argument, allowing empty strings 1184 1185 findDefined: function() { 1186 1187 for(var i = 0; i < arguments.length; i++) { 1188 1189 if ( arguments[i] !== undefined ) { 1190 1191 return arguments[i]; 1192 1193 } 1194 1195 } 1196 1197 return undefined; 1198 1199 }, 1200 1201 1202 1203 defaultMessage: function( element, method ) { 1204 1205 return this.findDefined( 1206 1207 this.customMessage( element.name, method ), 1208 1209 this.customDataMessage( element, method ), 1210 1211 // title is never undefined, so handle empty string as undefined 1212 1213 !this.settings.ignoreTitle && element.title || undefined, 1214 1215 $.validator.messages[method], 1216 1217 "<strong>Warning: No message defined for " + element.name + "</strong>" 1218 1219 ); 1220 1221 }, 1222 1223 1224 1225 formatAndAdd: function( element, rule ) { 1226 1227 var message = this.defaultMessage( element, rule.method ), 1228 1229 theregex = /\$?\{(\d+)\}/g; 1230 1231 if ( typeof message === "function" ) { 1232 1233 message = message.call(this, rule.parameters, element); 1234 1235 } else if (theregex.test(message)) { 1236 1237 message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters); 1238 1239 } 1240 1241 this.errorList.push({ 1242 1243 message: message, 1244 1245 element: element 1246 1247 }); 1248 1249 1250 1251 this.errorMap[element.name] = message; 1252 1253 this.submitted[element.name] = message; 1254 1255 }, 1256 1257 1258 1259 addWrapper: function( toToggle ) { 1260 1261 if ( this.settings.wrapper ) { 1262 1263 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 1264 1265 } 1266 1267 return toToggle; 1268 1269 }, 1270 1271 1272 1273 defaultShowErrors: function() { 1274 1275 var i, elements; 1276 1277 for ( i = 0; this.errorList[i]; i++ ) { 1278 1279 var error = this.errorList[i]; 1280 1281 if ( this.settings.highlight ) { 1282 1283 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.val
1283idClass ); 1284 1285 } 1286 1287 this.showLabel( error.element, error.message ); 1288 1289 } 1290 1291 if ( this.errorList.length ) { 1292 1293 this.toShow = this.toShow.add( this.containers ); 1294 1295 } 1296 1297 if ( this.settings.success ) { 1298 1299 for ( i = 0; this.successList[i]; i++ ) { 1300 1301 this.showLabel( this.successList[i] ); 1302 1303 } 1304 1305 } 1306 1307 if ( this.settings.unhighlight ) { 1308 1309 for ( i = 0, elements = this.validElements(); elements[i]; i++ ) { 1310 1311 this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); 1312 1313 } 1314 1315 } 1316 1317 this.toHide = this.toHide.not( this.toShow ); 1318 1319 this.hideErrors(); 1320 1321 this.addWrapper( this.toShow ).show(); 1322 1323 }, 1324 1325 1326 1327 validElements: function() { 1328 1329 return this.currentElements.not(this.invalidElements()); 1330 1331 }, 1332 1333 1334 1335 invalidElements: function() { 1336 1337 return $(this.errorList).map(function() { 1338 1339 return this.element; 1340 1341 }); 1342 1343 }, 1344 1345 1346 1347 showLabel: function( element, message ) { 1348 1349 var label = this.errorsFor( element ); 1350 1351 if ( label.length ) { 1352 1353 // refresh error/success class 1354 1355 label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 1356 1357 1358 1359 // check if we have a generated label, replace the message then 1360 1361 if ( label.attr("generated") ) { 1362 1363 label.html(message); 1364 1365 } 1366 1367 } else { 1368 1369 // create label 1370 1371 label = $("<" + this.settings.errorElement + "/>") 1372 1373 .attr({"for": this.idOrName(element), generated: true}) 1374 1375 .addClass(this.settings.errorClass) 1376 1377 .html(message || ""); 1378 1379 if ( this.settings.wrapper ) { 1380 1381 // make sure the element is visible, even in IE 1382 1383 // actually showing the wrapped element is handled elsewhere 1384 1385 label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 1386 1387 } 1388 1389 if ( !this.labelContainer.append(label).length ) { 1390 1391 if ( this.settings.errorPlacement ) { 1392 1393 this.settings.errorPlacement(label, $(element) ); 1394 1395 } else { 1396 1397 label.insertAfter(element); 1398 1399 } 1400 1401 } 1402 1403 } 1404 1405 if ( !message && this.settings.success ) { 1406 1407 label.text(""); 1408 1409 if ( typeof this.settings.success === "string" ) { 1410 1411 label.addClass( this.settings.success ); 1412 1413 } else { 1414 1415 this.settings.success( label, element ); 1416 1417 } 1418 1419 } 1420 1421 this.toShow = this.toShow.add(label); 1422 1423 }, 1424 1425 1426 1427 errorsFor: function( element ) { 1428 1429 var name = this.idOrName(element); 1430 1431 return this.errors().filter(function() { 1432 1433 return $(this).attr("for") === name; 1434 1435 }); 1436 1437 }, 1438 1439 1440 1441 idOrName: function( element ) { 1442 1443 return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); 1444 1445 }, 1446 1447 1448 1449 validationTargetFor: function( element ) { 1450 1451 // if radio/checkbox, validate first element in group instead 1452 1453 if ( this.checkable(element) ) { 1454 1455 element = this.findByName( element.name ).not(this.settings.ignore)[0]; 1456 1457 } 1458 1459 return element; 1460 1461 }, 1462 1463 1464 1465 checkable: function( element ) { 1466 1467 return (/radio|checkbox/i).test(element.type); 1468 1469 }, 1470 1471 1472 1473 findByName: function( name ) { 1474 1475 return $(this.currentForm).find("[name='" + name + "']"); 1476 1477 }, 1478 1479 1480 1481 getLength: function( value, element ) { 1482 1483 switch( element.nodeName.toLowerCase() ) { 1484 1485 case "select": 1486 1487 return $("option:selected", element).length; 1488 1489 case "input": 1490 1491 if ( this.checkable( element) ) { 1492 1493 return this.findByName(element.name).filter(":checked").length; 1494 1495 } 1496 1497 } 1498 1499 return value.length; 1500 1501 }, 1502 1503 1504 1505 depend: function( param, element ) { 1506 1507 return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; 1508 1509 }, 1510 1511 1512 1513 dependTypes: { 1514 1515 "boolean": function( param, element ) { 1516 1517 return param; 1518 1519 }, 1520 1521 "string": function( param, element ) { 1522 1523 return !!$(param, element.form).length; 1524 1525 }, 1526 1527 "function": function( param, element ) { 1528 1529 return param(element); 1530 1531 } 1532 1533 }, 1534 1535 1536 1537 optional: function( element ) { 1538 1539 var val = this.elementValue(element); 1540 1541 return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; 1542 1543 }, 1544 1545 1546 1547 startRequest: function( element ) { 1548 1549 if ( !this.pending[element.name] ) { 1550 1551 this.pendingRequest++; 1552 1553 this.pending[element.name] = true; 1554 1555 } 1556 1557 }, 1558 1559 1560 1561 stopRequest: function( element, valid ) { 1562 1563 this.pendingRequest--; 1564 1565 // sometimes synchronization fails, make sure pendingRequest is never < 0 1566 1567 if ( this.pendingRequest < 0 ) { 1568 1569 this.pendingRequest = 0; 1570 1571 } 1572 1573 delete this.pending[element.name]; 1574 1575 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { 1576 1577 $(this.currentForm).submit(); 1578 1579 this.formSubmitted = false;
1580 1581 } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { 1582 1583 $(this.currentForm).triggerHandler("invalid-form", [this]); 1584 1585 this.formSubmitted = false; 1586 1587 } 1588 1589 }, 1590 1591 1592 1593 previousValue: function( element ) { 1594 1595 return $.data(element, "previousValue") || $.data(element, "previousValue", { 1596 1597 old: null, 1598 1599 valid: true, 1600 1601 message: this.defaultMessage( element, "remote" ) 1602 1603 }); 1604 1605 } 1606 1607 1608 1609 }, 1610 1611 1612 1613 classRuleSettings: { 1614 1615 required: {required: true}, 1616 1617 email: {email: true}, 1618 1619 url: {url: true}, 1620 1621 date: {date: true}, 1622 1623 dateISO: {dateISO: true}, 1624 1625 number: {number: true}, 1626 1627 digits: {digits: true}, 1628 1629 creditcard: {creditcard: true} 1630 1631 }, 1632 1633 1634 1635 addClassRules: function( className, rules ) { 1636 1637 if ( className.constructor === String ) { 1638 1639 this.classRuleSettings[className] = rules; 1640 1641 } else { 1642 1643 $.extend(this.classRuleSettings, className); 1644 1645 } 1646 1647 }, 1648 1649 1650 1651 classRules: function( element ) { 1652 1653 var rules = {}; 1654 1655 var classes = $(element).attr("class"); 1656 1657 if ( classes ) { 1658 1659 $.each(classes.split(" "), function() { 1660 1661 if ( this in $.validator.classRuleSettings ) { 1662 1663 $.extend(rules, $.validator.classRuleSettings[this]); 1664 1665 } 1666 1667 }); 1668 1669 } 1670 1671 return rules; 1672 1673 }, 1674 1675 1676 1677 attributeRules: function( element ) { 1678 1679 var rules = {}; 1680 1681 var $element = $(element); 1682 1683 1684 1685 for (var method in $.validator.methods) { 1686 1687 var value; 1688 1689 1690 1691 // support for <input required> in both html5 and older browsers 1692 1693 if ( method === "required" ) { 1694 1695 value = $element.get(0).getAttribute(method); 1696 1697 // Some browsers return an empty string for the required attribute 1698 1699 // and non-HTML5 browsers might have required="" markup 1700 1701 if ( value === "" ) { 1702 1703 value = true; 1704 1705 } 1706 1707 // force non-HTML5 browsers to return bool 1708 1709 value = !!value; 1710 1711 } else { 1712 1713 value = $element.attr(method); 1714 1715 } 1716 1717 1718 1719 if ( value ) { 1720 1721 rules[method] = value; 1722 1723 } else if ( $element[0].getAttribute("type") === method ) { 1724 1725 rules[method] = true; 1726 1727 } 1728 1729 } 1730 1731 1732 1733 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 1734 1735 if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) { 1736 1737 delete rules.maxlength; 1738 1739 } 1740 1741 1742 1743 return rules; 1744 1745 }, 1746 1747 1748 1749 dataRules: function( element ) { 1750 1751 var method, value, 1752 1753 rules = {}, $element = $(element); 1754 1755 for (method in $.validator.methods) { 1756 1757 value = $element.data("rule-" + method.toLowerCase()); 1758 1759 if ( value !== undefined ) { 1760 1761 rules[method] = value; 1762 1763 } 1764 1765 } 1766 1767 return rules; 1768 1769 }, 1770 1771 1772 1773 staticRules: function( element ) { 1774 1775 var rules = {}; 1776
1777 var validator = $.data(element.form, "validator"); 1778 1779 if ( validator.settings.rules ) { 1780 1781 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 1782 1783 } 1784 1785 return rules; 1786 1787 }, 1788 1789 1790 1791 normalizeRules: function( rules, element ) { 1792 1793 // handle dependency check 1794 1795 $.each(rules, function( prop, val ) { 1796 1797 // ignore rule when param is explicitly false, eg. required:false 1798 1799 if ( val === false ) { 1800 1801 delete rules[prop]; 1802 1803 return; 1804 1805 } 1806 1807 if ( val.param || val.depends ) { 1808 1809 var keepRule = true; 1810 1811 switch (typeof val.depends) { 1812 1813 case "string": 1814 1815 keepRule = !!$(val.depends, element.form).length; 1816 1817 break; 1818 1819 case "function": 1820 1821 keepRule = val.depends.call(element, element); 1822 1823 break; 1824 1825 } 1826 1827 if ( keepRule ) { 1828 1829 rules[prop] = val.param !== undefined ? val.param : true; 1830 1831 } else { 1832 1833 delete rules[prop]; 1834 1835 } 1836 1837 } 1838 1839 }); 1840 1841 1842 1843 // evaluate parameters 1844 1845 $.each(rules, function( rule, parameter ) { 1846 1847 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 1848 1849 }); 1850 1851 1852 1853 // clean number parameters 1854 1855 $.each(["minlength", "maxlength", "min", "max"], function() { 1856 1857 if ( rules[this] ) { 1858 1859 rules[this] = Number(rules[this]); 1860 1861 } 1862 1863 }); 1864 1865 $.each(["rangelength", "range"], function() { 1866 1867 var parts; 1868 1869 if ( rules[this] ) { 1870 1871 if ( $.isArray(rules[this]) ) { 1872 1873 rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; 1874 1875 } else if ( typeof rules[this] === "string" ) { 1876 1877 parts = rules[this].split(/[\s,]+/); 1878 1879 rules[this] = [Number(parts[0]), Number(parts[1])]; 1880 1881 } 1882 1883 } 1884 1885 }); 1886 1887 1888 1889 if ( $.validator.autoCreateRanges ) { 1890 1891 // auto-create ranges 1892 1893 if ( rules.min && rules.max ) { 1894 1895 rules.range = [rules.min, rules.max]; 1896 1897 delete rules.min; 1898 1899 delete rules.max; 1900 1901 } 1902 1903 if ( rules.minlength && rules.maxlength ) { 1904 1905 rules.rangelength = [rules.minlength, rules.maxlength]; 1906 1907 delete rules.minlength; 1908 1909 delete rules.maxlength; 1910 1911 } 1912 1913 } 1914 1915 1916 1917 return rules; 1918 1919 }, 1920 1921 1922 1923 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 1924 1925 normalizeRule: function( data ) { 1926 1927 if ( typeof data === "string" ) { 1928 1929 var transformed = {}; 1930 1931 $.each(data.split(/\s/), function() { 1932 1933 transformed[this] = true; 1934 1935 }); 1936 1937 data = transformed; 1938 1939 } 1940 1941 return data; 1942 1943 }, 1944 1945 1946 1947 // http://docs.jquery.com/Plugins/Validation/Validator/addMethod 1948 1949 addMethod: function( name, method, message ) { 1950 1951 $.validator.methods[name] = method; 1952 1953 $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; 1954 1955 if ( method.length < 3 ) { 1956 1957 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 1958 1959 } 1960 1961 }, 1962 1963 1964 1965 methods: { 1966 1967 1968 1969 // http://docs.jquery.com/Plugins/Validation/Methods/required 1970 1971 required: function( value, element, param ) { 1972 1973 // check if dependency is met 1974 1975 if ( !this.depend(param, element) ) { 1976 1977 return "dependency-mismatch"; 1978 1979 } 1980 1981 if ( element.nodeName.toLowerCase() === "select" ) { 1982 1983 // could be an array for select-multiple or a string, both are fine this way 1984 1985 var val = $(element).val(); 1986 1987 return val && val.length > 0; 1988 1989 } 1990 1991 if ( this.checkable(element) ) { 1992 1993 return this.getLength(value, element) > 0; 1994 1995 } 1996 1997 return $.trim(value).length > 0; 1998 1999 }, 2000 2001 2002 2003 // http://docs.jquery.com/Plugins/Validation/Methods/remote 2004 2005 remote: function( value, element, param ) { 2006 2007 if ( this.optional(element) ) { 2008 2009 return "dependency-mismatch"; 2010 2011 } 2012 2013 2014 2015 var previous = this.previousValue(element); 2016 2017 if (!this.settings.messages[element.name] ) { 2018 2019 this.settings.messages[element.name] = {}; 2020 2021 } 2022 2023 previous.originalMessage = this.settings.messages[element.name].remote; 2024 2025 this.settings.messages[element.name].remote = previous.message; 2026 2027 2028 2029 param = typeof param === "string" && {url:param} || param; 2030 2031 2032 2033 if ( previous.old === value ) { 2034 2035 return previous.valid; 2036 2037 } 2038 2039 2040 2041 previous.old = value; 2042 2043 var validator = this; 2044 2045 this.startRequest(element); 2046 2047 var data = {}; 2048 2049 data[element.name] = value; 2050 2051 $.ajax($.extend(true, { 2052 2053 url: param, 2054 2055 mode: "abort", 2056 2057 port: "validate" + element.name, 2058 2059 dataType: "json", 2060 2061 data: data, 2062 2063 success: function( response ) { 2064 2065 validator.settings.messages[element.name].remote = previous.originalMessage; 2066
2067 var valid = response === true || response === "true"; 2068 2069 if ( valid ) { 2070 2071 var submitted = validator.formSubmitted; 2072 2073 validator.prepareElement(element); 2074 2075 validator.formSubmitted = submitted; 2076 2077 validator.successList.push(element); 2078 2079 delete validator.invalid[element.name]; 2080 2081 validator.showErrors(); 2082 2083 } else { 2084 2085 var errors = {}; 2086 2087 var message = response || validator.defaultMessage( element, "remote" ); 2088 2089 errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 2090 2091 validator.invalid[element.name] = true; 2092 2093 validator.showErrors(errors); 2094 2095 } 2096 2097 previous.valid = valid; 2098 2099 validator.stopRequest(element, valid); 2100 2101 } 2102 2103 }, param)); 2104 2105 return "pending"; 2106 2107 }, 2108 2109 2110 2111 // http://docs.jquery.com/Plugins/Validation/Methods/minlength 2112 2113 minlength: function( value, element, param ) { 2114 2115 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 2116 2117 return this.optional(element) || length >= param; 2118 2119 }, 2120 2121 2122 2123 // http://docs.jquery.com/Plugins/Validation/Methods/maxlength 2124 2125 maxlength: function( value, element, param ) { 2126 2127 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 2128 2129 return this.optional(element) || length <= param; 2130 2131 }, 2132 2133 2134 2135 // http://docs.jquery.com/Plugins/Validation/Methods/rangelength 2136 2137 rangelength: function( value, element, param ) { 2138 2139 var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 2140 2141 return this.optional(element) || ( length >= param[0] && length <= param[1] ); 2142 2143 }, 2144 2145 2146 2147 2148 2149 // http://docs.jquery.com/Plugins/Validation/Methods/min 2150 2151 min: function( value, element, param ) { 2152 2153 return this.optional(element) || value >= param; 2154 2155 }, 2156 2157 2158 2159 // http://docs.jquery.com/Plugins/Validation/Methods/max 2160 2161 max: function( value, element, param ) { 2162 2163 return this.optional(element) || value <= param; 2164 2165 }, 2166 2167 2168 2169 // http://docs.jquery.com/Plugins/Validation/Methods/range 2170 2171 range: function( value, element, param ) { 2172 2173 return this.optional(element) || ( value >= param[0] && value <= param[1] ); 2174 2175 }, 2176 2177 2178 2179 // http://docs.jquery.com/Plugins/Validation/Methods/email 2180 2181 email: function( value, element ) { 2182 2183 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ 2184 2185 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); 2186 2187 }, 2188 2189 2190 2191 // http://docs.jquery.com/Plugins/Validation/Methods/url 2192 2193 url: function( value, element ) { 2194 2195 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 2196 2197 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); 2198 2199 }, 2200 2201 2202 2203 // http://docs.jquery.com/Plugins/Validation/Methods/date 2204 2205 date: function( value, element ) { 2206 2207 return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString()); 2208 2209 }, 2210 2211 2212 2213 // http://docs.jquery.com/Plugins/Validation/Methods/dateISO 2214 2215 dateISO: function( value, element ) { 2216 2217 return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value); 2218 2219 }, 2220 2221 2222 2223 // http://docs.jquery.com/Plugins/Validation/Methods/number 2224 2225 number: function( value, element ) { 2226 2227 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); 2228 2229 }, 2230 2231 2232 2233 // http://docs.jquery.com/Plugins/Validation/Methods/digits 2234 2235 digits: function( value, element ) { 2236 2237 return this.optional(element) || /^\d+$/.test(value); 2238 2239 }, 2240 2241 2242 2243 // http://docs.jquery.com/Plugins/Validation/Methods/creditcard 2244 2245 // based on http://en.wikipedia.org/wiki/Luhn 2246 2247 creditcard: function( value, element ) { 2248 2249 if ( this.optional(element) ) { 2250 2251 return "dependency-mismatch"; 2252 2253 } 2254 2255 // accept only spaces, digits and dashes 2256 2257 if ( /[^0-9 \-]+/.test(value) ) { 2258 2259 return false;
2260 2261 } 2262 2263 var nCheck = 0, 2264 2265 nDigit = 0, 2266 2267 bEven = false; 2268 2269 2270 2271 value = value.replace(/\D/g, ""); 2272 2273 2274 2275 for (var n = value.length - 1; n >= 0; n--) { 2276 2277 var cDigit = value.charAt(n); 2278 2279 nDigit = parseInt(cDigit, 10); 2280 2281 if ( bEven ) { 2282 2283 if ( (nDigit *= 2) > 9 ) { 2284 2285 nDigit -= 9; 2286 2287 } 2288 2289 } 2290 2291 nCheck += nDigit; 2292 2293 bEven = !bEven; 2294 2295 } 2296 2297 2298 2299 return (nCheck % 10) === 0; 2300 2301 }, 2302 2303 2304 2305 // http://docs.jquery.com/Plugins/Validation/Methods/equalTo 2306 2307 equalTo: function( value, element, param ) { 2308 2309 // bind to the blur event of the target in order to revalidate whenever the target field is updated 2310 2311 // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 2312 2313 var target = $(param); 2314 2315 if ( this.settings.onfocusout ) { 2316 2317 target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 2318 2319 $(element).valid(); 2320 2321 }); 2322 2323 } 2324 2325 return value === target.val(); 2326 2327 } 2328 2329 2330 2331 } 2332 2333 2334 2335}); 2336 2337 2338 2339// deprecated, use $.validator.format instead 2340 2341$.format = $.validator.format; 2342 2343 2344 2345}(jQuery)); 2346 2347 2348 2349// ajax mode: abort 2350 2351// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 2352 2353// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 2354 2355(function($) { 2356 2357 var pendingRequests = {}; 2358 2359 // Use a prefilter if available (1.5+) 2360 2361 if ( $.ajaxPrefilter ) { 2362 2363 $.ajaxPrefilter(function( settings, _, xhr ) { 2364 2365 var port = settings.port; 2366 2367 if ( settings.mode === "abort" ) { 2368 2369 if ( pendingRequests[port] ) { 2370 2371 pendingRequests[port].abort(); 2372 2373 } 2374 2375 pendingRequests[port] = xhr; 2376 2377 } 2378 2379 }); 2380 2381 } else { 2382 2383 // Proxy ajax 2384 2385 var ajax = $.ajax; 2386 2387 $.ajax = function( settings ) { 2388 2389 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 2390 2391 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 2392 2393 if ( mode === "abort" ) { 2394 2395 if ( pendingRequests[port] ) { 2396 2397 pendingRequests[port].abort(); 2398 2399 } 2400 2401 return (pendingRequests[port] = ajax.apply(this, arguments)); 2402 2403 } 2404 2405 return ajax.apply(this, arguments); 2406 2407 }; 2408 2409 } 2410 2411}(jQuery)); 2412 2413 2414 2415// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 2416 2417// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 2418 2419(function($) { 2420 2421 $.extend($.fn, { 2422 2423 validateDelegate: function( delegate, type, handler ) { 2424 2425 return this.bind(type, function( event ) { 2426 2427 var target = $(event.target); 2428 2429 if ( target.is(delegate) ) { 2430 2431 return handler.apply(target, arguments); 2432 2433 } 2434 2435 }); 2436 2437 } 2438 2439 }); 2440 2441}(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.