(function() {
	jQuery.fn.LoadOnChange = function (options) {
		// Extend our defaults with the user's preferred options
		options = jQuery.extend({}, jQuery.fn.LoadOnChange.defaults, options);

		this.each(function () {
			$form = jQuery(this);

			// Make sure we have a jQuery object for the result element
			options.resultElement = jQuery(options.resultElement);

			// Set the options and timeout in the form's data
			$form.data("LoadOnChange", { options : options, timeout : null, request : null});

			// Attach our lastValue data to all elements
			jQuery("input, textarea, select").each(function (index, item) {
				item = jQuery(item);
				item.data("LoadOnChange", { lastValue : item.val()});
			});

			// Listen to all changes
			jQuery("input:text, textarea", $form).bind("keyup", { form : $form }, jQuery.fn.LoadOnChange.onFieldChange);
			jQuery("select", $form).bind("change keyup", { form : $form }, jQuery.fn.LoadOnChange.onFieldChange);
			jQuery("input:checkbox, input:radio", $form).bind("change", { form : $form }, jQuery.fn.LoadOnChange.onFieldChange);
			
			// Attach the form submit handler
			$form.bind("submit", { form : $form }, jQuery.fn.LoadOnChange.onSubmit);
			
			// Hide submit buttons
			if (options.hideSelector && options.hideSelector.length > 0)
				jQuery(options.hideSelector, $form).hide();
		});
	};

	jQuery.fn.LoadOnChange.onFieldChange = function (event) {
		var form = event.data.form;
		var data = form.data("LoadOnChange");
		var target = jQuery(event.currentTarget);
		var targetData = target.data("LoadOnChange");
		var tagName = event.currentTarget.tagName;

		// Return if the field's value did not change
		if (target.val() == targetData.lastValue && jQuery(":checkbox,:radio").length == 0) {
			return;
		}
		// Set the lastValue in our metadata
		targetData.lastValue = target.val();

		// Clear the timeout if it is waiting to trigger
		if (data.timeout != null) {
			clearTimeout(data.timeout);
		}

		// Start a new timeout in case there is no change
		data.timeout = setTimeout(function () {
			form.trigger("submit");
			form = null;
		}, data.options.delay);
	};
	
	jQuery.fn.LoadOnChange.onSubmit = function (event) {
		var form = event.data.form;
		var data = form.data("LoadOnChange");
		var actionUrl = data.options.url;
		var resultElement = data.options.resultElement;

		// Prevent form submission
		event.preventDefault();

		// Clear the timeout
		if (data.timeout != null) {
			clearTimeout(data.timeout);
		}

		// Empty the result element and set the indicator
		resultElement.empty();
		if (data.options.indicator) {
			resultElement.append(data.options.indicator);
		}

		// Cancel any previous requests
		if (data.request != null) {
			data.request.abort();
			data.request = null;
		}

		// Start the new request, using a fragment if one was configured
		data.request = jQuery.post(actionUrl, form.serialize(), function (result, status, request) {
			if (data.options.fragment) {
				result = jQuery(data.options.fragment, result).html();
			}
			resultElement.empty().append(result);
		});
	};

	jQuery.fn.LoadOnChange.defaults = {
		delay : 400,
		indicator : '<img src="/includes/images/indicator.gif" alt="Loading..." />',
		hideSelector : ":submit"
	};
})();
