/*
	Purdyforms JS
	Version 1.1.4
	
	Adam Edwards
	Flint Management Ltd
	
	==========================
	Changelog
	==========================
	Created 21/09/2010
	Updated 20/12/2010
	Updated 30/12/2010 - 1.1.0 Created public method for validation for internal and external validation
	Updated 04/08/2011 - 1.1.1
	Updated 14/09/2011 - 1.1.2
	Updated 23/09/2011 - 1.1.3 Modified to support related field validation 
	Updated 14/11/2011 - 1.1.4 Modified to set status to info when focusing on a field
*/

// Allows us to use $ alias without conflict with other plugins
(function ($) {
	
	// Define methods to be parsed to Purdyforms
	methods = {
		
		// Default method when Purdyforms is intialized
		init : function(options, callback)
		{

			// Set default options
			var defaults = {	
				postURL: "",
				staticBorderColor: "#999999",
				highlightBorderColor: "#0A7285",
				errorBorderColor: "#FF0000"
			}
			
			// Extend defaults if the user has supplied any custom options
			var options = $.extend(defaults, options);
		
			// Iterate over each element in the queue
			return this.each(function() {  
				
				// Assign form id
				var formId = "#" + $(this).attr('id');
				
				// Style the submit button
				$(this).children().find(':submit').addClass('submit');
				$(this).children().find(':button').addClass('submit');
				
				// Iterate through each form element
				$(this).children().find(':input').each(function() {			
					
					if(!$(this).is(':radio') && !$(this).is(':checkbox') && !$(this).is(':submit')){
						
						if(options.staticBorderColor){
						
							// Style input border color
							$(this).css("border", "1px solid " + options.staticBorderColor);
						}
					}
					
					// Is not a submit, hidden or readonly field
					if(!$(this).is(':submit') && !$(this).attr('readonly')){
						
						// Set fieldname
						var fieldname = $(this).attr("name");
						
						// Not radio or checkbox element
						if(!$(this).is(':radio') && !$(this).is(':checkbox')){
							
							// Set the status message from the title tag
							var statusMessage = $(this).attr('title');
							
							// Check status message isn't present
							if($(formId + ' [name=\'' + fieldname + '\']:first').next('.status').length <= 0){
							
								// Append status message to the DOM for after input
								$(formId + ' [name=\'' + fieldname + '\']:first').after('<div class=\"status\"></div>');
							}

							$(this).focus(function(){
									
								// Set the status message from the title tag
								var statusMessage = $(this).attr('title');
								
								// Check if the element has a title tag 
								if(statusMessage != undefined) {
									
									if(!$(this).is(':radio') && !$(this).is(':checkbox')){
										
										// Update status message and show
										$(this).next('.status').removeClass("pf_success pf_error").addClass("pf_info").attr("title", statusMessage).tipTip({
											defaultPosition: "right",
											delay: 0,
											fadeOut: 600
										});
									}
								}
								
								if(options.highlightBorderColor){
									// Set border on input
									$(this).css("border", "1px solid "+ options.highlightBorderColor);	
								}
								
							}).blur(function(){
								
								if(options.staticBorderColor){
									// Style input border color
									$(this).css("border", "1px solid " + options.staticBorderColor);
								}
							});
							
							// Check if the element has a title tag 
							if(statusMessage != undefined){
								
								if(!$(this).is(':radio') && !$(this).is(':checkbox')){
									// Update status message and show
									$(this).next('.status').removeClass("pf_success pf_error").addClass("pf_info").attr("title", statusMessage).tipTip({
										defaultPosition: "right",
										delay: 0,
										fadeOut: 600
									});
								
									if($(this).next('.status').is(':hidden')){
										$(this).next('.status').show();
									}
									
								}
								
							}

							// User changes content
							$(this).change(function(){
								
								if(options.staticBorderColor){
									// Reset border on input
									$(this).css("border", "1px solid "+ options.staticBorderColor + "");
								}
								
								// Run validation 
								$.fn.Purdyforms('validate', 
								{ 
									postURL: options.postURL,
									formId: formId,
									formSubmit: false,
									formField: fieldname,
									errorBorderColor: options.errorBorderColor,
									staticBorderColor: options.staticBorderColor
								});
								
							});
						
						// Deal with radio buttons and checkboxes						
						} else {
							
							// Set the status message from the title tag
							var statusMessage = $(this).parent().attr('title');
							
							// Check status message isn't present
							if($(formId + ' [name=\'' + fieldname + '\']:first').parent().next('.status').length <= 0){
							
								// Append status message to the DOM after label
								$(formId + ' [name=\'' + fieldname + '\']:first').parent().after('<div class=\"status\"></div>');
							
							}
							
							// Check if the element has a title tag 
							if(statusMessage != undefined) {
								
								$(this).parent().next('.status').removeClass("pf_success pf_error").addClass("pf_info").attr("title", statusMessage).tipTip({
									defaultPosition: "right",
									delay: 0,
									fadeOut: 600
								});
								
								// The status is hidden
								if($(this).parent().next('.status').is(':hidden')){
									// Show status
									$(this).parent().next('.status').show();
								} 
							}
							
							// User changes content
							$(this).bind("click", function(){
								
								// Validate input
								$.fn.Purdyforms('validate', { 
									postURL: options.postURL,
									formId: formId,
									formSubmit: false,
									formField: fieldname,
									errorBorderColor: options.errorBorderColor,
									staticBorderColor: options.staticBorderColor
								});
								
							});
						}
					}
				
				});
				
				// Listen for click event
				$(formId + " :submit").click(function(event){
					
					// Prevent default action
					event.preventDefault();
					
					// Validate all form fields

					$.fn.Purdyforms('validate', { 
						postURL: options.postURL,
						formId: formId,
						formSubmit: true,
						formField: false,
						errorBorderColor: options.errorBorderColor,
						staticBorderColor: options.staticBorderColor,
						callback: callback
					});
				
				});		
			});

		},

		/*===========================================
		Public methods for controlling Purdyforms
		===========================================*/
		
		/*
			Reset
			@syntax $( selector ).Purdyforms('reset');
			@description Reset the form elements and hide the status messages
		*/
		reset : function() 
		{
		
			return this.each(function() {

				// Iterate through each form element
				$(this).children().find(':input').each(function() {			
					
					if( !$(this).is(':radio') && !$(this).is(':submit') && !$(this).is(':button') && !$(this).is(':checkbox') ){
						
						statusMessage = $(this).attr("title");
						
						// Set the field to blank
						$(this).val("");
						
						// Check if the element has a title tag 
						if(statusMessage != undefined) {
							// Update status message and show
							$(this).next('.status').removeClass("pf_success pf_error").addClass("pf_info").attr("title", statusMessage).tipTip({
								defaultPosition: "right",
								delay: 0,
								fadeOut: 600
							});
						
							if($(this).next('.status').is(':hidden')){
								$(this).next('.status').show();
							}

							// Style input border color
							$(this).css("border", "1px solid #999999");

							
						} else {
							$(this).next('.status').removeClass("pf_success pf_error").hide();
						}
						
					} else if($(this).is(':checkbox') || $(this).is(':radio')){
						
						statusMessage = $(this).parent().parent().attr("title");
						
						// Check if the element has a title tag 
						if(statusMessage != undefined) {
							
							$(this).parent().next('.status').removeClass("pf_success pf_error").addClass("pf_info").attr("title", statusMessage).tipTip({
								defaultPosition: "right",
								delay: 0,
								fadeOut: 600
							});
							
							// The status is hidden
							if($(this).parent().next('.status').is(':hidden')){
								// Show status
								$(this).parent().next('.status').show();
							} 
						
						} else {
							$(this).parent().next('.status').removeClass("pf_success pf_error").hide();
						}
					}
				});
			});
		},
		
		/*
			Validate
			@syntax $( form ).Purdyforms('validate', { options });
			@description Validate the form on demand (Useful when using jQuery UI Autocomplete to fix onChange issue) 
		*/
		validate : function(options) 
		{
		
			// Form submission
			if(options.formSubmit){
			
				// Fetch the current submit value
				var value = $(options.formId + " :submit").attr('value');
				
				// Disable the submit button and change value to stop multiple requests at once
				$(options.formId + " :submit").attr('disabled', true).attr('value', 'LOADING...');
			}
			
			// Serialize form data and fields
			ajaxData = $(options.formId).serialize() + "&formSubmit=" + options.formSubmit;

			// Ajax post to send fields to be validated to backend form handler
			$.ajax({
				   
				type: "POST",
				url: options.postURL,
				data: ajaxData,
				success: function(data){

					// Parameter is a function
					if(typeof options.callback == 'function'){
						
						// Execute callback function
						options.callback(data);
					}
					
					if(data != ""){
					
						// Try to parse JSON response
						try
						{
							var jsonResponse = $.parseJSON(data);
							var run = true;
						}
						catch(e)
						{
							// ajax response is not json
							var run = false
						}
						
						if(run)
						{						
							// Parse JSON response
							var id;
							
							// Loop through each json element
							$.each(jsonResponse.fields, function(){
								
								// Assign id from field name
								id = $(options.formId + ' [name=' + this.name + ']');
								
								if(options.formField == this.name || options.formField == "" || this.name == $("#" + options.formField).attr('rel')){
									
									// Field isn't valid
									if(!this.valid){
										
										if(!$(id).is(':radio') && !$(id).is(':checkbox')){
											
											// Update status message and styles
											$(id).next('.status').removeClass("pf_info pf_success").addClass("pf_error").attr("title", this.message).tipTip({
												defaultPosition: "right",
												delay: 0,
												fadeOut: 600
											});
												
											if(options.errorBorderColor){
												
												// Found items related field
												$(options.formId + " [rel=" + this.name + "]").each(function(){
													
													// Style the field
													$(this).css("border", "1px solid " + options.errorBorderColor);

												});	

												// Style input border color
												$("#" + this.name).css("border", "1px solid " + options.errorBorderColor);
												
											}
											
										} else {
											
											// Update status message and styles
											$(id).parent().next('.status').removeClass("pf_info pf_success").addClass("pf_error").attr("title", this.message).tipTip({
												defaultPosition: "right",
												delay: 0,
												fadeOut: 600
											});

										}
										
									// Field is valid	
									} else if(this.valid) {
										
										if(!$(id).is(':radio') && !$(id).is(':checkbox')){

											// Update status message and styles
											$(id).next('.status').removeClass("pf_info pf_error").addClass("pf_success").attr("title", this.message).tipTip({
												defaultPosition: "right",
												delay: 0,
												fadeOut: 600
											});
											
											if(options.staticBorderColor){
												
												// Found items related field
												$(options.formId + " [rel=" + this.name + "]").each(function(){
													
													// Style the field
													$(this).css("border", "1px solid " + options.staticBorderColor);

												});	
												
												// Style input border color
												$(id).css("border", "1px solid " + options.staticBorderColor);
											}
											
											// Form submission
											if(options.formSubmit){
												
												// Show status message for all elements
												$(id).next('.status').show();
												
											}
										
										} else {
											
											// Update status message and styles
											$(id).parent().next('.status').removeClass("pf_info pf_error").addClass("pf_success").attr("title", this.message).tipTip({
												defaultPosition: "right",
												delay: 0,
												fadeOut: 600
											});
											
											// Form submission
											if(options.formSubmit){
												
												// Show status message for all elements
												$(id).parent().next('.status').show();
												
											}
										}
									}
								}
							});
						}
					}
				
					if(options.formSubmit){
						// Re-enable the submit button and reset the value
						$(options.formId + " :submit").removeAttr('disabled').attr('value', value);
					}
				}
				
			});
		}
	};
	
	// Define the plugin and it's methods
	$.fn.Purdyforms = function ( method ) {
    
		// Method calling logic
		if ( methods[method] ) {
		
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		
		} else if ( typeof method === 'object' || ! method ) {
		
			return methods.init.apply( this, arguments );
		
		// The method supplied doesn't exist
		} else {
		
			$.error( 'Method ' +  method + ' does not exist in jQuery.Purdyforms' );
		
		}    
	}
	

})(jQuery);
