(function($) {
	$.fn.smartInput = function(callback) {
		callback = callback || function(status) {};

		var status    = {valid: false};
		var getStatus = function(hash) {
			var valid = true;

			for(var i in hash) {
				if(i == "valid")
					continue;

				if(!hash[i]) {
					valid = false;
					break;
				}
			}

			hash.valid = valid;

			return hash;
		};

		return this.filter(":text, textarea, :select").each(function() {
			// really should be caught by the filter!
			if(this.nodeName.toLowerCase() == 'button')
				return;

			var displaying = false;

			var self = $(this);
			var req  = self.attr("required") ? self.attr("required").toLowerCase() == "true" : false;
			var fmt  = self.attr("format") ? self.attr("format") : false;

			status[this.name] = (req && self.val() != "") || ! req;

			self.parent().children("span").hide();

			$(this).blur(function() {
				var good = true;

				if(req && self.val() == "")
					good = false;

				if(fmt && self.val() != "") {
					var reg = new RegExp(fmt);

					if(!reg.test(self.val()))
						good = false;
				}

				var node = self.parent();

				// hide all of the spans
				node.children("span").hide();

				if(good && self.val() == "") {
					displaying = false;
					node.removeClass("info").removeClass("success").removeClass("error");
					status[this.name] = true;
					callback(getStatus(status));

					return;
				}

				if(good)
					node.removeClass("info").removeClass("error").addClass("success").children(".success").show();
				else
					node.removeClass("info").removeClass("success").addClass("error").children(".error").show();

				displaying = true;

				status[this.name] = good;
				callback(getStatus(status));

			}).focus(function() {
				if(!displaying)
					$(this).parent().addClass("info").children("span[class=info]").show();
			});
		}).end();
	}
})(jQuery);