/**
 * RapidEdit (for jQuery)
 * Version: 0.3 (2009-10-16)
 * @requires jQuery
 * The RapidEdit plugin fully supports the MetaData plugin. (Get it here: http://docs.jquery.com/Plugins/Metadata)
 * 
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright © 2009 Sebastian Norling [ bazze90@gmail.com ]
 * 
 * Plugin Description:
 * 
 * The RapidEdit plugin makes it possible to edit any content on your website without
 * reloading the page even once. The plugin provides a simple edit-link on elements marked
 * with the class 'editable' (this is the default class, can be changed) which replace the
 * content of the element with a textarea, where the content can be edited, when clicked. To
 * make the plugin as customizable as possible, loads of settings are provided so you can
 * change it to fit your needs and it also supports the MetaData plugin.
 *
 * Notes:
 *
 * Make sure you don't activate the plugin for an unathorized user and that
 * you perform a server-side check on the user before saving anything
 * to the database or even handling the data, since JavaScript is easy manipulated.
 *
 * PLEASE SEND ANY BUGS FOUND TO: bazze90@gmail.com
 *
 * Usage:
 *  
 * $(document).ready(function() {
 * 	 //saveTo is the path to the file which will receive the AJAX request when saving. [options] is optional.
 *   $.rapidEdit(saveTo[, options]); 
 * });
 *
 * Example:
 * 
 * <script type="text/javascript">
 * $(document).ready(function() {
 *   var options = { editLinkImagePath: "../images/edit.png",
 *					 editLinkHoverAttribute: "background-color",
 *					 editLinkHoverValue: "red",
 *					 animation: false,
 *					 tinymce: true
 *					};
 *   $.rapidEdit("ajax/saveContent.php", options); 
 * });
 * </script>
 *
 * <div class="header">
 *   This is a header.
 * </div>
 * <div class="main">
 * 
 *   <!-- Editable header -->
 *   <h1 class="editable">Main Content</h1>
 * 
 *   <!-- Editable paragraph -->
 *   <p class="editable">
 *     Lorum ipsum dolor sit amet, consectetuer adipiscing elit.
 *     <!-- Editable span -->  
 *     <span class="author editable">John Doe</span>
 *   </p>
 *
 *   <!-- Editable div which will have a green background
 *        when hovering over the edit-link (using MetaData plugin) -->
 *   <div class="editable { editLinkHoverValue: "green" }">
 *     Lorum ipsum dolor sit amet, consectetuer adipiscing elit.
 *   </div>
 *
 * </div>
 *
 * Data sent on save:
 *
 * @id - Contains the id of the edited element.
 * @class - Contains the classes of the edited element.
 * @content - Contains the textarea content.
 *
 * Example on received data with PHP (using setting saveType: "POST"):
 *
 * print_r($_POST);
 * //output
 * Array (
 * 			"id" => "header",
 *			"class" => "editable anotherClass",
 *			"content" => "Lorum ipsum dolor sit amet, consectetuer adipiscing elit."
 * )
 * 
 * Default settings (they can all be changed):
 *
 * rapidEditClass: 'editable',
 * saveTo: '',
 * saveType: 'POST',
 * editLinkImagePath: 'edit.png',
 * editLinkImageTitle: 'Edit',
 * editLinkClass: 'rapidEdit-link',
 * editLinkHoverAttribute: false,
 * editLinkHoverValue: false,
 * editLinkPosX: 'right',
 * editLinkPosY: 'top',
 * editLinkDistX: '0',
 * editLinkDistY: '0',
 * tinymce: false,
 * textareaMinWidth: '50',
 * textareaWidth: 'element',
 * textareaMinHeight: '50',
 * textareaHeight: 'element',
 * textareaClass: 'rapidEdit-textarea',
 * submitButtonClass: 'rapidEdit-submit',
 * submitButtonValue: 'Save',
 * cancelButtonClass: 'rapidEdit-cancel',
 * cancelButtonValue: 'Cancel',
 * setParentPositionRelative: true,
 * animation: true,
 * animationSpeed: 'fast'
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

(function($) {

	$.rapidEdit = function(saveTo, options) {
		var settings = $.extend({}, $.rapidEdit.defaults, options);
		settings.saveTo = saveTo;
		$.rapidEdit.settings = settings;
		
		return $("." + $.rapidEdit.settings.rapidEditClass).each(function() {
			$this = $(this);
			$.rapidEdit.attachEditLink($this);
		});
	};
	
	$.rapidEdit.bindClick = function(element) {
		var settings = $.rapidEdit.metadata(element);
		$(element).find("."+settings.editLinkClass).bind('click', function() {
			$("." + settings.editLinkClass).hide();
			$.rapidEdit.editElement(element);
		});
		if (settings.editLinkHoverAttribute != false && settings.editLinkHoverValue != false) {
			$(element).children("."+settings.editLinkClass).hover( function() {
				$(element).css(settings.editLinkHoverAttribute, settings.editLinkHoverValue);
			}, function() {
				$.rapidEdit.resetHover(element);
			});
		}
	};
	
	$.rapidEdit.bindSubmit = function(element) {
		var settings = $.rapidEdit.metadata(element);
		$(element).children("." + settings.submitButtonClass).bind('click', function() {
			if (settings.tinymce == true) {
				value = tinyMCE.get(settings.textareaClass).getContent();
			} else {
				value = $(element).children("textarea").val();
			}
			id = $(element).attr("id") ? $(element).attr("id") : null;
			classes = $(element).attr("class");
			$.ajax({
				url: settings.saveTo,
				type: settings.saveType,
				dataType: "json",
				data: "id=" + id + "&class=" + classes + "&content=" + escape(value),
				success: function(json) {
					$.rapidEdit.restoreElement(value, element);
				},
				error: function(error) {
					alert("Something went wrong. Save was unsuccessful. ("+error.status+": "+error.statusText+")");
				}
			});
			
		});
	};
	
	$.rapidEdit.bindCancel = function(oldContent, element) {
		var settings = $.rapidEdit.settings;
		$(element).children("." + settings.cancelButtonClass).bind('click', function() {
			$.rapidEdit.restoreElement(oldContent, element);
		});
	};
	
	$.rapidEdit.resetHover = function(element) {
		var settings = $.rapidEdit.settings;
		$(element).css(settings.editLinkHoverAttribute, "");
	};

	$.rapidEdit.attachEditLink = function(element) {
		var settings = $.rapidEdit.metadata(element);
		if (settings.setParentPositionRelative == true) {
			//To make sure the link will position correctly we set the current element position to relative
			$(element).css("position", "relative");
		}
		var editLink = '<div class="' + settings.editLinkClass + '" style="cursor: pointer; position: absolute; ' + settings.editLinkPosY + ': ' + settings.editLinkDistY + '; ' + settings.editLinkPosX + ': ' + settings.editLinkDistX + ';"><img src="' + settings.editLinkImagePath + '" alt="' + settings.editLinkImageTitle + '" title="' + settings.editLinkImageTitle + '" /></div>';
		$(element).append(editLink);
		$.rapidEdit.bindClick(element);
	};
	
	$.rapidEdit.editElement = function(element) {
		var settings = $.rapidEdit.metadata(element);
		$.rapidEdit.resetHover(element);
		$(element).find("." + settings.editLinkClass).remove();
		if (settings.textareaWidth == 'element') {
			var width = $(element).width();
		} else {
			var width = settings.textareaWidth;
		}
		if (settings.textareaHeight == 'element') {
			var height = $(element).height();
		} else {
			var height = settings.textareaHeight;
		}
		
		if (width < settings.textareaMinWidth) {
			width = settings.textareaMinWidth;
		}
		
		if (height < settings.textareaMinHeight) {
			height = settings.textareaMinHeight;
		}
		
		var oldContent = $(element).html();
		var textarea = '<textarea id="'+settings.textareaClass+'" name="'+settings.textareaClass+'" class="' + settings.textareaClass + '" style="width: ' + width + 'px; height: ' + height + 'px;">' + oldContent + '</textarea>';
		var submitButton = '<input type="submit" class="' + settings.submitButtonClass + '" value="' + settings.submitButtonValue +'" />';
		var cancelButton = '<input type="button" class="' + settings.cancelButtonClass + '" value="' + settings.cancelButtonValue + '" />';
		if (settings.animation == true) {
			$(element).slideUp(settings.animationSpeed, function() {
				$(element).html(textarea);
				$(element).append(submitButton);
				$(element).append(cancelButton);
				$.rapidEdit.bindSubmit(element);
				$.rapidEdit.bindCancel(oldContent, element);
				if (settings.tinymce == true) {
					tinyMCE.execCommand('mceAddControl', false, settings.textareaClass);
				}
				$(element).slideDown(settings.animationSpeed, function() {
					$(element).find("."+settings.textareaClass).css({"z-index": settings.zindex, "position": "relative"});
					$(element).find("."+settings.submitButtonClass).css({"z-index": settings.zindex, "position": "relative"});
					$(element).find("."+settings.cancelButtonClass).css({"z-index": settings.zindex, "position": "relative"});
				});
			});
		} else {
			$(element).html(textarea);
			$(element).append(submitButton);
			$(element).append(cancelButton);
			$.rapidEdit.bindSubmit(element);
			$.rapidEdit.bindCancel(oldContent, element);
		}
	};
	
	$.rapidEdit.restoreElement = function(content, element) {
		var settings = $.rapidEdit.metadata(element);
		if (settings.animation == true) {
			$(element).slideUp(settings.animationSpeed, function() {
				if (settings.tinymce == true) {
					tinyMCE.execCommand('mceFocus', false, settings.textareaClass);                    
					tinyMCE.execCommand('mceRemoveControl', false, settings.textareaClass);
				}
				$(element).html(content);
				$(element).slideDown(settings.animationSpeed, function() {
					$(element).find("." + settings.rapidEditClass).each( function () {
						$.rapidEdit.attachEditLink(this);
					});
					$.rapidEdit.attachEditLink(element);
					$("." + settings.editLinkClass).show();
				});
			});
		} else {
			$(element).html(content);
			$(element).find("." + settings.rapidEditClass).each( function () {
				$.rapidEdit.attachEditLink(this);
			});
			$.rapidEdit.attachEditLink(element);
			$("." + settings.editLinkClass).show();
		}
	};
	
	$.rapidEdit.metadata = function(element) {
		var settings = $.rapidEdit.settings;
		return $.metadata ? $.extend({}, settings, $(element).metadata()) : settings;
	};
	
	$.rapidEdit.settings = {};
	
	$.rapidEdit.defaults = {
		rapidEditClass: 'editable',
		saveTo: '',
		saveType: 'POST',
		editLinkImagePath: 'edit.png',
		editLinkImageTitle: 'Edit',
		editLinkClass: 'rapidEdit-link',
		editLinkHoverAttribute: false,
		editLinkHoverValue: false,
		editLinkPosX: 'right',
		editLinkPosY: 'top',
		editLinkDistX: '0',
		editLinkDistY: '0',
		tinymce: false,
		textareaMinWidth: '50',
		textareaWidth: 'element',
		textareaMinHeight: '50',
		textareaHeight: 'element',
		textareaClass: 'rapidEdit-textarea',
		submitButtonClass: 'rapidEdit-submit',
		submitButtonValue: 'Save',
		cancelButtonClass: 'rapidEdit-cancel',
		cancelButtonValue: 'Cancel',
		setParentPositionRelative: true,
		animation: true,
		animationSpeed: 'fast'
	};

})(jQuery);