var editingObject = false;

new function($) 
{ 
	$.fn.setCursorPosition = function(pos) 
	{ 
		if ($(this).get(0).setSelectionRange) 
		{ 	
			$(this).get(0).setSelectionRange(pos, pos); 	
		} 
		else if ($(this).get(0).createTextRange) 
		{ 
			var range = $(this).get(0).createTextRange(); 
			range.collapse(true); range.moveEnd("character", pos); 
			range.moveStart("character", pos); range.select(); 
		} 
	} 
} (jQuery);

/* This  version use a live event on the editable element, so it can be removed and readded 
to the page between edits. The element must have an id for this to work correctly.*/

(function( $ ) {

$.fn.editInPlace = function(options) {
	
	if (options == 'getObjectText') {
		//return htmlToText(
		var tmp = arguments[1];
		return htmlToText.apply(this, [tmp]);

	}
	
	//Set the default values, use comma to separate the settings, example:
	var defaults = {
		html : false, //indicates whether HTML is parsed
		multiline: false, //when true a textarea is used
		minheight: '40', //the minimum height of a dynamic textbox
		maxheight: '400', //the maximum height in pixels of a resizeable text box.
		rows: null, //the number of rows in the textarea. When this is null the textarea will resize itself.
		cols: null, //the width of the textbox (this will only be used
		maxlength : null, //the maximum input length. 
		classPrefix : 'eip', //a prefix added to all class names within the control
		startCallBack: function(obj){}, //Called when the control is rendered
		cancelCallBack: function(obj){}, //Called when the edit is canceled
		saveCallBack: function(obj, text, fromKeypress){}, //Called when the edit is saved
		
		pEnclose: true, //Indicates wheteher the contens should be enclosed in p tags
		//Specifies tags and attributes allowed in the generated html
		//all other tags will be replacewd with &lt;tagName&gt; 
		//attributes not specifically allowed for an allowed tag will be removed
		allowedHTMLTags: [
			['br'],
			['p', 'style'],
			['strong'],
			['a','href', 'style', 'target', 'class', 'rel'],
			['i'],
			['em'],
			['u'],
			['b'],
			['strong'],
			['u'],
			['ul', 'style'],
			['ol', 'style'],
			['li', 'style'],
			['span', 'style', 'class'],
			['div', 'style', 'class'],
			['sub'],
			['sup'],
			['blockquote', 'style', 'class'],
			['center'],
			['strike'],
			['s'],
			['h1',  'style'],
			['h2',  'style'],
			['h3',  'style'],
			['h4',  'style'],
			['h5',  'style'],
			['h6',  'style'],
			['font', 'color', 'face', 'style'],
			['iframe', 'width', 'height', 'src', 'style', 'class', 'scrolling', 'title'],
			['img','src', 'style', 'width', 'height', 'class', 'id','alt']

			
			],
		uploadImageFunction: function(){}, 
		uploadVideoFunction: function(){}, 
		createCropper: function(element, imageId){}, //function for handling cropping
		destroyCropper: function(element, imageId){}, //function that handles image resizing
		alignment: true, 
		disAllowedHTMLTags: [], //Allows the user to remove tags from the default list
														//without having to pass the allowed tags array
	
		preferredTags: [
			['strong', 'b', 'span .*? style="font-weight: bold;"'],
			['em', 'i', 'span .* style="font-style: italic;"'],
			['strike', 's' , "span .*? style=\"text-decoration: line-through;\""],
			['u', 'span .*? style="text-decoration: underline;"']
			], 
		outsideClick: 'save', //what to do wihrn the user clicks outside the box: save or cancel; any other value does nothing
		outsideClickPrompt: function() {},
		//defaultMarkUp: '', //The text to display when the editable element has no content. REQUIRED
		wysiwyg: true, //whenther or not to use a wysiwyg editor
		customClasses: [], //custom classes to add to the wysiwyg menu bar
		htmlTemplate: "",
		addBlankTarget: true,//if true all generated links will have target="_blank"
		autoResize: false,
		container: $('body'),
		initializeEvent: 'click', //the event that triggers the edit in place
		startingText: null, //if set use this text instead of teh elementtext.
		wysiwygAllowImages: true,
		wysiwygAllowVideo: true,
		wysiwygAllowTables: true
	};
	
	
	
	options =  $.extend(defaults, options);
	
	
	//remove the disAllowedHTMLTags from allowedHTMLTags
	for (var i=0;i< options.disAllowedHTMLTags.length;i++) {
		for (var j=0;j< options.allowedHTMLTags.length;j++) {
			if (options.allowedHTMLTags[j][0]== options.disAllowedHTMLTags[i]) {
				options.allowedHTMLTags.splice(j, 1);
			}
		}
	}
	
	//The default markup must be specified.
	if (!options.defaultMarkUp) {
		alert("Default value must be specified.");
		return;
	}
	
	/***************Methods that don't depend on the  calling element ***********************************/

	//Returns true if the tag is in the list of allowedtags.
	function tagIsOk(tagName) {
		for (var i=0;i< options.allowedHTMLTags.length;i++) {
			if (options.allowedHTMLTags[i][0]==tagName.toLowerCase()) {
				return true;
			}
		}
		return false;
	}
	
	//Generates a regular expression that matches the tagNames specified in
	//allowedTags.
	function allowedTagRegex() {
		var exp="";
		for (var i=0;i< options.allowedHTMLTags.length;i++) {
			if (options.allowedHTMLTags[i]) {
				if (exp !== "") { exp += "|"; }
				exp += "(?:" + options.allowedHTMLTags[i][0] + ")";
			}
		}
		return exp;
	}	

	//Returns true if the given attrName is allowed for tagName. 
	function attrIsOk(tagName,attrName) {
		for (var i=0;i<options.allowedHTMLTags.length;i++) {
			if (options.allowedHTMLTags[i][0] == tagName.toLowerCase()) {
				for (var j=1;j<options.allowedHTMLTags[i].length;j++) {
					if (options.allowedHTMLTags[i][j]==attrName.toLowerCase()) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	//Remove line breaks from the beginning of str.
	function trimBreaks(str) {
		return str.replace(/^[\r\n]*/g,'');
	}

	//Replace < with &lt; and  > with &gt; within str.
	function escapeTags(str) {

		//	function ampersandReplace(strMatchingString, rest) {
		//	if (rest.match(/(#\d+;)|[a-z]+;/i)) {
		//		return strMatchingString;
		//	} else {
		//		return "&amp;" + rest; 
		//	}
		//	}
		//escape all html tags
		str = str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
		//	str = str.replace(/&([^\s])\s/, ampersandReplace);
		return str;	
	}

	//remove the weird tags that word generates.
	function sanitizeWordHTML(str) {
		
		//put everything on one line for simplicity.
		str = str.replace(/\r\n|\n|\n\r/g, ' ');
		//remove everything wrapped in <!--[if ]> <![endif]--> this should
		//remove the remainder of what word creates. extra elements are removed
		//from the dom after the paste, but this is invisible to the dom.
		str = str.replace(/&lt;!\-\-\[if.*&lt;!\[endif\]\-\-&gt;/gi, '');
		
		/* //str = str.replace(/&lt;w.*\/&gt;/g,"");
		str = str.replace(/m:val=".*"/g, "");
		str = str.replace(/&lt;m:[^&]*\/&gt;/g,"");		
		str = str.replace(/&lt;m:[^&]*\/&gt;/g,"");		
		str = str.replace(/&lt;m:[\[&\w;!\-\s\*\/@{:\d}\.,"%]*&gt;[&\w;!\-\s\*\/@{:\d}\.,"%]*&lt;\/w:[\w:]*&gt;/g, "");
		str = str.replace(/&lt;w:[\w\s="]*\/&gt;/g,"");
		str = str.replace(/&lt;link\b[\s\w\d:\/%\._=\-"]*&gt;/g, "");
		str = str.replace(/&lt;w:[\w\s="]*&gt;[\w\-\s="]*&lt;\/w:[\w\-\s="]*&gt;/g, "");
		str = str.replace(/&lt;meta\b[\s\d\w\.;\/=\-"]*&gt;/g, "");
		//str =str.replace(/&lt;!\-\-\b.*\-\-&gt;/g, "");
		str = str.replace(/&lt;style&gt;[&\w;!\-\s\*\/@{:\d}\.,"%]*&lt;\/style&gt;/gi, "");
		str = str.replace(/&lt;!(\-\-)?\[[\w!\s]+\](\-\-)?&gt;/g, "");
		str = str.replace(/&lt;w:[\w\s="]*&gt;&lt;\/w&gt;/g,"");
		str = str.replace(/&lt;xml&gt;.*&lt;\/xml&gt;/g, "");
		str = str.replace(/&lt;(\/)?o:p&gt;/g, ""); 
		str = str.replace(/&lt;\?xml:[^&]+&gt;/g, "");
		str = str.replace(/\&lt;!\-\-.*\-\-&gt;/g, "");
		str = str.replace(/&lt;\\w&gt;/g, ""); */
		return str;
	}
	
	//cnovert the HTML string str to acceptable HTML by escaping
	//all taggs that are not explicitly allowed and eliminating attributes that are not allowed. 
	function textToHTML(str) {

		if (options.html) {
			//replacement method for the allowed tag matchng regexp
			//replaces the escaped tag with an actual tag with all specified allowed attributes.
			function tagReplace(strMatchingString, tag, attributes) {
				var allowedAttributes ="";
				
				//local function for replacing attributes.
				function attributeReplace(strMatchingString, attribute, value) {
		
					if (attrIsOk(tag, attribute)) {
						
						value =value.replace(/\s+/, ' ');
						if (!value.match(/^\s*$/)) {
							return " " + attribute + "=\"" + value + "\"";
						}
					}
					return "";
				}
				if (attributes) {
					
					//allowedAttributes = attributes.replace(/(\w+)=\"([\s\w\d\.%\-:;'\(\)]+)\"/g, attributeReplace);
					allowedAttributes = attributes.replace(/(\w+)=\"([^"]*)\"/g, attributeReplace);
					
				}
			
				if (options.addBlankTarget && tag.toLowerCase() == "a") {
					if (allowedAttributes.indexOf("target") == -1) {
						allowedAttributes += " target=\"_blank\"";
					}
				}
				
				//close image tags
				if (tag.toLowerCase() == "img") {
					return "<" +tag.toLowerCase() + " " + allowedAttributes +"/>";
				}
				
				return "<" +tag.toLowerCase() + " " + allowedAttributes +">";
				
			}
	
			//escape all tags to begin with.
			str = escapeTags(str);
			str = sanitizeWordHTML(str);

	
		
			//unescape the allowed tags
			//str = str.replace(new RegExp("&lt;(\/?(?:" + allowedTagRegex() +"))((?:\\b.*?)|\/)&gt;", "gi"), tagReplace);
			str = str.replace(/&quot;/g, "ANDquot;");
			str = str.replace(/&amp;/g, "ANDamp;");
			//))((?:\\b[\.\"\/\\w\\d\\?\\s;:\\-%=#'\\(\\)]+?)|\/
			str = str.replace(new RegExp("&lt;(\/?(?:" + allowedTagRegex() +"))(?:\\s([^&]*))?&gt;", "gi"), tagReplace);
			//str = str.replace(new RegExp("&lt;((?:" + allowedTagRegex() +"))&gt;", "gi"), tagReplace);
			
			str = str.replace( /ANDquot;/g,"&quot;");
			str = str.replace( /ANDamp;/g,"&amp;");
			//remove linebreaks before block elements
		
			str = str.replace(/(?:<br \/>)+\s*(<\/?((?:ul)|(?:li)|(?:p)(?:div)>))/gi,"$1");
			
			//remove trailing line breaks.
			str = str.replace(/(<br\s*\/>)+$/i, "");
				str = str.replace(/<br\s*>/g, "<br />");
			
		} else {
			//str = str.replace(/</g, "&lt;").replace(/>/g, "&gt;")
			str = str.replace( /&quot;/g,"\"");
			str = str.replace( /&amp;/g,"&");
			//str = str.replace(/\n/g,'<br />'); //turn single carriage returns into <br /> tags
		}
	
		
	
		//remove any leftover 'invisible' characters inserted by the html editor
		str = str.replace(/\uFEFF/g, '');
	
		return str;
	}
	
	//Succeds when the string contains only whitespace.
	function isEmpty(str) {
		str =str.toLowerCase();		
		return ( str === '' ||  /^(\s|(\xA0)|(\r*\n)|(<br\s*\/*>)|(<\/?p>)|(&nbsp;))*$/g.test(str));
	}
		
	//return the HTML contained in the srcObject  sanitised correcly
	//for the current edit mode.
	function htmlToText(srcObject) {
		var text ='';
		
		//in plain text mode remove all html tags and unescape any
		//html escaped characters
		if (!options.html) {
			text = srcObject.html();
			if (!text) { text =''}
			text = text.replace(/<br\s*\/*>/gi,"\n")
				//.replace(/<[^>]*?>/g, "") //this is plain text editing, ther should be no html tags
				.replace (/&lt;/g, "<")
				.replace (/&gt;/g, ">")
				.replace (/&amp;/g, "&");
			return $.trim(text);
			
		//wysiwyg mode can deal with the raw html
		} else if (options.wysiwyg) {
			return srcObject.html();
		}

		//in html (non wysiwyg) mode make a few substitutions for readability.
		srcObject.contents().each(function() {			
			if (this.nodeType == 3) {
				text += isEmpty(trimBreaks(this.nodeValue)) ? '' : trimBreaks(this.nodeValue);
			} else if (this.nodeType == 1) {
				if (tagIsOk(this.tagName)) {
					switch(this.nodeName.toLowerCase()) {
						case 'br':	//turn <br />s into carriage returns
							text += '\n';
							break;
						case 'p':	//turn <p>s into surrounding carriage returns
							text += '\n' + htmlToText($(this)) + '\n';
							break;
						default:	//keep all other tags intact, along with allowable attributes
							var openTag = '<' + this.tagName.toLowerCase();
							for (var j=0;j<this.attributes.length;j++) {
								if (attrIsOk(this.tagName,this.attributes[j].name)) {
									openTag += ' ' + this.attributes[j].name + '="' + this.attributes[j].value + '"';
								}
							}
							openTag += '>';
							var closeTag = '</' + this.tagName.toLowerCase() + '>';
							text += openTag + htmlToText($(this)) + closeTag;
							break;
					}
				} else {
					text += htmlToText($(this));
				}
			}
		});
	
		//add linebreak before block elemnts for better readability.
		text = text.replace(/\n*((?:<div>)|(?:<ul>)|(?:<ol>)|(?:<li>))/g, "\n$1");
		return text;
	}	
	
	//generate a random string, used for generating unique ids for elements created by the editor.
	function randomString() {
		var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
		var string_length = 8;
		var randomstring = '';
		for (var i=0; i<string_length; i++) {
			var rnum = Math.floor(Math.random() * chars.length);
			randomstring += chars.substring(rnum,rnum+1);
		}
		return randomstring;
	}
	
	return this.each(function() {
		
		var obj = $(this);
		var objectId =  $(this).attr('id');
		var originalContents = "";
		var idString = objectId;
		var altPressed = false;
	
	
		if (idString === '') {
			alert("Edit in place object must have id set!");
			return false;
			//idString = randomString();
		}
	
		 //Insert the defualt content to empty elements.
	
		if (isEmpty(obj.text())) {
			obj.html(options.defaultMarkUp);
		}

		//create a twin of the textbox, whose height can be more easily measured. This element is used to
		//allow the textbox to grow and shrink as the user types.
		function createTwin() {
			var twin;
			var textArea =  $('#editObj' + idString);   	
			var mimics = [
				'paddingTop',
				'paddingRight',
				'paddingBottom',
				'paddingLeft',
				'fontSize',
				'lineHeight',
				'fontFamily',
				'width',
				'fontWeight'];
			twin = $('<div />');
			twin.css({'position': 'absolute', 'display' : 'none'});
			twin.attr('id', 'twin-' + idString);  
			for (var i=0; i<mimics.length; i++) {
					twin.css(mimics[i],textArea.css(mimics[i]));
			}
			return twin;
		}
	
		//Resize the textarea based on its content (use the twin's height as a guide)
		function resizeTextArea(textarea) {
			var twin = $('#twin-' + idString);   	        
			twin.html(escapeTags(textarea.val()).replace(/\n/g,'<br />'));
			if (options.maxheight && twin.height() + 20 >= options.maxheight) {
				textarea.height(options.maxheight);
				textarea.css('overflow', 'auto'); 
					textarea.scrollTop = textarea.scrollHeight;
			   
			} else {
				textarea.css('overflow', 'hidden');        
				textarea.height(twin.height() +20);	
			}
		}
		
		function handleTextAreaKeyDown(event) {
			if (event.keyCode == 18) {
				altPressed= true;
			}
		}
		//handle the keyup event. This will resize the textarea as needed and
		//check the textlength against the max length.
		function handleTextAreaKeyUp(textarea,event) {
			if (options.multiline  && !options.rows && options.autoResize){
				resizeTextArea(textarea);
			}
			if (options.maxlength) {
				if(textarea.val().length > options.maxlength) {
					textarea.val(textarea.val().substr(0, options.maxlength));
				}
			}
			if (event.keyCode == ENTER && altPressed) {
				saveChanges(event, true);
			}
			if (event.keyCode == ALT) {
				altPressed = false;
			}
			
		}
		
		//Event that fires when the user clicks outside of the edit control/
		function handleOutsideClick(event) {
			
			//cancel this event if any dialog is open
			var cancelEvent =false;
			$(".ui-dialog-content").each(function() {
				if ($(this).dialog('isOpen')) {
					cancelEvent = true;
					return false;
				}
			});
			
			if (cancelEvent) {
				return;
			}
			event.stopImmediatePropagation();
			var e = event ? event  : window.event;
			//if the element clicked on is a descendent of the editable element
			//then do nothing.
			if ($(e.target) == obj) {
				return;
			}
			
			//the image control doesnt count
			if ($(e.target).parents().andSelf().filter(".imageControl").length) {
				return;
			}
			
			if (e.target.nodeName == "OBJECT") {
				return;
			}
			
			//check that the clicked element has no parents within the edit control.
			var parents = $(e.target).parents();
			
			//orphans don't count
			if (parents.filter("body").length == 0) { return; }
			for (var i=0; i< parents.length; i++) {
				if ($(parents[i]).hasClass(options.classPrefix + "_container") || $(parents[i]).hasClass("ui-dropdownchecklist-dropcontainer") ) {
					return;
				}
			
				
			}
			
			
			switch (options.outsideClick) {
				case 'save':			
					saveChanges(e);
					break;
				case 'cancel':
					cancelChanges(e);
					break;
				case 'prompt':
					options.outsideClickPrompt(
						function () {
							saveChanges(e);
						},
						function() {
							cancelChanges(e);
						}
					);
					break;
			}
			return false;
		}
	
		//handle the escape keypress
		function handleEscape(e) {
				
				var event = e ? e : window.event;
				var code = (event.keyCode ? event.keyCode : event.which);
				if (code == 27) {
					e.stopPropagation();
					cancelChanges(event);
				}
		}		
	
		//clean things up when the user leaves editmode/
		function cleanUp() {
			editingObject = false;
			//remove the editmode class
			$("#" + idString).removeClass( options.classPrefix + "_editMode");
			$("#" + idString).css('display', '');
			//remove the edit in place container.
			$('#eipContainer-' + idString).remove();
			
			//unbind the global events.
			$(document).unbind('click', handleOutsideClick);
		//	$(document).unbind('keydown.eip', handleEscape);
			//clear the selection
			if (!$.browser.msie) {
				window.getSelection().removeAllRanges();
			} else {
				document.selection.clear();
			}
			if (options.wysiwyg) {
				
			}
		}
		
		//remove any tag that is not a <BR> tag and has no children.
		//the wysiwyg editor tends to make empty tags unnesting
		//elements, so this cleans the markup.
		function removeEmptyTags(el) {
			var allowedEmptyTags = ['br', 'iframe'];
		
			el.children().each(function() {
				if ( $.inArray(this.tagName.toLowerCase(), allowedEmptyTags) == -1 &&  $(this).text() === "") {
					$(this).remove();
				} else {
					removeEmptyTags($(this));
				}
			
			});
		}
	
		//save the chanes to the original element and call the save callback.
		function saveChanges(event,fromKeypress) {
			
			event.stopPropagation();
			if (options.wysiwyg) {
				$('#editObj' +idString).wysiwyg('saveContent');
			}
			var text = '';
			
			if ($('#editObj' + idString).length) {
				var text = textToHTML($('#editObj' + idString).val());
		
				
				//special case for when the text is only an image.
				if (options.html && (text.indexOf("<img") == -1) &&
					($("<div/>").append(text).text() == "" || $("<div/>").append(text).html() == $("<div/>").append(options.htmlTemplate).html())) {
					text = options.defaultMarkUp;
				}
				$("#" + idString).empty();
				
				$("#" + idString).append(text.replace(/\n/g,'<br />'));
				
			}
			options.saveCallBack($("#" + idString), text, originalContents, fromKeypress);
			//removeEmptyTags(obj);
			cleanUp();
			
		
		}
		
		//revert the element to its original value and call the cancel callback.
		function cancelChanges(event) {
			if (options.wysiwyg) {
				$('#editObj' +idString).wysiwyg('cleanUp');
			}
			event.stopPropagation();
			$("#" + idString).html(originalContents);
			cleanUp();
			options.cancelCallBack($("#" + idString));
		}
		
		//When the user presses enter in the single line mode the text should be
		//saved and editor closed.
		function handleEnter(e) {
				
				var event = e ? e : window.event;
				var code = (event.keyCode ? event.keyCode : event.which);
				if (code == ENTER) 	{
					e.stopPropagation();
					saveChanges(event, true);
					
				}
		}

		//make a link from the selected text. (not used)
		/*function makeLinkFromSelection(event) {
			event.stopPropagation();
			var txtarea = document.getElementById('editObj' + idString);
			var selection = getSelectedText(txtarea);
			
			//if no text is slected, notift the user
			if (selection.text.length<1) {
				alert('Please select some text to turn into a link');
				//showMessage($('#dialogBox-' + idString),'Please select some text to turn into a link.');
				return false;
			}
		
			//otherwise prompt the user to enter the URL, and wrap teh text.
			showPrompt(txtarea, 
				$('#dialogBox-' + idString),
				"Enter the destination URL to make a link out of \""+escapeTags(selection.text)+"\":",
				"http://",
				 selection,
				 "Enter Link location"); 
			return;
		}*/

		//create a button control.
		function createButton(text, classSuffix, clickEvent) {
			var button = $("<a />")
				.attr('title',text)
				.attr('id', classSuffix + '-' + idString)
				.attr('class', options.classPrefix + "_" + classSuffix)
				.click(clickEvent);
			return button;
		
		}
		
		//greate the save and cancel buttons.
		function createButtons() {
			var buttonBox = (options.multiline) ? $("<div />") : $("<span />");
			buttonBox.attr('id', 'eip_buttons' + idString)
				.attr('class', options.classPrefix + "_buttons");
				//.css("min-width", "120px"); //min-width so the buttons always apper side by side.
				//make link button is no longer used.
			/*		if (options.html && !options.wysiwyg) {
				buttonBox.append(
					createButton(
						"Make Link From Selection", 
						"makeLinkButton", 
						makeLinkFromSelection));
			} */
			buttonBox.append(createButton("Save", "saveButton", saveChanges))
				.append(createButton("Cancel", "cancelButton", cancelChanges));
			
			return buttonBox;
		}
		
		//Create the textnode and initialize its content:
			//a textbox for single line editing
			//a textarea for multiline
			//an editable element for wysiwyg
		function createTextNode() {
			obj = $("#" + idString);
			var inputField;
			if (options.multiline || options.wysiwyg) {
				inputField = $("<textarea />");
				if (!options.rows)  {
					var textboxHeight = obj.height() < options.minheight ? options.minheight : obj.height();
					//inputField.css({ 'height': textboxHeight, 'overflow':'hidden' });
					//inputField.css({ 'overflow':'hidden' });
				
				} else {
					inputField.attr('rows', options.rows)
						.attr('cols', options.cols);
				}
				inputField.keydown(function(event) { handleTextAreaKeyDown(event); });
				inputField.keyup(function(event) { handleTextAreaKeyUp($(this), event); });
				if (options.autoResize) {
					inputField.focus(function() {  resizeTextArea($(this)); });
				}
				
			} else {
					inputField = $("<input class=\"" + options.classPrefix + "_textbox\ " + $(obj).attr("class") +"\" type=\"text\" />");
					inputField.bind('keyup', handleEnter);
				if (options.maxlength) {
					inputField.attr('maxlength',options.maxlength); 
				}
			}
		
			inputField.attr('id' ,'editObj' + idString)
				.addClass(options.classPrefix + "_editObj")
				.val(options.startingText == null? htmlToText(obj) : options.startingText)
				.bind('keydown', handleEscape);
			
			return $("<div />").addClass(options.classPrefix + "_editObjWrapper").append(inputField);
		}
		
		//NOT USED
		//create a div to hold a dialogbox or prompt.
		/*function createDialog() {
			var dialog = $("<div></div>")
				.attr('id', 'dialogBox-' + idString)
				.attr('class', options.classPrefix + "_dialogBox")
				.css('display', 'none');
			return dialog;
		}*/	
		
		//Create teh edit in place control and all its elements.
		function createEipControl() {
	
			var id = idString;
			var container = $("<div></div>")
				.attr('id','eipContainer-' + id)
				.attr('class', options.classPrefix + "_container")
				.append(createTextNode())
				.append(createButtons());
				
			if (options.multiline) {
				container.addClass(options.classPrefix + "_multiline");
			}
			
			return container;
		}
	
		//detrmines wheter or not the element can contain block level elements.
		function isInlineOnly() {
			obj = $("#" + idString);
			switch (obj.get(0).tagName.toLowerCase()) {
				case 'div':
				case 'blockquote':
				case 'body':
					return false;
				//the editor is contained in a div after the element we want to edit. So making
				//these nodes editable will break the DOM tree,
				case 'li':
				case 'th':
				case 'td':
					throw "Elements of type " + obj.get(0).tagName.toLowerCase() + " cannot be made editable.";
				default:
					return true;
			}
		}
	
		$("#" + idString).die('setStartingText').live("setStartingText", function(e, data) {
			options.startingText = data;
		});
		
		$("#" + idString).die(options.initializeEvent).live(options.initializeEvent, function(event) { 
			obj = $(this);
			//This will stop the outsideClick event from firing for ant other 
			//active textboxes
			event.stopPropagation();
			editingObject = true;
			   
			//don't do anything if the edit control is already showing.            
			if ($(this).hasClass(options.classPrefix + "_editMode")) {
				return;            
			}
			
			$(this).addClass( options.classPrefix + "_editMode");
      
			//store the original contents for use when the edit is canceled
			originalContents = $(this).html();
            
			//remove default content
			var div = $("<div />");
			div.append($(options.defaultMarkUp));
			
			//let jquery reformat the html for comparison
			var div2 = $("<div />");
			div2.append($(this).html());
			
				//remove style attributes
			div.removeAttr('style');
			div2.removeAttr('style');
			
			
			if (div2.text() == div.text()) {
				$(this).html(options.htmlTemplate);
			}
			
		
            //render the control.
			$(this).after(createEipControl($(this)));
			$(this).css('display', 'none');
			$(this).bind("saveChanges",saveChanges);
			
			if (options.wysiwyg && options.html) {
				var inlineOnly = isInlineOnly();
				$('#editObj' +idString).wysiwyg(
					{
						'allowedTags': options.allowedHTMLTags,
						'maxlength' : options.maxlength,
						'maxheight': options.maxheight,
						'stylesheets': options.stylesheets,
						'multiline': options.multiline,
						'inlineOnly': inlineOnly,
						'elementTag': obj.get(0).tagName + " class=\"" + $(obj).attr("class")  + "\"",
						'customClasses': options.customClasses,
						'pEnclose': options.pEnclose,
						'uploadImageFunction': options.uploadImageFunction,
						'uploadVideoFunction': options.uploadVideoFunction,
						'createCropper': options.createCropper,
						'destroyCropper': options.destroyCropper,
						'alignment': options.alignment,
						'container': options.container,
						'allowImages': options.wysiwygAllowImages,
						'allowVideo': options.wysiwygAllowVideo,
						'allowTables': options.wysiwygAllowTables
					});
			} else  if (options.multiline  && !options.rows) {
                var twin = createTwin($(this)); 
                $(this).append(twin);
            }

			if (options.wysiwyg) {
				//$($('#editObj' + idString + "ContentEditable").children()[0]).select();
			//	$($('#editObj' + idString  + "ContentEditable").children()[0]).focus();
			} else {
				//$('#editObj' + idString ).select();
				$('#editObj' + idString ).focus();
				$('#editObj' + idString ).setCursorPosition( $('#editObj' + idString ).val().length);
			}
			
            //bind the outside click event to the document.
			$(document).bind('click',  handleOutsideClick);
			
            //call the start callback.
			options.startCallBack(this);
			return false;
		});
		
		$(this).bind("setOriginalContents", function(e, data) {
			originalContents = data;
		});
		
		$(this).bind("getObjectText", function(e, obj) {
			return htmlToText(obj);
		});
		
	});
};

})(jQuery);


