/*
 *
 * Copyright (c) 2008 Chris Lam (admin@knetgb.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */

/*
 * jQuery Autofill plugin
 *
 *
 * @name     Autofill
 * @param    data		the data object
 * @param    options  callback functions
 * @author   Chris Lam (admin@knetgb.com)
 * @example  $('form').autoFill({ username: 'Peter', password: 'peter' });
 * @example  $('form').autoFill('get_data.php');
 *
 */
/*
Full example:
 $('form').autoFill('get_data.php',
{
	type: 'GET', // AJAX request method

	data: { record_id: 2 }, // Request parameters

	// if the JSON object contains this key,
	// error callback will be triggered.
	// Useful if server side returns a custom error message
	errorTrigger: 'error',
	
	//JSONObject에 담긴 값이 없을 경우에는 무시되고
	//지정된 키값이 있을경우(ex:JworkErrorTrigger: 키값)이
	//존재할 경우에는 에러메시지 출력 
	jworkErrorTrigger: "Failure"
	
	// Default to false.
	// True:  look for multiple select boxes with their name
	// False: look for multiple select boxes with their ID
	mSelectCheckName: false,

	ajaxError: function(error, form)
	{
		// do something if AJAX error occurs
		alert(error);
		$(form).hide();
	},
	error: function(form)
	{
		// do something if error occurs
		alert('Unable to fill form!');
		$(form).hide();
	},
	beforeFillForm: function(form)
	{
		// do something before start filling the form
		$(form).show();
	},
	beforeFill: function(key, value, form)
	{
		// do something BEFORE filling an element

		if(key == 'password')
			return false; // return false to skip current form element

		if(key == 'gender' && value == 'female')
			alert("OH! She's a lady!");
	},
	afterFill: function(key, value, form)
	{
		// do something AFTER filling an element
		if(value == 'blah')
			confirm('What are you talking about?');

		if(key == 'zip' && value == '')
			return false; // return false to skip all pending form elements
	},
	complete: function(processed, form)
	{
		// do something when all elements have been filled
		alert(processed + ' elements have been filled!');
	}
});
*/
jQuery.fn.autoFill = function(target, options)
{
	options = options || {};

	// AJAX request method
	options.type = options.type || 'get';

	// AJAX request parameters
	options.params = options.data || {};

	// if the JSON object contains this as its key,
	// error callback will be triggered.
	// Useful if server side returns a custom error message
	options.errorTrigger = options.errorTrigger || null;
	
	//JSONObject에 담긴 값이 없을 경우에는 무시되고
	//지정된 키값이 있을경우(ex:JworkErrorTrigger: 키값)이
	//존재할 경우에는 에러메시지 출력
	//상단의 errorTrigger를 응용함. 
	options.jworkErrorTrigger= "Failure";
	
	//fill() 안에서 서블릿단의 에러키워드 유무에 따라 호출되는 메서드.
	options.jworError= function(errorMessage)
	{
		alert(errorMessage);
	};
	
	// True:  look for multiple select boxes with their name
	// False: look for multiple select boxes with their ID
	options.mSelectCheckName = options.mSelectCheckName || false;

	var isEmpty = function(obj)
	{
		if(typeof(obj) == 'object')
		{
			for(var i in obj)
			{
				return false;
			}
		}
		return true;
	};

	var fillMultipleSelect = function(key, val, form)
	{
		if(options.mSelectCheckName)
		{
			// use ^= as we usually write: <select name="users[]">,
			// the square brackets at the end of the name will results in collision
			jQuery('select[name^=' + key + '] option', form).each(function()
			{
				this.selected = (jQuery.inArray(this.value, val) != -1);
			});
		}
		else
		{
			jQuery('select[id=' + key + '] option', form).each(function()
			{
				this.selected = (jQuery.inArray(this.value, val) != -1);
			});
		}
	};

	var fill = function(data, form)
	{
		// 서블릿 단의 에러 키워드를 검색해서 존재하면 메시지를 출력함
		if(options.jworkErrorTrigger !== null && typeof(data[options.jworkErrorTrigger]) != 'undefined')
		{
			if(jQuery.isFunction(options.jworError))
				options.jworError(data[options.jworkErrorTrigger]);
			return false;
		}
		
		// error callback if the JSON object is empty,
		// or contains errorTrigger as its key
		if(isEmpty(data) || (
			options.errorTrigger !== null &&
			typeof(data[options.errorTrigger]) != 'undefined'
		))
		{
			if(jQuery.isFunction(options.error))
				options.error(form);
			return false;
		}
		
		// beforeFillForm callback before filling the form
		if(jQuery.isFunction(options.beforeFillForm))
		{
			if(options.beforeFillForm(form) === false)
				return false;
		}

		var processed = 0; // form elements processed
			
		for(var key in data)
		{
			// beforeFill callback before filling an form element
			if(jQuery.isFunction(options.beforeFill))
			{
				if(options.beforeFill(key, data[key], form) === false)
				{
					continue;	
				}
			}
			// beforeFill callback before filling an form element
			if(jQuery.isFunction(options.jworkBeforeFill))
			{
				if(options.beforeFill(key, data[key], form) === false)
				{
					continue;	
				}
			}
			// Skip if null
			if(data[key] === null)
				continue;
			
			// if the current value is an array, it should be a multiple select
			
			if(data[key].constructor == Array)
			{
				fillMultipleSelect(key, data[key], form);
			}
			else
			{
				var obj = jQuery(':input[name=' + key + ']', form);

				obj = obj.length > 0 ? obj : jQuery(':input[id=' + key + ']', form);

				// is there any input element?
				if(obj.length == 0)
					continue;

				if(obj.attr('type') == 'radio') // radio
				{
					obj.each(function()
					{
						if(this.value == data[key])
							this.checked = true;
					});
				}
				else if(obj.attr('type') == 'checkbox') // checkbox
				{
					if(obj.val() == data[key])
						obj.attr('checked', true);
				}
				else obj.val(data[key], data); // other input elements
			}

			processed++;

			// afterFill callback after filling an form element
			
			if(jQuery.isFunction(options.afterFill))
			{				
				if(options.afterFill(key, data[key], form) === false);
					break;
			}
		}

		// complete callback after filling all form elements
		if(jQuery.isFunction(options.complete))
			options.complete(processed, data, form);
	};

	return this.each(function()
	{
		var form = jQuery(this).get(0);

		// if target is not a JSON object, it should be an URL
		if(typeof(target) != 'object')
		{
			jQuery.ajax(
			{
				type: options.type,
				url: target,
				dataType: 'json',
				data: options.data,
				success: function(d)
				{
					fill(d, form);
				},
				error: function(xmlhttp, status, e)
				{
					//ajaxError 속성이 업으면 Default 메시지 출력
					if(options.ajaxError)
					{
						options.ajaxError(e, form);
					}
					else
					{
						alert("프로세스 실행중 에러가 발생하였습니다.");
					}
				}
			});
		}
		else fill(target, form);
	});
};
