home *** CD-ROM | disk | FTP | other *** search
/ 61.19.244.139 / 61.19.244.139.zip / 61.19.244.139 / wsCompulTransfer / cp2013 / Scripts / jquery.validate-vsdoc.js < prev    next >
Text File  |  2013-06-07  |  44KB  |  1,289 lines

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