/*
  jQuery Ketchup Plugin - Tasty Form Validation
  ---------------------------------------------
  
  Version 0.3.1.beta - 12. Luglio 2011
  Added:
  * type = Telefono: controls for italian fix and mobile phone, with exclusion of number like xx123456xx, x3333333x etc.
  * type = myEmail: controls for email address like uno.two_tre&four£five/etc@uno.two_tre&four£five/etc.it etc.
    
  Copyright (c) 2011 by Sebastian Senf:
    http://mustardamus.com/
    http://usejquery.com/
    http://twitter.com/mustardamus

  Dual licensed under the MIT and GPL licenses:
    http://www.opensource.org/licenses/mit-license.php
    http://www.gnu.org/licenses/gpl.html

  Demo: http://demos.usejquery.com/ketchup-plugin/
  Repo: http://github.com/mustardamus/ketchup-plugin
 */

(function(g) {
	g.ketchup = {
		defaults : {
			attribute : "data-validate",
			validateIndicator : "validate",
			eventIndicator : "on",
			validateEvents : "blur",
			validateElements : [ "input", "textarea", "select" ],
			createErrorContainer : null,
			showErrorContainer : null,
			hideErrorContainer : null,
			addErrorMessages : null
		},
		dataNames : {
			validationString : "ketchup-validation-string",
			validations : "ketchup-validations",
			events : "ketchup-events",
			elements : "ketchup-validation-elements",
			container : "ketchup-container"
		},
		validations : {},
		helpers : {},
		validation : function(b, c, d, h) {
			var j;
			if (typeof c == "function")
				c = c;
			else {
				j = c;
				c = d
			}
			this.validations[b] = {
				message : j,
				func : c,
				init : h || function() {
				}
			};
			return this
		},
		message : function(b, c) {
			this.addMessage(b, c);
			return this
		},
		messages : function(b) {
			for (name in b)
				this.addMessage(name, b[name]);
			return this
		},
		addMessage : function(b, c) {
			if (this.validations[b])
				this.validations[b].message = c
		},
		helper : function(b, c) {
			this.helpers[b] = c;
			return this
		},
		init : function(b, c, d) {
			this.options = c;
			var h = this;
			c = this.initFunctions().initFields(b, d);
			c.each(function() {
				var j = g(this);
				h.bindValidationEvent(b, j).callInitFunctions(b, j)
			});
			b.data(this.dataNames.elements, c);
			this.bindFormSubmit(b)
		},
		initFunctions : function() {
			var b = this.options, c = [ "createErrorContainer",
					"showErrorContainer", "hideErrorContainer",
					"addErrorMessages" ];
			for (f = 0; f < c.length; f++) {
				var d = c[f];
				b[d] || (b[d] = this[d])
			}
			return this
		},
		initFields : function(b, c) {
			var d = this, h = this.dataNames, j = g(!c ? this.fieldsFromForm(b)
					: this.fieldsFromObject(b, c));
			j
					.each(function() {
						var l = g(this), m = d.extractValidations(l
								.data(h.validationString),
								d.options.validateIndicator);
						l.data(h.validations, m)
					});
			return j
		},
		callInitFunctions : function(b, c) {
			var d = c.data(this.dataNames.validations);
			for (i = 0; i < d.length; i++)
				d[i].init.apply(this.helpers, [ b, c ])
		},
		fieldsFromForm : function(b) {
			var c = this, d = this.options, h = this.dataNames, j = d.validateElements, l = [];
			j = typeof j == "string" ? [ j ] : j;
			for (i = 0; i < j.length; i++) {
				var m = b.find(j[i] + "[" + d.attribute + "*="
						+ d.validateIndicator + "]");
				m.each(function() {
					var k = g(this), p = k.attr(d.attribute), q = c
							.extractEvents(p, d.eventIndicator);
					k.data(h.validationString, p).data(h.events,
							q ? q : d.validateEvents)
				});
				l.push(m.get())
			}
			return this.normalizeArray(l)
		},
		fieldsFromObject : function(b, c) {
			var d = this.options, h = this.dataNames, j = [];
			for (s in c) {
				var l, m;
				if (typeof c[s] == "string") {
					l = c[s];
					m = d.validateEvents
				} else {
					l = c[s][0];
					m = c[s][1]
				}
				var k = b.find(s);
				l = this.mergeValidationString(k, l);
				m = this.mergeEventsString(k, m);
				k.data(h.validationString, d.validateIndicator + "(" + l + ")")
						.data(h.events, m);
				j.push(k.get())
			}
			return this.normalizeArray(j)
		},
		mergeEventsString : function(b, c) {
			var d = b.data(this.dataNames.events), h = "";
			if (d) {
				d = d.split(" ");
				for (i = 0; i < d.length; i++)
					if (c.indexOf(d[i]) == -1)
						h += " " + d[i]
			}
			return g.trim(c + h)
		},
		mergeValidationString : function(b, c) {
			var d = this.options, h = b.data(this.dataNames.validationString), j = function(
					k) {
				var p = k.name;
				if (k.arguments.length)
					p = p + "(" + k.arguments.join(",") + ")";
				return p
			}, l = function(k, p) {
				for (i = 0; i < k.length; i++)
					if (k[i].name == p.name)
						return true
			};
			if (h) {
				var m = this.extractValidations(d.validateIndicator + "(" + c
						+ ")", d.validateIndicator);
				d = this.extractValidations(h, d.validateIndicator);
				c = "";
				for (o = 0; o < d.length; o++)
					c += j(d[o]) + ",";
				for (n = 0; n < m.length; n++)
					l(d, m[n]) || (c += j(m[n]) + ",")
			}
			return c
		},
		bindFormSubmit : function(b) {
			var c = this;
			b.submit(function() {
				return c.allFieldsValid(b, true)
			})
		},
		allFieldsValid : function(b, c) {
			var d = this, h = true;
			b.data(this.dataNames.elements).each(function() {
				var j = g(this);
				if (d.validateElement(j, b) != true) {
					c == true && d.triggerValidationEvents(j);
					h = false
				}
			});
			b.trigger("formIs" + (h ? "Valid" : "Invalid"), [ b ]);
			return h
		},
		bindValidationEvent : function(b, c) {
			var d = this, h = this.options, j = this.dataNames, l = c.data(
					j.events).split(" ");
			for (i = 0; i < l.length; i++) {
				c.bind("ketchup." + l[i], function() {
					var m = d.validateElement(c, b), k = c.data(j.container);
					if (m != true) {
						if (!k) {
							k = h.createErrorContainer(b, c);
							c.data(j.container, k)
						}
						h.addErrorMessages(b, c, k, m);
						h.showErrorContainer(b, c, k)
					} else
						k && h.hideErrorContainer(b, c, k)
				});
				this.bindValidationEventBridge(c, l[i])
			}
			return this
		},
		bindValidationEventBridge : function(b, c) {
			b.bind(c, function() {
				b.trigger("ketchup." + c)
			})
		},
		validateElement : function(b, c) {
			var d = [], h = b.data(this.dataNames.validations), j = [ c, b,
					b.val() ];
			for (i = 0; i < h.length; i++)
				h[i].func.apply(this.helpers, j.concat(h[i].arguments))
						|| d.push(h[i].message);
			c.trigger("fieldIs" + (d.length ? "Invalid" : "Valid"), [ c, b ]);
			return d.length ? d : true
		},
		elementIsValid : function(b) {
			var c = this.dataNames;
			if (b.data(c.validations)) {
				c = b.parentsUntil("form").last().parent();
				return this.validateElement(b, c) == true ? true : false
			} else if (b.data(c.elements))
				return this.allFieldsValid(b);
			return null
		},
		triggerValidationEvents : function(b) {
			for ( var c = b.data(this.dataNames.events).split(" "), d = 0; d < c.length; d++)
				b.trigger("ketchup." + c[d])
		},
		extractValidations : function(b, c) {
			for ( var d = b.substr(b.indexOf(c) + c.length + 1), h = "", j = [], l = 0, m = [], k = 0; k < d.length; k++)
				switch (d.charAt(k)) {
				case "(":
					h += "(";
					l++;
					break;
				case ")":
					if (l) {
						h += ")";
						l--
					} else
						j.push(g.trim(h));
					break;
				case ",":
					if (l)
						h += ",";
					else {
						j.push(g.trim(h));
						h = ""
					}
					break;
				default:
					h += d.charAt(k)
				}
			for (v = 0; v < j.length; v++) {
				l = j[v].indexOf("(");
				d = j[v];
				h = [];
				if (l != -1) {
					d = g.trim(j[v].substr(0, l));
					h = g.map(j[v].substr(d.length).split(","), function(p) {
						return g.trim(p.replace("(", "").replace(")", ""))
					})
				}
				if ((l = this.validations[d]) && l.message) {
					k = l.message;
					for (a = 1; a <= h.length; a++)
						k = k.replace("{arg" + a + "}", h[a - 1]);
					m.push({
						name : d,
						arguments : h,
						func : l.func,
						message : k,
						init : l.init
					})
				}
			}
			return m
		},
		extractEvents : function(b, c) {
			var d = false, h = b.indexOf(c + "(");
			if (h != -1)
				d = b.substr(h + c.length + 1).split(")")[0];
			return d
		},
		normalizeArray : function(b) {
			var c = [];
			for (i = 0; i < b.length; i++)
				for (e = 0; e < b[i].length; e++)
					b[i][e] && c.push(b[i][e]);
			return c
		},
		createErrorContainer : function(b, c) {
			if (typeof b == "function") {
				this.defaults.createErrorContainer = b;
				return this
			} else {
				var d = c.offset();
				return g("<div/>", {
					html : "<ul></ul><span></span>",
					"class" : "ketchup-error",
					css : {
						top : d.top,
						left : d.left + c.outerWidth() - 20
					}
				}).appendTo("body")
			}
		},
		showErrorContainer : function(b, c, d) {
			if (typeof b == "function") {
				this.defaults.showErrorContainer = b;
				return this
			} else
				d.show().animate({
					top : c.offset().top - d.height(),
					opacity : 1
				}, "fast")
		},
		hideErrorContainer : function(b, c, d) {
			if (typeof b == "function") {
				this.defaults.hideErrorContainer = b;
				return this
			} else
				d.animate({
					top : c.offset().top,
					opacity : 0
				}, "fast", function() {
					d.hide()
				})
		},
		addErrorMessages : function(b, c, d, h) {
			if (typeof b == "function") {
				this.defaults.addErrorMessages = b;
				return this
			} else {
				b = d.children("ul");
				b.html("");
				for (i = 0; i < h.length; i++)
					g("<li/>", {
						text : h[i]
					}).appendTo(b)
			}
		}
	};
	g.fn.ketchup = function(b, c) {
		var d = g(this);
		if (typeof b == "string")
			switch (b) {
			case "validate":
				g.ketchup.triggerValidationEvents(d);
				break;
			case "isValid":
				return g.ketchup.elementIsValid(d)
			}
		else
			this.each(function() {
				g.ketchup.init(d, g.extend({}, g.ketchup.defaults, b), c)
			});
		return this
	}
})(jQuery);
jQuery.ketchup.validation(
		"required",
		"Campo indispensabile!",
		function(g, b, c) {
			g = b.attr("type").toLowerCase();
			return g == "checkbox" || g == "radio" ? b.attr("checked") == true
					: c.length != 0
		}).validation("minlength", "Inserisci almeno {arg1} caratteri.",
		function(g, b, c, d) {
			return c.length >= +d
		}).validation("maxlength",
		"Non puoi inserire più di {arg1} caratteri.", function(g, b, c, d) {
			return c.length <= +d
		}).validation("rangelength",
		"Devi inserire almeno {arg1} caratteri, ma non più di {arg2}.",
		function(g, b, c, d, h) {
			return c.length >= d && c.length <= h
		}).validation("min", "Non puoi inserire numeri inferiori a {arg1}.",
		function(g, b, c, d) {
			return this.isNumber(c) && +c >= +d
		}).validation("max", "Non puoi inserire numeri maggiori a {arg1}.",
		function(g, b, c, d) {
			return this.isNumber(c) && +c <= +d
		}).validation("range", "Deve essere compreso tra {arg1} e {arg2}.",
		function(g, b, c, d, h) {
			return this.isNumber(c) && +c >= +d && +c <= +h
		}).validation("number", "Puoi inserire solo numeri.",
		function(g, b, c) {
			return this.isNumber(c)
		}).validation("digits", "Puoi inserire solo numeri.",
		function(g, b, c) {
			return /^\d+$/.test(c)
		}).validation("email", "Inserisci un indirizzo e-Mail valido.",
		function(g, b, c) {
			return this.isEmail(c)
		}).validation("myEmail", "Inserisci un indirizzo e-Mail valido.",
		function(g, b, c) {
			//return this.isMyEmail(c)
			return this.isEmail(c)
		}).validation("commento", "Inserisci un commento valido.",
		function(g, b, c, d, h) {
			return c.length >= d && c.length <= h
		}).validation("cognomeNome", "Inserisci Cognome e Nome validi.",
		function(g, b, c, d, h) {
			return /^[a-zA-Z][a-zA-Z0-9\'\&\,àèéìòù\ ]*[a-zA-Z0-9\'\ àèéìòù]$/.test(c) && !/([a-zA-Z0-9])\1{3}/.test(c) && c.length >= d && c.length <= h && !/(pinco|sempronio|befana|babbo|stronzo|cazzo|figa|coglione|prova)/i.test(c)
		}).validation("telefono", "Inserisci un numero di telefono valido.",
		function(g, b, c, d, h) {
			return c.length >= d && c.length <= h && this.isTelefono(c)
		}).validation("url", "Inserisci un URL valido.", function(g, b, c) {
	return this.isUrl(c)
}).validation("username", "Inserisci uno username valido.",
		function(g, b, c) {
			return this.isUsername(c)
		}).validation("match", "Puoi inserire solo {arg1}.",
		function(g, b, c, d) {
			return b.val() == d
		}).validation("contain", "Deve contenere {arg1}", function(g, b, c, d) {
	return this.contains(c, d)
}).validation("date", "Inserisci una data valida.", function(g, b, c) {
	return this.isDate(c)
}).validation("minselect", "Seleziona almeno {arg1} checkbox.",
		function(g, b, c, d) {
			return d <= this.inputsWithName(g, b).filter(":checked").length
		}, function(g, b) {
			this.bindBrothers(g, b)
		}).validation("maxselect", "Seleziona al massimo {arg1} checkbox.",
		function(g, b, c, d) {
			return d >= this.inputsWithName(g, b).filter(":checked").length
		}, function(g, b) {
			this.bindBrothers(g, b)
		}).validation("rangeselect",
		"Seleziona tra {arg1} e {arg2} checkboxe.", function(g, b, c, d, h) {
			g = this.inputsWithName(g, b).filter(":checked").length;
			return d <= g && h >= g
		}, function(g, b) {
			this.bindBrothers(g, b)
		});
jQuery.ketchup
		.helper("isNumber", function(g) {
			return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(g)
		})
		.helper("contains", function(g, b) {
			return g.indexOf(b) != -1
		})
		.helper(
				"isEmail",
				function(g) {
					return /^((([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(g)
				})
		.helper(
				"isMyEmail",
				function(g) {
					return /^([a-zA-Z0-9]+[\.|_|\-|£|$|%|&]{0,1})*[a-zA-Z0-9]{1}@([a-zA-Z0-9]+[\.|_|\-|£|$|%|&]{0,1})*([\.]{1}([a-zA-Z]{2,4}))$/
							.test(g)
				})
		.helper(
				"isTelefono",
				function(g) {
					return /^[3][1-9][0-9]([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){6,7}(\ )*$|^[+](39)[\,|\-,|\/|\\|\.|\ |\_]?[3][1-9][0-9]([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){6,7}(\ )*$|^[0][0][\,|\-,|\/|\\|\.|\ |\_]?(39)[\,|\-,|\/|\\|\.|\ |\_]?[3][1-9][0-9]([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){6,7}(\ )*$|^[0][1-9][0-9]{0,2}([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){5,10}(\ )*$|^[+](39)[\,|\-,|\/|\\|\.|\ |\_]?[0][1-9][0-9]{0,2}([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){5,10}(\ )*$|^[0][0][\,|\-,|\/|\\|\.|\ |\_]?(39)[\,|\-,|\/|\\|\.|\ |\_]?[0][1-9][0-9]{0,2}([\,|\-,|\/|\\|\.|\ |\_]?[0-9]){5,10}(\ )*$/.test(g) && !(/(1)[\,|\-,|\/|\\|\.|\ |\_]?(2)[\,|\-,|\/|\\|\.|\ |\_]?(3)[\,|\-,|\/|\\|\.|\ |\_]?(4)[\,|\-,|\/|\\|\.|\ |\_]?(5)[\,|\-,|\/|\\|\.|\ |\_]?(6)|(6)[\,|\-,|\/|\\|\.|\ |\_]?(5)[\,|\-,|\/|\\|\.|\ |\_]?(4)[\,|\-,|\/|\\|\.|\ |\_]?(3)[\,|\-,|\/|\\|\.|\ |\_]?(2)[\,|\-,|\/|\\|\.|\ |\_]?(1)|(0)[\,|\-,|\/|\\|\.|\ |\_]?(1)[\,|\-,|\/|\\|\.|\ |\_]?(2)[\,|\-,|\/|\\|\.|\ |\_]?(3)[\,|\-,|\/|\\|\.|\ |\_]?(4)[\,|\-,|\/|\\|\.|\ |\_]?(5)|(5)[\,|\-,|\/|\\|\.|\ |\_]?(4)[\,|\-,|\/|\\|\.|\ |\_]?(3)[\,|\-,|\/|\\|\.|\ |\_]?(2)[\,|\-,|\/|\\|\.|\ |\_]?(1)[\,|\-,|\/|\\|\.|\ |\_]?(0)|(4)[\,|\-,|\/|\\|\.|\ |\_]?(5)[\,|\-,|\/|\\|\.|\ |\_]?(6)[\,|\-,|\/|\\|\.|\ |\_]?(7)[\,|\-,|\/|\\|\.|\ |\_]?(8)[\,|\-,|\/|\\|\.|\ |\_]?(9)|(9)[\,|\-,|\/|\\|\.|\ |\_]?(8)[\,|\-,|\/|\\|\.|\ |\_]?(7)[\,|\-,|\/|\\|\.|\ |\_]?(6)[\,|\-,|\/|\\|\.|\ |\_]?(5)[\,|\-,|\/|\\|\.|\ |\_]?(4)|((0)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((1)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((2)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((3)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((4)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((5)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((6)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((7)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((8)[\,|\-,|\/|\\|\.|\ |\_]?){6}|((9)[\,|\-,|\/|\\|\.|\ |\_]?){6}/).test(g)
				})
		.helper(
				"isUrl",
				function(g) {
					return /^(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(g)
				})
		.helper(
				"isUsername",
				function(g) {
					return /^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$/
							.test(g)
				}).helper("isDate", function(g) {
			return !/Invalid|NaN/.test(new Date(g))
		}).helper("inputsWithName", function(g, b) {
			return $('input[name="' + b.attr("name") + '"]', g)
		}).helper("inputsWithNameNotSelf", function(g, b) {
			return this.inputsWithName(g, b).filter(function() {
				return $(this).index() != b.index()
			})
		}).helper("getKetchupEvents", function(g) {
			g = g.data("events").ketchup;
			var b = [];
			for (i = 0; i < g.length; i++)
				b.push(g[i].namespace);
			return b.join(" ")
		}).helper(
				"bindBrothers",
				function(g, b) {
					this.inputsWithNameNotSelf(g, b).bind(
							this.getKetchupEvents(b), function() {
								b.ketchup("validate")
							})
				});
