Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebApplication/MVC2/HeuristicLabWeb.PluginHost/HLWebPluginHost/Scripts/jquery.validate-vsdoc.js @ 10182

Last change on this file since 10182 was 4604, checked in by dkahn, 14 years ago

#1198 Imported new Plugin Host solution for the new MVC2 based web application

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