/* String functions */

	String.prototype.trim = function() {
		var sString = this;
		while (sString.substring(0,1) == ' ') {
			sString = sString.substring(1, sString.length);
		}
		while (sString.substring(sString.length-1, sString.length) == ' ') {
			sString = sString.substring(0,sString.length-1);
		}
		return sString;	
		}


	String.prototype.wordWrap = function(m, b, c){
		var i, j, l, s, r = this.split("\n");
		if(m > 0) for(i = -1, l = r.length; ++i < l;){
			for(s = r[i], r[i] = ""; s.length > m;
				j = c ? m : (j = s.substr(0, m).match(/\S*$/)).input.length - j[0].length
				|| j.input.length + (j = s.substr(m).match(/^\S*/)).input.length + j[0].length,
				r[i] += s.substr(0, j) + ((s = s.substr(j)).length ? b : "")
			);
			r[i] += s;
		}
		return r.join("\n");
	};

	/* Add a class to a string */
	String.prototype.addClass = function(theClass) {
		if (this != "")	{
			if (!this.classExists(theClass)) return this + " " + theClass;
		}
		else {
			return theClass;
		}
		return this;
		}

	/* Remove a class from a string */
	String.prototype.removeClass = function(theClass) {
		var regString = "(^| )" + theClass + "\W*";
		var regExpression = new RegExp(regString);
		return this.replace(regExpression, "");
		}
		
	
	/* Check if a class exists in a string */
	String.prototype.classExists = function(theClass) {
		var regString = "(^| )" + theClass + "\W*";
		var regExpression = new RegExp(regString);
		if (regExpression.test(this)) return true;
		return false;
		}

	/* Check if a string is the nodeName of an inline element */
	String.prototype.isInlineName = function() {
		var inlineList = ["#text", "a", "em", "font", "span", "strong", "u"];
		var theName = this.toLowerCase();
		if (inlineList.exists(theName)) return true;
		return false;
		}


/* General functions */
		

	/* Replace a node with its children -- delete the item and move its children up one level in the hierarchy */
	function replaceNodeWithChildren(theNode) {
		var theChildren = new Array();
		var theParent = theNode.parentNode;
		if (theParent != null) {
			for (var i = 0; i < theNode.childNodes.length; i++) {
				theChildren.push(theNode.childNodes[i].cloneNode(true));
			}
			for (var i = 0; i < theChildren.length; i++) {
				theParent.insertBefore(theChildren[i], theNode);
			}
			theParent.removeChild(theNode);
			return theParent;
		}
		return true;
		}

	function returnSelection(windowObject) {
		var textSelection = null;
		if (windowObject.document.selection) {
			textSelection = windowObject.document.selection.createRange().text;
		}
		else {
			textSelection = windowObject.getSelection();
		}
		//if (textSelection!=null) textSelection = textSelection+'';
		return (textSelection);
		}	


	function findParentElement(e,elementName,className) {
		e = e.parentNode;
		if (e.tagName.toLowerCase() == elementName && e.className.toLowerCase() == className) {
			return e;
		} else if (e.tagName.toLowerCase() == "body") {
			return null;
		} else {
			return findParentElement(e,elementName,className);
		}
		}

	function insertAtCursor(myField, myValue) {
		if (document.selection) {
			myField.focus();
			sel = document.selection.createRange();
			sel.text = myValue;
		}
		else if (myField.selectionStart || myField.selectionStart == '0') {
			var startPos = myField.selectionStart;
			var endPos = myField.selectionEnd;
			myField.value = myField.value.substring(0, startPos)
			+ myValue
			+ myField.value.substring(endPos, myField.value.length);
		} else {
			myField.value += myValue;
		}
		}

	function appendElement(parentField, childField, childValue) {
		var theElement = document.createElement(childField);
		if (childValue!='') {
			var theText = document.createTextNode(childValue);
			theElement.appendChild(theText);
			}
		parentField.appendChild(theElement);
		return (theElement);
		}


	function wrap(txt, length) {
		return (txt);
		}
	
	function cleanupText(txt,isHtmlText) {

		//if (!isHtmlText) {	
			/*	Encode tags within pre tags */
			txt = txt.replace(/<pre>([\s|\S]*?)<\/pre>/gi, function(w,m1) { return String("<pre>"+m1.replace(/</gi,"&lt;").replace(/>/gi,"&gt;")+"</pre>").wordWrap(60,"\n",false)} );	
		//}
		

		/*	Remove tags and attributes we don't like */
		txt = balanceHtml(txt);
		txt = txt.replace(/<(.*?)>/gi,function(w,m1) {return processTag(m1.toLowerCase()); });
		txt = txt.replace('javascript:','#');
		for(var i=0; i<tag_counts.length; i++){
			if (tag_counts[i]>0)
				txt += "</" +allowedTags[i]+">";
		}
		
		if (!isHtmlText) {
			/*	Replace carriage returns with breaks */
			txt = txt.replace(/\n/gi,"<br />");
			/* 	Sort out p and br tags */	
			txt = "<p>" + txt + "</p>";
		}
		
		txt = txt.replace(/<p[^>]*><\/p>/gi,"");
		txt = txt.replace(/<p[^>]*><br \/><br \/>/gi,"<p>");
		txt = txt.replace(/<br \/><br \/><\/p>/gi,"</p>");
		txt = txt.replace(/<p[^>]*><br \/><\/p>/gi,"");
		txt = txt.replace(/<br \/><br \/>/gi,"</p><p>");
		txt = txt.replace(/<p[^>]*><br \/>/gi,"<p>");
		txt = txt.replace(/<br \/><\/p>/gi,"</p>");


		/* Remove the <br's> for the pre section */
		txt = txt.replace(/<pre>([\s|\S]*?)<\/pre>/gi, function(w,m1) { return "<pre>" + m1.replace(/<[^>]*?>/gi,"\n") + "</pre>" } );	
		txt = txt.replace(/<p><pre>/gi,"<pre>");
		txt = txt.replace(/<\/pre><\/p>/gi,"</pre>");	

		return(txt);
		}

	function balanceHtml(txt){
		txt = txt.replace("/<([^>]*?)(?=<|$)/", "<$1>");
		txt = txt.replace("/(^|>)([^<]*?)(?=>)/", "$1<$2");
		return (txt);
		}
		
	function processTag(tag) {
		// Handle end tags
		var tags = tag.match(/^\/([a-z0-9]+)/i);
		if (tag.match(/^\/([a-z0-9]+)/i)) {
		var tagname = RegExp.$1;
		if (tagname.length>0) {
			if (allowedTags.exists(tagname)) {
				if (no_close.exists(tagname)==false) {
					if (tag_counts[allowedTags.getindex(tagname)]>0) {
						tag_counts[allowedTags.getindex(tagname)] = tag_counts[allowedTags.getindex(tagname)]-1;
						var cr = "";
						if (carriageReturnTags.exists(tagname)) cr = "\n";
						return ("</"+tagname+">"+cr);
					}
				}
			} else {
				return ("");
			}
		}
		}
		// Handle start tags
		var tags = tag.match(/^([a-z0-9]+)(.*?)(\/?)$/i);
		var tagname = RegExp.$1;
		var body = RegExp.$2;
		var ending = RegExp.$3;
		if (tagname.length>0) {
		
			if (allowedTags.exists(tagname)) {
				var params = "";
				params = body.replace(/([a-z0-9]+)=\"(.*?)\"/gi,function(w,m1,m2) { return tagAttributes(m1,m2); });
				//if (params.match(/([a-z0-9]+)=([^\"\s]+)/gi)!=null) {
				//	params += params.replace(/([a-z0-9]+)=([^\"\s]+)/gi,function(w,m1,m2) { return tagAttributes(m1,m2); });
				//}
				if (no_close.exists(tagname)){
					ending = ' /';
				}
				if (!ending){
					tag_counts[allowedTags.getindex(tagname)] = tag_counts[allowedTags.getindex(tagname)]+1;
				}
				if (ending){
					ending = ' /';
				}
				return ("<"+tagname+params+ending+">");
				}
		}
		return ("");
		}

	function tagAttributes(attr,val) {
		if (allowedAttributes.exists(attr)) {
			if (protocol_attributes.exists(attr)) val = processParamProtocol(val);
			var param = " " + attr + "=\"" + val + "\"";
			return (param);
		}
		return ("");
		}


	function processParamProtocol(val){
		if (val.match(/^([^:]+)\:/gi)){
			if (!allowed_protocols.exists(RegExp.$1)) {
				val = '#'+val.substring(0,(RegExp.$1.length)+1);
			}
		}
		return (val);
		}


	function fnGenerateSummary(generateSummaryField,summary,detail,textlength) {
		var detailsField = document.getElementById(detail);
		if (detailsField.nodeName.toLowerCase()=="iframe") {
			//detailsField.updateEditorInput();
			detailsField = detailsField.contentWindow.document.body; //body_editorIframe
		}
		var summaryField = document.getElementById(summary);
		if (generateSummaryField.checked == true) {
			var detailsValue = detailsField.innerHTML;
			detailsValue = detailsValue.trim();
			detailsValue = detailsValue.replace(/\t/gi,"");
			detailsValue = detailsValue.replace(/\r/gi,"");
			detailsValue = detailsValue.replace(/\n/gi,"");
			re = new RegExp("</[p|h][^>]*>","gi");
			detailsValue = detailsValue.replace(re," | ");
			re = new RegExp("<[^>]*>","gi");
			detailsValue = detailsValue.replace(re,"");
			var summaryValue = "";
			if (detailsValue.length>textlength) {
				var firstSentenceIndex = detailsValue.indexOf(".",textlength);
				if (firstSentenceIndex>textlength) summaryValue = detailsValue.substring(0,firstSentenceIndex+1) + " ...";
				if (summaryValue.length==0) {
				if (detailsValue.length>(textlength*2)) {
					var extract = detailsValue.substring(0,(textlength*2));
					indexSpace = 1;
					while (indexSpace<=200&&indexSpace>-1) {
						indexSpace = extract.indexOf(" ",indexSpace);
						if (indexSpace>0) {
							currentIndex = indexSpace;
							indexSpace = indexSpace+1;
						}
					}
					summaryValue = detailsValue.substring(0,currentIndex) + " ...";
				}
				}
			}
			if (summaryValue.length==0) summaryValue = detailsValue;
			summaryField.value = summaryValue;
		}
	}


Array.prototype.exists=function(val){
	for(var i=0;i<this.length;i++){
	if(this[i]==val) return true;
	}
	return false;
	}

Array.prototype.getindex=function(val){
	for(var i=0;i<this.length;i++){
	if(this[i]==val) return i;
	}
	return -1;
	}



/*	Initialise editor */

	var oldOnload = window.onload;
	if (typeof window.onload != "function") {
		window.onload = function() {
			initNetfundiEditor();
		}
	}
	else {
		window.onload = function() {
			initNetfundiEditor();				
			return oldOnload();
	}
	}

//alert(window.onload);


/* Editor functions */

	var ua = navigator.userAgent.toLowerCase();
	var isIE = ((ua.indexOf("msie") != -1) && (ua.indexOf("opera") == -1) && (ua.indexOf("webtv") == -1)); 
	var isGecko = (ua.indexOf("gecko") != -1);
	var isSafari = (ua.indexOf("safari") != -1);
	var isKonqueror = (ua.indexOf("konqueror") != -1);
	var isRichText = false;
	
	//check to see if designMode mode is available
	if (document.getElementById && document.designMode && !isSafari && !isKonqueror) {
		isRichText = true;
	}

	function initNetfundiEditor() {
		//if (typeof(document.designMode) == "string" && (document.all || document.designMode == "off")) {
		if (isRichText) {
			var theTextareas = document.getElementsByTagName("textarea");
			for (var i = 0; i < theTextareas.length; i++) {
				var theTextarea = theTextareas[i];
				if (theTextarea.className.classExists("netfundiEditor")) {
					if (theTextarea.id == "") theTextarea.id = theTextarea.name;
					setTimeout("new netfundiEditor('" + theTextarea.id + "')", 500 * (i));
				
				}
			}
		}
		else {
			return false;
		}
		return true;
		}
	

	/* netfundiEditor */
	function netfundiEditor(replacedTextareaID) {
	
		var self = this;
		this.theTextarea = document.getElementById(replacedTextareaID);
		this.theContainer = document.createElement("div");
		this.theIframe = document.createElement("iframe");
		this.theInput = document.createElement("input");
		this.theExtraInput = document.createElement("input");
		this.IE = false;
		this.Safari = false;
		this.locked = true;
		this.pasteCache = "";
		this.wysiwyg = true;
		if (navigator.appName=="Microsoft Internet Explorer") {
			this.IE = true;
		}
		if (navigator.appVersion.toLowerCase().indexOf("safari")>-1) {
			this.Safari = true;
		}		
		if (this.theTextarea.id == null) {
			this.theTextarea.id = this.theTextarea.name;
		}
		this.theTextarea.style.visibility = "hidden";
		this.theContainer.id = this.theTextarea.id + "_editorContainer";
		this.theContainer.className = "editorContainer";
		this.theIframe.id = this.theTextarea.id + "_editorIframe";
		this.theIframe.className = "editorIframe";
		this.theInput.type = "hidden";
		this.theInput.id = this.theTextarea.id;
		this.theInput.name = this.theTextarea.name;
		this.theInput.value = this.theTextarea.value;
		this.theToolbar = new editorToolbar(this);		
		this.theTextarea.id += "_editorTextarea";
		this.theTextarea.name += "_editorTextarea";
		this.theContainer.appendChild(this.theToolbar.theList);
		this.theContainer.appendChild(this.theIframe);
		this.theContainer.appendChild(this.theInput);
		//this.theContainer.appendChild(this.theExtraInput);
		this.theContainer.style.visibility = "hidden";
		this.theTextarea.parentNode.replaceChild(this.theContainer, this.theTextarea);
		/* Fill editor with old textarea content */
		this.writeDocument(this.theInput.value);
		/* Make editor editable */
		this.initEdit();
		/* Attach onsubmit to parent form */
		this.modifyFormSubmit();

	/* This is handle different message types */
	var messagetypeObj = document.getElementById("messagetype");
	if (messagetypeObj) messagetypeObj.value = "html";
	
		return true;
		}


	/* netfundiEditor.writeDocument */
	netfundiEditor.prototype.writeDocument = function(documentContent) {
		
		if (documentContent.trim().length<=2) documentContent = "<p>&nbsp;</p>";
		/* HTML template into which the HTML Editor content is inserted */
		var documentTemplate = "\
			<html>\
				<head>\
					<style type=\"text/css\">@import url(\"INSERT:STYLESHEET:END\");</style>\
				</head>\
				<body id=\"iframeBody\">\
					INSERT:CONTENT:END\
				</body>\
			</html>\
		";
		/* Insert dynamic variables/content into document */
		documentTemplate = documentTemplate.replace(/INSERT:STYLESHEET:END/, editorStylesheet);
		documentTemplate = documentTemplate.replace(/INSERT:CONTENT:END/, documentContent);
		this.theIframe.contentWindow.document.open();
		this.theIframe.contentWindow.document.write(documentTemplate);
		this.theIframe.contentWindow.document.close();
		return true;
		}


	/* netfundiEditor.initEdit */
	netfundiEditor.prototype.initEdit = function() {
		var self = this;
		try {
			this.theIframe.contentWindow.document.designMode = "on";
		}
		catch (e) {
		/* setTimeout needed to counteract Mozilla bug whereby you can't immediately change designMode on newly created iframes */
		setTimeout(function(){self.initEdit()}, 500);
		return false;
		}
		if (!this.IE) {
			setTimeout(function(){self.convertStyleAttributes(false)}, 500);
		}
		this.theContainer.style.visibility = "visible";
		this.theTextarea.style.visibility = "visible";
		/* Mozilla event capturing */
		if (typeof document.addEventListener == "function") {
		//this.theIframe.contentWindow.document.addEventListener("mouseup", function(){widgToolbarCheckState(self); return true;}, false);
		//this.theIframe.contentWindow.document.addEventListener("keyup", function(){widgToolbarCheckState(self); return true;}, false);
		//this.theIframe.contentWindow.document.addEventListener("keydown", function(e){self.detectPaste(e); return true;}, false);
		}
		/* IE event capturing */
		else {
		//this.theIframe.contentWindow.document.attachEvent("onmouseup", function(){widgToolbarCheckState(self); return true;});
		//this.theIframe.contentWindow.document.attachEvent("onkeyup", function(){widgToolbarCheckState(self); return true;});
		this.theIframe.contentWindow.document.attachEvent("onkeydown", function(e){self.detectPaste(e); return true;}, false);
		}
		this.locked = false;
		return true;	
		}

	/* netfundiEditor.modifyFormSubmit */
	netfundiEditor.prototype.modifyFormSubmit = function() {
		var self = this;
		var theForm = this.theContainer.parentNode;
		var oldOnsubmit = null;
		/* Find the parent form element */
		while (theForm.nodeName.toLowerCase() != "form") {
			theForm = theForm.parentNode;
		}
		/* Add onsubmit without overwriting existing function calls */
		oldOnsubmit = theForm.onsubmit;
		if (typeof theForm.onsubmit != "function"){
			theForm.onsubmit = function(){
				return self.updateEditorInput();
				}
		} 
		else {
			theForm.onsubmit = function() {
				self.updateEditorInput();
				return oldOnsubmit();			
			}
		}
		return true;
		}
		

		
	/* netfundiEditor.updateEditorInput */
	netfundiEditor.prototype.updateEditorInput = function() {
		if (this.wysiwyg) {
			/* Convert spans to semantics in Mozilla */
			if (!this.IE) {
				this.convertStyleAttributes(true);
			}
			this.paragraphise();		
			this.cleanSource();
		}
		else {
			this.theInput.value = this.theTextarea.value;
		}
		return true;
	}	

	/* netfundiEditor.switchMode */
	netfundiEditor.prototype.switchMode = function() {
		if (!this.locked) {
			this.locked = true;
			/* Switch to HTML source */
			if (this.wysiwyg) {
				this.updateEditorInput();
				this.theTextarea.value = this.theInput.value;	
				this.theContainer.replaceChild(this.theTextarea, this.theIframe);
				this.theToolbar.disable();
				this.wysiwyg = false;
				this.locked = false;
			}
			/* Switch to WYSIWYG */
			else {
				this.updateEditorInput();
				this.theContainer.replaceChild(this.theIframe, this.theTextarea);
				var inputValue = this.theInput.value;
				this.writeDocument(inputValue);
				this.theToolbar.enable();
				this.initEdit();
				this.wysiwyg = true;
			}
		}
		return true;
	}

	/* netfundiEditor.convertStyleAttributes */
	netfundiEditor.prototype.convertStyleAttributes = function(bln) {
		if (bln) {
			var styleTags = ["p","span","li","ul","div","blockquote"];
			for(var s=0; s<styleTags.length; s++) {
				var theElementArray = this.theIframe.contentWindow.document.getElementsByTagName(styleTags[s]);		
				var elementCount = theElementArray.length;
				for(var e=0; e<elementCount; e++) {
					var theChildren = new Array();
					var theReplacementElement = null;
					var theParentElement = null;
					var theNestedElement = null;
					for (var j = 0; j < theElementArray[e].childNodes.length; j++) {
						theChildren.push(theElementArray[e].childNodes[j].cloneNode(true));
					}
					// Detect type of style

					switch (theElementArray[e].getAttribute("style")) {
						case "font-weight: bold;":
							theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;
						case "font-style: italic;":
							theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;
						case "font-weight: bold; font-style: italic;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("strong");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;
						case "font-style: italic; font-weight: bold;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("em");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;
						case "margin-left: 40px;":
							theReplacementElement = this.theIframe.contentWindow.document.createElement("blockquote");
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);						
							break;
						case "font-weight: bold; margin-left: 40px;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("strong");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("blockquote");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;							
						case "margin-left: 40px; font-weight: bold;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("blockquote");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;							
						case "font-style: italic; margin-left: 40px;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("em");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("blockquote");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;							
						case "margin-left: 40px; font-style: italic;":
							theNestedElement = this.theIframe.contentWindow.document.createElement("blockquote");
							theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
							theNestedElement.appendChild(theReplacementElement);
							theParentElement = this.theIframe.contentWindow.document.createElement(styleTags[s]);
							theParentElement.appendChild(theReplacementElement);
							break;	
						default:
							//replaceNodeWithChildren(theSPANs[0]);
							break;
					}
					if (theReplacementElement != null) {
						for (var j = 0; j < theChildren.length; j++) {
							theReplacementElement.appendChild(theChildren[j]);
						}
						theElementArray[e].parentNode.replaceChild(theParentElement,theElementArray[e]);
					}
				}
			}
		}
		else {
			/* Replace em and strong tags with styled spans */
			try {
			var theEMs = this.theIframe.contentWindow.document.getElementsByTagName("em");
			while(theEMs.length > 0) {
				var theChildren = new Array();
				var theSpan = this.theIframe.contentWindow.document.createElement("span");
				theSpan.setAttribute("style", "font-style: italic;");
				for (var j = 0; j < theEMs[0].childNodes.length; j++) {
					theChildren.push(theEMs[0].childNodes[j].cloneNode(true));
				}
				for (var j = 0; j < theChildren.length; j++) {
					theSpan.appendChild(theChildren[j]);
				}
				theEMs[0].parentNode.replaceChild(theSpan, theEMs[0]);
				theEMs = this.theIframe.contentWindow.document.getElementsByTagName("em");
			}
			var theSTRONGs = this.theIframe.contentWindow.document.getElementsByTagName("strong");
			while(theSTRONGs.length > 0) {
				var theChildren = new Array();
				var theSpan = this.theIframe.contentWindow.document.createElement("span");
				theSpan.setAttribute("style", "font-weight: bold;");
				for (var j = 0; j < theSTRONGs[0].childNodes.length; j++) {
					theChildren.push(theSTRONGs[0].childNodes[j].cloneNode(true));
				}
				for (var j = 0; j < theChildren.length; j++) {
					theSpan.appendChild(theChildren[j]);
				}
				theSTRONGs[0].parentNode.replaceChild(theSpan, theSTRONGs[0]);
				theSTRONGs = this.theIframe.contentWindow.document.getElementsByTagName("strong");
			}	
			}
			catch(e) {}
		}
		//alert(this.theIframe.contentWindow.document.getElementsByTagName("p")[0].innerHTML)
		return true;
		}	

	/* netfundiEditor.paragraphise */
	netfundiEditor.prototype.paragraphise = function() {

		if (editorInsertParagraphs && this.wysiwyg) {
			var theBody = this.theIframe.contentWindow.document.getElementsByTagName("body")[0];
			/* Remove all text nodes containing just whitespace */
			for (var i = 0; i < theBody.childNodes.length; i++) {
				if (theBody.childNodes[i].nodeName.toLowerCase() == "#text" &&
					theBody.childNodes[i].data.search(/^\s*$/) != -1) {
					theBody.removeChild(theBody.childNodes[i]);
					i--;
				}
			}
			var removedElements = new Array();
			for (var i = 0; i < theBody.childNodes.length; i++) {
			if (theBody.childNodes[i].nodeName.isInlineName()) {
				removedElements.push(theBody.childNodes[i].cloneNode(true));
				theBody.removeChild(theBody.childNodes[i]);
				i--;
			}
			else if (theBody.childNodes[i].nodeName.toLowerCase() == "br") {
				if (i + 1 < theBody.childNodes.length) {
					/* If the current break tag is followed by another break tag */
					if (theBody.childNodes[i + 1].nodeName.toLowerCase() == "br") {
						/* Remove consecutive break tags */
						while (i < theBody.childNodes.length && theBody.childNodes[i].nodeName.toLowerCase() == "br") {
							theBody.removeChild(theBody.childNodes[i]);
						}
						if (removedElements.length > 0) {
							this.insertNewParagraph(removedElements, theBody.childNodes[i]);
							removedElements = new Array();
						}
					}
					/* If the break tag appears before a block element */
					else if (!theBody.childNodes[i + 1].nodeName.isInlineName()) {
						theBody.removeChild(theBody.childNodes[i]);
					}
					else if (removedElements.length > 0) {
						removedElements.push(theBody.childNodes[i].cloneNode(true));
						theBody.removeChild(theBody.childNodes[i]);
					}
					else {
						theBody.removeChild(theBody.childNodes[i]);
					}
					i--;
				}
				else {
					theBody.removeChild(theBody.childNodes[i]);
				}
			}
			else if (removedElements.length > 0) {
				this.insertNewParagraph(removedElements, theBody.childNodes[i]);
				removedElements = new Array();
			}
		}
		if (removedElements.length > 0) {
			this.insertNewParagraph(removedElements);
		}
		}
		
		return true;
		}

	/* netfundiEditor.insertNewParagraph */
	netfundiEditor.prototype.insertNewParagraph = function(elementArray, succeedingElement) {
		var theBody = this.theIframe.contentWindow.document.getElementsByTagName("body")[0];
		var theParagraph = this.theIframe.contentWindow.document.createElement("p");
		for (var i = 0; i < elementArray.length; i++) {
			theParagraph.appendChild(elementArray[i]);
		}
		if (typeof(succeedingElement) != "undefined") {
			theBody.insertBefore(theParagraph, succeedingElement);
		} 
		else {
		theBody.appendChild(theParagraph);
		}
		return true;
		}
		
	/* netfundiEditor.cleanSource */
	netfundiEditor.prototype.cleanSource = function() {
		var theHTML = "";
		if (this.wysiwyg) {
			theHTML = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
		}
		else {
			theHTML = this.theTextarea.value;
		}
		theHTML = cleanupText(theHTML,true);
		theHTML = theHTML.replace(/\t/gi,"");
		if (this.wysiwyg) {
			this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML = theHTML;
		}
		else {
			this.theTextarea.value = theHTML;
		}
		this.theInput.value = theHTML;
		return true;
		}
		

	/* netfundiEditor.detectPaste */
	netfundiEditor.prototype.detectPaste = function(e) {
		var keyPressed = null;
		var theEvent = null;
		if (e) {
			theEvent = e;
		}
		else {
			theEvent = event;
		}
		if (theEvent.ctrlKey && theEvent.keyCode == 86 && this.wysiwyg) {
			var self = this;
			this.pasteCache = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
			/* Because Mozilla can't access the clipboard directly, must rely on timeout to check pasted differences in main content */
			setTimeout(function(){self.cleanPaste(); return true;}, 100);
		}
		return true;
		}

	/* netfundiEditor.detectPaste */
	netfundiEditor.prototype.cleanPaste = function() {
		this.cleanSource();
		}

/* Toolbar functions */		
	
	/* editorToolbar */
	function editorToolbar(theEditor) {
		var self = this;
		this.editorObject = theEditor;
		this.theList = document.createElement("ul");
		this.theList.id = this.editorObject.theInput.id + "_editorToolbar";
		this.theList.className = "editorToolbar";
		this.theList.editorToolbarObject = this;
		/* Create toolbar items */
		for (var i=0; i<editorToolbarItems.length; i++) {
			switch (editorToolbarItems[i]) {
				case "bold":
					this.addButton(this.theList.id + "ButtonBold", "editorButtonBold", "Bold", "bold");
					break;
				case "italic":
					this.addButton(this.theList.id + "ButtonItalic", "editorButtonItalic", "Italic", "italic");
					break;
				case "hyperlink":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonLink", "editorButtonLink", "Hyperlink", "link");
					break;
				case "unorderedlist":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonUnordered", "editorButtonUnordered", "Unordered List", "insertunorderedlist");
					break;
				case "orderedlist":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonOrdered", "editorButtonOrdered", "Ordered List", "insertorderedlist");
					break;
				case "indent":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonIndent", "editorButtonIndent", "Indent", "indent");
					break;
				case "outdent":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonOutdent", "editorButtonOutdent", "Outdent", "outdent");
					break;					
				case "image":
					if (!this.editorObject.Safari)
					this.addButton(this.theList.id + "ButtonImage", "editorButtonImage", "Insert Image", "image");
					break;
				case "htmlsource":
					this.addButton(this.theList.id + "ButtonHTML", "editorButtonHTML", "HTML Source", "html");
					break;
				case "blockformat":
					this.addSelect(this.theList.id + "SelectBlock", "editorSelectBlock", editorSelectBlockOptions, "formatblock");
					break;
			}
		}
		return true;
		}


	/* editorToolbar.addButton */
	editorToolbar.prototype.addButton = function(theID, theClass, theLabel, theAction){
		var menuItem = document.createElement("li");
		var theLink = document.createElement("a");
		var theText = document.createTextNode(theLabel);
		menuItem.id = theID;
		menuItem.className = "editorButton";
		//theLink.href = "";
		theLink.title = theLabel;
		theLink.className = theClass;
		theLink.action = theAction;
		theLink.unselectable = "on";
		theLink.onmousedown = editorToolbarAction; // onmousedown instead of onclick, for Safari
		//theLink.onmouseover = editorToolbarMouseover;
		//theLink.appendChild(theText);
		menuItem.appendChild(theLink);
		this.theList.appendChild(menuItem);
		return true;
		}

	/* editorToolbar.enable */
	editorToolbar.prototype.enable = function() {
		/* Change class to enable buttons using CSS */
		this.theList.className = this.theList.className.replace(/ editorSource/, "");
		/* Loop through lis */
		for (var i = 0; i < this.theList.childNodes.length; i++) {
			var theChild = this.theList.childNodes[i];
			if (theChild.nodeName.toLowerCase() == "li" && theChild.className == "editorSelect") {
				/* Loop through li children to find select */
				for (j = 0; j < theChild.childNodes.length; j++) {
					if (theChild.childNodes[j].nodeName.toLowerCase() == "select") {
						theChild.childNodes[j].disabled = "";
						break;
					}
				}
			}
		}
		return true;
		}

	/* editorToolbar.disable */
	editorToolbar.prototype.disable = function() {
		/* Change class to disable buttons using CSS */
		this.theList.className += " editorSource";
		/* Loop through lis */
		for (var i = 0; i < this.theList.childNodes.length; i++) {
			var theChild = this.theList.childNodes[i];
			if (theChild.nodeName.toLowerCase() == "li" && theChild.className == "netfundiEditSelect") {
				/* Loop through li children to find select */
				for (j = 0; j < theChild.childNodes.length; j++) {
					if (theChild.childNodes[j].nodeName.toLowerCase() == "select") {
						theChild.childNodes[j].disabled = "disabled";
						break;
					}
				}
			}
		}
		return true;
		}

	/* editorToolbar.setState */
	editorToolbar.prototype.setState = function(theState, theStatus) {
		if (theState != "SelectBlock") {
			var theButton = document.getElementById(this.theList.id + "Button" + theState);
			if (theButton != null) {
				if (theStatus == "on") {
					theButton.className = theButton.className.addClass("on");
				}
				else {
					theButton.className = theButton.className.removeClass("on");
				}
			}
		}
		else {
			var theSelect = document.getElementById(this.theList.id + "SelectBlock");
			if (theSelect != null) {
				theSelect.value = "";
				theSelect.value = theStatus;
			}
		}
		return true;	
		}



	/* editorToolbarAction */
	function editorToolbarAction(e) {

		var theToolbar = this.parentNode.parentNode.editorToolbarObject;
		var theEditor = theToolbar.editorObject;
		var theIframe = theEditor.theIframe;
		var theSelection = "";
		/* If somehow a button other than "HTML source" is clicked while viewing HTML source, ignore click */	
		if (!theEditor.wysiwyg && this.action != "html") return false;
		switch (this.action) {
			case "html":
				theEditor.switchMode();
				break;
			case "link":
				if (this.parentNode.className.classExists("on")) {
					theIframe.contentWindow.document.execCommand("Unlink", false, null);
					theEditor.theToolbar.setState("Link", "off");
				}
				else {
					theSelection = returnSelection(theIframe.contentWindow);
					if (theSelection == "") {
						alert("Please select the text you wish to hyperlink.");
						break;
						}
					var theURL = prompt("Enter the URL for this link:", "http://");
					if (theURL != null && theURL != "") {			
						theIframe.contentWindow.document.execCommand("CreateLink", false, theURL);
						theEditor.theToolbar.setState("Link", "on");
					}
					else {
					theIframe.contentWindow.document.execCommand("Unlink", false, null);
					}
				}
				break;				
			case "image":
				var theImage = prompt("Enter the location for this image:", "");
				if (theImage != null && theImage != "") {
					var theAlt = prompt("Enter the alternate text for this image:", "");
					var theSelection = null;
					var theRange = null;
					if (theIframe.contentWindow.document.selection) {
						theSelection = theIframe.contentWindow.document.selection;
						theAlt = theAlt.replace(/"/g, "'");
						theRange = theSelection.createRange();
						theRange.collapse(false);
						theRange.pasteHTML("<img alt=\"" + theAlt + "\" src=\"" + theImage + "\" />");
						break;
					} 
					else { 
						theSelection = theIframe.contentWindow.getSelection();
						theRange = theSelection.getRangeAt(0);
						theRange.collapse(false);
						var theImageNode = theIframe.contentWindow.document.createElement("img");
						theImageNode.src = theImage;
						theImageNode.alt = theAlt;
						theRange.insertNode(theImageNode);
						break;
					}
				}
				else
				{
					return false;
				}
			default:
				theIframe.contentWindow.document.execCommand(this.action, false, null);
		}
		if (!e) var e = window.event;
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();		
		if (theEditor.wysiwyg == true) {
			theIframe.contentWindow.focus();
		}
		else {
			theEditor.theTextarea.focus();
		}
		return false;	
		}
		
