jQuery(function($) {
	$.fn.quicksearch = function(target, opt) {

		var timeout, cache, rowcache, jq_results, val = '', e = this, options = $
				.extend( {
					delay : 100,
					selector : null,
					stripeRows : null,
					loader : null,
					noResults : '',
					bind : 'keyup',
					onBefore : function() {
						return;
					},
					onAfter : function() {
						return;
					},
					show : function() {
						this.style.display = "";
					},
					hide : function() {
						this.style.display = "none";
					}
				}, opt);

		this.go = function() {

			var i = 0, noresults = true, vals = val.toLowerCase().split(' ');

			var rowcache_length = rowcache.length;
			for ( var i = 0; i < rowcache_length; i++) {
				if (this.test(vals, cache[i]) || val == "") {
					options.show.apply(rowcache[i]);
					noresults = false;
				} else {
					options.hide.apply(rowcache[i]);
				}
			}

			if (noresults) {
				this.results(false);
			} else {
				this.results(true);
				this.stripe();
			}

			this.loader(false);
			options.onAfter();

			return this;
		};

		this.stripe = function() {

			if (typeof options.stripeRows === "object"
					&& options.stripeRows !== null) {
				var joined = options.stripeRows.join(' ');
				var stripeRows_length = options.stripeRows.length;

				jq_results.not(':hidden').each(
						function(i) {
							$(this).removeClass(joined).addClass(
									options.stripeRows[i % stripeRows_length]);
						});
			}

			return this;
		};

		this.strip_html = function(input) {
			var output = input.replace(new RegExp('<[^<]+\>', 'g'), "");
			output = $.trim(output.toLowerCase());
			return output;
		};

		this.results = function(bool) {
			if (typeof options.noResults === "string"
					&& options.noResults !== "") {
				if (bool) {
					$(options.noResults).hide();
				} else {
					$(options.noResults).show();
				}
			}
			return this;
		};

		this.loader = function(bool) {
			if (typeof options.loader === "string" && options.loader !== "") {
				(bool) ? $(options.loader).show() : $(options.loader).hide();
			}
			return this;
		};

		this.test = function(vals, t) {
			for ( var i = 0; i < vals.length; i += 1) {
				if (t.indexOf(vals[i]) === -1) {
					return false;
				}
			}
			return true;
		};

		this.cache = function() {

			jq_results = $(target);

			if (typeof options.noResults === "string"
					&& options.noResults !== "") {
				jq_results = jq_results.not(options.noResults);
			}

			var t = (typeof options.selector === "string") ? jq_results
					.find(options.selector) : $(target).not(options.noResults);
			cache = t.map(function() {
				return e.strip_html(this.innerHTML);
			});

			rowcache = jq_results.map(function() {
				return this;
			});

			return this.go();
		};

		this.trigger = function() {
			this.loader(true);
			options.onBefore();

			window.clearTimeout(timeout);
			timeout = window.setTimeout(function() {
				e.go();
			}, options.delay);

			return this;
		};

		this.cache();
		this.results(true);
		this.stripe();
		this.loader(false);

		return this.each(function() {
			$(this).bind(options.bind, function() {
				val = $(this).val();
				e.trigger();
			});
		});

	};
});
