/**
 * WYSIWYG - jQuery plugin 0.4
 *
 * Copyright (c) 2008 Juan M Martinez
 * http://plugins.jquery.com/project/jWYSIWYG
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * $Id: $
 */
(function($)
{
	$.fn.document = function()
	{
		var element = this[0];
		if (element.nodeName.toLowerCase() == 'iframe') 
			return element.contentWindow.document;
		else 
			return $(this);
	};
	$.fn.documentSelection = function()
	{
		var element = this[0];
		if (element.contentWindow.document.selection) 
			return element.contentWindow.document.selection.createRange().text;
		else 
			return element.contentWindow.getSelection().toString();
	};
	$.fn.wysiwyg = function(options)
	{
		if (arguments.length > 0 && arguments[0].constructor == String) 
		{
			var action = arguments[0].toString();
			var params = [];
			for (var i = 1; i < arguments.length; i++) 
				params[i - 1] = arguments[i];
			if (action in Wysiwyg) 
			{
				return this.each(function()
				{
					$.data(this, 'wysiwyg').designMode();
					Wysiwyg[action].apply(this, params);
				});
			} else 
				return this;
		}
		var controls = {};
		/**
		 * If the user set custom controls, we catch it, and merge with the
		 * defaults controls later.
		 */
		if (options && options.controls) 
		{
			var controls = options.controls;
			delete options.controls;
		}
		var options = $.extend(
		{
			html: '<' + '?xml version="1.0" encoding="UTF-8"?' + '><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">STYLE_SHEET</head><body style="font:.75em arial,verdana,sans-serif;background-color:#666;color:#fff;">INITIAL_CONTENT</body></html>',
			css: {},
			debug: false,
			autoSave: true,
			rmUnwantedBr: true,
			brIE: true,
			controls: {},
			messages: {}
		}, options);
		$.extend(options.messages, Wysiwyg.MSGS_EN);
		$.extend(options.controls, Wysiwyg.TOOLBAR);
		for (var control in controls) 
		{
			if (control in options.controls) 
				$.extend(options.controls[control], controls[control]);
			else 
				options.controls[control] = controls[control];
		}
		// not break the chain
		return this.each(function()
		{
			Wysiwyg(this, options);
		});
	};
	function Wysiwyg(element, options)
	{
		return this instanceof Wysiwyg ? this.init(element, options) : new Wysiwyg(element, options);
	}
	$.extend(Wysiwyg, 
	{
		insertImage: function(szURL, attributes)
		{
			var self = $.data(this, 'wysiwyg');
			if (self.constructor == Wysiwyg && szURL && szURL.length > 0) 
			{
				if (attributes) 
				{
					self.editorDoc.execCommand('insertImage', false, '#jwysiwyg#');
					var img = self.getElementByAttributeValue('img', 'src', '#jwysiwyg#');
					if (img) 
					{
						img.src = szURL;
						for (var attribute in attributes) 
						{
							img.setAttribute(attribute, attributes[attribute]);
						}
					}
				} else 
				{
					self.editorDoc.execCommand('insertImage', false, szURL);
				}
			}
		},
		createLink: function(szURL)
		{
			var self = $.data(this, 'wysiwyg');
			if (self.constructor == Wysiwyg && szURL && szURL.length > 0) 
			{
				var selection = $(self.editor).documentSelection();
				if (selection.length > 0) 
				{
					self.editorDoc.execCommand('unlink', false, []);
					self.editorDoc.execCommand('createLink', false, szURL);
				} else if (self.options.messages.nonSelection) 
					alert(self.options.messages.nonSelection);
			}
		},
		clear: function()
		{
			var self = $.data(this, 'wysiwyg');
			self.setContent('');
			self.saveContent();
		},
		MSGS_EN: 
		{
			nonSelection: 'Selecciona primero el texto que quieres enlazar'
		},
		TOOLBAR: 
		{
			bold: 
			{
				visible: true,
				tags: ['strong'],
				css: 
				{
					fontWeight: 'bold'
				},
				title: 'Negrita'
			},
			italic: 
			{
				visible: true,
				tags: ['em'],
				css: 
				{
					fontStyle: 'italic'
				},
				title: 'Cursiva'
			},
			strikeThrough: 
			{
				visible: false,
				css: 
				{
					textDecoration: 'line-through'
				},
				title: 'Tachado'
			},
			underline: 
			{
				visible: false,
				css: 
				{
					textDecoration: 'underline'
				},
				title: 'Subrayado'
			},
			separator00: 
			{
				visible: true,
				separator: true
			},
			subscript: 
			{
				visible: false,
				tags: ['sub'],
				title: 'Superindice'
			},
			superscript: 
			{
				visible: false,
				tags: ['sup'],
				title: 'Subindice'
			},
			separator01: 
			{
				visible: false,
				separator: true
			},
			insertOrderedList: 
			{
				visible: true,
				tags: ['ol'],
				title: 'Lista numerada'
			},
			insertUnorderedList: 
			{
				visible: true,
				tags: ['ul'],
				title: 'Lista'
			},
			separator02: 
			{
				separator: true
			},
			createLink: 
			{
				visible: true,
				exec: function()
				{
					var selection = $(this.editor).documentSelection();
					if (selection.length > 0) 
					{
						if ($.browser.msie) 
							this.editorDoc.execCommand('createLink', true, null);
						else 
						{
							var szURL = prompt('Dirección web', 'http://');
							if (szURL && szURL.length > 0) 
							{
								this.editorDoc.execCommand('unlink', false, []);
								this.editorDoc.execCommand('createLink', false, szURL);
							}
						}
					} else if (this.options.messages.nonSelection) 
						alert(this.options.messages.nonSelection);
				},
				tags: ['a'],
				title: 'Insertar enlace'
			},
			insertImage: 
			{
				visible: false,
				exec: function()
				{
					if ($.browser.msie) 
						this.editorDoc.execCommand('insertImage', true, null);
					else 
					{
						var szURL = prompt('URL', 'http://');
						if (szURL && szURL.length > 0) 
							this.editorDoc.execCommand('insertImage', false, szURL);
					}
				},
				tags: ['img'],
				title: 'Insertar imagen'
			},
			separator03: 
			{
				separator: true
			},
			h1mozilla: 
			{
				visible: false && $.browser.mozilla,
				className: 'h1',
				command: 'heading',
				arguments: ['h1'],
				tags: ['h1'],
				title: 'Titulo nivel 1'
			},
			h2mozilla: 
			{
				visible: false && $.browser.mozilla,
				className: 'h2',
				command: 'heading',
				arguments: ['h2'],
				tags: ['h2'],
				title: 'Titulo nivel 2'
			},
			h3mozilla: 
			{
				visible: false && $.browser.mozilla,
				className: 'h3',
				command: 'heading',
				arguments: ['h3'],
				tags: ['h3'],
				title: 'Titulo nivel 3'
			},
			h1: 
			{
				visible: false && !($.browser.mozilla),
				className: 'h1',
				command: 'formatBlock',
				arguments: ['Heading 1'],
				tags: ['h1'],
				title: 'Titulo nivel 1'
			},
			h2: 
			{
				visible: false && !($.browser.mozilla),
				className: 'h2',
				command: 'formatBlock',
				arguments: ['Heading 2'],
				tags: ['h2'],
				title: 'Titulo nivel 2'
			},
			h3: 
			{
				visible: false && !($.browser.mozilla),
				className: 'h3',
				command: 'formatBlock',
				arguments: ['Heading 3'],
				tags: ['h3'],
				title: 'Titulo nivel 3'
			},
			html: 
			{
				visible: false,
				exec: function()
				{
					if (this.viewHTML) 
					{
						this.setContent($(this.original).val());
						$(this.original).hide();
					} else 
					{
						this.saveContent();
						$(this.original).show();
					}
					this.viewHTML = !(this.viewHTML);
				},
				title: 'Ver codigo'
			},
			removeFormat: 
			{
				visible: true,
				exec: function()
				{
					this.editorDoc.execCommand('removeFormat', false, []);
					this.editorDoc.execCommand('unlink', false, []);
				},
				title: 'Quitar formato'
			}
		}
	});
	$.extend(Wysiwyg.prototype, 
	{
		original: null,
		options: {},
		element: null,
		editor: null,
		init: function(element, options)
		{
			var self = this;
			this.editor = element;
			this.options = options ||
			{};
			$.data(element, 'wysiwyg', this);
			var newX = element.width || element.clientWidth;
			var newY = element.height || element.clientHeight;
			if (element.nodeName.toLowerCase() == 'textarea') 
			{
				this.original = element;
				if (newX == 0 && element.cols) 
				{
					newX = (element.cols * 8) + 21;
				}
				if (newY == 0 && element.rows) 
				{
					newY = (element.rows * 16) + 16;
				}
				var editor = this.editor = $('<iframe></iframe>').css(
				{
					minHeight: '150px'
				}).attr('id', $(element).attr('id') + 'IFrame');
				if ($.browser.msie) 
				{
					this.editor.css(
					{
						height: '150px'
					});
				}
			}
			var panel = this.panel = $('<ul></ul>').addClass('panel');
			this.appendControls();
			this.element = $('<div></div>').addClass('wysiwyg').append(panel).append(editor);
			$(element).hide().before(this.element);
			this.viewHTML = false;
			this.initialHeight = newY - 8;
			this.initialContent = $(element).text();
			this.initFrame();
			if (this.initialContent.length == 0) 
				this.setContent('');
			if (this.options.autoSave) 
				$('form').submit(function()
				{
					self.saveContent();
				});
		},
		initFrame: function()
		{
			var self = this;
			var style = '';
			/**
			 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=14
			 */
			if (this.options.css && this.options.css.constructor == String) 
				style = '<link rel="stylesheet" type="text/css" media="screen" href="' + this.options.css + '" />';
			this.editorDoc = $(this.editor).document();
			this.editorDoc_designMode = false;
			try 
			{
				this.editorDoc.designMode = 'on';
				this.editorDoc_designMode = true;
			} catch (e) 
			{
				$(this.editorDoc).focus(function()
				{
					self.designMode();
				});
			}
			this.editorDoc.open();
			this.editorDoc.write(this.options.html.replace(/INITIAL_CONTENT/, this.initialContent).replace(/STYLE_SHEET/, style));
			this.editorDoc.close();
			this.editorDoc.contentEditable = 'true';
			if ($.browser.msie) 
			{
				/**
				 * Remove the horrible border it has on IE.
				 */
				setTimeout(function()
				{
					$(self.editorDoc.body).css('border', 'none');
				}, 0);
			}
			$(this.editorDoc).click(function(event)
			{
				self.checkTargets(event.target ? event.target : event.srcElement);
			});
			/**
			 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
			 */
			$(this.original).focus(function()
			{
				$(self.editorDoc.body).focus();
			});
			if (this.options.autoSave) 
			{
				/**
				 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=11
				 */
				$(this.editorDoc).keydown(function()
				{
					self.saveContent();
				}).mousedown(function()
				{
					self.saveContent();
				});
			}
			if (this.options.css) 
			{
				setTimeout(function()
				{
					if (self.options.css.constructor == String) 
					{
					} else 
						$(self.editorDoc).find('body').css(self.options.css);
				}, 0);
			}
			$(this.editorDoc).keydown(function(event)
			{
				if ($.browser.msie && self.options.brIE && event.keyCode == 13) 
				{
					var rng = self.getRange();
					rng.pasteHTML('<br />');
					rng.collapse(false);
					rng.select();
					return false;
				}
			});
		},
		designMode: function()
		{
			if (!(this.editorDoc_designMode)) 
			{
				try 
				{
					this.editorDoc.designMode = 'on';
					this.editorDoc_designMode = true;
				} catch (e) 
				{
				}
			}
		},
		getSelection: function()
		{
			return (window.getSelection) ? window.getSelection() : document.selection;
		},
		getRange: function()
		{
			var selection = this.getSelection();
			if (!(selection)) 
				return null;
			return (selection.rangeCount > 0) ? selection.getRangeAt(0) : selection.createRange();
		},
		getContent: function()
		{
			return $($(this.editor).document()).find('body').html();
		},
		setContent: function(newContent)
		{
			$($(this.editor).document()).find('body').html(newContent);
		},
		saveContent: function()
		{
			if (this.original) 
			{
				var content = this.getContent();
				if (this.options.rmUnwantedBr) 
					content = (content.substr(-4) == '<br>') ? content.substr(0, content.length - 4) : content;
				$(this.original).val(content);
			}
		},
		appendMenu: function(cmd, args, className, fn, title)
		{
			var self = this;
			var args = args || [];
			$('<li title="' + title + '"></li>').append($('<a><!-- --></a>').addClass(className || cmd)).mousedown(function()
			{
				if (fn) 
					fn.apply(self);
				else 
					self.editorDoc.execCommand(cmd, false, args);
				if (self.options.autoSave) 
					self.saveContent();
			}).appendTo(this.panel);
		},
		appendMenuSeparator: function()
		{
			$('<li class="separator"></li>').appendTo(this.panel);
		},
		appendControls: function()
		{
			for (var name in this.options.controls) 
			{
				var control = this.options.controls[name];
				if (control.separator) 
				{
					if (control.visible !== false) 
						this.appendMenuSeparator();
				} else if (control.visible) 
				{
					this.appendMenu(control.command || name, control.arguments || [], control.className || control.command || name || 'empty', control.exec, control.title);
				}
			}
		},
		checkTargets: function(element)
		{
			for (var name in this.options.controls) 
			{
				var control = this.options.controls[name];
				var className = control.className || control.command || name || 'empty';
				$('.' + className, this.panel).removeClass('active');
				if (control.tags) 
				{
					var elm = element;
					do 
					{
						if (elm.nodeType != 1) 
							break;
						if ($.inArray(elm.tagName.toLowerCase(), control.tags) != -1) 
							$('.' + className, this.panel).addClass('active');
					} while (elm = elm.parentNode);
				}
				if (control.css) 
				{
					var elm = $(element);
					do 
					{
						if (elm[0].nodeType != 1) 
							break;
						for (var cssProperty in control.css) 
							if (elm.css(cssProperty).toString().toLowerCase() == control.css[cssProperty]) 
								$('.' + className, this.panel).addClass('active');
					} while (elm = elm.parent());
				}
			}
		},
		getElementByAttributeValue: function(tagName, attributeName, attributeValue)
		{
			var elements = this.editorDoc.getElementsByTagName(tagName);
			for (var i = 0; i < elements.length; i++) 
			{
				var value = elements[i].getAttribute(attributeName);
				if ($.browser.msie) 
				{
					/** IE add full path, so I check by the last chars. */
					value = value.substr(value.length - attributeValue.length);
				}
				if (value == attributeValue) 
					return elements[i];
			}
			return false;
		}
	});
})(jQuery);
window.onload = function()
{
	$('textarea').wysiwyg();
}
