/***

@title:

Live Search



@version:

2.0



@author:

Andreas Lagerkvist



@date:

2008-08-31



@url:

http://andreaslagerkvist.com/jquery/live-search/



@license:

http://creativecommons.org/licenses/by/3.0/



@copyright:

2008 Andreas Lagerkvist (andreaslagerkvist.com)



@requires:

jquery, jquery.liveSearch.css



@does:

Use this plug-in to turn a normal form-input in to a live ajax search widget. The plug-in displays any HTML you like in the results and the search-results are updated live as the user types.



@howto:

jQuery('#q').liveSearch({url: '/ajax/search.php?q='}); would add the live-search container next to the input#q element and fill it with the contents of /ajax/search.php?q=THE-INPUTS-VALUE onkeyup of the input.



@exampleHTML:

<form method="post" action="/search/">



	<p>

		<label>

			Enter search terms<br />

			<input type="text" name="q" />

		</label> <input type="submit" value="Go" />

	</p>



</form>



@exampleJS:

jQuery('#jquery-live-search-example input[name="q"]').liveSearch({url: Router.urlForModule('SearchResults') + '&q='});

***/

jQuery.fn.liveSearch = function (conf) {

	var config = jQuery.extend({

		url:			'/search-results.php?q=', 

		id:				'jquery-live-search', 

		duration:		400, 

		typeDelay:		200,

		loadingClass:	'loading', 

		onSlideUp:		function () {}, 
		uptadePosition:	false

	}, conf);


	var liveSearch	= jQuery('#' + config.id);


	// Create live-search if it doesn't exist

	if (!liveSearch.length) {

		liveSearch = jQuery('<div id="' + config.id + '"></div>')
						.appendTo(document.body)
						.hide()
						.slideUp(0);


		// Close live-search when clicking outside it

		jQuery(document.body).click(function(event) {

			var clicked = jQuery(event.target);



			if (!(clicked.is('#' + config.id) || clicked.parents('#' + config.id).length || clicked.is('input'))) {

				liveSearch.slideUp(config.duration, function () {

					config.onSlideUp();

				});

			}

		});

	}


	return this.each(function () {

		var input							= jQuery(this).attr('autocomplete', 'off');

		var liveSearchPaddingBorderHoriz	= parseInt(liveSearch.css('paddingLeft'), 10) + parseInt(liveSearch.css('paddingRight'), 10) + parseInt(liveSearch.css('borderLeftWidth'), 10) + parseInt(liveSearch.css('borderRightWidth'), 10);

		// Re calculates live search's position
		var repositionLiveSearch = function () {
			var tmpOffset	= input.offset();

			var inputDim	= {

				left:		tmpOffset.left, 

				top:		tmpOffset.top, 

				width:		input.outerWidth(), 

				height:		input.outerHeight()

			};



			inputDim.topPos		= inputDim.top + inputDim.height;

			inputDim.totalWidth	= inputDim.width - liveSearchPaddingBorderHoriz;


			liveSearch.css({

				position:	'absolute', 

				left:		inputDim.left + 'px', 

				top:		inputDim.topPos + 'px',

				width:		inputDim.totalWidth + 'px'

			});
		};

		// Shows live-search for this input
		var showLiveSearch = function () {
			// Always reposition the live-search every time it is shown
			// in case user has resized browser-window or zoomed in or whatever
			repositionLiveSearch();

			// We need to bind a resize-event every time live search is shown
			// so it resizes based on the correct input element
			$(window).unbind('resize', repositionLiveSearch);
			$(window).bind('resize', repositionLiveSearch);

			liveSearch.slideDown(config.duration);
		};

		// Hides live-search for this input
		var hideLiveSearch = function () {
			liveSearch.slideUp(config.duration, function () {

				config.onSlideUp();

			});
		};


		input
			// On focus, if the live-search is empty, perform an new search
			// If not, just slide it down. Only do this if there's something in the input

			.focus(function () {

				if (this.value !== '') {
					// Perform a new search if there are no search results

					if (liveSearch.html() == '') {

						this.lastValue = '';

						input.keyup();

					}
					// If there are search results show live search

					else {
						// HACK: In case search field changes width onfocus
						setTimeout(showLiveSearch, 1);
					}

				}

			})
			// Auto update live-search onkeyup

			.keyup(function () {
				// Don't update live-search if it's got the same value as last time

				if (this.value != this.lastValue) {

					input.addClass(config.loadingClass);



					var q = this.value;


					// Stop previous ajax-request

					if (this.timer) {

						clearTimeout(this.timer);

					}


					// Start a new ajax-request in X ms

					this.timer = setTimeout(function () {

						jQuery.get(config.url + q, function (data) {

							input.removeClass(config.loadingClass);


							// Show live-search if results and search-term aren't empty

							if (data.length && q.length) {

								liveSearch.html(data);
								showLiveSearch();

							}

							else {
								hideLiveSearch();

							}

						});

					}, config.typeDelay);



					this.lastValue = this.value;

				}

			});

	});

};

