﻿/*
* Validate plugin extension
* for Asp.Net
* Extends jQuery validation plug-in 1.4
*/

(function($) {
    $.extend($.fn, {
        currentValidator: function() {
            return $.data($(this[0]).subForm(), 'validator');
        },
        subForm: function() {
            return $(this[0]).parents()
            .filter(function(index) {
                return $.data(this, 'validator');
            })[0];
        },

        rules: function(command, argument) {
            var element = this[0];

            if (command) {
                var settings = $(element).currentValidator().settings;
                var staticRules = settings.rules;
                var existingRules = $.validator.staticRules(element);
                switch (command) {
                    case "add":
                        $.extend(existingRules, $.validator.normalizeRule(argument));
                        staticRules[element.name] = existingRules;
                        if (argument.messages)
                            settings.messages[element.name] = $.extend(settings.messages[element.name], argument.messages);
                        break;
                    case "remove":
                        if (!argument) {
                            delete staticRules[element.name];
                            return existingRules;
                        }
                        var filtered = {};
                        $.each(argument.split(/\s/), function(index, method) {
                            filtered[method] = existingRules[method];
                            delete existingRules[method];
                        });
                        return filtered;
                }
            }

            var data = $.validator.normalizeRules(
		    $.extend(
			    {},
			    $.validator.metadataRules(element),
			    $.validator.classRules(element),
			    $.validator.attributeRules(element),
			    $.validator.staticRules(element)
		    ), element);

            // make sure required is at front
            if (data.required) {
                var param = data.required;
                delete data.required;
                data = $.extend({ required: param }, data);
            }

            return data;
        },

        valid: function() {
            if ($(this[0]).is('form') || $.data(this[0], 'validator')) {
                return this.validate().form();
            }
            else {
                var valid = false;
                var validator = $(this[0]).currentValidator();
                this.each(function() {
                    valid |= validator.element(this);
                });
                return valid;
            } 
        }
    });
})(jQuery);


(function($) {
$.extend($.validator.prototype, {
        init: function() {
            this.labelContainer = $(this.settings.errorLabelContainer);
            this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
            this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer);
            this.submitted = {};
            this.valueCache = {};
            this.pendingRequest = 0;
            this.pending = {};
            this.invalid = {};
            this.reset();

            var groups = (this.groups = {});
            $.each(this.settings.groups, function(key, value) {
                $.each(value.split(/\s/), function(index, name) {
                    groups[name] = key;
                });
            });
            var rules = this.settings.rules;
            $.each(rules, function(key, value) {
                rules[key] = $.validator.normalizeRule(value);
            });

            function delegate(event) {
                var validator = $(this[0]).currentValidator();
                validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0]);
            }
            $(this.currentForm)
				        .delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
				        .delegate("click", ":radio, :checkbox", delegate);
            if (this.settings.invalidHandler)
                $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
            				        
        },
        elements: function() {
            var validator = this,
				    rulesCache = {};

            // select all valid inputs inside the form (no submit or reset buttons)
            // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
            var el;

            if ($(this.currentForm).is('form'))
                el = $([]).add(this.currentForm.elements);
            else
                el = $(this.currentForm).find('*');
            return el
			    .filter(":input")
			    .not(":submit, :reset, :image, [disabled]")
			    .not(this.settings.ignore)
			    .filter(function() {
			        !this.name && validator.settings.debug && window.console && console.error("%o has no name assigned", this);

			        // select only the first element for each name, and only those with rules specified
			        if (this.name in rulesCache || !validator.objectLength($(this).rules()))
			            return false;

			        rulesCache[this.name] = true;
			        return true;
			    });
        },
        findByName: function(name) {
            // select by name and filter by form for performance over form.find("[name=...]")
            var form = this.currentForm;
            if ($(form).is('form'))
                return $(document.getElementsByName(name)).map(function(index, element) {
                    return element.form == form && element.name == name && element || null;
                });
            else
                return $(form).find("[name=" + name + "]");
        },
        
        dependTypes: {
            "boolean": function(param, element) {
                return param;
            },
            "string": function(param, element) {
                return !!$(param, $(element).subForm()).length;
            },
            "function": function(param, element) {
                return param(element);
            }
        }     
    });
})(jQuery);

(function($) {
    $.extend($.validator, {
        metadataRules: function(element) {
		if (!$.metadata) return {};

		var meta = $(element).currentValidator().settings.meta;
		return meta ?
			$(element).metadata()[meta] :
			$(element).metadata();
	    },
    	
	    staticRules: function(element) {
		    var rules = {};
		    var validator = $(element).currentValidator();
		    if (validator.settings.rules) {
			    rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
		    }
		    return rules;
	    },
	    normalizeRules: function(rules, element) {
		    // handle dependency check
		    $.each(rules, function(prop, val) {
			    // ignore rule when param is explicitly false, eg. required:false
			    if (val === false) {
				    delete rules[prop];
				    return;
			    }
			    if (val.param || val.depends) {
				    var keepRule = true;
				    switch (typeof val.depends) {
					    case "string":
						    keepRule = !!$(val.depends, $(element).subForm()).length;
						    break;
					    case "function":
						    keepRule = val.depends.call(element, element);
						    break;
				    }
				    if (keepRule) {
					    rules[prop] = val.param !== undefined ? val.param : true;
				    } else {
					    delete rules[prop];
				    }
			    }
		    });
    		
		    // evaluate parameters
		    $.each(rules, function(rule, parameter) {
			    rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
		    });
    		
		    // clean number parameters
		    $.each(['minlength', 'maxlength', 'min', 'max'], function() {
			    if (rules[this]) {
				    rules[this] = Number(rules[this]);
			    }
		    });
		    $.each(['rangelength', 'range'], function() {
			    if (rules[this]) {
				    rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			    }
		    });
    		
		    if ($.validator.autoCreateRanges) {
			    // auto-create ranges
			    if (rules.min && rules.max) {
				    rules.range = [rules.min, rules.max];
				    delete rules.min;
				    delete rules.max;
			    }
			    if (rules.minlength && rules.maxlength) {
				    rules.rangelength = [rules.minlength, rules.maxlength];
				    delete rules.minlength;
				    delete rules.maxlength;
			    }
		    }
    		
		    // To support custom messages in metadata ignore rule methods titled "messages"
		    if (rules.messages) {
			    delete rules.messages
		    }
    		
		    return rules;
	    }
    });
})(jQuery);
