/*    
**     based on great work by: Cameron Adams (http://www.themaninblue.com/)
*/




// Configure /////////////////////////////////////////////////////////

//edit field style sheet (shoud match the sites settings)
var soloStylesheet = "css/soloWYG.css";

//tool bar item array
var soloToolbarItems = new Array();

soloToolbarItems.push("bold");
soloToolbarItems.push("italic");
//soloToolbarItems.push("hyperlink");
soloToolbarItems.push("unorderedlist");
soloToolbarItems.push("orderedlist");
//soloToolbarItems.push("image");
//soloToolbarItems.push("htmlsource");
soloToolbarItems.push("blockformat");

	var soloSelectBlockOptions = new Array();
		
	//soloSelectBlockOptions.push("", "Change Font");
	soloSelectBlockOptions.push("Times New Roman", "Times New Roman");
	soloSelectBlockOptions.push("Helvetica", "Helvetica");
	soloSelectBlockOptions.push("Courier New", "Courier");

if(window.loadStuff){
	// for block formatting options dropdown (value, name)

	//soloSelectBlockOptions.push("<h4>", "Georgia");
	
} else {
	soloToolbarItems.push("htmlsource");	
}



// for block formatting 2 options dropdown (value, name)
//var soloSelectBlockOptions = new Array();

//soloSelectBlockOptions.push("", "Change Font");

/*soloSelectBlockOptions.push("<h2>", "");
soloSelectBlockOptions.push("<h3>", "");
soloSelectBlockOptions.push("<h4>", "");
soloSelectBlockOptions.push("<h5>", "");
soloSelectBlockOptions.push("<h6>", "");
soloSelectBlockOptions.push("<p>", "Paragraph");
*/


// this will add <p></p> around everything else just use <BR> for new lines
var soloInsertParagraphs = false;

// this will attempt to clean pasted in code if set to true it will do it automatically
// else it will ask the user
var soloAutoClean = false;

// allows user to use style tags to make custom formatting
var soloAllowStyle = true;

// END configure //////////////////////////////////////////////////////////////////


run();




function run(){
	var oldOnload = window.onload; //retain current onload
    if(window.loadStuff){
		loadStuff(); //temporary iwi letter
	}
	if (typeof(window.onload) != "function"){
		window.onload = soloInit;
	}else{
		window.onload = function(){
			oldOnload();
			soloInit();
		}
	}
}




function soloInit(){
	// Detects if Rich Editing designMode is available. Also if IE or Mozilla.
	if (typeof(document.designMode) == "string" && (document.all || document.designMode == "off")){
		var theTextareas = document.getElementsByTagName("textarea");
		
		for (var i = 0; i < theTextareas.length; i++){
			var theTextarea = theTextareas[i];
			
			if (theTextarea.className.classExists("soloWYG")){
				if (theTextarea.id == ""){
					theTextarea.id = theTextarea.name;
				}
				
				setTimeout("new soloWYG('" + theTextarea.id + "')", 500 * (i));
			}
		}
	}else{
		return false;
	}
	
	return true;
}




function soloWYG(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.locked = true;
	this.pasteCache = "";
	this.wysiwyg = true;
		
	if (document.all){
		this.IE = true;
	}
	
	if (this.theTextarea.id == null){
		this.theTextarea.id = this.theTextarea.name;
	}
	
	//iwi stuff
	this.theFontFamily = document.createElement("input");
	this.theFontFamily.name = "fontfamily";
	this.theFontFamily.type = "hidden";
	this.theContainer.appendChild(this.theFontFamily);
	
	this.theTextarea.style.visibility = "hidden";

	// Modify DOM objects for editor 
	this.theContainer.id = this.theTextarea.id + "SoloContainer";
	this.theContainer.className = "soloContainer";
	
	this.theIframe.id = this.theTextarea.id + "SoloIframe";
	this.theIframe.className = "soloIframe";
	
	this.theInput.type = "hidden";
	this.theInput.id = this.theTextarea.id;
	this.theInput.name = this.theTextarea.name;
	this.theInput.value = this.theTextarea.value.replace(/<break/g,'<br'); //stupid IE hack with breaks
	

	this.theToolbar = new soloToolbar(this);
	
	// An extra input to determine if the submitted data is from the normal textarea or from the soloWYG 
	this.theExtraInput.type = "hidden";	
	this.theExtraInput.id = this.theTextarea.id + "SoloEditor";
	this.theExtraInput.name = this.theTextarea.name + "SoloEditor";
	this.theExtraInput.value = "true";
	
	this.theTextarea.id += "SoloTextarea";
	this.theTextarea.name += "SoloTextarea";
	
	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.theInput.soloWYGObject = this;
	
	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();
	
	return true;
}




// Clean pasted content 
soloWYG.prototype.cleanPaste = function(){
	soloAutoClean = 0;
	if (soloAutoClean){ //|| confirm("Do you wish to clean the HTML source of the content you just pasted?")){

		var matchedHead = "";
		var matchedTail = "";
		var newContent = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
		var newContentStart = 0;
		var newContentFinish = 0;
		var newSnippet = "";
		var tempNode = document.createElement("div");

		// Find start of both strings that matches 
		for (newContentStart = 0; newContent.charAt(newContentStart) == this.pasteCache.charAt(newContentStart); newContentStart++){
			matchedHead += this.pasteCache.charAt(newContentStart);
		}
		
		// If newContentStart is inside a HTML tag, move to opening brace of tag
		for (var i = newContentStart; i >= 0; i--){
			if (this.pasteCache.charAt(i) == "<"){
				newContentStart = i;
				matchedHead = this.pasteCache.substring(0, newContentStart);
				
				break;
			} else if(this.pasteCache.charAt(i) == ">"){
				break;
			}
		}

		newContent = newContent.reverse();
		this.pasteCache = this.pasteCache.reverse();

		// Find end of both strings that matches 
		for (newContentFinish = 0; newContent.charAt(newContentFinish) == this.pasteCache.charAt(newContentFinish); newContentFinish++) {
			matchedTail += this.pasteCache.charAt(newContentFinish);
		}

		// If newContentFinish is inside a HTML tag, move to closing brace of tag 
		for (var i = newContentFinish; i >= 0; i--) {
			if (this.pasteCache.charAt(i) == ">"){
				newContentFinish = i;
				matchedTail = this.pasteCache.substring(0, newContentFinish);
				
				break;
			}else if(this.pasteCache.charAt(i) == "<"){
				break;
			}
		}

		matchedTail = matchedTail.reverse();

		// If there's no difference in pasted content 
		if (newContentStart == newContent.length - newContentFinish){
			return false;
		}

		newContent = newContent.reverse();
		newSnippet = newContent.substring(newContentStart, newContent.length - newContentFinish);
		newSnippet = newSnippet.validTags();
/*
      // google treats botht the same the dipreciated i and b take up less kb
		// Replace opening bold tags with strong 
		newSnippet = newSnippet.replace(/<b(\s+|>)/g, "<strong$1");
		// Replace closing bold tags with closing strong 
		newSnippet = newSnippet.replace(/<\/b(\s+|>)/g, "</strong$1");

		// Replace italic tags with em 
		newSnippet = newSnippet.replace(/<i(\s+|>)/g, "<em$1");
		// Replace closing italic tags with closing em 
		newSnippet = newSnippet.replace(/<\/i(\s+|>)/g, "</em$1");
*/
		/* Strip out unaccepted attributes */
		newSnippet = newSnippet.replace(/<[^>]*>/g, function(match)	{
				match = match.replace(/ ([^=]+)="[^"]*"/g, function(match2, attributeName) {
						if (attributeName == "alt" || attributeName == "href" || attributeName == "src" || attributeName == "title") {
							return match2;
						}

						return "";
					});

				return match;
			}
		   );

		tempNode.innerHTML = newSnippet;

		acceptableChildren(tempNode);
		
		this.theInput.value = matchedHead + tempNode.innerHTML + matchedTail;

		// Cleanout for MS Word crap!!
		this.theInput.value = this.theInput.value.replace(/<\?xml[^>]*>/g, "");
		this.theInput.value = this.theInput.value.replace(/<[^ >]+:[^>]*>/g, "");
		this.theInput.value = this.theInput.value.replace(/<\/[^ >]+:[^>]*>/g, "");

		this.refreshDisplay();
		
		// Convert semantics to spans in Mozilla 
		if (!this.IE) {
			this.convertSPANs();
		}
	}
	
	return true;
}




// Clean the HTML code of the content area 
soloWYG.prototype.cleanSource = function(){
	var theHTML = "";
	
	if (this.wysiwyg)	{
		theHTML = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
	}else{
		theHTML = this.theTextarea.value;
	}

	theHTML = theHTML.validTags();
	
	/// Remove leading and trailing whitespace 
	theHTML = theHTML.replace(/^\s+/, "");
	theHTML = theHTML.replace(/\s+$/, "");
	
	
   if(!soloAllowStyle){
		// Remove style attribute inside any tag 
		theHTML = theHTML.replace(/ style="[^"]*"/g, "");
	}
	
	// Replace improper BRs | stardards are kinda lame
	theHTML = theHTML.replace(/<br>/g, "<br />");
	
	// Remove BRs right before the end of blocks 
	theHTML = theHTML.replace(/<br \/>\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/g, "</$1");
	
	// Replace improper IMGs | again lame standards
	theHTML = theHTML.replace(/(<img [^>]+[^\/])>/g, "$1 />");
	
	// Remove empty tags 
	theHTML = theHTML.replace(/(<[^\/]>|<[^\/][^>]*[^\/]>)\s*<\/[^>]*>/g, "");
	
	if (this.wysiwyg) {
		this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML = theHTML;
	}else{
		this.theTextarea.value = theHTML;
	}
	
	this.theInput.value = theHTML;
	
	return true;
}



//because these browser editors aren't that good must do trick to display things right
soloWYG.prototype.convertSPANs = function(theSwitch){
	if (theSwitch)	{
		// Replace styled spans with their semantic equivalent 
		var theSPANs = this.theIframe.contentWindow.document.getElementsByTagName("span");
	
		while(theSPANs.length > 0)	{
			var theChildren = new Array();
			var theReplacementElement = null;
			var theParentElement = null;
			
			for (var j = 0; j < theSPANs[0].childNodes.length; j++){
				theChildren.push(theSPANs[0].childNodes[j].cloneNode(true));
			}
			
			// Detect type of span style 
			switch (theSPANs[0].getAttribute("style")){
				case "font-weight: bold;":
					theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
					theParentElement = theReplacementElement;
					
					break;
				
				case "font-style: italic;":
					theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
					theParentElement = theReplacementElement;
					
					break;
					
				case "font-weight: bold; font-style: italic;":
					theParentElement = this.theIframe.contentWindow.document.createElement("em");
					theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
					theReplacementElement.appendChild(theParentElement);
					
					break;
					
				case "font-style: italic; font-weight: bold;":
					theParentElement = this.theIframe.contentWindow.document.createElement("strong");
					theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
					theReplacementElement.appendChild(theParentElement);
					
					break;
					
				default:
					replaceNodeWithChildren(theSPANs[0]);
				
					break;
			}
			
			if (theReplacementElement != null)	{
				for (var j = 0; j < theChildren.length; j++)	{
					theParentElement.appendChild(theChildren[j]);
				}

				theSPANs[0].parentNode.replaceChild(theReplacementElement, theSPANs[0]);
			}
			
			theSPANs = this.theIframe.contentWindow.document.getElementsByTagName("span");
		}
	}else{
		// Replace em and strong tags with styled spans 
		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");
		}
	}
	
	return true;
}




// Check for pasted content 
soloWYG.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);
	}

  
	if (theEvent.keyCode == 9 && theEvent.srcElement == obj) {
		obj.selection = document.selection.createRange();
		obj.selection.text = String.fromCharCode(tabKeyCode);
		theEvent.returnValue = false;
	}

	return true;
}




// Turn on document editing 
soloWYG.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()}, 250);
			
		return false;
	}
	
	if (!this.IE){
		this.convertSPANs(false);
	}
	
	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(){soloToolbarCheckState(self); return true;}, false);
		this.theIframe.contentWindow.document.addEventListener("keyup", function(){soloToolbarCheckState(self); return true;}, false);
		this.theIframe.contentWindow.document.addEventListener("keydown", function(e){self.detectPaste(e); return true;}, false);
	}else{ // IE event capturing 
		this.theIframe.contentWindow.document.attachEvent("onmouseup", function(){soloToolbarCheckState(self); return true;});
		this.theIframe.contentWindow.document.attachEvent("onkeyup", function(){soloToolbarCheckState(self); return true;});
		this.theIframe.contentWindow.document.attachEvent("onkeydown", function(e){self.detectPaste(e); return true;}, false);
	}
	
	this.locked = false;

	return true;	
}




// Add elements to a paragraph and inserts the paragraph before a given element in the body 
soloWYG.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;
}




// Add submit listener to parent form 
soloWYG.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.updateSoloInput();
		}
	}else{
		theForm.onsubmit = function(){
			self.updateSoloInput();

			return oldOnsubmit();			
		}
	}

	return true;
}




// Format the HTML with paragraphs. Any parentless text is enclosed in a paragraph, double breaks are paragraph markers 
soloWYG.prototype.paragraphise = function(){
	if (soloInsertParagraphs && 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();
						}
					}else if (!theBody.childNodes[i + 1].nodeName.isInlineName())	{
						// If the break tag appears before a block element 
						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;
}




// Update hidden input to reflect editor contents, for submission 
soloWYG.prototype.refreshDisplay = function(){
	if (this.wysiwyg)	{
		this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML	= this.theInput.value;
	}else{
		this.theTextarea.value = this.theInput.value;
	}

	return true;
}




// Switch between WYSIWYG and HTML source 
soloWYG.prototype.switchMode = function(){
	if (!this.locked)	{
		this.locked = true;
		
		// Switch to HTML source 
		if (this.wysiwyg)	{
			this.updateSoloInput();
			this.theTextarea.value = this.theInput.value;	
			this.theContainer.replaceChild(this.theTextarea, this.theIframe);
			this.theToolbar.disable();
			this.wysiwyg = false;
			this.locked = false;
		}else{ 
			this.updateSoloInput();
			this.theContainer.replaceChild(this.theIframe, this.theTextarea);
			this.writeDocument(this.theInput.value);
			this.theToolbar.enable();
			this.initEdit();
			this.wysiwyg = true;
		}
	}
			
	return true;
}




// Update hidden input to reflect editor contents, for submission 
soloWYG.prototype.updateSoloInput = function(){
	if (this.wysiwyg)	{
		// Convert spans to semantics in Mozilla 
		if (!this.IE){
			this.convertSPANs(true);
		}
		
		this.paragraphise();		
		this.cleanSource();
	}else{
		this.theInput.value = this.theTextarea.value;
	}

	return true;
}




// Write initial content to editor 
soloWYG.prototype.writeDocument = function(documentContent){
	// 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/, soloStylesheet);
	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;
}




// Toolbar items 
function soloToolbar(theEditor){
	var self = this;
	
	this.soloWYGObject = theEditor;
	
	// Create toolbar ul element 
	this.theList = document.createElement("ul");
	this.theList.id = this.soloWYGObject.theInput.id + "SoloToolbar";
	this.theList.className = "soloToolbar";
	this.theList.soloToolbarObject = this;

	// Create toolbar items 
	for (var i = 0; i < soloToolbarItems.length; i++)	{
		switch (soloToolbarItems[i]){
			case "bold":
				this.addButton(this.theList.id + "ButtonBold", "soloButtonBold", "Bold", "bold");
				
				break;
				
			case "italic":
				this.addButton(this.theList.id + "ButtonItalic", "soloButtonItalic", "Italic", "italic");
				
				break;
				
			case "hyperlink":
				this.addButton(this.theList.id + "ButtonLink", "soloButtonLink", "Hyperlink", "link");
				
				break;
				
			case "unorderedlist":
				this.addButton(this.theList.id + "ButtonUnordered", "soloButtonUnordered", "Unordered List", "insertunorderedlist");
				
				break;
				
			case "orderedlist":
				this.addButton(this.theList.id + "ButtonOrdered", "soloButtonOrdered", "Ordered List", "insertorderedlist");
				
				break;
				
			case "image":
				this.addButton(this.theList.id + "ButtonImage", "soloButtonImage", "Insert Image", "image");
				
				break;
				
			case "htmlsource":
				this.addButton(this.theList.id + "ButtonHTML", "soloButtonHTML", "HTML Source", "html");
				
				break;
				
			case "blockformat":
				//this.addSelect(this.theList.id + "SelectBlock", "soloSelectBlock", soloSelectBlockOptions, "formatblock");
				this.addSelect(this.theList.id + "SelectBlock", "soloSelectBlock", soloSelectBlockOptions, "changefont");
				break;
		}
	}

	return true;
}





// Add button to toolbar 
soloToolbar.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 = "soloEditButton";

	theLink.href = "#";
	theLink.title = theLabel;
	theLink.className = theClass;
	theLink.action = theAction;
	theLink.onclick = soloToolbarAction;
	theLink.onmouseover = soloToolbarMouseover;

	theLink.appendChild(theText);
	menuItem.appendChild(theLink);
	this.theList.appendChild(menuItem);

	return true;
}




// Add select box to toolbar. theContentArray is an array of string pairs (option value, option label) 
soloToolbar.prototype.addSelect = function(theID, theClass, theContentArray, theAction){
	var menuItem = document.createElement("li");
	var theSelect = document.createElement("select");
	
	menuItem.className = "soloEditSelect";
	
	theSelect.id = theID;
	theSelect.name = theID;
	theSelect.className = theClass;
	theSelect.action = theAction;
	theSelect.onchange = soloToolbarAction;

	for (var i = 0; i < theContentArray.length; i += 2){
		var theOption = document.createElement("option");
		var theText = document.createTextNode(theContentArray[i + 1]);
		
		theOption.value = theContentArray[i];

		theOption.appendChild(theText);
		theSelect.appendChild(theOption);
	}
	
	menuItem.appendChild(theSelect);
	this.theList.appendChild(menuItem);

	return true;
}




// Turn off toolbar items 
soloToolbar.prototype.disable = function(){
	// Change class to disable buttons using CSS 
	this.theList.className += " soloSource";

	// 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 == "soloEditSelect")	{
			// 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;
}




// Turn on toolbar items 
soloToolbar.prototype.enable = function(){
	// Change class to enable buttons using CSS 
	this.theList.className = this.theList.className.replace(/ soloSource/, "");
	
	// 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 == "soloEditSelect")	{
			// 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;
}




// Change the status of the selected toolbar item 
soloToolbar.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;	
}





// Action taken when toolbar item activated 
function soloToolbarAction(){
	var theToolbar = this.parentNode.parentNode.soloToolbarObject;
	var theSoloEditor = theToolbar.soloWYGObject;
	var theIframe = theSoloEditor.theIframe;
	var theSelection = "";

	// If somehow a button other than "HTML source" is clicked while viewing HTML source, ignore click
	if (!theSoloEditor.wysiwyg && this.action != "html"){
		return false;
	}
	
	switch (this.action)	{
		case "formatblock":
			theIframe.contentWindow.document.execCommand(this.action, false, this.value);
			
			theSoloEditor.theToolbar.setState("SelectBlock", this.value);
			
			break;
			
		case "html":
			theSoloEditor.switchMode();
			
			break;
		
		case "changefont":
			//document.getElementById('fontfamily').value = this.value; //iwiletter
			//theIframe.contentWindow.document.getElementById('iframeBody').innerHTML= "<font>" + theIframe.contentWindow.document.getElementById('iframeBody').innerHTML + "</h1>";
			theSoloEditor.theFontFamily.value = this.value;
			theIframe.contentWindow.document.getElementById('iframeBody').style.fontFamily = this.value;
			break;
			
		case "link":
			if (this.parentNode.className.classExists("on")){
				theIframe.contentWindow.document.execCommand("Unlink", false, null);
				theSoloEditor.theToolbar.setState("Link", "off");
			}else{
				if (theIframe.contentWindow.document.selection){
					theSelection = theIframe.contentWindow.document.selection.createRange().text;

					if (theSelection == ""){
						alert("Please select the text you wish to hyperlink.");

						break;
					}
				}else{
					theSelection = theIframe.contentWindow.getSelection();

					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){			
					theIframe.contentWindow.document.execCommand("CreateLink", false, theURL);
					theSoloEditor.theToolbar.setState("Link", "on");
				}
			}
			
			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;
				
				// IE selections
				if (theIframe.contentWindow.document.selection){
					// Escape quotes in alt text 
					theAlt = theAlt.replace(/"/g, "'");
			
					theSelection = theIframe.contentWindow.document.selection;
					theRange = theSelection.createRange();
					theRange.collapse(false);
					theRange.pasteHTML("<img alt=\"" + theAlt + "\" src=\"" + theImage + "\" />");
					
					break;
				}else{ // Mozilla selections 
					try{
						theSelection = theIframe.contentWindow.getSelection();
					}catch (e){
						return false;
					}

					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);
			
			var theAction = this.action.replace(/^./, function(match){return match.toUpperCase();});

			// Turn off unordered toolbar item if ordered toolbar item was activated
			if (this.action == "insertorderedlist"){
				theAction = "Ordered";
				theSoloEditor.theToolbar.setState("Unordered", "off");
			}
			
			// Turn off ordered toolbar item if unordered toolbar item was activated 
			if (this.action == "insertunorderedlist")	{
				theAction = "Unordered";
				theSoloEditor.theToolbar.setState("Ordered", "off");
			}
			
			// If toolbar item was turned on 
			if (theIframe.contentWindow.document.queryCommandState(this.action, false, null)){
				theSoloEditor.theToolbar.setState(theAction, "on");
			}else{
				theSoloEditor.theToolbar.setState(theAction, "off");
			}
	}
	
	if (theSoloEditor.wysiwyg == true){
		theIframe.contentWindow.focus();
	}else{
		theSoloEditor.theTextarea.focus();
	}
	
	return false;	
}




// Check the nesting of the current cursor position/selection 
function soloToolbarCheckState(theSoloEditor, resubmit){
	if (!resubmit)	{
		// Allow browser to update selection before using the selection 
		setTimeout(function(){soloToolbarCheckState(theSoloEditor, true); return true;}, 500);
	}
	
	var theSelection = null;
	var theRange = null;
	var theParentNode = null;
	var theLevel = 0;
	
	// Turn off all the buttons 
	var menuListItems = theSoloEditor.theToolbar.theList.childNodes;
	for (var i = 0; i < menuListItems.length; i++){
		menuListItems[i].className = menuListItems[i].className.removeClass("on");
	}
	
	// IE selections 
	if (theSoloEditor.theIframe.contentWindow.document.selection){
		theSelection = theSoloEditor.theIframe.contentWindow.document.selection;
		theRange = theSelection.createRange();
		try{
			theParentNode = theRange.parentElement();
		}catch (e){
			return false;
		}
	}else{ // Mozilla selections 
		try{
			theSelection = theSoloEditor.theIframe.contentWindow.getSelection();
		}catch (e){
			return false;
		}
		
		theRange = theSelection.getRangeAt(0);
		theParentNode = theRange.commonAncestorContainer;
	}
	
	while (theParentNode.nodeType == 3){
		theParentNode = theParentNode.parentNode;
	}
	
	while (theParentNode.nodeName.toLowerCase() != "body"){
		switch (theParentNode.nodeName.toLowerCase()){
			case "a":
				theSoloEditor.theToolbar.setState("Link", "on");
				
				break;
				
			case "em":
				theSoloEditor.theToolbar.setState("Italic", "on");
				
				break;
				
			case "li":
			
				break;
				
			case "ol":
				theSoloEditor.theToolbar.setState("Ordered", "on");
				theSoloEditor.theToolbar.setState("Unordered", "off");
				
				break;
				
			case "span":
				if (theParentNode.getAttribute("style") == "font-weight: bold;")
				{
					theSoloEditor.theToolbar.setState("Bold", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-style: italic;")
				{
					theSoloEditor.theToolbar.setState("Italic", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-weight: bold; font-style: italic;")
				{
					theSoloEditor.theToolbar.setState("Bold", "on");
					theSoloEditor.theToolbar.setState("Italic", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-style: italic; font-weight: bold;")
				{
					theSoloEditor.theToolbar.setState("Bold", "on");
					theSoloEditor.theToolbar.setState("Italic", "on");
				}
				
				break;
			
			case "strong":
				theSoloEditor.theToolbar.setState("Bold", "on");
				
				break;
			
			case "ul":
				theSoloEditor.theToolbar.setState("Unordered", "on");
				theSoloEditor.theToolbar.setState("Ordered", "off");
				
				break;
			
			default:
				theSoloEditor.theToolbar.setState("SelectBlock", "<" + theParentNode.nodeName.toLowerCase() + ">");
			
				break;
		}
		
		theParentNode = theParentNode.parentNode;
		theLevel++;
	}
	
	return true;			
}




// Turn off browser status display for toolbar items 
function soloToolbarMouseover(){
	window.status = "";
	
	return true;
}




function acceptableChildren(theNode){
	var theChildren = theNode.childNodes;
	
	for (var i = 0; i < theChildren.length; i++){
		if (!theChildren[i].nodeName.isAcceptedElementName())	{
			if (!theChildren[i].nodeName.isInlineName()){
				if (theNode.nodeName.toLowerCase() == "p"){
					acceptableChildren(replaceNodeWithChildren(theNode));
					
					return true;
				}
				
				changeNodeType(theChildren[i], "p");
			}else{
				replaceNodeWithChildren(theChildren[i]);
			}
				
			i = -1;
		}
	}
	
	for (var i = 0; i < theChildren.length; i++){
		acceptableChildren(theChildren[i]);
	}
	
	return true;
}




// Change the type of a node, e.g. h3 to p 
function changeNodeType(theNode, nodeType){
	var theChildren = new Array();
	var theNewNode = document.createElement(nodeType);
	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++){
			theNewNode.appendChild(theChildren[i]);
		}
		
		theParent.replaceChild(theNewNode, theNode);
	}
	
	return true;
}




// 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;
}




// 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;
}




// 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 accepted element 
String.prototype.isAcceptedElementName = function(){
	var elementList = new Array("#text", "a", "em", "h1", "h2", "h3", "h4", "h5", "h6", "img", "li", "ol", "p", "strong", "ul");
	var theName = this.toLowerCase();
	
	for (var i = 0; i < elementList.length; i++)	{
		if (theName == elementList[i]){
			return true;
		}
	}
	
	return false;
}




// Check if a string is the nodeName of an inline element 
String.prototype.isInlineName = function(){
	var inlineList = new Array("#text", "a", "em", "font", "span", "strong", "u");
	var theName = this.toLowerCase();
	
	for (var i = 0; i < inlineList.length; i++){
		if (theName == inlineList[i])	{
			return true;
		}
	}
	
	return false;
}




// Remove a class from a string
String.prototype.removeClass = function(theClass){
	var regString = "(^| )" + theClass + "\W*";
	var regExpression = new RegExp(regString);
	
	return this.replace(regExpression, "");
}




// Reverse a string 
String.prototype.reverse = function(){
	var theString = "";
	
	for (var i = this.length - 1; i >= 0; i--){
		theString += this.charAt(i);
	}
	
	return theString;
}




// Make tags valid by converting uppercase element and attribute names to lowercase and quoting attributes 
String.prototype.validTags = function(){
	var theString = this;
	
	// Replace uppercase element names with lowercase 
	theString = theString.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});
	
	// Replace uppercase attribute names with lowercase 
	theString = theString.replace(/<[^>]*>/g, function(match){
			match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});

			return match;
		});
			
	// Put quotes around unquoted attributes 
	theString = theString.replace(/<[^>]*>/g, function(match){
			match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
			
			return match;
		});
		
	return theString;
}