function Trace()
{	
		// PUBLIC PROPERTIES
		// BEGINNNING OF STRUCTURE BUILDING METHODS
		this.__beginHTML = function()
		{
			html  = '<html>\n';
			html += '<head>\n';
			return html;
		}
		this.__buildMainScriptBlock = function()
		{
			script  = "<script langauge='javascript'>\n";
			script += "</script>\n";
			return script;
		}
		this.__buildPrefsScriptBlock = function()
		{
			script  = "<script langauge='javascript'>\n";
			script += "</script>\n"
			
			
			return script;
		}
		this.__buildMainStyleBlock = function()
		{
			style  = "<style>\n";
			style += "body{margin:0;padding:0;overflow:hidden;color:white;}\n";
			style += "table td{border: 1px solid gray}\n";
			style += "#traceContainer{height:100%;width:100%;background-color:black;color:white;font-family:courier;font-size:11px;}\n";
			style += "#traceHeader{height:20px;background-color:gray;text-align:right;}\n";
			style += "#traceBody{width:100%;height:100%}\n";
			style += "#traceIFrame,#prefsIFrame{height:100%;width:100%;overflow:auto;border:0}\n";
			style += "#prefsIFrame{display:none}\n";
			style += "#traceFooter{height:20px;background-color:gray;}\n";
			style += "#traceFooterText{height:59px;width:100%;background-color:gray;overflow-y:auto;border:0;color:white;font-family:courier;line-height:11px;font-size:11px}\n";
			style += ".options{padding:0 2px 0 2px;border:1px solid white;cursor:default;}";
			style += "</style>\n";
			return style;
		}
		this.__buildIFrameStyleBlock = function()
		{
			style  = "<style>\n";
			style += "body{background-color:black;color:white;margin:0;padding:5px;overflow:auto;border:none;font-family:courier;font-size:11px}\n";
			style += "fieldset{border:1px solid gray;padding:5px;color:white;}";
			style += "legend{font-weight:bold;color:white;}";	
			style += "fieldset span{height:10px;margin-bottom:5px;}";
			style += "#traceItemGroup{margin:0;padding:0;list-style-type:none;color:white;border-bottom:1px dashed gray;}\n";
			style += "#traceItemGroup li{text-indent:-33px;margin-left:32px;padding-bottom:2px;}"
			style += ".traceItem span,.traceItemSelected span{padding-right:10px;}"
			style += ".traceItem, .traceItemSelected{border-left:1px solid gray;padding-left:4px;}\n";
			style += ".traceItemSelected{background-color:#FFFFC5;color:#491919;}\n";
			style += ".traceItemSelected span{color:orange;}";
			style += ".divider{line-height:5px;height:-1px;border-top:1px dashed gray;padding:2px;margin-top:12px;}";
			style += ".label{font-size:10px;font-weight:bold;text-decoration:underline;}"
			style += "</style>\n";
			return style;
		}
		
		this.__midHTML = function()
		{
			html  = "</head>\n";
			html += "\t<body>\n";
			return html;
		}
		this.__contentHTML = function()
		{
			html  = "\t<table border=1 id=\"traceContainer\" contentEditable=\"true\">\n";
			// header
			html += "\t<tr><td id=\"traceHeader\"><span class=\"options\" onclick=\"window.opener.trace.__showHidePrefs()\">prefs</span> ";
			html += "<span class=\"options\" title=\"Clear the contents\" onclick=\"window.opener.trace.clear()\">clear</span> ";
			html += "<span class=\"options\" title=\"Trace Window Object \nVersion 2 - Beta \">?</span>";
			html += "</td></tr>\n";
			html += "\t<tr><td valign=\"top\" id=\"traceBody\" >\n";
			// body
			html += "\t<iframe id=\"traceIFrame\"></iframe>\n";
			// preferences IFrame
			html += "\t<iframe id=\"prefsIFrame\"></iframe>\n";
			html += "\t</td></tr>\n";
			html += "\t<tr><td id=\"traceFooter\"><textArea id=\"traceFooterText\" readonly></textArea>";
			html += "\t</td></tr>\n";
			html += "\t</table>";
			
			return html;
		}
				
		this.__buildPrefsContentHTML = function()
		{
			html  = "<fieldset><legend>Capture Events</legend><br />";
			html +="<span class=\"label\">Mouse</span><br />";
			// Mouse
			html += "<input id=\"mouseup\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\"/> mouseup<br />";
			html += "<input id=\"mousedown\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> mousedown<br />";
			html += "<input id=\"mouseover\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> mouseover<br />";
			html += "<input id=\"mouseout\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> mouseout<br />";
			html += "<input id=\"click\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> click<br />";
			html += "<input id=\"dblclick\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> double click<br />";
			// Divider
			html += "<div class=\"divider\">&nbsp;</div>"
			// Keyboard
			html +="<span class=\"label\">Keyboard</span><br />";
			html += "<input id=\"keydown\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> keydown<br />";
			html += "<input id=\"keyup\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> keyup<br />";
			// Divider
			html += "<div class=\"divider\">&nbsp;</div>";
			// Other
			html +="<span class=\"label\">Other</span><br />";
			html += "<input id=\"error\" type=\"checkbox\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.checked)\" /> error<br />";
			html += "</fieldset><br />";
			html += "<fieldset><legend> Settings </legend><br />";
			html +="<span class=\"label\">Dimensions</span><br />";
			html += "<input id=\"height\" type=\"text\" maxlength=\"4\" style=\"width:35px;\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.value)\" /> Height<br />";
			html += "<input id=\"width\" type=\"text\" maxlength=\"4\" style=\"width:35px;\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.value)\" /> Width<br/>";
			// Divider
			html += "<div class=\"divider\">&nbsp;</div>"
			// Position
			html +="<span class=\"label\">Position</span><br />";
			html += "<input id=\"top\" type=\"text\" maxlength=\"4\" style=\"width:35px;\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.value)\" /> Top<br />";
			html += "<input id=\"left\" type=\"text\" maxlength=\"4\" style=\"width:35px;\" onchange=\"window.parent.opener.trace.__setCookie(this.id,this.value)\" /> Left<br />";
			html += "</fieldset>";

			return html;
		}
		this.__endHTML = function()
		{
			html  = "\t</body>\n";
			html += "</html>\n";
			return html;
		}
		// END OF STRUCTURE BUILDING METHODS
	
		// BEGIN PUBLIC USER FUNCTIONS
		// set the contents
		this.set = function(event,str)
		{
			if(this.open)
			{
				this.clear();
				this.append(event,str)

			}
		}
		
	
		this.append = function(event,str)
		{
			var txt = ((arguments.length>1 && str != undefined)?str:event)
			var evt = ((arguments.length>1 && event.type)?event:null)
			
			if(this.open())
			{
				//__tw.focus()
				
			// end remove
				var content = doc.getElementById("traceBody");
		
			
				// Setup row numbers
					__rowNum+=1;
					var strRowNum = __rowNum.toString();
					while(strRowNum.length < 3)
					strRowNum = "0"+strRowNum;
		
				// Build each inner node
					var ul = (ul?ul:__iDoc.createElement("ul"));
					var li =__iDoc.createElement("li");
					
					__iDoc.body.appendChild(ul)
					ul.setAttribute("id","traceItemGroup");
					li.setAttribute("id",('trace_'+strRowNum));
					li.className  = "traceItem";
					li.innerHTML  = "<span>" + strRowNum + "</span>";
					li.innerHTML += txt;
					
				// build the status data
					var statusData = new __row(evt);
					var footer = doc.getElementById('traceFooterText')
					
					li.onmouseover = function()
					{
						li.className = "traceItemSelected";
						footer.value  = "Row Number:" + strRowNum + "\n";
						footer.value += "Event Type:" + statusData.eType + "\n";
						footer.value += "Event Source:" + statusData.eSrc  + "\n";
						footer.value += "Event Node:" + statusData.eNode;
					}
					li.onmouseout = function()
					{
						li.className = "traceItem";
					}
					ul.appendChild(li);
				  li.scrollIntoView(true)
			}
		}		// clear the contents
		this.clear = function()
		{
			if(__tw != null && !__tw.closed)
			{
				if(this.open())
				{
					var doc = __tw.document;
					var content = doc.getElementById("traceBody");
					__rowNum = 0;
					__iDoc.body.innerHTML = "";
					__tw.focus();
				}
			}
		}
		
		this.open = function()
		{
			var traceAtt = document.body.getAttribute("trace");
			var traceEnabled =((traceAtt!=null && traceAtt == "false")?false:true);
			if(!__isOpen && (traceEnabled)){
				var height = this.__getCookie("height");
				var width = this.__getCookie("width");
				var top = this.__getCookie("top");
				var left = this.__getCookie("left");
				
				__tw = window.open('','trWin','menubar=no,toolbar=no,height='+height+',width='+width+',left='+left+',top='+top+',status=0,scrollbars=no,resizable=yes,dependent=yes');
				__isOpen = true;
				this.__init();
				__tw.focus();
			}
			
			return traceEnabled;
		}
		// END PUBLIC USER METHODS
		
		// BEGIN INTERNAL PRIVATE METHODS(yeah, yeah - I know they aren't really private)
		var __tw = null;
		var __rowNum = 0;
		var __statusData;
		var __iDoc = null;
		var __pDoc = null;
		var __isOpen = false;		
		
		
		this.__init = function()
		{
				doc = __tw.document;
				doc.writeln(this.__beginHTML());
				doc.writeln(this.__buildMainStyleBlock());
				doc.writeln(this.__buildMainScriptBlock());
				doc.writeln(this.__midHTML());
				doc.writeln(this.__contentHTML());			
				doc.writeln(this.__endHTML());
				doc.close();
				doc.title = "jsTrace";
				
				var traceIFrame = doc.getElementById("traceIFrame");
				__iDoc = (traceIFrame.contentDocument?traceIFrame.contentDocument:traceIFrame.contentWindow.document);
				__iDoc.open()
				__iDoc.writeln(this.__beginHTML());
				__iDoc.writeln(this.__buildIFrameStyleBlock());
				//iBody.writeln(this.__buildMainScriptBlock());
				__iDoc.writeln(this.__midHTML());
				__iDoc.writeln(this.__endHTML());
				__iDoc.close();
				
				var prefsIFrame = doc.getElementById("prefsIFrame");
				__pDoc = (prefsIFrame.contentDocument?prefsIFrame.contentDocument:prefsIFrame.contentWindow.document);
				__pDoc.open()
				__pDoc.writeln(this.__beginHTML());
				__pDoc.writeln(this.__buildPrefsScriptBlock());
				__pDoc.writeln(this.__buildIFrameStyleBlock());
				__pDoc.writeln(this.__midHTML());
				__pDoc.writeln(this.__buildPrefsContentHTML());
				__pDoc.writeln(this.__endHTML());
				__pDoc.close();
				
				this.__setupPrefs();
				
				// attach load / unload events
				//if(__pDoc.attachEvent){__pDoc.attachEvent("onclick",trackChange)};
				if(this.__getCookie("error")=="true")
				{
					if(__tw.attachEvent){__tw.attachEvent("onerror", error)};
					if(__tw.captureEvents){__tw.captureEvents(Event.onerror)};
				}

				if(__tw.opener.attachEvent){__tw.opener.attachEvent("onunload", parentunload)};
				if(__tw.attachEvent){__tw.attachEvent("onresize", resize)};
				if(__tw.captureEvents){__tw.captureEvents(Event.resize)};
				if(__tw.attachEvent){__tw.attachEvent("onunload", unload)};
				if(__tw.captureEvents){__tw.captureEvents(Event.onunload)};
				
				function error(e)
				{
					this.append(e.type)
				}
				function parentunload(){__tw.close()}
				function unload(){__isOpen = false}
				function resize(){}
				__tw.onerror = error;
				__tw.onresize = resize;
				__tw.onunload = unload;
		}


		
		var __row = function(e)
		{
			evt=((e==null)?window.event:e);
			var nullMsg = "Pass event as first arg";
			if(evt && typeof(evt)=='object')
			{
				var evtObj = (evt.srcElement?evt.srcElement:evt.target);
				this.eType = (evtObj.type);
				this.eSrc =  (evtObj.id);
				this.eNode = (evtObj.nodeName);
			}
			else
			{
				this.eType = nullMsg;
				this.eSrc = nullMsg;
				this.eNode = nullMsg;
			}
		}
	
	// BEGIN PREFERENCE METHODS
	this.__showHidePrefs = function(state)
	{

		var prefs = __tw.document.getElementById('prefsIFrame');
		var trace = __tw.document.getElementById('traceIFrame');
		if(prefs.style.display == 'none' || prefs.style.display == '')
		{
			prefs.style.display = 'block';
			trace.style.display = 'none';
		}
		else
		{
			prefs.style.display = 'none';
			trace.style.display = 'block';
		}
		
	}
	// END PREFERENCE METHODS
	
	// UTILITY FUNCTIONS



	
	this.__setupPrefs = function()
	{
		var prefs = __tw.document.getElementById('prefsIFrame');
		
		var inputs = __pDoc.getElementsByTagName("input");
		var inputsLen = inputs.length;
		for(var i = 0;i<inputsLen;i++)
		{
			switch(inputs[i].type)
			{
				case "checkbox":
				inputs[i].checked = this.__getCookie(inputs[i].id)=="true"?true:false;
				this.append(inputs[i].id + " : " + this.__getCookie(inputs[i].id))
				break;
				
				case "text":
				inputs[i].value = this.__getCookie(inputs[i].id)!=""?this.__getCookie(inputs[i].id):"";
				break;
				
				default:
				break;
			}
		}
	}
			this.__setCookie = function(name, value, expires, path, domain) 
			{
				var date = new Date()
				date.setMonth(date.getMonth()+2);
				var curCookie = name + "=" + escape(value) +
				((expires) ? "; expires=" + expires.toGMTString() : "; expires="+date.toGMTString()) +
				((path) ? "; path=" + path : "") +
				((domain) ? "; domain=" + domain : "")
				document.cookie = curCookie;
				this.append(name + " : " + value)
			}		
			
			this.__getCookie = function(name){			
				var dc = document.cookie;
				var prefix = name + "=";
				var begin = dc.indexOf("; " + prefix);
				if (begin == -1) {
					begin = dc.indexOf(prefix);
				if (begin != 0) return null;
				} else
				begin += 2;
				var end = document.cookie.indexOf(";", begin);
				if (end == -1)
				end = dc.length;
				return unescape(dc.substring(begin + prefix.length, end));
			}
			// End script block
}
var trace = new Trace();

