/**
 * Constructs dropdown elements from a list of objects.  Each object must contain a value member and a
 * text member.  The value member translates to the <option> value and the text member translates to the
 * text shown in the dropdown.
 * @param {Object} data
 * @param {Object} value
 */
jQuery.fn.buildDropDown = function(data, value) {
	var obj = jQuery(this);
	return this.each(function() {
		if (obj.is("select")) {
			var html = "<option value='-1'>Choose...</option>";
			
			for(var i=0; i < data.length; i++) {
				html += "<option value='" + data[i].value + "'>" + data[i].text + "</option>";
			}
			
			obj.html(html);
			
			if (value) {
				obj.val(value);
			}
		}
	});
};

/**
 * Load data values for the selected object and bind them to the named children of the
 * object.  For example:
 * 
 * $("#mydiv").load({url: "foo"}); 
 * 
 * will call the url to get some JSON data.  If the JSON data returns a data.field.testfield = '123',
 * then any object in mydiv with a name='testfield' will be set to 123.  This works correctly 
 * with all input field types as well as div, span, and td tags.
 * 
 * This makes it very easy to use backend services to load different parts of the page, or the entire
 * page at once (using $('body').load(...))
 * 
 * This method takes the options available in jQuery.ajax() with the following exceptions:
 * 
 * 1.  options.datatype is always "json".
 * 2.  options.formatter is an additional function that can be specified to format the 
 * 		returned data prior to it being placed into the form.  function(field, data){}.
 * 3.  options.onComplete is an optional function that will be called when the form load
 * 		is complete.  function(result){} where result is the returned JSON object.
 * 
 * Note that this function expects returned values that it places into DOM objects, but
 * places no restriction on what the returned value is.  For example it's possible to return
 * a string and have it placed into a text field.  But it's also possible to return a full-blown
 * HTML construct and have it placed in a DIV.
 * 
 * @param {Object} options
 */
jQuery.fn.load = function(options) {
	if (!options) {
		options = {};
	}

	return this.each(function() {
		var jobj = jQuery(this);
		
		options.datatype = "json";
			
		options.success = function(json){
			if (json) {
				var response = eval("((" + json + "))");
				
				for (var field in response.data) {
					data = response.data[field];
					
					if (options.formatter) {
						result = options.formatter(field, data);
						data = result || data;
					}
					
					jobj.find(' [name=' + field + ']').val(data);
					jobj.find(' div[name=' + field + ']').html(data);
					jobj.find(' span[name=' + field + ']').html(data);
					jobj.find(' td[name=' + field + ']').html(data);
				}
				
				for (error in response.errors) {
					jobj.find('.' + error + '_error').val(response.errors[error]);
					jQuery('.' + error + '_error').html(response.errors[error]);
				}
			}
			
			if(options.onComplete) {
				options.onComplete(response);
			}
		}
		
		jQuery.ajax(options);
	});
};

/**
 * Submit the form values and bind any response to the page. This method takes the options
 * available in jQuery.ajax() with the following exceptions:
 * 
 * 1.  options.datatype is always "json".
 * 2.  options.type is taken from the form's METHOD attribute.
 * 3.  options.url is taken from the form's ACTION attribute.
 * 4.  options.data is the serialized data of the form.
 * 5.  options.validator is an optional function that will be called prior to form submission
 * 		in order to pre-validate the form.  function(){}.  Returning false will cause the 
 * 		form processing to stop prior to submission.  Return true or nothing at all will cause
 * 		the form to be submitted.
 * 6.  options.formatter is an additional function that can be specified to format the 
 * 		returned data prior to it being placed into the form.  function(field, data){}.
 * 7.  options.onComplete is an optional function that will be called when the form load
 * 		is complete.  function(result){} where result is the returned JSON object.
 * 
 * @param {Object} options
 */
jQuery.fn.submit = function(options) {
	if (!options) {
		options = {};
	}
	
	return this.each(function() {
		var jobj = jQuery(this);
		
		options.datatype = "json";
		options.type = jobj.attr("method");
		options.url = jobj.attr("action");
		options.data = jobj.serialize();
			
		options.success = function(json){
			if (json) {
				var response = eval("((" + json + "))");
				
				for (var field in response.data) {
					data = response.data[field];
					
					if (options.formatter) {
						result = options.formatter(field, data);
						data = result || data;
					}
					
					jobj.find(' [name=' + field + ']').val(data);
					jobj.find(' div[name=' + field + ']').html(data);
					jobj.find(' span[name=' + field + ']').html(data);
					jobj.find(' td[name=' + field + ']').html(data);
				}
				
				for (error in response.errors) {
					jobj.find('.' + error + '_error').val(response.errors[error]);
					jQuery('.' + error + '_error').html(response.errors[error]);
				}
			}
			
			if (options.onComplete) {
				options.onComplete(response);
			}
		}
		
		//
		// Pretend validation worked, unless validation actually happened and failed.
		//
		var validated = true;
		
		if(options.validator) {
			var result = options.validator();
			if (result !== null) {
				validated = result;
			}
		}
		
		if (validated && options.url) {
			jQuery.ajax(options);
		}
	});
};
