/*
 * Another In Place Editor - a jQuery edit in place plugin
 *
 * Copyright (c) 2009 Dave Hauenstein
 *
 * License:
 * This source file is subject to the BSD license bundled with this package.
 * Available online: {@link http://www.opensource.org/licenses/bsd-license.php}
 * If you did not receive a copy of the license, and are unable to obtain it,
 * email davehauenstein@gmail.com,
 * and I will send you a copy.
 *
 * Project home:
 * http://code.google.com/p/jquery-in-place-editor/
 *
 */

/*
 * Version 1.0.1
 *
 * bg_out (string) default: transparent hex code of background color on restore from hover
 * bg_over (string) default: #ffc hex code of background color on hover
 * callback (function) default: null function to be called when editing is complete; cancels ajax submission to the url param
 * cancel_button (string) default: <input type=”submit” class=”inplace_cancel” value=”Cancel”/> image button tag to use as “Cancel” button
 * default_text (string) default: “(Click here to add text)” text to show up if the element that has this functionality is empty
 * element_id (string) default: element_id name of parameter holding element_id
 * error (function) this function gets called if server responds with an error
 * field_type (string) “text”, “textarea”, or “select”; default: “text” The type of form field that will appear on instantiation
 * on_blur (string) “save” or null; default: “save” what to do on blur; will be overridden if $param show_buttons is true
 * original_html (string) default: original_html name of parameter holding original_html
 * params (string) example: first_name=dave&last_name=hauenstein paramters sent via the post request to the server
 * save_button (string) default: <input type=”submit” class=”inplace_save” value=”Save”/> image button tag to use as “Save” button
 * saving_image (string) default: uses saving text specify an image location instead of text while server is saving
 * saving_text (string) default: “Saving…” text to be used when server is saving information
 * select_options (string) comma delimited list of options if field_type is set to select
 * select_text (string)default text to show up in select box
 * show_buttons (boolean) default: false will show the buttons: cancel or save; will automatically cancel out the onBlur functionality
 * success (function) default: null this function gets called if server responds with a success
 * textarea_cols (integer) default: 25 set cols attribute of textarea, if field_type is set to textarea
 * textarea_rows (integer) default: 10 set rows attribute of textarea, if field_type is set to textarea
 * update_value (string) default: update_value name of parameter holding update_value
 * url (string) POST URL to send edited content
 * value_required (string) default: false if set to true, the element will not be saved unless a value is entered
 *
 */

jQuery.fn.editInPlace = function(options) {

	/* DEFINE THE DEFAULT SETTINGS, SWITCH THEM WITH THE OPTIONS USER PROVIDES */
	var settings = {
		url:				"",
		params:				"",
		field_type:			"text",
		select_options:		"",
		textarea_cols:		"25",
		textarea_rows:		"10",
		bg_over:			"#FFFF99",
		bg_out:				"transparent",
		saving_text:		"Saving...",
		saving_image:		"",
		default_text:		"Saving...",
		default_text1:		"(click here to add text)",
		select_text:		"",
		value_required:		null,
		element_id:			"element_id",
		update_value:		"update_value",
		original_html:		"original_html",
		save_button:		'<button class="inplace_save">Save</button>',
		cancel_button:		'<button class="inplace_cancel">Cancel</button>',
		show_buttons:		false,
		on_blur:			"save",
		callback:			null,
		success:			null,
		error:				function(request){
                                alert("Failed to save value: " + request.responseText || 'Unspecified Error');
                            }
	};

	if(options) {
        jQuery.extend(settings, options);
    }

    /* preload the loading icon if it exists */
    if(settings.saving_image != ""){
        var loading_image = new Image();
        loading_image.src = settings.saving_image;
    }

    /* THIS FUNCTION WILL TRIM WHITESPACE FROM BEFORE/AFTER A STRING */
    String.prototype.trim = function() {
        return this.replace(/^\s+/, '')
                             .replace(/\s+$/, '');
    };

    /* THIS FUNCTION WILL ESCAPE ANY HTML ENTITIES SO "Quoted Values" work */
    String.prototype.escape_html = function() {
        return this.replace(/&/g, "&amp;")
                             .replace(/</g, "&lt;")
                             .replace(/>/g, "&gt;")
							 .replace(/&amp;/g, "&")
                             .replace(/"/g, "&quot;");
	};
	String.prototype.br2newline = function() {
		return this.replace(/<br\s*\/>/g, "\n")
					.replace(/<br\s*>/g, "\n");
					
  	};
	
	String.prototype.amp = function() {
		return this.replace(/&amp;/g, "and")
		.replace(/&/g, "and");
		//.replace(/\n/, '<br>');
  	};
	

    /* CREATE THE INPLACE EDITOR */
    return this.each(function(){
    
        if(jQuery(this).html() == "") jQuery(this).html(settings.default_text1);
		
        var editing = false;   

        //save the original element - for change of scope
        var original_element = jQuery(this);
		
        var click_count = 0;
        
        var state = 'original';
        
        var original_html = jQuery(this).html();
		
		var buttons_code  = (settings.show_buttons) ? settings.save_button + ' ' + settings.cancel_button : '';
		
        jQuery(this)

        .mouseover(function(){
            jQuery(this).css("background", settings.bg_over);
        })

        .mouseout(function(){
            jQuery(this).css("background", settings.bg_out);
        })

        .click(function(){
            click_count++;
            
			if(click_count == 1)
            {
            
            	function captureEnter()
            	{
			   		$("#inplace_form").bind("keypress", function(e) {
			  			if (e.keyCode == 13) {
			  				saveAction();
			  				return false;
			  			}
					});            	
            	
            	}
	        
				function onBlurAction()
				{
									
					/* set the focus to the new input element */
					////////
					$("#inplace_field").focus().select();
			
					$("#inplace_field").blur(function () {
						saveAction();
					});
			 
				}
	        
				function onBlurActionDatepicker()
				{
				
					/* set the focus to the new input element */
					////////
					$('#ui-datepicker-div').data('hover', 1);
					
					$("#inplace_field").focus().select();
									
					$("#ui-datepicker-div").hover(
					    function(){ $('#ui-datepicker-div').data('hover', 1); },
					    function(){ $('#ui-datepicker-div').data('hover', 0); }
					);
			
					$("#inplace_field").blur(function () {
						if($("#ui-datepicker-div").data('hover')){
							return true;
						} else {
							saveAction();
						}
					});
			 
				}	        
	
				function onBlurActionDynamicSelect()
				{
				
					/* set the focus to the new input element */
					////////
					$("#inplace_field").focus().select();
									
					$("#inplace_link").hover(
					    function(){ $('#inplace_link').data('hover', 1); },
					    function(){ $('#inplace_link').data('hover', 0); }
					);
			
					$("#inplace_field").blur(function () {
						if($("#inplace_link").data('hover')){
								onAddValueDynamicSelectAction();
							} else {
								saveAction();
							}
					});
			 
				}
				
				function onAddValueDynamicSelectAction()
	            {
	            
	            	state = 'alternate';

					original_element.html('<table><tr><td><form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;"><input type="text" name="inplace_value" id="inplace_field" class="inplace_field" value="" style="width:75px;"/></form></td><td><a href="#" id="inplace_link">Cancel</a></td></tr></table>');
	        		
	        		/* set the focus to the new input element */
					////////
					$("#inplace_field").focus().select();
									
					$("#inplace_link").hover(
					    function(){ $('#inplace_link').data('hover', 1); },
					    function(){ $('#inplace_link').data('hover', 0); }
					);
			
					$("#inplace_field").blur(function () {
						if($("#inplace_link").data('hover')){
							onCancelDynamicSelectAction();
						} else {
							saveAction();
						}
					});

					captureEnter();
	        		
				}
				
				function onCancelDynamicSelectAction()
	            {
	            
	            	state = 'original';
	            	            	
					original_element.html('<table><tr><td><form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;">' + use_field_type + '</form></td><td><a href="#" id="inplace_link">Add Value</a></form></td></tr></table>');
	        			        		
	        		captureEnter();
	        		onBlurActionDynamicSelect();
	        		
				}			
				
				
	            function cancelAction()
	            {
	                editing = false;
	                click_count = 0;
	                state = 'original';
	
	                /* put the original background color in */
	                original_element.css("background", settings.bg_out);
	
	                /* put back the original text */
	                original_element.html(original_html);
	
	                return false;
	            }
	
	           function saveAction()
	            {                					
					/* put the original background color in */
					original_element.css("background", settings.bg_out);
	
					var this_elem = jQuery(this);
	
					var value = escape($("#inplace_field").val().amp());
					
					var text = escape($("#inplace_field").val().amp());
					
					if (settings.field_type == 'select' || (settings.field_type == 'select_dynamic' && state == 'original')) {
						text = $('#inplace_field :selected').text();
					}
							
					/* set saving message */
					if(settings.saving_image != ""){
						var saving_message = '<img src="' + settings.saving_image + '" alt="Saving..." />';
					} else {
						var saving_message = settings.saving_text;
					}
	
					/* place the saving text/image in the original element */
					original_element.html(saving_message);
	
					if(settings.params != ""){
						settings.params = "&" + settings.params;
					}
	
					if (settings.value_required && (value == "" || value == undefined)){
						editing = false;
						click_count = 0;
						state = 'original';
						original_element.html(original_html);
						alert("Error: You must enter a value to save this field");
					} else {
						jQuery.ajax({
							url: settings.url,
							type: "POST",
							data: settings.update_value + '=' + value + '&' + settings.element_id + '=' + original_element.attr("id") + settings.params + '&' + settings.original_html + '=' + original_html + '&state=' + state + '&update_text=' + text,
							dataType: "html",
							complete: function(request){
								editing = false;
								click_count = 0;
								state = 'original';
								original_html = text;
							},
							success: function(html){
								/* if the text returned by the server is empty, */
								/* put a marker as text in the original element */
								//html.replace(/\n/, '<br>');
								/*if (html == "")
								{
									var	new_text = html || settings.default_text1;
								}
								else
								{*/
									var new_text = html || settings.default_text;
								//}
								 
								
								/* put the newly updated info into the original element */
								
								
								
								original_element.html(new_text);
								
								if (settings.success) settings.success(html, original_element);
								
								//if (settings.field_type == "textarea" || settings.field_type == "datepicker") window.location.reload();
								window.location.reload();
							},
							error: function(request) {
								original_element.html(original_html);
								if (settings.error) settings.error(request, original_element);
							}
						});
					}
	
					return false;
	            }//end save action
			}//end if click_count == 1            
            
			
            if(!editing)
            {
                editing = true;

                //save original text - for cancellation functionality
                var original_text = jQuery(this).text();
                original_text = original_text.replace(/\n|\t/g, '');
                
                //if html is our default text, clear it out to prevent saving accidentally
                if (original_html == settings.default_text) jQuery(this).html('');

                if (settings.field_type == "textarea")
                {
                    var use_field_type = '<textarea name="inplace_value" style="border:1px solid #dedede; width:100%;" class="inplace_field" id="inplace_field" rows="' + settings.textarea_rows + '" cols="' + settings.textarea_cols + '">' + original_html.br2newline().trim().escape_html() + '</textarea>';
                    
					original_element.html('<form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;">' + use_field_type + '</form>');
					
					//captureEnter();
					onBlurAction();
                }
                else if(settings.field_type == "text")
                {
                    var use_field_type = '<input type="text" name="inplace_value" class="inplace_field" id="inplace_field" value="' + jQuery(this).text().trim().escape_html() + '" />';
                    
					original_element.html('<form class="inplace_form" id="inplace_form" style="display:inline; margin: 0; padding: 0;">' + use_field_type  + '</form>');
					
					captureEnter();
					onBlurAction();
                }
                else if(settings.field_type == "datepicker")
                {
					var oDate = document.getElementById('pure_age').value;
                    var use_field_type = '<input type="text" name="inplace_value" class="inplace_field" id="inplace_field" value="' + oDate + '" />';
                    
					original_element.html('<form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;">' + use_field_type + '</form>');
					
					$('#inplace_field').datepicker({
						onSelect: function(tsDate, troPicker) {
							$("#inplace_field").datepicker('destroy');
							$("#inplace_field").focus().select();
						},
						onClose: function(tsDate, troPicker) {
							$("#inplace_field").datepicker('destroy');
							$("#inplace_field").focus().select();
							
						},
						changeFirstDay: false,
						showButtonPanel: true,
						changeMonth: true,
						changeYear: true
						//defaultDate: oDate
						
 					});
					
					captureEnter();
					onBlurActionDatepicker();
                }               
				else if(settings.field_type == "select")
                {
					var optionsArray = settings.select_options.split(',');
					var use_field_type = '<select name="inplace_value" class="inplace_field" id="inplace_field"><option value="">' + settings.select_text + '</option>';
					for(var i=0; i<optionsArray.length; i++){
						var optionsValuesArray = optionsArray[i].split(':');
						var use_value = optionsValuesArray[1] || optionsValuesArray[0];
						var display_value = optionsValuesArray[0];
						display_value = display_value.replace(/\n/g, '');
						var selected = display_value == original_text ? 'selected="selected" ' : '';
						use_field_type += '<option ' + selected + 'value="' + use_value.trim().escape_html() + '">' + display_value.trim().escape_html() + '</option>';
					}
					
					original_element.html('<form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;">' + use_field_type + '</form>');
					
					captureEnter();
					onBlurAction();
     	
                } 
                else if(settings.field_type == "select_dynamic")
                {
                
					original_element.html(settings.loading_text);
                
                	$.get(settings.select_dynamic_url + '?' + settings.select_dynamic_params, function(data){
                		optionsArray = data.split(',');
                		use_field_type = '<select name="inplace_value" style="width:75px;" class="inplace_field" id="inplace_field"><option value="">' + settings.select_text + '</option>';
						for(var i=0; i<optionsArray.length; i++){
							var optionsValuesArray = optionsArray[i].split(':');
							var use_value = optionsValuesArray[1] || optionsValuesArray[0];
							var display_value = optionsValuesArray[0];
							display_value = display_value.replace(/\n/g, '');
							var selected = display_value == original_text ? 'selected="selected" ' : '';
							use_field_type += '<option ' + selected + 'value="' + use_value.trim().escape_html() + '">' + display_value.trim().escape_html() + '</option>';
						}
												
						original_element.html('<table><tr><td><form class="inplace_form" id="inplace_form" style="margin: 0; padding: 0;">' + use_field_type + '</form></td><td><a href="#" id="inplace_link">Add Value</a></td></tr></table>');
						
						captureEnter();
						onBlurActionDynamicSelect();
						
					});
				}
				
				/* hit esc key */
				$(document).keyup(function(event){
					if (event.keyCode == 27 && editing == true) {
						cancelAction();
					}
				});
				
            }/* END- if(!editing) -END */

        });//end click function
    });//end each function
};
