Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Web/Scripts/jquery.validate.js @ 9070

Last change on this file since 9070 was 8384, checked in by fschoepp, 12 years ago

#1888:

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