// JavaScript Document

function pretty_txt(elem){
	
	/* 
	When using callbacks there are two ways to bind this to the current object instance
	1. var _this = this; -> binds the object instace to _this -> _this can then be referenced in a function like this
	2. curry(func,this) -> function has to be set up to use thisArg as this reference and accept thisArg as the first argument.
	*/
	
	// Set Vars
	this.editor;
	this.txtarea;
	this.doc;
	this.win;
	this.plain_txt;
	this.elem_id = elem;
	this.swatches = Array(
		"#ffffff","#000000",
		"#ff0000","#cc0000","#990000","#660000","#330000",
		"#ffff00","#ccff00","#99ff00","#66ff00","#33ff00",
		"#00ff00","#00cc00","#009900","#006600","#003300",
		"#00ffff","#00ccff","#0099ff","#0066ff","#0033ff",
		"#0000ff","#0000cc","#000099","#000066","#000033",
		"#ff00ff","#ff00cc","#ff0099","#ff0066","#ff0033",
		"#ffcc00","#ff9900","#ff6600","#ff3300"
	);
	this.fonts = Array("arial","courier new","georgia","impact","verdana");
	this.sizes = { 1 : "x-small", 2 : "small", 3 : "medium", 4 : "large", 5 : "x-large", 6 : "xx-large" }		
	
	this.make_pretty = function(elem){
		
		/* Get DOM Node Object */
		/* ------------------------------------------- */
		
		if(!elem){ // Use Stored Id 
			this.textarea = (typeof this.elem_id == 'object') ? this.elem_id : document.getElementById(this.elem_id) ;		
		}else{ // Attach to New Id
			this.textarea = (typeof elem == 'object') ? elem : document.getElementById(elem) ;
			this.elem_id = elem;
		}
		
		/* Container + Control Box */
		/* ------------------------------------------- */
		
		//Generate Container
		var container = document.createElement("div");
		container.style.width = this.textarea.offsetWidth + 10 + "px";
		container.textAlign = "center";
		container.style.margin = "auto";
		
		//Control Box
		var ctrl = document.createElement("div");
		ctrl.style.width = this.textarea.offsetWidth + "px";
		ctrl.style.margin = "auto";
		
		//Button Template
		var button = document.createElement("a");
		button.setAttribute("href","javascript:void(0);");
		
		/* Dropdowns */
		/* ------------------------------------------- */		
		
		//menu onclick hide wrapper
		this.menu_hide_wrap = this.curry(this.hide_dd,this);
		
		//Font colour
		this.swatch_content = document.createElement("div");
		for( i in this.swatches ){
			var opt = document.createElement("a");
			opt.style.display = "block";
			opt.style.cssFloat = "left";
			opt.style.styleFloat = "left";
			opt.style.width = "8px";
			opt.style.height = "8px";
			opt.style.margin = "1px";
			opt.style.border = "1px solid #333333";
			opt.style.backgroundColor = this.swatches[i];
			opt.setAttribute("alt",this.swatches[i]);
			opt.setAttribute("title",this.swatches[i]);
			this['fc_'+i] = this.curry(this.rich_cmd,this,"foreColor",this.swatches[i]);		
			this.add_e_handler(opt,'mousedown',this['fc_'+i]);
			this.add_e_handler(opt,'click',this.menu_hide_wrap);	
			this.swatch_content.appendChild(opt);
		}		
		
		//font colour button
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_fc";
		but.setAttribute("alt","Text Colour");
		but.setAttribute("title","Text Colour");		
		this.do_dd_fc = this.curry(this.show_dd,this,this.swatch_content);				
		this.add_e_handler(but,'click',this.do_dd_fc);
		ctrl.appendChild(but);		
		
		//Font Size
		this.size_content = document.createElement("div");
		for( i in this.sizes ){
			var opt = document.createElement("a");
			opt.style.display = "block";
			opt.style.margin = "1px";
			opt.setAttribute("href","javascript:void(0);");
			opt.innerHTML = this.sizes[i];
			this['fs_'+i] = this.curry(this.rich_cmd,this,"fontSize",i);	
			this.add_e_handler(opt,'mousedown',this['fs_'+i]);
			this.add_e_handler(opt,'click',this.menu_hide_wrap);
			this.size_content.appendChild(opt);
		}		
		
		//font size button
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_fs";
		but.setAttribute("alt","Font Size");
		but.setAttribute("title","Font Size");		
		this.do_dd_fs = this.curry(this.show_dd,this,this.size_content);				
		this.add_e_handler(but,'click',this.do_dd_fs);
		ctrl.appendChild(but);
		
		//Font Type
		this.font_content = document.createElement("div");
		for( i in this.fonts ){
			var opt = document.createElement("a");
			opt.style.display = "block";
			opt.style.margin = "1px";
			opt.setAttribute("href","javascript:void(0);");
			opt.innerHTML = this.fonts[i];
			this['ft_'+i] = this.curry(this.rich_cmd,this,"fontName",this.fonts[i]);		
			this.add_e_handler(opt,'mousedown',this['ft_'+i]);
			this.add_e_handler(opt,'click',this.menu_hide_wrap);
			this.font_content.appendChild(opt);
		}		
		
		//Font Type button
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_ft";
		but.setAttribute("alt","Font Type");
		but.setAttribute("title","Font Type");		
		this.do_dd_ft = this.curry(this.show_dd,this,this.font_content);				
		this.add_e_handler(but,'click',this.do_dd_ft);
		ctrl.appendChild(but);
		
		/* Standard Buttons */
		/* ------------------------------------------- */		
			
		//Bold
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_b";
		but.setAttribute("alt","Bold");
		but.setAttribute("title","Bold");
		this.do_b = this.curry(this.rich_cmd,this,"bold");		
		this.add_e_handler(but,'click',this.do_b);
		ctrl.appendChild(but);
		
		//Italic Button
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_i";
		but.setAttribute("alt","Italic");
		but.setAttribute("title","Italic");		
		this.do_i = this.curry(this.rich_cmd,this,"italic");		
		this.add_e_handler(but,'click',this.do_i);
		ctrl.appendChild(but);

		//Underline Button
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_u";
		but.setAttribute("alt","Underline");
		but.setAttribute("title","Underline");		
		this.do_u = this.curry(this.rich_cmd,this,"underline");		
		this.add_e_handler(but,'click',this.do_u);
		ctrl.appendChild(but);

		//Align - L
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_align_l";
		but.setAttribute("alt","Align Left");
		but.setAttribute("title","Align Left");
		this.do_align_l = this.curry(this.rich_cmd,this,"justifyLeft");		
		this.add_e_handler(but,'click',this.do_align_l);
		ctrl.appendChild(but);
		
		//Align - C
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_align_c";
		but.setAttribute("alt","Align Centre");
		but.setAttribute("title","Align Centre");		
		this.do_align_c = this.curry(this.rich_cmd,this,"justifyCenter");		
		this.add_e_handler(but,'click',this.do_align_c);
		ctrl.appendChild(but);

		//Align - R
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_align_r";
		but.setAttribute("alt","Align Right");
		but.setAttribute("title","Align Right");		
		this.do_align_r = this.curry(this.rich_cmd,this,"justifyRight");		
		this.add_e_handler(but,'click',this.do_align_r);
		ctrl.appendChild(but);
		
		//UL
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_ul";
		but.setAttribute("alt","Unordered List");
		but.setAttribute("title","Unordered List");		
		this.do_ul = this.curry(this.rich_cmd,this,"insertUnorderedList");		
		this.add_e_handler(but,'click',this.do_ul);
		ctrl.appendChild(but);

		//OL
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_ol";
		but.setAttribute("alt","Ordered List");
		but.setAttribute("title","Ordered List");		
		this.do_ol = this.curry(this.rich_cmd,this,"insertOrderedList");		
		this.add_e_handler(but,'click',this.do_ol);
		ctrl.appendChild(but);		
		
		//Link
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_link";
		but.setAttribute("alt","Link");
		but.setAttribute("title","Link");		
		this.do_a = this.curry(this.rich_link,this,"createLink","Link URL: ");		
		this.add_e_handler(but,'click',this.do_a);
		ctrl.appendChild(but);
		
		//Image
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_img";
		but.setAttribute("alt","Image");
		but.setAttribute("title","Image");		
		this.do_img = this.curry(this.rich_img,this,"insertImage","Image URL: ");		
		this.add_e_handler(but,'click',this.do_img);
		ctrl.appendChild(but);
		
		//Remove Format
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_r_format";
		but.setAttribute("alt","Remove Formatting");
		but.setAttribute("title","Remove Formatting");		
		this.do_r_format = this.curry(this.rich_cmd,this,"removeFormat");		
		this.add_e_handler(but,'click',this.do_r_format);
		ctrl.appendChild(but);
				
		//Toggle Plain Text
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_src";
		but.setAttribute("alt","Toggle Source Code");
		but.setAttribute("title","Toggle Source Code");		
		this.do_pt = this.curry(this.toggle_plain_txt,this,false);				
		this.add_e_handler(but,'click',this.do_pt);
		ctrl.appendChild(but);
		
		//Expand Editor Area
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_expand_editor";
		but.setAttribute("alt","Expand Editor Area");
		but.setAttribute("title","Expand Editor Area");		
		this.do_ea = this.curry(this.change_editor_size,this,{ 'h' : 200 , 'w' : 0 });				
		this.add_e_handler(but,'click',this.do_ea);
		ctrl.appendChild(but);
								
		//Reduce Editor Area
		var but = button.cloneNode(true);
		but.className = "ptxt_button ptxt_reduce_editor";
		but.setAttribute("alt","Reduce Editor Area");
		but.setAttribute("title","Reduce Editor Area");		
		this.do_ra = this.curry(this.change_editor_size,this,{ 'h' : -200 , 'w' : 0 });				
		this.add_e_handler(but,'click',this.do_ra);
		ctrl.appendChild(but);
								
								
		//Float Clear
		var cb = document.createElement("div");
		cb.style.clear = "both";
		cb.style.height = "1px";
		ctrl.appendChild(cb);
				
		//Insert Control Box into Container
		container.appendChild(ctrl);
		
		/* Editor Window */
		/* ------------------------------------------------ */
		
		//Generate editor div - Styles ( iframe document accessed via element.document in IE and element.contentDocument in w3c )
		var edit_box = document.createElement("iframe");
		var edit_id = this.textarea.id+"_ptxt";
		edit_box.id = edit_id;
		edit_box.style.width = this.textarea.offsetWidth + "px";
		edit_box.style.height = this.textarea.offsetHeight + "px";
		edit_box.style.overflow = "auto";
		edit_box.style.margin = "auto";
		edit_box.className = "ptxt_editor";

		//Insert Control Box into Container
		container.appendChild(edit_box);

		//Insert Editor
		var ta_tmp = this.textarea.cloneNode(true);
		container.appendChild(ta_tmp);
		this.textarea.parentNode.replaceChild(container,this.textarea);
		this.textarea = document.getElementById(this.elem_id);
		this.editor = document.getElementById(edit_id);
		
		//Initialise
		//Initialise has to be attached to the onload event in mozilla as designMode doesn't get assigned unless the element already exists
		//Webkit wont fire the onload unless it is attached before element is added to the document which means that designMode assignment fails
		//However Webkit allows the designMode property to be assigned instantly so calling the init function manually as well solves the issue
		this.c_init = this.curry(this.init,this);
		if(!this.add_e_handler(this.editor,'load',this.c_init)){ // Accounts for delay in loading the iframe - also IE returns true and w3c return undefined
			this.c_init();
		}
		
		//Attach prep src to form submission
		this.prepare_src = this.curry(this.toggle_plain_txt,this,true);	
		this.add_e_handler(this.textarea.form,'submit',this.prepare_src)
		
		//Hide Text Area
		this.textarea.style.display = "none";		
	}
	
	/* Call Back Functions */
	/* ------------------------------------------- */

	this.init = function(_this){
		//Set Win and Doc Vars
		_this.win = (_this.editor.contentWindow) ? _this.editor.contentWindow : _this.editor.window; //obj.contentWindow -> ie5.5+
		_this.doc = (_this.editor.contentDocument) ? _this.editor.contentDocument : _this.win.document; //obj.contentDocument -> ie8+ || obj.contentWindow.document -> ie5.5+
		//Get Text Area Content
		_this.doc.body.innerHTML = _this.textarea.value;
		//Turn on designMode
		_this.doc.designMode = 'On';
	}
	
	this.rich_cmd = function (_this, cmd, arg){
		//alert("this:"+_this+" cmd:"+cmd+" arg:"+arg)
		//_this.win.onfocus = function(){ alert("!"); }
		_this.win.focus();
		_this.doc.execCommand(cmd, false, arg);
	}

	this.rich_cmd_select_wrap = function (_this, cmd, selector_id, e){
		// Call Command
		if( document.getElementById(selector_id).value!=0 ){ _this.rich_cmd(_this, cmd, document.getElementById(selector_id).value); }
		// Reset Selector
		if (!e) var e = window.event;
		if(e.target){
			e.target.selectedIndex=0;
		}else if(e.srcElement){
			e.srcElement.selectedIndex=0;
		}
	}
	
	this.rich_cmd_prompt_wrap = function (_this, cmd, msg, vars){
		var response = _this.cb_prompt(msg,"",vars);
		if(response===false){ return false }
		_this.rich_cmd(_this, cmd, response);
	}
	
	this.rich_link = function (_this, cmd, msg){
		//Get Selection
		var rng = _this.get_range_obj( _this.win , _this.doc );
		var container = document.createElement("div");
		(rng.cloneContents) ? container.appendChild(rng.cloneContents()) : container.innerHTML = rng.htmlText ;
		//Find Links + generate output
		var href = container.innerHTML.match( /<a[^"]+href=(")?[^"]+(")?/gi );
		if(href){
			msg = "\n" + msg;
			for( i=0 ; i < href.length ; i++ ){
				if(typeof href[i] == "string"){
					var m = href[i].match( /href=(")?([^"]+)(")?/i );
					msg = m[2] + "\n" + msg
				}
			}
			msg = "Replacing these links:\n\n" + msg;
		}
		//perform command
		_this.rich_cmd_prompt_wrap(_this, cmd, msg);
	}	

	this.rich_img = function (_this, cmd, msg){
		//Get Selection
		var rng = _this.get_range_obj( _this.win , _this.doc );
		var container = document.createElement("div");
		(rng.cloneContents) ? container.appendChild(rng.cloneContents()) : container.innerHTML = rng.htmlText ;
		//Find Links + generate output
		var href = container.innerHTML.match( /<img[^"]+src=(")?[^"]+(")?/gi );
		if(href){
			msg = "\n" + msg;
			for( i=0 ; i < href.length ; i++ ){
				if(typeof href[i] == "string"){
					var m = href[i].match( /src=(")?([^"]+)(")?/i );
					msg = m[2] + "\n" + msg
				}
			}
			msg = "Replacing these Images:\n\n" + msg;
		}
		var vars = {'mode':'img','w':550,'h':550}
		_this.rich_cmd_prompt_wrap(_this, cmd, msg, vars);
	}

	this.toggle_plain_txt = function (_this, xhtml){
		if(!_this.plain_txt){
			_this.textarea.style.display = "inline";
			_this.textarea.value = (xhtml) ? _this.process_content(_this.doc.body.innerHTML, true) : _this.process_content(_this.doc.body.innerHTML, false) ;
			_this.editor.style.display = "none";
			_this.textarea.focus();
			_this.plain_txt = true;
		}else{
			_this.editor.style.display = "block";
			_this.doc.body.innerHTML = _this.textarea.value;
			_this.textarea.style.display = "none";			
			_this.win.focus();
			_this.plain_txt = false;
		}
	}

	this.change_editor_size = function(_this, data){
		var current = { "h" : parseFloat(_this.editor.style.height.substring(0,_this.editor.style.height.length-2)), "w" : parseFloat(_this.editor.style.width.substring(0,_this.editor.style.width.length-2)) };
		var hn = ( (current.h + data.h) > 0 ) ? (current.h + data.h) : current.h ;
		var wn = ( (current.w + data.w) > 0 ) ? (current.w + data.w) : current.w ;		
		_this.editor.style.height = hn + "px";
		_this.editor.style.width = wn + "px";
	}
	
	this.refocus = function (_this){
		_this.win.focus();
	}

	/* HTML to XHTML + Supporting Replacement Functions */
	/* ------------------------------------------- */
	
	this.process_content = function(str, xhtml){
		
		//&nbsp; over kill
		str = str.replace(/&nbsp;/gi, " ");
		
		//convert to standard output 
		if(xhtml){ str = this.html_to_xhtml(str); }
		
		return str;
		
	}
	
	this.html_to_xhtml = function(str){
		
		//<br>
		str = str.replace(/<br>/gi, "<br />");

		//<img>
		str = str.replace(/<img([^>]*)>/gi, "<img$1 />");

		//Uppercase Tags
		str = str.replace(/<(\/?)([A-Z]+)([^>]*)>/g, this.tags_to_lower);
		
		//Font Tags
		var pft = this.curry(this.process_font_tags,this);
		str = str.replace(/<(\/?)font([^>]*)>/ig, pft);		
		
		return str;
		
	}
	
	this.tags_to_lower = function(str, p1, p2, p3, offset, s){
		p2 = p2.toLowerCase();
		p3 = p3.toLowerCase();
		return "<"+p1+p2+p3+">";
	}
	
	this.process_font_tags = function(_this, str, p1, p2, offset, s){
		var style = "";
		if(p1){ 
			var out = "</span>";
		}else{
			//size
			var size = p2.match( /size=(")?([0-9]+)(")?/i )
			if( size ){ style+= "font-size:"+_this.sizes[size[2]]+";"; }
			//face
			var face = p2.match( /face=(")?([^"]+)(")?/i )
			if( face ){ style+= "font-family:"+face[2]+";"; }
			//color
			var color = p2.match( /color=(")?([^"]+)(")?/i )
			if( color ){ style+= "color:"+color[2]+";"; }			
			//out
			var out = "<span style='"+ style +"'>";
		}
		return out;
	}
	
	/* Drop Menu */
	/* ------------------------------------------- */		
	
	//Show Menu
	this.show_dd = function(_this, content, e){
		if (!e) var e = window.event;
		var target = (e.target) ? e.target : e.srcElement ;
		var pos = _this.get_abs_pos(target);
		var x = pos['x'] + "px";
		var y = ( pos['y'] + target.offsetHeight + 5 ) + "px";
		if(document.getElementById("ptxt_dd")){
			var dd = document.getElementById("ptxt_dd");
			dd.style.display = "block";
			dd.style.left = x;
			dd.style.top = y;
			_this.clear_child_nodes(dd);
			dd.appendChild(content);
		}else{
			var dd = document.createElement("div");
			dd.id = "ptxt_dd";
			dd.style.display = "block";
			dd.style.position = "absolute";
			dd.style.padding = "2px";
			dd.style.left = x;
			dd.style.top = y;
			dd.appendChild(content);
			document.body.appendChild(dd);
			_this.c_act_dd = _this.curry( _this.act_dd, _this)
			_this.add_e_handler(dd, "mouseover", _this.c_act_dd);
		}
	}
	
	//Activate Menu
	this.act_dd = function(_this){
		var dd = document.getElementById("ptxt_dd");
		_this.c_hide_dd = _this.curry( _this.hide_dd, _this);
		_this.add_e_handler(dd, "mouseout", _this.c_hide_dd);
	}
	
	//Hide Menu
	this.hide_dd = function(_this,e){
		var dd = document.getElementById("ptxt_dd");
		//Find what the mouse come from + has moved to
		if (!e) var e = window.event;
		//if the event is a mouseover then do some checks
		if(e.type=="mouseout" || e.type=="onmouseout"){
			var tg = (window.event) ? e.srcElement : e.target;
			var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
			//Kill function if not triggered by dd
			if(tg!=dd) return ;
			//Move up the dom until we hit the element that has mouseout attached
			while (reltg != tg && reltg.nodeName != 'BODY'){
				reltg = reltg.parentNode;
			}
			//if we hit the mouseout attached elem -> reltg is inside tg -> kill func
			if (reltg == tg) return;
		}
		//Hide
		dd.style.display = "none";
		//Deactivate menu
		_this.remove_e_handler(dd, "mouseout", _this.c_hide_dd);		
	}
	
	/* Supporting Methods */
	/* ------------------------------------------- */	
	
	this.ie_prompt = function(str,vars){
		str = str.replace(/\n/gi, "<br />");
		if(vars){
			var w = vars.w;
			var h = vars.h;
		}else{
			var m = str.match( /<br \/>/gi );
			var w = "290"
			var h = (m) ? 15 * m.length + 100 : 100 ;
		}
		var settings = "dialogWidth: "+w+"px; dialogHeight: "+h+"px; center: yes; edge: raised; scroll: no; status: no; resizable: yes;";
		str = {'str':str,'vars':vars}
		return window.showModalDialog("ptxt/resources/ie_prompt.html", str, settings);
	}
	
	this.cb_prompt = function(str,dflt,vars){
		try{
			if(window.showModalDialog && !/AppleWebKit\/530\.5/.test(navigator.userAgent) ){ // AppleWebKit/530.5 has a broken showModalDialogue
				return this.ie_prompt(str, vars); 
			}else{ 
				return prompt(str, dflt); 
			}
		}catch(e){ 
			return false; 
		}
	}
	
	this.get_abs_pos = function(elem){
		var x = 0;
		var y = 0;
		for (var offMark = elem; offMark; offMark = offMark.offsetParent) {
			x += offMark.offsetLeft;
		}
		for (var offMark = elem; offMark; offMark = offMark.offsetParent) {
			y += offMark.offsetTop;
		}
		return { "x":x, "y":y };
	}

	this.clear_child_nodes = function(element){
		if ( element.hasChildNodes() ){
			while ( element.childNodes.length >= 1 ){
				element.removeChild( element.firstChild );       
			} 
		}
	}
		
	this.add_e_handler = function(obj, e, func){
		//test if func exists - prevents problems in IE
		if(typeof func != "undefined"){		
			if(obj.attachEvent){
				return obj.attachEvent('on' + e, func);
			}else if(obj.addEventListener){
				return obj.addEventListener(e, func, false);
			}else{
				obj['on' + e] = func;
			}
		}
	}
	
	this.remove_e_handler = function(obj, e, func){
		//test if func exists - prevents problems in IE		
		if(typeof func != "undefined"){
			if (obj.detachEvent){
				return obj.detachEvent('on' + e, func);
			}else if(obj.removeEventListener){
				return obj.removeEventListener(e, func, false);
			}else{
				obj['on' + e] = null;
			}
		}
	}

	this.curry = function(method){
		var curried = [];
		for (var i = 1; i < arguments.length; i++) {
			curried.push(arguments[i]);
		}
		return function() {
			var args = [];
			for (var i = 0; i < curried.length; i++) {
				args.push(curried[i]);
			}
			for (var i = 0; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			return method.apply(null, args);
		}
	}
	
	this.get_range_obj = function(win_a,doc_a){
		
		//Mozilla - mozilla selection object / w3c range object
		//Opera - mozilla selection object / w3c range object / MS textRange object
		//IE - MS textRange object
		
		var win = (win_a) ? win_a : window ;
		var doc = (doc_a) ? doc_a : document ;
		
		var selObj;
		var rangeObj;
		if(win.getSelection){ //Moz/Opera/Webkit
			selObj = win.getSelection(); //Get Selection Object
			if(selObj.getRangeAt){ //Moz/Opera
				rangeObj =  selObj.getRangeAt(0); //Get w3c range object
			}else{ //Webkit
				var range = doc.createRange(); //Get w3c range object (no getRangeAt support)
				rangeObj.setStart(selObj.anchorNode,selObj.anchorOffset);
				rangeObj.setEnd(selObj.focusNode,selObj.focusOffset);			
			}
		}else if(doc.selection){ //IE
			selObj = doc.selection.createRange(); 	//Get ms textRange Object
			rangeObj =  selObj;
		}
		return rangeObj;
	}	
	
	this.dumpObj = function(obj, name, indent, depth){
		var MAX_DUMP_DEPTH = 10;
		if(depth > MAX_DUMP_DEPTH){
			return indent + name + ": <Maximum Depth Reached>\n";
		}
		if (typeof obj == "object"){
			var child = null;
			var output = indent + name;
			var total = 0;
			if(obj instanceof Array){
				total = obj.length;
				output += " (Array)\n";
			}else{
				for(var item in obj){
				   total++;
				}
				output += " (Object)\n";
			}
			output += indent + "Total item: " + total + "\n";
			indent += "\t";
			if(obj instanceof Array){
				for(var i = 0; i < obj.length; i++){
				   child = obj[i];
				   output += dumpObj(child, i, indent, depth + 1);
				}
			}else{
				for(var item in obj){
				   try{
					   child = obj[item];
				   }catch(e){
					   child = "<Unable to Evaluate>";
				   }
				   if(typeof child == "object"){
					   output += this.dumpObj(child, item, indent, depth + 1);
				   }else{
					   output += indent + item + ": " + child + "\n";
				   }
				}
			}
			return output;
		}else{
			return obj + " is not an object.";
		}
	}

}