Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveStatistics/sources/HeuristicLab.Services.Hive.Statistics/3.3/Scripts/jquery.validate.js @ 9604

Last change on this file since 9604 was 9604, checked in by pfleck, 11 years ago

#2063:
Set up basic webpage layout based on WebApplication branch.
Added Asp.Net MVC packages and some helper packages.
Implemented login.

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