var doc = document; // shorten document for easier coding
//var code_id; // place holder to store id of code we are working with
var cursor_pos;
var id_count = 1;
var last_element; // used to track element info prior to clicking on a button in toolbar
var current_element;
var color_type = "ForeColor"; // this is set right before opening a color picker, so color_click() knows what color to change
var evt_x; // to grab event coordinates
var evt_y; // to grab event coordinates
var current_div; // reference to div element that is being modified via popup
var current_design; // reference to current design div
var current_editor; // reference to current editor, including toolbars, design, code, etc....
var current_code; 	// reference to current code window (textarea)
var lastTabClicked; // reference to the img tag clicked to activate the current tab
var mode; // either "design" or "code"


// function called when body is clicked on
// only need to add to body tag if another onclick has been added prior, else, click_design adds this function the body.onload on first click of editor
function body_click() {
	hide_color_picker(); 
	track_elements();
}


// make all elements accept for form fields unselectable, so editor can't be copied and pasted into itself
function make_unselectable() {
	var all = document.all;
	var l = all.length;
	for (var i = 0; i < l; i++) {
		if (all[i].tagName != "INPUT" && all[i].tagName != "TEXTAREA" && all[i].name != "design_window" && all[i].tagName != "DIV") all[i].unselectable = "on";
	}
}

// track elements
function track_elements(){
	last_element = current_element;
	current_element = document.activeElement;
	loop_count = 0;	
	//alert("clicked on: " + current_element.id + " " + current_element.tagName);

	// if a design div was just clicked
	if (current_element.contentEditable == "bypass") {
		current_design = current_element;
	} else {
		
		// climb through parents until we find the one with the name property of "rt_editor"...this is the top level parent
		// div (or whatever) for the editor
		temp_el = current_element;
		top_el = "";

		while (temp_el.parentElement) {
			loop_count++;
			//alert("temp el ID: " + temp_el.id + ", tag name: " + temp_el.tagName + " name: " + temp_el.name);
			if (temp_el.name == "rt_editor") {
				top_el  = temp_el;
				current_editor = top_el;
				break;
			} else {
				temp_el = temp_el.parentElement;
			}
		}
		
		// find 1st element below this one that is contenteditable
		//alert(document.elements);
		if (top_el.name == "rt_editor") {
			divs = top_el.getElementsByTagName("DIV");
			//alert(divs);
			for(x=0;divs[x];x++) {
				if (divs[x].contentEditable == "true") current_design = divs[x];
			}
			//current_design = "";
		}
		
		// current code window (textarea)
		current_code = get_code_window();
	}
	
	//alert("current design: " + current_design.id + " \nlooped " + loop_count + " times through top parent " + top_el.id + " div of editor");
	
	//alert("content editable property: " + current_element.contentEditable + ", content editable method: " + current_element.isContentEditable);
	//next_sib = current_element.nextSibling;
	//alert("next sib: " + next_sib.tagName + ", " + next_sib.id);
}

function get_current_editor() {
	// used before initial click....to grab current editor
	if (current_editor) {
		return current_editor;
	} else {
		track_elements();
		return current_editor;
	}
}

function get_current_design() {
	if (current_design) {
		return current_design;
	} else {
		track_elements();
		return current_design;
	}
}

// purpose of function is to return an element reference by name,
// if that element is inside the element specified by parent_el
function get_child_by_name(parent_el,child_name) {
	if (typeof(parent_el) == "undefined" || typeof(child_name) == "undefined") return;
	//alert("checking now for " + child_name);
	elements = document.getElementsByName(child_name);
	if (elements) {

		//alert("found elements");
		
		for(x=0;elements[x];x++) {
			//alert ("looping...element tagName: "+ elements[x].tagName + " className: " + elements[x].className);
			if (parent_el.contains(elements[x])) {
				//alert("found it: " + elements[x].tagName);
				return elements[x];
			}
		}
	}
}


// purpose of function is to return an element reference by className,
// if that element is inside the element specified by parent_el
// and the class name is only used once inside the parent element
// specify tag_type (uppercase) to limit search to only certain tags
function get_child_by_classname(parent_el,class_name,tag_type) {
	if (typeof(parent_el) == "undefined" || typeof(class_name) == "undefined") return;
	//alert("checking now for " + child_name);
	elements = document.getElementsByTagName(tag_type);
	if (elements) {
		//alert("found elements");
		for(x=0;elements[x];x++) {
			//alert ("in loop...element tagName: "+ elements[x].tagName + " className: " + elements[x].className);
			if (elements[x].className == class_name){
				//alert("match");
				if (parent_el.contains(elements[x])) {
					//alert("found it: " + elements[x].tagName);
					return elements[x];
				}
			}
		}
	}
}

// purpose of function is to return an element reference to the textarea field inside editor, 
// relies on the class name being "code_window"
function get_code_window() {
	elements = document.getElementsByTagName("TEXTAREA");
	if (elements) {
		for(x=0;elements[x];x++) {
			//alert ("looping");
			if (get_current_editor().contains(elements[x])) {
				//alert("found it: " + elements[x].tagName + " class name: " + elements[x].className);
				return elements[x];
			}
		}
	}
}


// determine true left pixel pos of element
function get_element_left(eElement)
{
    var nLeftPos = eElement.offsetLeft;          // initialize var to store calculations
    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nLeftPos += eParElement.offsetLeft;      // appending left offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nLeftPos;                             // return the number calculated
}

// determine true top pixel pos of element
function get_element_top(eElement)
{
    var nTopPos = eElement.offsetTop;            // initialize var to store calculations
    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nTopPos += eParElement.offsetTop;        // appending top offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nTopPos;                              // return the number calculated
}



// track cursor position inside divs, and store in cursor_pos...must be called onclick and onkeypress from contenteditable div tag
function save_cursor_pos(){
	if (doc.selection != null && doc.selection.type == "Text") cursor_pos=document.selection.createRange().duplicate();
}





// paste string as HTML into current cursor position
function insert_html(str){
	var sel = document.selection;
	
	// replace selected text with str
	if (sel!=null) {
		rng = sel.createRange();
		if (rng.text != "") {
			rng.pasteHTML(str);
		} else {
			// else, insert text at cursor position
			if(str && cursor_pos) cursor_pos.pasteHTML(str);
			cursor_pos.select();
		}
	}
}


function div_style(style_str) {
	if (document.selection.type == "Control"){ 
		var oControlRange = document.selection.createRange();
		for (i = 0; i < oControlRange.length; i++)
			if (oControlRange(i).tagName == "DIV"){
				oControlRange(i).style.cssText += (';' + style_str);

				//alert("after: " + oControlRange(i).style.cssText);
				//oControlRange(i).style.border="black solid 1px";
			}
		}
}

function set_current_div() {
	track_elements();
	
	current_div = "";
	if (document.selection.type == "Control"){ 
		var oControlRange = document.selection.createRange();
		for (i = 0; i < oControlRange.length; i++)
			if (oControlRange(i).tagName == "DIV"){
				current_div = oControlRange(i);
				//alert("after: " + oControlRange(i).style.cssText);
				//oControlRange(i).style.border="black solid 1px";
			}
		}
}



// purpose is to surround current selection with HTML
function surround_html(str_start,str_end){
	var sel = document.selection;
	if (sel!=null && sel.type=="Text") {
		rng = sel.createRange();
		if (rng.text != "") {
			rng.pasteHTML(str_start + rng.text + str_end);
		}
	}
}

//test
function insert_text_box() {
    var oNode=document.createElement("div");
    get_current_design().insertBefore(oNode);
//    oNode.style.fontFamily=oTxtFont;
    oNode.innerText='Enter some text here';
    id_count++
    var iTempCount = "text" + id_count;
    oNode.id = iTempCount;
    oNode.style.position='absolute';
    
    <!-- Set the new text as the active element for editing. -->
    oNode.setActive();
    document.execCommand("2D-Position", true, true);

}

// function to handle any formatting command
function format(action){
	
//	var sel = document.selection;
//	if (sel!=null) {
//		alert(sel.createRange().text);
//	}
	// only some format actions will require a call to focus, hence the if statement
	switch (action) {
		case "JustifyCenter":
		case "JustifyLeft":
		case "JustifyRight":
			get_current_design().focus(); // apply focus when needed
			doc.execCommand(action); // simplest method...no parameters
			click_design();
			break;
		case "InsertHorizontalRule":
		case "SelectAll":
		//case "InsertImage":
		case "CreateLink":
		case "Indent":
		case "Outdent":
		case "InsertOrderedList":
		case "InsertUnorderedList":
			get_current_design().focus(); // apply focus when needed
		case "InsertImage":
		case "CreateLink":
			doc.execCommand(action,true); // for commands that need a user prompt
			break;
		default:
			get_current_design().focus(); // apply focus when needed...this keeps people from formatting things outside the div!
			doc.execCommand(action,true); // simplest method...no parameters
	}
	click_design(); // so button state is set properly
}

function change_font(name) {
	get_current_design().focus(); // apply focus when needed...this keeps people from formatting things outside the div!
	doc.execCommand("FontName", false, name);
	click_design(); // so button state is set properly
}

function change_fontsize(size) {
	get_current_design().focus(); // apply focus when needed...this keeps people from formatting things outside the div!
	doc.execCommand("FontSize", false, size);
	click_design(); // so button state is set properly
}

function set_button_state(action){
	// pass this function an action name, and it will set the button state according to whether the action
	// was performed on the selection
	//alert("action : " + action);
	button = get_child_by_name(get_current_editor(),action);
	
	if (doc.queryCommandState(action)) {
		button.className = "button_active";
		//doc.getElementById(code_id + "_" + action).className = "button_active";
	} else {
		button.className = "button";
		//doc.getElementById(code_id + "_" + action).className = "button";
	}
}


// purpose is to handle the popup window to insert a new image
function selectImage() {
	window.open('image_select.php','newwin','menubar=0,scrollbars=1,resizable=1');
}

function addImage(imgPath) {
	get_current_design().focus(); // apply focus when needed
	doc.execCommand('InsertImage',false,imgPath); // for commands that need a user prompt
}



function click_design() {
	
	// add the onclick function to the body, if its not there
	if (!document.body.onclick) document.body.onclick = function anonymous(){body_click()};
	
	// purpose of this function is to gather info from design area each time it is clicked..
	// this is used to grab the font name, size, etc...and automatically set the select inputs
	// in the toolbar accordingly
	var current_font = doc.queryCommandValue("FontName"); // grab current font name
	var current_fontsize = doc.queryCommandValue("FontSize"); // grab current font size
//	alert (current_fontsize);
	get_child_by_name(get_current_editor(),"fontname").value = current_font; // set current font name in drop down
	get_child_by_name(get_current_editor(),"fontsize").value = current_fontsize; // set current font size in drop down
	//doc.getElementById(code_id + "_rt_form").fontsize.value = current_fontsize; // set current font size in drop down

	// below section will make buttons look pressed if the actions were applied to the selection
	set_button_state("bold");
	set_button_state("italic");
	set_button_state("underline");
	set_button_state("strikethrough");
	set_button_state("insertorderedlist");
	set_button_state("insertunorderedlist");
	set_button_state("justifycenter");
	set_button_state("justifyleft");
	set_button_state("justifyright");
}


function click_toolbar(toolbar) {
	if (mode == "code") {
		if (current_editor.contains(toolbar)){
			if (confirm("Would you like to switch to Design View? Any changes you made in Code View will be kept.")) design_tab_active(lastTabClicked.parentNode.nextSibling.firstChild);
		}
	}
}

function design_tab_active (src_element) {
	mode = "design";
	
	lastTabClicked = src_element;
	
	// store the active window (code or design) in the editor...will be used on form post to copy design code to textarea field if needed
	get_current_editor().activeWindow = mode;

	track_elements();
	
	// this is the span that contains the current visible tabs
	spanRef = src_element.parentElement;

	// hide this span, show the one for when code tab is on....
	spanRef.style.display='none';	
	spanRef.previousSibling.style.display='';	
	
	
	// copy any code entered into the code window into the design window
	if (typeof(get_code_window().value) == 'string') get_current_design().innerHTML = get_code_window().value;
	// show design window
	get_current_design().style.display = "block";
	
	// hide code window
	get_code_window().parentElement.style.display = "none";

	// show toolbar
	toolbar = get_child_by_classname(current_editor,"toolbar_disabled","DIV");
	if (toolbar) {
		toolbar.className = "toolbar";
	
		// enable links
		links = document.getElementsByTagName("A");
		for(x=0;links[x];x++) {
			if (toolbar.contains(links[x])) {
				enableLink(links[x]);
				//alert("disabled " + links[x].innerHTML);
			}
		}

		// enable form fields inside toolbar
		get_child_by_name(get_current_editor(),"fontname").disabled = false;
		get_child_by_name(get_current_editor(),"fontsize").disabled = false;
	}
}

function code_tab_active (src_element,dontChangeVis) {
	// dontChangeVis when passed as true will keep the tabs the same (won't swap them)
	mode = "code";
	
	lastTabClicked = src_element;

	// store the active window (code or design) in the editor...will be used on form post to copy design code to textarea field if needed
	get_current_editor().activeWindow = mode;

	track_elements();
	
	// grab some references
	currentDesign 	= get_current_design();
	currentCode 	= get_code_window(); 
	
	// grab html code from textarea, and fix formatting
	//hdata = fix_html(get_current_design().innerHTML);
	if (currentDesign) var hdata = currentDesign.innerHTML;
	
	// populate code window (textarea) with changes made in design window
	if (typeof(hdata) == 'string') currentCode.value = hdata;

	if (!dontChangeVis) {
		// this is the span that contains the current visible tabs
		spanRef = src_element.parentElement;
		// hide this span, show the one for when code tab is on....
		spanRef.style.display='none';	
		spanRef.nextSibling.style.display='';	
	
		// hide the design window
		currentDesign.style.display = "none";
		
		// show the code window
		currentCode.parentElement.style.display = "block";
	
		// hide toolbar
		toolbar = get_child_by_classname(current_editor,"toolbar","DIV");
		if (toolbar) {
			toolbar.className = "toolbar_disabled";
			toolbar.unselectable = "on";
	
			// disable links
			links = document.getElementsByTagName("A");
			for(x=0;links[x];x++) {
				if (toolbar.contains(links[x])) {
					disableLink(links[x]);
					links[x].unselectable = "true";
					links[x].className = "button";
					//alert("disabled " + links[x].innerHTML);
				}
			}
		
			// disable form fields inside toolbar
			get_child_by_name(get_current_editor(),"fontname").disabled = true;
			get_child_by_name(get_current_editor(),"fontsize").disabled = true;
		}
	}
}





function cancelLink () {
  return false;
}

function disableLink (link) {
	if (link.href) {
  		link.oldHref = link.href;
  		link.removeAttribute("href");
  	}
	if (link.onclick) {
  		link.oldOnClick = link.onclick;
  		link.onclick = cancelLink;
  	}
	if (link.onmouseover) {
		link.oldOnMouseOver = link.onmouseover;
		link.onmouseover = cancelLink;
	}
	if (link.onmouseout) {
		link.oldOnMouseOut = link.onmouseout;
  		link.onmouseout = cancelLink;
	}
  	if (link.style) link.style.cursor = 'default';
}

function enableLink (link) {
	link.href = link.oldHref ? link.oldHref : null;
	link.onclick = link.oldOnClick ? link.oldOnClick : null;
	link.onmouseover = link.oldOnMouseOver ? link.oldOnMouseOver : null;
	link.onmouseout = link.oldOnMouseOut ? link.oldOnMouseOut : null;
	if (link.style) link.style.cursor = "default";
}






function fix_html(hdata){
	// cleanup html to remove problems generated by IE formatting
	hdata = hdata.replace(/\r\n/g, ''); 
	hdata = hdata.replace(/\n/g, ''); 
	hdata = hdata.replace(/\r/g, '');       
	hdata = hdata.replace(/\&nbsp\;/g,''); 
	// keep tags, strip attributes 
	hdata = hdata.replace(/ class=[^\s|>]*/gi,''); 
	//hdata = hdata.replace(/<p [^>]*TEXT-ALIGN: justify[^>]*>/gi,'<p align="justify">'); 
	hdata = hdata.replace(/ style=\"[^>]*\"/gi,''); 
	//clean up tags 
	hdata = hdata.replace(/<b [^>]*>/gi,'<b>'); 
	hdata = hdata.replace(/<i [^>]*>/gi,'<i>'); 
	hdata = hdata.replace(/<li [^>]*>/gi,'<li>'); 
	hdata = hdata.replace(/<ul [^>]*>/gi,'<ul>'); 
	// replace outdated tags 
	hdata = hdata.replace(/<b>/gi,'<strong>'); 
	hdata = hdata.replace(/<\/b>/gi,'</strong>'); 
	hdata = hdata.replace(/<i>/gi,'<em>'); 
	hdata = hdata.replace(/<\/i>/gi,'</em>'); 
	// kill unwanted tags 
	hdata = hdata.replace(/<\?xml\:[^>]*>/g, ''); // Word xml 
	hdata = hdata.replace(/<\/?st1\:[^>]*>/g,''); // Word SmartTags 
	hdata = hdata.replace(/<\/st1\:[^>]*>/g,''); // 
	hdata = hdata.replace(/<st1\:[^>]*>/g,''); // 
	hdata = hdata.replace(/<\/?[a-z]\:[^>]*>/g,''); // All other funny Word non-HTML stuff 
	hdata = hdata.replace(/<\/[a-z]\:[^>]*\/>/g,''); // 
//	hdata = hdata.replace(/<\/?font[^>]*>/gi,''); // Disable if you want to keep font formatting 
	hdata = hdata.replace(/<\/?span[^>]*>/gi,''); 
	hdata = hdata.replace(/<span[^>]*>/gi,''); 
	hdata = hdata.replace(/<\/?div[^>]*>/gi,''); 
	//remove empty tags 
	hdata = hdata.replace(/<strong><\/strong>/gi,''); 
	hdata = hdata.replace(/<P[^>]*><\/P>/gi,''); 
	return hdata;
}

// functions for color picker
function show_picker(color_typer,x,y){
	color_type = color_typer; // this sets the global var named color_type to whatever is passed as color_typer. this s/be "ForeColor" or "BackColor"
	//function shows color picker popup for text color
	picker = doc.getElementById("color_picker"); // grab picker element reference
	picker.style.display = ""; // display picker
	// move picker to mouse coordinates
	picker.style.left = x + content.scrollLeft;
	picker.style.top = y + content.scrollTop - 25;

	// set position of iframe right behind the div, so it will cover up select inputs
	shim = document.getElementById("color_picker_shim");
	shim.style.width = picker.offsetWidth; 
	shim.style.height = picker.offsetHeight; 
	shim.style.top = picker.style.top; 
	shim.style.left = picker.style.left; 
	shim.style.zIndex = picker.style.zIndex - 1; 
	shim.style.display = "block"; 
}


function hide_color_picker () {
	doc.getElementById("color_picker").style.display = "none";
	doc.getElementById("color_picker_shim").style.display = "none";
}

function color_over (cname, ccode, obj){
	obj.style.borderTop = 'gray solid 1px' ; obj.style.borderLeft = 'gray solid 1px' ; obj.style.borderRight = 'white solid 1px' ; obj.style.borderBottom = 'white solid 1px' ;
	doc.getElementById('color_picker_preview').style.background = ccode
	doc.getElementById('color_picker_preview_name').innerHTML = cname
	doc.getElementById('color_picker_preview_code').innerHTML = "#" + ccode
}

function color_out (obj){
	obj.style.borderTop = 'white solid 1px' ; obj.style.borderLeft = 'white solid 1px' ; obj.style.borderRight = 'gray solid 1px' ; obj.style.borderBottom = 'gray solid 1px' ;
}

function color_click (ccode){
	// if color_type is ForeColor or BackColor, then we are altering text....
	if (color_type == "ForeColor" || color_type == "BackColor") {
		get_current_design().focus();
		doc.execCommand(color_type, false, ccode);
	} else {
		// else, we are altering a style of a selected div, via a popup window
		if (color_type == "border-color") {
			change_border("color",ccode); 
			document.getElementById("border_color_preview").style.backgroundColor = ccode;
		}
		if (color_type == "background-color") {
			window.opener.div_style("background-color: " + ccode); 
			document.getElementById("bg_preview").style.backgroundColor = ccode;
		}
		window.focus()
	}
	hide_color_picker();
	// document.selection.empty(); // unselect text
}


function richTextSubmit() {
	// this function is called from the record_submit() function....
	// purpose is to copy any changes made in design mode to the textarea field
	// only if the activeWindow when the form was submitted was design
	// grab array containing all DIVs
	
	// bail if no editing was done
	if (!current_editor) return;
	
	divs = document.getElementsByTagName('DIV');
	
	// loop through all divs
	for(i=0; i < divs.length; i++) {
		div = divs[i];
		// find the editors...
		if (div.name == "rt_editor") {
			// activeWindow will = design when the design tab was clicked...
			// on first load, activeWindow won't be set, but design will be visibile
			if (div.activeWindow == 'design' || !div.activeWindow) {
				code_tab_active(div, true);
			}
		}
	}
	
}





/**********************************************************************
	Purpose of function is to control whether the horizontal
	separators between toolbars should be visible or not. It requires
	the img tag for the separators be right up against the openining
	and closing divs, like this:
	<div>blah</div><img name="RT_horiz_sep" /></div>
**********************************************************************/
function toggleSeparators(fName) {
	// grab all horizontal separators
	sepsRef = document.getElementsByName('RT_horiz_sep');
	
	// loop through separators
	for(i=0; i < sepsRef.length; i++) {
		if (sepsRef[i].nextSibling.id.indexOf(fName) != -1) {
			// if the div b4 this separator is visible
			if (sepsRef[i].previousSibling.id.indexOf(fName) != -1 && sepsRef[i].previousSibling.style.display != 'none') {
				// if div after this one is visible
				if (sepsRef[i].nextSibling.id.indexOf(fName) != -1 && sepsRef[i].nextSibling.style.display != 'none') {
					showSep = true;
					// if next div is visible
				} else if (sepsRef[i+i]) {
					if (sepsRef[i+1].nextSibling.id.indexOf(fName) != -1 && sepsRef[i+1].nextSibling.style.display != 'none') {
						showSep = true;
					} else if (sepsRef[i+2]) {
						if (sepsRef[i+2].nextSibling.id.indexOf(fName) != -1 && sepsRef[i+2].nextSibling.style.display != 'none') {
							showSep = true;
						} else {
							showSep = false;
						}
					} else {
						showSep = false;
					}
				} else {
					showSep = false;
				}
			} else {
				showSep = false;
			}
		
			if(showSep) {
				sepsRef[i].style.display = 'block';
			} else {
				sepsRef[i].style.display = 'none';
			}
		}
	}
}

