﻿/* ---------------------------------------------------------------------- *\
  Global Variables: Set global variables such as images directory, 
	                  WYSIWYG Height, Width, and CSS Directory.
\* ---------------------------------------------------------------------- */

// Images Directory
imagesDir = "ultralight/icons/";

// CSS Directory
cssDir = "ultralight/styles/";

// Popups Directory
popupsDir = "ultralight/popups/";

// Include Style Sheet
document.write('<link rel="stylesheet" type="text/css" href="' +cssDir+ 'styles.css">\n');


/* ---------------------------------------------------------------------- *\
  Toolbar Settings: Set the features and buttons available in the WYSIWYG
	                  Toolbar.
\* ---------------------------------------------------------------------- */

// Order of available commands in toolbar one
var buttonName = new Array();
buttonName[0]  = "bold";
buttonName[1]  = "italic";
buttonName[2]  = "underline";
buttonName[3]  = "seperator";
buttonName[4] = "unorderedlist";
buttonName[5] = "orderedlist";
buttonName[6]  = "seperator";
buttonName[7]  = "cut";
buttonName[8]  = "copy";
buttonName[9]  = "paste";
buttonName[10]  = "seperator";
buttonName[11]  = "undo";
buttonName[12]  = "redo";
buttonName[13]  = "seperator";
buttonName[14]  = "createlink";
buttonName[15]  = "wordclean";
buttonName[16]  = "help";

// List of available actions and their respective ID and images
var ToolbarList = 
{	"bold": ['Bold', 'Bold', imagesDir + 'bold.gif', imagesDir + 'bold_on.gif'],
	"italic": ['Italic', 'Italic', imagesDir + 'italics.gif', imagesDir + 'italics_on.gif'],
	"underline": ['Underline', 'Underline', imagesDir + 'underline.gif', imagesDir + 'underline_on.gif'],
	"seperator": ['', '', imagesDir + 'seperator.gif', imagesDir + 'seperator.gif'],
	"unorderedlist": ['InsertUnorderedList', 'InsertUnorderedList', imagesDir + 'list_unordered.gif', imagesDir + 'list_unordered_on.gif'],
	"orderedlist": ['InsertOrderedList', 'InsertOrderedList', imagesDir + 'list_ordered.gif', imagesDir + 'list_ordered_on.gif'],
	"cut": ['Cut', 'Cut', imagesDir + 'cut.gif', imagesDir + 'cut_on.gif'],
	"copy": ['Copy', 'Copy', imagesDir + 'copy.gif', imagesDir + 'copy_on.gif'],
	"paste": ['Paste', 'Paste', imagesDir + 'paste.gif', imagesDir + 'paste_on.gif'],
	"undo": ['Undo', 'Undo', imagesDir + 'undo.gif', imagesDir + 'undo_on.gif'],
	"redo": ['Redo', 'Redo', imagesDir + 'redo.gif', imagesDir + 'redo_on.gif'],
	"createlink": ['CreateLink', 'CreateLink', imagesDir + 'insert_hyperlink.gif', imagesDir + 'insert_hyperlink_on.gif'],
	"wordclean": ['WordClean', 'WordClean', imagesDir + 'wordclean.gif', imagesDir + 'wordclean_on.gif'],
	"help": ['Help', 'Help', imagesDir + 'help.gif', imagesDir + 'help_on.gif']
};



/* ---------------------------------------------------------------------- *\
  Function    : insertAdjacentHTML(), insertAdjacentText() and insertAdjacentElement()
  Description : Emulates insertAdjacentHTML(), insertAdjacentText() and 
	              insertAdjacentElement() three functions so they work with 
								Netscape 6/Mozilla
  Notes       : by Thor Larholm me@jscript.dk
\* ---------------------------------------------------------------------- */
if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement)
{  HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
	{ switch (where)
		{
			case 'beforeBegin':
				this.parentNode.insertBefore(parsedNode,this)
				break;
			case 'afterBegin':
				this.insertBefore(parsedNode,this.firstChild);
				break;
			case 'beforeEnd':
				this.appendChild(parsedNode);
				break;
			case 'afterEnd':
				if (this.nextSibling) 
			this.parentNode.insertBefore(parsedNode,this.nextSibling);
				else this.parentNode.appendChild(parsedNode);
				break;
		}
	}

	HTMLElement.prototype.insertAdjacentHTML = function (where,htmlStr)
	{	var r = this.ownerDocument.createRange();
		r.setStartBefore(this);
		var parsedHTML = r.createContextualFragment(htmlStr);
		this.insertAdjacentElement(where,parsedHTML)
	}

	HTMLElement.prototype.insertAdjacentText = function (where,txtStr)
	{	var parsedText = document.createTextNode(txtStr)
		this.insertAdjacentElement(where,parsedText)
	}
};


// Create viewTextMode global variable and set to 0
// enabling all toolbar commands while in HTML mode
viewTextMode = 0;


/* ---------------------------------------------------------------------- *\
  Function    : generate_wysiwyg()
  Description : replace textarea with wysiwyg editor
  Usage       : generate_wysiwyg("textarea_id");
  Arguments   : textarea_id - ID of textarea to replace
\* ---------------------------------------------------------------------- */
function generate_wysiwyg(textareaID, wysiwygWidth, wysiwygHeight) 
{

/* Degrade where there is no design mode */
	if ((navigator.userAgent.indexOf('Safari') != -1 ) || !document.getElementById || !document.designMode ) 
	{	//no designMode (Safari lies)
		return;  //leaves standard text box in place
	}
  	// Hide the textarea 
	document.getElementById(textareaID).style.display = 'none'; 
	
	// Pass the textareaID to the "n" variable.
	var n = textareaID;
	
	// Toolbars width is 2 pixels wider than the wysiwygs
	toolbarWidth = parseFloat(wysiwygWidth) + 2;
	
		// Generate WYSIWYG toolbar one
	var toolbar;
	toolbar =  '<table cellpadding="0" cellspacing="0" border="0" class="toolbar1" style="width:' + toolbarWidth + 'px;"><tr><td style="width: 6px;"><img src="' +imagesDir+ 'seperator2.gif" alt="" hspace="3"></td>';
	
	// Create IDs for inserting Font Type and Size drop downs
	// toolbar += '';	toolbar += '';  
	// Output all command buttons that belong to toolbar one
	for (var i = 0; i <= buttonName.length;) 
	{   if (buttonName[i]) 
		{	var buttonObj            = ToolbarList[buttonName[i]];
			var buttonID             = buttonObj[0];
			var buttonTitle          = buttonObj[1];
			var buttonImage          = buttonObj[2];
			var buttonImageRollover  = buttonObj[3];
		 
			if (buttonName[i] == "seperator") 
			{	toolbar += '<td style="width: 12px;" align="center"><img src="' +buttonImage+ '" border=0 unselectable="on" width="2" height="18" hspace="2" unselectable="on"></td>';
			}
			else if (buttonName[i] == "viewSource")
			{	toolbar += '<td style="width: 22px;">';
				toolbar += '<span id="HTMLMode' + n + '"><img src="'  +buttonImage+  '" border=0 unselectable="on" title="' +buttonTitle+ '" id="' +buttonID+ '" class="button" onClick="formatText(this.id,\'' + n + '\');" onmouseover="if(className==\'button\'){className=\'buttonOver\'}; this.src=\'' +buttonImageRollover+ '\';" onmouseout="if(className==\'buttonOver\'){className=\'button\'}; this.src=\'' + buttonImage + '\';" unselectable="on"  width="20" height="20"></span>';
				toolbar += '<span id="textMode' + n + '"><img src="' +imagesDir+ 'view_text.gif" border=0 unselectable="on" title="viewText"          id="ViewText"       class="button" onClick="formatText(this.id,\'' + n + '\');" onmouseover="if(className==\'button\'){className=\'buttonOver\'}; this.src=\'' +imagesDir+ 'view_text_on.gif\';"    onmouseout="if(className==\'buttonOver\'){className=\'button\'}; this.src=\'' +imagesDir+ 'view_text.gif\';" unselectable="on"  width="20" height="20"></span>';
				toolbar += '</td>';
			}
			else 
			{	toolbar += '<td style="width: 22px;"><img src="' +buttonImage+ '" border=0 unselectable="on" title="' +buttonTitle+ '" id="' +buttonID+ '" class="button" onClick="formatText(this.id,\'' + n + '\');" onmouseover="if(className==\'button\'){className=\'buttonOver\'}; this.src=\'' + buttonImageRollover + '\';" onmouseout="if(className==\'buttonOver\'){className=\'button\'}; this.src=\'' + buttonImage + '\';" unselectable="on" width="20" height="20"></td>';
			}
		}
    i++;
  }
	toolbar += '<td>&nbsp;</td></tr></table>';  
	
	// Create iframe which will be used for rich text editing
	var iframe = '<table cellpadding="0" cellspacing="0" border="0" style="width:' + wysiwygWidth + 'px; height:' + wysiwygHeight + 'px; border: 1px solid silver;"><tr><td valign="top">\n'
  + '<iframe frameborder="0" id="wysiwyg' + n + '"></iframe>\n'
  + '</td></tr></table>\n';

	// Insert toolbar after the textArea
	document.getElementById(n).insertAdjacentHTML("afterEnd", toolbar + iframe);

	// Hide the "Text Mode" button
	
	// Give the iframe the global wysiwyg height and width
  document.getElementById("wysiwyg" + n).style.height = wysiwygHeight + "px";
  document.getElementById("wysiwyg" + n).style.width = wysiwygWidth + "px";
	
	// Pass the textarea's existing text over to the content variable
	var content = document.getElementById(n).value;
	
	var doc = document.getElementById("wysiwyg" + n).contentWindow.document;
	
	// Write the textarea's content into the iframe  with style applied
	doc.open();
	doc.write('<style type="text/css" media="screen">body { color: #000000; font-size: 12px; font-family: Arial, Verdana, Tahoma, sans-serif; }</style>' + content);
	doc.close();
	
	// Make the iframe editable in both Mozilla and IE
	doc.body.contentEditable = true;
	doc.designMode = "on";
 
	// Update the textarea with content in WYSIWYG when user submits form
	var browserName = navigator.appName;
	if (browserName == "Microsoft Internet Explorer") 
	{	for (var idx=0; idx < document.forms.length; idx++) 
		{	document.forms[idx].attachEvent('onsubmit', function() { updateTextArea(n); });
		}
	}
	else
	{	for (var idx=0; idx < document.forms.length; idx++) 
		{	document.forms[idx].addEventListener('submit',function OnSumbmit() { updateTextArea(n); }, true);
		}
	}
};

/* ---------------------------------------------------------------------- *\
  Function    : formatText()
  Description : replace textarea with wysiwyg editor
  Usage       : formatText(id, n, selected);
  Arguments   : id - The execCommand (e.g. Bold)
                n  - The editor identifier that the command 
								     affects (the textarea's ID)
                selected - The selected value when applicable (e.g. Arial)
\* ---------------------------------------------------------------------- */
function formatText(id, n, selected) 
{	// When user clicks toolbar button make sure it always targets its respective WYSIWYG
	document.getElementById("wysiwyg" + n).contentWindow.focus();
	// When in Text Mode these execCommands are disabled
	var formatIDs = new Array("FontName","Bold","Italic","Underline","InsertUnorderedList","InsertOrderedList");

	// Check if button clicked is in disabled list
	for (var i = 0; i <= formatIDs.length;) 
	{	if (formatIDs[i] == id) 
		{	var disabled_id = 1;
		}
		i++;
	}

	// Check if in Text Mode and disabled button was clicked
	if (viewTextMode == 1 && disabled_id == 1) 
	{	alert ("You are in HTML Mode. This feature has been disabled.");	
	}
	
	//Insert Image
	else if (id == "InsertImage") 
	{
		window.open(popupsDir + 'insert_image.html?wysiwyg=' + n,'popup','location=0,status=0,scrollbars=0,resizable=0,width=400,height=190');
	}
	
	// CreateLink
	else if (id == "CreateLink") 
	{	window.open(popupsDir + 'insert_hyperlink.html?wysiwyg=' + n,'popup','location=0,status=0,scrollbars=0,resizable=0,width=300,height=110');
	}
	
	// Word Clean
   else if (id == "WordClean")
   {	var getDocument = document.getElementById("wysiwyg" + n).contentWindow.document;
		var iHTML = getDocument.body.innerHTML;
		getDocument.body.innerHTML = CodeCleaner(iHTML);
	}
	
	// ViewSource
	else if (id == "ViewSource")
	{	viewSource(n);
	}
		
	// ViewText
	else if (id == "ViewText")
	{	viewText(n);
	}

	// Help
	else if (id == "Help")
	{	window.open(popupsDir + 'help.html','popup','location=0,status=0,scrollbars=1,resizable=1,width=400,height=500');
	}
	
	// Every other command
	else 
	{	document.getElementById("wysiwyg" + n).contentWindow.document.execCommand(id, false, null);
	}
};

/* ---------------------------------------------------------------------- *\
  Function    : insertHTML()
  Description : insert HTML into WYSIWYG in rich text
  Usage       : insertHTML(<b>hello</b>, "textareaID")
  Arguments   : html - The HTML being inserted (e.g. <b>hello</b>)
                n  - The editor identifier that the HTML 
								     will be inserted into (the textarea's ID)
\* ---------------------------------------------------------------------- */
function insertHTML(html, n) 
{	var browserName = navigator.appName;

	if (browserName == "Microsoft Internet Explorer") 
	{	document.getElementById('wysiwyg' + n).contentWindow.document.selection.createRange().pasteHTML(html);
	}
	else 
	{	var div = document.getElementById('wysiwyg' + n).contentWindow.document.createElement("div");
		div.innerHTML = html;
		var node = insertNodeAtSelection(div, n);
	}
	
}

/* ---------------------------------------------------------------------- *\
  Function    : insertNodeAtSelection()
  Description : insert HTML into WYSIWYG in rich text (mozilla)
  Usage       : insertNodeAtSelection(insertNode, n)
  Arguments   : insertNode - The HTML being inserted (must be innerHTML 
	                           inserted within a div element)
                n          - The editor identifier that the HTML will be 
								             inserted into (the textarea's ID)
\* ---------------------------------------------------------------------- */
function insertNodeAtSelection(insertNode, n) 
{	// get current selection
	var sel = document.getElementById('wysiwyg' + n).contentWindow.getSelection();
	
	// get the first range of the selection
	// (there's almost always only one range)
	var range = sel.getRangeAt(0);
	
	// deselect everything
	sel.removeAllRanges();
	
	// remove content of current selection from document
	range.deleteContents();
	
	// get location of current selection
	var container = range.startContainer;
	var pos = range.startOffset;
	
	// make a new range for the new selection
	range=document.createRange();
	
	if (container.nodeType==3 && insertNode.nodeType==3) 
	{	// if we insert text in a textnode, do optimized insertion
		container.insertData(pos, insertNode.nodeValue);
		
		// put cursor after inserted text
		range.setEnd(container, pos+insertNode.length);
		range.setStart(container, pos+insertNode.length);
	}
	else 
	{	var afterNode;
		if (container.nodeType==3) 
		{	// when inserting into a textnode
			// we create 2 new textnodes
			// and put the insertNode in between
			
			var textNode = container;
			container = textNode.parentNode;
			var text = textNode.nodeValue;
			
			// text before the split
			var textBefore = text.substr(0,pos);
			// text after the split
			var textAfter = text.substr(pos);
			
			var beforeNode = document.createTextNode(textBefore);
			afterNode = document.createTextNode(textAfter);
			
			// insert the 3 new nodes before the old one
			container.insertBefore(afterNode, textNode);
			container.insertBefore(insertNode, afterNode);
			container.insertBefore(beforeNode, insertNode);
			
			// remove the old node
			container.removeChild(textNode);
		} 
		else 
		{	// else simply insert the node
			afterNode = container.childNodes[pos];
			container.insertBefore(insertNode, afterNode);
		}
		range.setEnd(afterNode, 0);
		range.setStart(afterNode, 0);
	}
	sel.addRange(range);
};	

/* ---------------------------------------------------------------------- *\
  Function    : viewSource()
  Description : Shows the HTML source code generated by the WYSIWYG editor
  Usage       : showFonts(n)
  Arguments   : n   - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
function viewSource(n) 
{	var getDocument = document.getElementById("wysiwyg" + n).contentWindow.document;
	var browserName = navigator.appName;
	
	// View Source for IE 	 
  if (browserName == "Microsoft Internet Explorer") 
	{	var iHTML = getDocument.body.innerHTML;
		getDocument.body.innerText = iHTML;
	}
 
	// View Source for Mozilla/Netscape
	else 
	{	var html = document.createTextNode(getDocument.body.innerHTML);
		getDocument.body.innerHTML = "";
		getDocument.body.appendChild(html);
	}

	// Hide the HTML Mode button and show the Text Mode button
	document.getElementById('HTMLMode' + n).style.display = 'none'; 
	document.getElementById('textMode' + n).style.display = 'block';
	
	// set the font values for displaying HTML source
	getDocument.body.style.fontSize = "12px";
	getDocument.body.style.fontFamily = "Courier New"; 
	
  viewTextMode = 1;
};

/* ---------------------------------------------------------------------- *\
  Function    : viewSource()
  Description : Shows the HTML source code generated by the WYSIWYG editor
  Usage       : showFonts(n)
  Arguments   : n   - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
function viewText(n) { 
  var getDocument = document.getElementById("wysiwyg" + n).contentWindow.document;
  var browserName = navigator.appName;
	
	// View Text for IE 	  	 
  if (browserName == "Microsoft Internet Explorer") {
    var iText = getDocument.body.innerText;
    getDocument.body.innerHTML = iText;
	}
  
	// View Text for Mozilla/Netscape
  else {
    var html = getDocument.body.ownerDocument.createRange();
    html.selectNodeContents(getDocument.body);
    getDocument.body.innerHTML = html.toString();
	}
  
	// Hide the Text Mode button and show the HTML Mode button
  document.getElementById('textMode' + n).style.display = 'none'; 
	document.getElementById('HTMLMode' + n).style.display = 'block';
	
	// reset the font values
  getDocument.body.style.fontSize = "";
	getDocument.body.style.fontFamily = ""; 
	viewTextMode = 0;
};

/* ---------------------------------------------------------------------- *\
  Function    : CodeCleaner()
  Description : Attempts to clean up after MS Word paste
  Usage       : CodeCleaner(code)
  Arguments   : code   - Text to clean up
\* ---------------------------------------------------------------------- */

function CodeCleaner(code){

   code = code.replace(/<([\w]+) class=([^ |>]*)([^>]*)/gi, '<$1$3');
   code = code.replace(/<([\w]+) style="([^"]*)"([^>]*)/gi, '<$1$3');
   
   code = code.replace(/width=([^ |>]*)([^>]*)/gi, '');
   code = code.replace(/type=([^ |>]*)([^>]*)/gi, '');
   code = code.replace(/classname=([^ |>]*)([^>]*)/gi, '');
   code = code.replace(/align=([^ |>]*)([^>]*)/gi, '');
   code = code.replace(/valign=([^ |>]*)([^>]*)/gi, '');
   code = code.replace(/<\\?\??xml[^>]>/gi, '');
   code = code.replace(/<\/?\w+:[^>]*>/gi, '');
   code = code.replace(/<st1:.*?>/gi, '');
   code = code.replace(/o:/gi, '');

   code = code.replace(/<span([^>])*>(&nbsp;)*\s*<\/span>/gi, '');
   code = code.replace(/<span[^>]*>/gi, '');
   code = code.replace(/<\/span[^>]*>/gi, '');
   
   code = code.replace(/<font[^>]*>/gi, '');
   code = code.replace(/<\/font>/gi, '');

   code = code.replace(/<p([^>])*>(&nbsp;)*\s*<\/p>/gi, '');
   code = code.replace(/<p[^>]*>/gi, '');
   code = code.replace(/<\/p[^>]*>/gi, '');

   code = code.replace(/<h([^>])[0-9]>(&nbsp;)*\s*<\/h>/gi, '');
   code = code.replace(/<h[^>][0-9]>/gi, '');
   code = code.replace(/<\/h[^>][0-9]>/gi, '');

   return code;
}



/* ---------------------------------------------------------------------- *\
  Function    : updateTextArea()
  Description : Updates the text area value with the HTML source of the WYSIWYG
  Usage       : updateTextArea(n)
  Arguments   : n   - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
function updateTextArea(n) {
  document.getElementById(n).value = document.getElementById("wysiwyg" + n).contentWindow.document.body.innerHTML;
};