static/admin/print_r.js
function print_rr (objRef, strObjRef) 
{
	// Objects Properties
	// Container for this instance of Print_R
	this.container = {};
	// Reference to the Title Bar
	this.titleBar = {};
	// Reference to the Body 
	this.body = {};
	// Reference to Header
	this.header = {};
	// Object Reference to Object we are viewing
	this.objRef = objRef;
	// String Representation of object we are viewing
	this.strObjRef = strObjRef;
	// Object Reference to refresh Button
	this.refreshBtn = {};
	// Object Reference to Close Button
	this.closeBtn = {};
	// Parsed parts of object we are viewing
	this.arrStrObjRef = [];
	// Simple name of Variable we are parsing
	this.objParseName = "";
	/*
		converts strObjRef to an Array of the parts of the object i,e ["window", "document", "childNodes", "[", "0", "]"]
	*/
	this.parseStrObjRef = function ()
	{
		// first split on the "." character	
		var temp = this.strObjRef;
		//alert ("'" + temp + "'");
		var temp2 = [];
		var x = 0;
		var buffer = ""; 	
		var inSingle = false;
		var inDouble = false;
		var inBracket = false;	
		//Now check for "[" and "]" chars to indicate arrays
		for (var elem =0;elem < temp.length;elem++)
		{
			// make sure we only look at the array elements not the clear() function
				switch (temp.charAt(elem))
				{					
					case "'":
						if (!inDouble)
						{	
							if (inSingle)
							{
								inSingle = false;
							}						
							else
							{
								inSingle = true;
							}
						}	
						buffer += temp.charAt(elem);
						break;
					case '"':
						if (!inSingle)
						{	
							if (inDouble)
							{
								inDouble = false;
							}						
							else
							{
								inDouble = true;
							}
						}
						buffer += temp.charAt(elem);
						break;
					case "[":
						if (!inSingle && !inDouble)
						{
							inBracket = true;
							if (buffer != "")
							{				
								temp2[temp2.length] = buffer;								
							}					
							buffer = new String();						
							temp2[temp2.length] = temp.charAt(elem);							
						}
						else
						{
							buffer += temp.charAt(elem);
						}
						break;
					case "]":
						if (!inSingle && !inDouble)
						{
							inBracket = false;
							if (buffer != "")
							{				
								temp2[temp2.length] = buffer;								
							}
							buffer = new String();
							temp2[temp2.length] = temp.charAt(elem);							
						}	
						else
						{
							buffer += temp.charAt(elem);
						}					
						break;
					case ".":
						if (!inSingle && !inDouble && !inBracket)
						{
							if (buffer != "")
							{
								temp2[temp2.length] = buffer;
								temp2[temp2.length] = temp.charAt(elem);
							}											
							buffer = "";	
						}
						else
						{
							buffer += temp.charAt(elem);
						}
						break;
					default: 						
						buffer += temp.charAt(elem);						
						break;
				}
				if (buffer != "]" && buffer != "" && buffer != null)
				{
					this.objParseName = buffer;
				}
								//will be overwritten unless it is the last entry 
				// which is the one we want							
			}			
			
		
		if (buffer != "")
		{
			temp2[temp2.length] = buffer;			
		}
		//alert (temp2);	
		// add the newly created array to our main object
		this.arrStrObjRef = temp2;	
		//alert (temp2);
	};
	// function to close the instance
	this.close = function ()
	{
		document.body.removeChild(this.container);
	}
	// this function sets up the container for everything else
	this.createContainers = function ()
	{
		//remove any existing Containers if for some reason it is called twice
		try {
			document.body.removeChild(this.container);
		} catch (e){}	
		this.container = document.createElement('div');
		this.applyStyles (styleObj.container, this.container);
		this.titleBar = document.createElement('div');
		this.applyStyles (styleObj.titleBar, this.titleBar);	
		this.container.appendChild(this.titleBar);
		this.header = document.createElement('div');
		this.container.appendChild(this.header);		
		this.body = document.createElement('div');		
		this.container.appendChild(this.body);
	};	
	// Function creates the title Bar
	this.populateTitleBar = function ()
	{			
		var table = document.createElement('table');		
		var tbody = table.appendChild(document.createElement('tbody'));
		var tr = tbody.appendChild(document.createElement('tr'));
		var td1 = tr.appendChild(document.createElement('td'));
		td1.appendChild(document.createTextNode(this.objParseName));
		var td2 = tr.appendChild(document.createElement('td'));
		this.refreshBtn = td2.appendChild(document.createElement('button'));	
		this.refreshBtn.appendChild(document.createTextNode('Refresh'));
		this.closeBtn = td2.appendChild(document.createElement('button'));	
		this.closeBtn.appendChild(document.createTextNode('close'));		
		this.applyStyles(styleObj.propTable, table);		
		this.applyStyles(styleObj.titleTd1, td1);
		this.applyStyles(styleObj.titleTd2, td2);
		this.titleBar.appendChild(table);
	};
	/*
	//function creates the browseable header
	this.populateHeader = function ()
	{
		//alert(this.arrStrObjRef);
		// the string we will change this.objStrRef when updating object
		var strRef = "";
		// iterate through each element of this.arrStrObjRef
		for (var x =0;x<this.arrStrObjRef.length;x++)
		{
			// if it is a "[" or a "]" char
			if ((this.arrStrObjRef[x].match(/\[/g)) || (this.arrStrObjRef[x].match(/\]/g))) 
			{
				// just output a single char "[" or "]"
				this.header.appendChild(document.createTextNode(this.arrStrObjRef[x]));
				// if it is a "[" make sure we add it to strRef
				if (this.arrStrObjRef[x] == "[")
				{
					strRef += "[";	
				}				
			}
			// it it is anything but a "[" or "]"
			else
			{
				// we want to make it browseable
				var a = document.createElement('a');
				a.href = "javascript:void(0);";
				// apply our styles
				this.applyStyles (styleObj.a , a);
				// add the name of the object we looking at
				a.appendChild(document.createTextNode(this.arrStrObjRef[x]));
				// if there is a previous item in the list is it a "]" char 
				if (this.arrStrObjRef[x-1] && this.arrStrObjRef[x-1] == "]" && x != (this.arrStrObjRef.length -1))
				{
					// if so we need to generate the "." char for output and strRef
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";
				}	
				// now add the name to strRef we do it here so that the "." is in the right place
				strRef += this.arrStrObjRef[x];
				//if the next item in the array is a "]"
				if (this.arrStrObjRef[x+1] == "]")
				{
					// add it to strRef
					strRef += "]";	
				}	
				// now we have a working strRef set the onclick handler for the output
				a.onclick = clickMe(this, strRef);		
				// add the "a" element to the dom				
				this.header.appendChild(a);		
				// now we need to add the "." operator to the dom and strRef for the next pass		
				if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
				{
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";					
				}				
			}			
		}
		try 
		{
		// this makes sure we don't have trailing "."'s in our dom
		if (this.header.lastChild.value == ".")
		{			
			this.header.removeChild(this.header.lastChild);
		}
		} catch (e){}		
	};
	*/
	//function creates the browseable header
	this.populateHeader = function ()
	{
		//alert(this.arrStrObjRef);
		// the string we will change this.objStrRef when updating object
		var strRef = "";
		// iterate through each element of this.arrStrObjRef
		var inBracket = false;
		for (var x =0;x<this.arrStrObjRef.length;x++)
		{
			switch (this.arrStrObjRef[x])
			{				
				case "[":
				case "]":				
				case ".":
					if (this.arrStrObjRef[x] == "[")
					{
						inBracket = true;
					}	
					if (this.arrStrObjRef[x] == "]")
					{
						inBracket = false;
					}									
					this.header.appendChild(document.createTextNode(this.arrStrObjRef[x]));
					if (this.arrStrObjRef[x] != "]")
					{
						strRef += this.arrStrObjRef[x];
					}
					break;
				default:
					if (this.arrStrObjRef[x-1] == ']')
					{
						this.header.appendChild(document.createTextNode("."));
					strRef += ".";
					}
					var a = document.createElement('a');
					a.appendChild(document.createTextNode(this.arrStrObjRef[x]));					
					strRef += this.arrStrObjRef[x];					
					if (inBracket)
					{
						strRef += "]";
					}
					a.onclick = clickMe(this, strRef);
					a.href = "javascript:void(0);";
					this.header.appendChild(a);
			}
			/*		
			// if it is a "[" or a "]" char
			if ((this.arrStrObjRef[x].match(/\[/g))) 
			{
				// just output a single char "[" or "]"
				
				// if it is a "[" make sure we add it to strRef
				if (this.arrStrObjRef[x] == "[")
				{
					strRef += "[";	
				}				
			}
			// it it is anything but a "[" or "]"
			else
			{
				// we want to make it browseable
				
				
				// apply our styles
				this.applyStyles (styleObj.a , a);
				// add the name of the object we looking at
				
				// if there is a previous item in the list is it a "]" char 
				if (this.arrStrObjRef[x-1] && this.arrStrObjRef[x-1] == "]" && x != (this.arrStrObjRef.length -1))
				{
					// if so we need to generate the "." char for output and strRef
					//this.header.appendChild(document.createTextNode("."));
					//strRef += ".";
				}	
				// now add the name to strRef we do it here so that the "." is in the right place
				strRef += this.arrStrObjRef[x];
				//if the next item in the array is a "]"
				if (this.arrStrObjRef[x] == "]")
				{	
					if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
					{
						this.header.appendChild(document.createTextNode("."));
						strRef += ".";					
					}
				}	
				
				if (this.arrStrObjRef[x] != "]")
				{
					// now we have a working strRef set the onclick handler for the output
					a.onclick = clickMe(this, strRef);
					a.href = "javascript:void(0);";
				}		
				// add the "a" element to the dom				
				this.header.appendChild(a);		
				// now we need to add the "." operator to the dom and strRef for the next pass		
				if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
				{
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";					
				}				
			}
			*/	
			//alert(strRef);
		}
		try 
		{
		// this makes sure we don't have trailing "."'s in our dom
		if (this.header.lastChild.value == ".")
		{			
			this.header.removeChild(this.header.lastChild);
		}
		} catch (e){}		
	};
	/*
		This is the main function to populate the dom
	*/
	this.populateBody = function ()
	{
		// we want our properties, events, functions alphabatized so we need to cache them so we can sort them
		var properties = [];
		var functions = [];
		var events = [];
		// start creating the output dom
		var table = document.createElement('table');
		var tbodyobj = document.createElement('tbody');
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('th'));
		this.applyStyles (styleObj.propTableTh, th1);
		th1.appendChild(document.createTextNode('This Object'));
		th1.colSpan = "3";
		//Even if the object has no props we want to make sure we tell them about the object they are looking at
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('Name'));

		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode(this.objParseName));
		
		th1.colSpan = "2";
		
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('toString'));
		
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		var pre = document.createElement('pre');
		// in Some browsers calling the "toString" method of built in objects causes an error so plan for it
		try 
		{
			pre.appendChild(document.createTextNode(getString(this.objRef)));
				
		}catch(e) {
			pre.appendChild(document.createTextNode("undefined"));
		}
		th1.appendChild(pre);
		this.applyStyles (styleObj.tostring, pre);
		th1.colSpan = "2";
		
		
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('Type'));
		
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);
		var type= typeof(this.objRef);
		// Arrays report to be Objects when typeof is used
		// however if they are true arrays we attempt to compare their constructor to 
		// known arrays constructor
		if (properties.constructor == this.objRef.constructor)
		{
			type = "array";
		}			
		th1.appendChild(document.createTextNode(type));		
		th1.colSpan = "2";
		tbodyobj.appendChild(tr);
		table.appendChild(tbodyobj);	
		// start the dom ouptut for the props funcs and events		
		var tbodyprops = document.createElement('tbody');
		var tbodyfuncs = document.createElement('tbody'); 
		var tbodyevents = document.createElement('tbody');
		//this is main walking of object here
		// it is enclosed in a try because enumerating a built in object sometimes causes an Error
		var props = [];
		var x = 0;
		try{
		  for (prop in this.objRef)
		  {
			props[props.length] = prop;			
		  }
		} catch(e) {}
		
			// the boolean false is not the same as null so we need another known false to test against
			var boolFalse = false;
			// enumerate over every property of this.objRef
			for (prop in props)
			{
				//document.write(props[prop] +  "<br />");
				if (props[prop] != 'sun')
				{
				try 
				{
					// as long as it is a valid object and not null run the typeof method on it
					if (this.objRef[props[prop]] || this.objRef[props[prop]] == boolFalse)
					{				
						var type = typeof(this.objRef[props[prop]]);
					}
					// if it is null mark it with an * so we know it is not enumerable
					else
					{	
						type = "object*";
					}
				}
				catch (e) {
					type = "undefined";
				}
				
				// alright depending on the type of object add it to the appropriate array
				switch (type)
				{
					// event handlers are always prefaced with _e__ so lets look for it
					// btw event handlers are 
					case "function":
						if (prop.indexOf('_e__') > -1)
						{
							type = "event";
							events[events.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						}
						else
						{													
							functions[functions.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						}
						break;						
					case "boolean":
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;
					case "string":				
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]) + unescape('%A0'), type:type};			
						break;
					case "number":
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;	
					case "object":												
						if (properties.constructor == this.objRef[props[prop]].constructor)
						{
							type = "array";
						}						
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;
					default:
						properties[properties.length] = {name:props[prop], toString:"null", type:type};
						break;
				}
				}
				
			}
		
		{
			//alert('An Error occured ' + e.message);		
		}
		//var testObj2 = new Object();
		//properties.push({name:"isPrototypeOf", toString:this.objRef["constructor"].isPrototypeOf(Array), type:typeof(this.objRef["constructor"])});		
		// Write table is a reusable function for writing the tables out
		if (typeof(this.objRef) != 'string')
		{
			writeTable(properties, tbodyprops, 'Properties', this);
			writeTable(functions, tbodyfuncs, 'Methods', this);
			writeTable(events, tbodyevents, 'Events', this);
		}
		// add the new Tbody elements to the table
		table.appendChild(tbodyprops);
		table.appendChild(tbodyfuncs);
		table.appendChild(tbodyevents);
		// apply appropriate styles
		this.applyStyles (styleObj.propTable, table);
		// Add to the body object
		this.body.appendChild(table);
		// Sometimes calling the toString of an object generates an error so we catch it here
		function getString(ref)
		{
			try
			{
				if (ref)
				{
					try 
					{	
						return ref;
					} catch (e) {
						return ref.toString();
					}
				}
				else {
					try 
					{
						return ref.toString();
					}
					catch (e) 
					{
						return "undefined";
					}
				}
				
			} catch (e)
			{
				// if we can not convert it to a string write "undefined" just like javascript
				return "undefined";
			}
		}
		// helper function to perform repeating tasks
		function writeTable(properties, tbodyprops, name, print_r)
		{
			// only output to the tbody if there are actually props to enumerate
			if (properties.length > 0)
			{
				// Build the Header Row
				var tr = tbodyprops.appendChild(document.createElement('tr'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTh, th1);
				th1.appendChild(document.createTextNode(name));
				th1.colSpan = "3";	
				// Build the Header
				var tr = tbodyprops.appendChild(document.createElement('tr'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);				
				th1.appendChild(document.createTextNode('Name'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);
				th1.appendChild(document.createTextNode('toString'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);
				th1.appendChild(document.createTextNode('Type'));
				// before we do anything lets alphabatize the list
				properties.sort(arrSort);
				// now we iterate through the list
				for (prop in properties)
				{
					if (properties[prop] && properties[prop].name)
					{
					// create a row for the object
					var tr = document.createElement('tr');
					var tdname = document.createElement('td');
					// output the div that will be clickable for appropriate elements				
					var z = document.createElement('div');	
					var a = document.createElement('a');		
					a.appendChild(document.createTextNode(properties[prop].name));					
					var type = 	properties[prop].type;				
					// if the object is enumerable or null don't run the onclick function
					if (type  != "object*")
					{
						a.href = "javascript:void(0);";
						// if the property name is a number access it as an array otherwise access it as an object 
						//i.e. array obj[4] object obj.prop
						if (isNaN(parseInt(properties[prop].name.charAt(0))))
						{
							try
							{
								var test = eval(print_r.strObjRef + "." + properties[prop].name);
								a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							} catch(e) 
							{
								try {									
									var test = eval(print_r.strObjRef + "[" + properties[prop].name + "]");									
									a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");
								}
								catch (e) 
								{
									a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
								}
							}
							//a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							/*
							if (properties[prop].name.match(/[^a-zA-Z_\-]/g))
							{
								a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
							}
							else
							{
								a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							}	
							*/			
						}	
						else
						{
							try
							{
								var test = eval(print_r.strObjRef + "." + properties[prop].name);	
								a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");	
							} catch(e) 
							{
								try {
									var test = eval(print_r.strObjRef + "[" + properties[prop].name + "]");									
									a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");
								}
								catch (e) 
								{
									a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
								}
							}							
						}
					}
					z.appendChild(a);
					tdname.appendChild(z);
						
					// now add the toString representation of the code.
					// some browsers keep formatting so add it to a <pre> element					
					var tdstring = document.createElement('td');	
					var pre = document.createElement('pre');
					try 
					{
						pre.appendChild(document.createTextNode(properties[prop].toString));
					} catch (e) {
						pre.appendChild(document.createTextNode('undefined1'));						
					}
					tdstring.appendChild(pre);
					// finally add the type and apply appropriate styles
					var tdtype = document.createElement('td');				
					tdtype.appendChild(document.createTextNode(properties[prop].type));
					print_r.applyStyles (styleObj.propTableTd, tdname);
					print_r.applyStyles (styleObj.name, z);
					print_r.applyStyles (styleObj.propTableTd, tdstring);
					print_r.applyStyles (styleObj.propTableTd, tdtype);					
					print_r.applyStyles (styleObj.tostring, pre);					
					tr.appendChild(tdname);
					tr.appendChild(tdstring);
					tr.appendChild(tdtype);
					tbodyprops.appendChild(tr);	
										
					} 
				}
				
			}
		}
	};
	this.center = function ()
	{
		
	}
	// this function will be used to rebuild the information stored in the container
	this.refresh = function ()
	{
		this.container.removeChild(this.titleBar);
		this.container.removeChild(this.header);
		this.container.removeChild(this.body);
		this.titleBar = document.createElement('div');
		this.container.appendChild(this.titleBar);
		this.header = document.createElement('div');
		this.container.appendChild(this.header);		
		this.body = document.createElement('div');
		this.container.appendChild(this.body);
		this.parseStrObjRef();
		this.populateTitleBar();
		this.refreshBtn.onclick = refreshThis(this);
		this.closeBtn.onclick = closeThis(this);
		this.applyStyles(styleObj.titleBar, this.titleBar);
		this.populateHeader();
		this.populateBody();
		this.container.style.left = (this.container.offsetLeft + (parseInt(this.container.style.width)/2)) + "px";
		this.container.style.top = (this.container.offsetTop + (parseInt(this.container.style.height)/2)) + "px";
		if (!this.container.style.MarginLeft)
		{
			this.container.style.MarginTop = "";
			this.container.style.MarginLeft = "";
		}		
		
		// make it draggable
		Drag.init(this.titleBar, this.container);
		// internal closure for the refresh button
	function refreshThis(print_r)
	{
		return (function(){
			return print_r.refresh();
		});
	}
	// internal closure for the close button
	function closeThis(print_r)
	{
		return (function(){
			return print_r.close();				
		});
	}
	};
	// similar to above but initializes rather than refreshes
	this.render = function ()
	{
		// Add Container to Document.	
		document.body.appendChild(this.container);
		// populate the refresh  amd close buttons
		this.refreshBtn.onclick = refreshThis(this);
		this.closeBtn.onclick = closeThis(this);
		this.applyStyles(styleObj.titleBar, this.titleBar);
		// Ugly Fix to make DOM DRAG WORK right
		this.container.style.left = (this.container.offsetLeft + (parseInt(this.container.style.width)/2)) + "px";
		this.container.style.top = (this.container.offsetTop + (parseInt(this.container.style.height)/2)) + "px";
		if (!this.container.style.MarginLeft)
		{
			this.container.style.MarginTop = "";
			this.container.style.MarginLeft = "";
		}		
		// start dragging
		Drag.init(this.titleBar, this.container);
		// internal closure for the refresh button
	function refreshThis(print_r)
	{
		return (function(){
			return print_r.refresh();
		});
	}
	// internal closure for the close button
	function closeThis(print_r)
	{
		return (function(){
			return print_r.close();				
		});
	}
	};	
	/*
		Since I could not get a css file to work consistently accross browsers in the 
		Bookmarklet edition, I went with this approach so I would not have so many
		dom.style.***** = "50px"; lines. And also to make it easy to customize
	*/
	this.applyStyles = function (styleObject, domObject)
	{
		for (prop in styleObject)
		{
			try 
			{
				domObject.style[prop] = styleObject[prop];
			} catch (e)
			{
			}
		}
	};	
	// initialize the function
	// parse the string
	this.parseStrObjRef();
	// create the Containers
	this.createContainers();
	// create the title bar
	this.populateTitleBar();
	// write the header
	this.populateHeader();
	// and the meat and potatoes
	this.populateBody();
	// the render function adds the final touches and makes it visible
	this.render();
	
	// internal function for the clickable Elements
	function clickMe (print_r, str)
	{
		return (function(){
			print_r.objRef = eval(str);
			print_r.strObjRef = str;
			print_r.refresh();					
		});
	}
	// Function to help sort the arrays
	function arrSort(a,b)
	{
		var acomp = a['name'].toString(10);
		var bcomp = b['name'].toString(10);
		if (!isNaN(Number(acomp)))
		{
			acomp = Number(acomp);
		}
		if (!isNaN(Number(bcomp)))
		{
			bcomp = Number(bcomp);
		}
		if (acomp < bcomp)
		{
			return -1;
		}
		if (acomp > bcomp)
		{
			return 1;
		}
		return 0;
	}		
}
function print_rr (objRef, strObjRef) 
{
	// Objects Properties
	// Container for this instance of Print_R
	this.container = {};
	// Reference to the Title Bar
	this.titleBar = {};
	// Reference to the Body 
	this.body = {};
	// Reference to Header
	this.header = {};
	// Object Reference to Object we are viewing
	this.objRef = objRef;
	// String Representation of object we are viewing
	this.strObjRef = strObjRef;
	// Object Reference to refresh Button
	this.refreshBtn = {};
	// Object Reference to Close Button
	this.closeBtn = {};
	// Parsed parts of object we are viewing
	this.arrStrObjRef = [];
	// Simple name of Variable we are parsing
	this.objParseName = "";
	/*
		converts strObjRef to an Array of the parts of the object i,e ["window", "document", "childNodes", "[", "0", "]"]
	*/
	this.parseStrObjRef = function ()
	{
		// first split on the "." character	
		var temp = this.strObjRef;
		//alert ("'" + temp + "'");
		var temp2 = [];
		var x = 0;
		var buffer = ""; 	
		var inSingle = false;
		var inDouble = false;
		var inBracket = false;	
		//Now check for "[" and "]" chars to indicate arrays
		for (var elem =0;elem < temp.length;elem++)
		{
			// make sure we only look at the array elements not the clear() function
				switch (temp.charAt(elem))
				{					
					case "'":
						if (!inDouble)
						{	
							if (inSingle)
							{
								inSingle = false;
							}						
							else
							{
								inSingle = true;
							}
						}	
						buffer += temp.charAt(elem);
						break;
					case '"':
						if (!inSingle)
						{	
							if (inDouble)
							{
								inDouble = false;
							}						
							else
							{
								inDouble = true;
							}
						}
						buffer += temp.charAt(elem);
						break;
					case "[":
						if (!inSingle && !inDouble)
						{
							inBracket = true;
							if (buffer != "")
							{				
								temp2[temp2.length] = buffer;								
							}					
							buffer = new String();						
							temp2[temp2.length] = temp.charAt(elem);							
						}
						else
						{
							buffer += temp.charAt(elem);
						}
						break;
					case "]":
						if (!inSingle && !inDouble)
						{
							inBracket = false;
							if (buffer != "")
							{				
								temp2[temp2.length] = buffer;								
							}
							buffer = new String();
							temp2[temp2.length] = temp.charAt(elem);							
						}	
						else
						{
							buffer += temp.charAt(elem);
						}					
						break;
					case ".":
						if (!inSingle && !inDouble && !inBracket)
						{
							if (buffer != "")
							{
								temp2[temp2.length] = buffer;
								temp2[temp2.length] = temp.charAt(elem);
							}											
							buffer = "";	
						}
						else
						{
							buffer += temp.charAt(elem);
						}
						break;
					default: 						
						buffer += temp.charAt(elem);						
						break;
				}
				if (buffer != "]" && buffer != "" && buffer != null)
				{
					this.objParseName = buffer;
				}
								//will be overwritten unless it is the last entry 
				// which is the one we want							
			}			
			
		
		if (buffer != "")
		{
			temp2[temp2.length] = buffer;			
		}
		//alert (temp2);	
		// add the newly created array to our main object
		this.arrStrObjRef = temp2;	
		//alert (temp2);
	};
	// function to close the instance
	this.close = function ()
	{
		document.body.removeChild(this.container);
	}
	// this function sets up the container for everything else
	this.createContainers = function ()
	{
		//remove any existing Containers if for some reason it is called twice
		try {
			document.body.removeChild(this.container);
		} catch (e){}	
		this.container = document.createElement('div');
		this.applyStyles (styleObj.container, this.container);
		this.titleBar = document.createElement('div');
		this.applyStyles (styleObj.titleBar, this.titleBar);	
		this.container.appendChild(this.titleBar);
		this.header = document.createElement('div');
		this.container.appendChild(this.header);		
		this.body = document.createElement('div');		
		this.container.appendChild(this.body);
	};	
	// Function creates the title Bar
	this.populateTitleBar = function ()
	{			
		var table = document.createElement('table');		
		var tbody = table.appendChild(document.createElement('tbody'));
		var tr = tbody.appendChild(document.createElement('tr'));
		var td1 = tr.appendChild(document.createElement('td'));
		td1.appendChild(document.createTextNode(this.objParseName));
		var td2 = tr.appendChild(document.createElement('td'));
		this.refreshBtn = td2.appendChild(document.createElement('button'));	
		this.refreshBtn.appendChild(document.createTextNode('Refresh'));
		this.closeBtn = td2.appendChild(document.createElement('button'));	
		this.closeBtn.appendChild(document.createTextNode('close'));		
		this.applyStyles(styleObj.propTable, table);		
		this.applyStyles(styleObj.titleTd1, td1);
		this.applyStyles(styleObj.titleTd2, td2);
		this.titleBar.appendChild(table);
	};
	/*
	//function creates the browseable header
	this.populateHeader = function ()
	{
		//alert(this.arrStrObjRef);
		// the string we will change this.objStrRef when updating object
		var strRef = "";
		// iterate through each element of this.arrStrObjRef
		for (var x =0;x<this.arrStrObjRef.length;x++)
		{
			// if it is a "[" or a "]" char
			if ((this.arrStrObjRef[x].match(/\[/g)) || (this.arrStrObjRef[x].match(/\]/g))) 
			{
				// just output a single char "[" or "]"
				this.header.appendChild(document.createTextNode(this.arrStrObjRef[x]));
				// if it is a "[" make sure we add it to strRef
				if (this.arrStrObjRef[x] == "[")
				{
					strRef += "[";	
				}				
			}
			// it it is anything but a "[" or "]"
			else
			{
				// we want to make it browseable
				var a = document.createElement('a');
				a.href = "javascript:void(0);";
				// apply our styles
				this.applyStyles (styleObj.a , a);
				// add the name of the object we looking at
				a.appendChild(document.createTextNode(this.arrStrObjRef[x]));
				// if there is a previous item in the list is it a "]" char 
				if (this.arrStrObjRef[x-1] && this.arrStrObjRef[x-1] == "]" && x != (this.arrStrObjRef.length -1))
				{
					// if so we need to generate the "." char for output and strRef
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";
				}	
				// now add the name to strRef we do it here so that the "." is in the right place
				strRef += this.arrStrObjRef[x];
				//if the next item in the array is a "]"
				if (this.arrStrObjRef[x+1] == "]")
				{
					// add it to strRef
					strRef += "]";	
				}	
				// now we have a working strRef set the onclick handler for the output
				a.onclick = clickMe(this, strRef);		
				// add the "a" element to the dom				
				this.header.appendChild(a);		
				// now we need to add the "." operator to the dom and strRef for the next pass		
				if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
				{
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";					
				}				
			}			
		}
		try 
		{
		// this makes sure we don't have trailing "."'s in our dom
		if (this.header.lastChild.value == ".")
		{			
			this.header.removeChild(this.header.lastChild);
		}
		} catch (e){}		
	};
	*/
	//function creates the browseable header
	this.populateHeader = function ()
	{
		//alert(this.arrStrObjRef);
		// the string we will change this.objStrRef when updating object
		var strRef = "";
		// iterate through each element of this.arrStrObjRef
		var inBracket = false;
		for (var x =0;x<this.arrStrObjRef.length;x++)
		{
			switch (this.arrStrObjRef[x])
			{				
				case "[":
				case "]":				
				case ".":
					if (this.arrStrObjRef[x] == "[")
					{
						inBracket = true;
					}	
					if (this.arrStrObjRef[x] == "]")
					{
						inBracket = false;
					}									
					this.header.appendChild(document.createTextNode(this.arrStrObjRef[x]));
					if (this.arrStrObjRef[x] != "]")
					{
						strRef += this.arrStrObjRef[x];
					}
					break;
				default:
					if (this.arrStrObjRef[x-1] == ']')
					{
						this.header.appendChild(document.createTextNode("."));
					strRef += ".";
					}
					var a = document.createElement('a');
					a.appendChild(document.createTextNode(this.arrStrObjRef[x]));					
					strRef += this.arrStrObjRef[x];					
					if (inBracket)
					{
						strRef += "]";
					}
					a.onclick = clickMe(this, strRef);
					a.href = "javascript:void(0);";
					this.header.appendChild(a);
			}
			/*		
			// if it is a "[" or a "]" char
			if ((this.arrStrObjRef[x].match(/\[/g))) 
			{
				// just output a single char "[" or "]"
				
				// if it is a "[" make sure we add it to strRef
				if (this.arrStrObjRef[x] == "[")
				{
					strRef += "[";	
				}				
			}
			// it it is anything but a "[" or "]"
			else
			{
				// we want to make it browseable
				
				
				// apply our styles
				this.applyStyles (styleObj.a , a);
				// add the name of the object we looking at
				
				// if there is a previous item in the list is it a "]" char 
				if (this.arrStrObjRef[x-1] && this.arrStrObjRef[x-1] == "]" && x != (this.arrStrObjRef.length -1))
				{
					// if so we need to generate the "." char for output and strRef
					//this.header.appendChild(document.createTextNode("."));
					//strRef += ".";
				}	
				// now add the name to strRef we do it here so that the "." is in the right place
				strRef += this.arrStrObjRef[x];
				//if the next item in the array is a "]"
				if (this.arrStrObjRef[x] == "]")
				{	
					if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
					{
						this.header.appendChild(document.createTextNode("."));
						strRef += ".";					
					}
				}	
				
				if (this.arrStrObjRef[x] != "]")
				{
					// now we have a working strRef set the onclick handler for the output
					a.onclick = clickMe(this, strRef);
					a.href = "javascript:void(0);";
				}		
				// add the "a" element to the dom				
				this.header.appendChild(a);		
				// now we need to add the "." operator to the dom and strRef for the next pass		
				if (this.arrStrObjRef[x+1] && this.arrStrObjRef[x+1] != "]" && this.arrStrObjRef[x+1] != "[")
				{
					this.header.appendChild(document.createTextNode("."));
					strRef += ".";					
				}				
			}
			*/	
			//alert(strRef);
		}
		try 
		{
		// this makes sure we don't have trailing "."'s in our dom
		if (this.header.lastChild.value == ".")
		{			
			this.header.removeChild(this.header.lastChild);
		}
		} catch (e){}		
	};
	/*
		This is the main function to populate the dom
	*/
	this.populateBody = function ()
	{
		// we want our properties, events, functions alphabatized so we need to cache them so we can sort them
		var properties = [];
		var functions = [];
		var events = [];
		// start creating the output dom
		var table = document.createElement('table');
		var tbodyobj = document.createElement('tbody');
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('th'));
		this.applyStyles (styleObj.propTableTh, th1);
		th1.appendChild(document.createTextNode('This Object'));
		th1.colSpan = "3";
		//Even if the object has no props we want to make sure we tell them about the object they are looking at
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('Name'));

		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode(this.objParseName));
		
		th1.colSpan = "2";
		
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('toString'));
		
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		var pre = document.createElement('pre');
		// in Some browsers calling the "toString" method of built in objects causes an error so plan for it
		try 
		{
			pre.appendChild(document.createTextNode(getString(this.objRef)));
				
		}catch(e) {
			pre.appendChild(document.createTextNode("undefined"));
		}
		th1.appendChild(pre);
		this.applyStyles (styleObj.tostring, pre);
		th1.colSpan = "2";
		
		
		var tr = tbodyobj.appendChild(document.createElement('tr'));
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);				
		th1.appendChild(document.createTextNode('Type'));
		
		var th1 = tr.appendChild(document.createElement('td'));
		this.applyStyles (styleObj.propTableTd, th1);
		var type= typeof(this.objRef);
		// Arrays report to be Objects when typeof is used
		// however if they are true arrays we attempt to compare their constructor to 
		// known arrays constructor
		if (properties.constructor == this.objRef.constructor)
		{
			type = "array";
		}			
		th1.appendChild(document.createTextNode(type));		
		th1.colSpan = "2";
		tbodyobj.appendChild(tr);
		table.appendChild(tbodyobj);	
		// start the dom ouptut for the props funcs and events		
		var tbodyprops = document.createElement('tbody');
		var tbodyfuncs = document.createElement('tbody'); 
		var tbodyevents = document.createElement('tbody');
		//this is main walking of object here
		// it is enclosed in a try because enumerating a built in object sometimes causes an Error
		var props = [];
		var x = 0;
		try{
		  for (prop in this.objRef)
		  {
			props[props.length] = prop;			
		  }
		} catch(e) {}
		
			// the boolean false is not the same as null so we need another known false to test against
			var boolFalse = false;
			// enumerate over every property of this.objRef
			for (prop in props)
			{
				//document.write(props[prop] +  "<br />");
				if (props[prop] != 'sun')
				{
				try 
				{
					// as long as it is a valid object and not null run the typeof method on it
					if (this.objRef[props[prop]] || this.objRef[props[prop]] == boolFalse)
					{				
						var type = typeof(this.objRef[props[prop]]);
					}
					// if it is null mark it with an * so we know it is not enumerable
					else
					{	
						type = "object*";
					}
				}
				catch (e) {
					type = "undefined";
				}
				
				// alright depending on the type of object add it to the appropriate array
				switch (type)
				{
					// event handlers are always prefaced with _e__ so lets look for it
					// btw event handlers are 
					case "function":
						if (prop.indexOf('_e__') > -1)
						{
							type = "event";
							events[events.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						}
						else
						{													
							functions[functions.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						}
						break;						
					case "boolean":
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;
					case "string":				
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]) + unescape('%A0'), type:type};			
						break;
					case "number":
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;	
					case "object":												
						if (properties.constructor == this.objRef[props[prop]].constructor)
						{
							type = "array";
						}						
						properties[properties.length] = {name:props[prop], toString:getString(this.objRef[props[prop]]), type:type};
						break;
					default:
						properties[properties.length] = {name:props[prop], toString:"null", type:type};
						break;
				}
				}
				
			}
		
		{
			//alert('An Error occured ' + e.message);		
		}
		//var testObj2 = new Object();
		//properties.push({name:"isPrototypeOf", toString:this.objRef["constructor"].isPrototypeOf(Array), type:typeof(this.objRef["constructor"])});		
		// Write table is a reusable function for writing the tables out
		if (typeof(this.objRef) != 'string')
		{
			writeTable(properties, tbodyprops, 'Properties', this);
			writeTable(functions, tbodyfuncs, 'Methods', this);
			writeTable(events, tbodyevents, 'Events', this);
		}
		// add the new Tbody elements to the table
		table.appendChild(tbodyprops);
		table.appendChild(tbodyfuncs);
		table.appendChild(tbodyevents);
		// apply appropriate styles
		this.applyStyles (styleObj.propTable, table);
		// Add to the body object
		this.body.appendChild(table);
		// Sometimes calling the toString of an object generates an error so we catch it here
		function getString(ref)
		{
			try
			{
				if (ref)
				{
					try 
					{	
						return ref;
					} catch (e) {
						return ref.toString();
					}
				}
				else {
					try 
					{
						return ref.toString();
					}
					catch (e) 
					{
						return "undefined";
					}
				}
				
			} catch (e)
			{
				// if we can not convert it to a string write "undefined" just like javascript
				return "undefined";
			}
		}
		// helper function to perform repeating tasks
		function writeTable(properties, tbodyprops, name, print_r)
		{
			// only output to the tbody if there are actually props to enumerate
			if (properties.length > 0)
			{
				// Build the Header Row
				var tr = tbodyprops.appendChild(document.createElement('tr'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTh, th1);
				th1.appendChild(document.createTextNode(name));
				th1.colSpan = "3";	
				// Build the Header
				var tr = tbodyprops.appendChild(document.createElement('tr'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);				
				th1.appendChild(document.createTextNode('Name'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);
				th1.appendChild(document.createTextNode('toString'));
				var th1 = tr.appendChild(document.createElement('th'));
				print_r.applyStyles (styleObj.propTableTd, th1);
				th1.appendChild(document.createTextNode('Type'));
				// before we do anything lets alphabatize the list
				properties.sort(arrSort);
				// now we iterate through the list
				for (prop in properties)
				{
					if (properties[prop] && properties[prop].name)
					{
					// create a row for the object
					var tr = document.createElement('tr');
					var tdname = document.createElement('td');
					// output the div that will be clickable for appropriate elements				
					var z = document.createElement('div');	
					var a = document.createElement('a');		
					a.appendChild(document.createTextNode(properties[prop].name));					
					var type = 	properties[prop].type;				
					// if the object is enumerable or null don't run the onclick function
					if (type  != "object*")
					{
						a.href = "javascript:void(0);";
						// if the property name is a number access it as an array otherwise access it as an object 
						//i.e. array obj[4] object obj.prop
						if (isNaN(parseInt(properties[prop].name.charAt(0))))
						{
							try
							{
								var test = eval(print_r.strObjRef + "." + properties[prop].name);
								a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							} catch(e) 
							{
								try {									
									var test = eval(print_r.strObjRef + "[" + properties[prop].name + "]");									
									a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");
								}
								catch (e) 
								{
									a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
								}
							}
							//a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							/*
							if (properties[prop].name.match(/[^a-zA-Z_\-]/g))
							{
								a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
							}
							else
							{
								a.onclick = clickMe(print_r, print_r.strObjRef + "." + properties[prop].name);
							}	
							*/			
						}	
						else
						{
							try
							{
								var test = eval(print_r.strObjRef + "." + properties[prop].name);	
								a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");	
							} catch(e) 
							{
								try {
									var test = eval(print_r.strObjRef + "[" + properties[prop].name + "]");									
									a.onclick = clickMe(print_r, print_r.strObjRef + "[" + properties[prop].name + "]");
								}
								catch (e) 
								{
									a.onclick = clickMe(print_r, print_r.strObjRef + "['" + properties[prop].name + "']");
								}
							}							
						}
					}
					z.appendChild(a);
					tdname.appendChild(z);
						
					// now add the toString representation of the code.
					// some browsers keep formatting so add it to a <pre> element					
					var tdstring = document.createElement('td');	
					var pre = document.createElement('pre');
					try 
					{
						pre.appendChild(document.createTextNode(properties[prop].toString));
					} catch (e) {
						pre.appendChild(document.createTextNode('undefined1'));						
					}
					tdstring.appendChild(pre);
					// finally add the type and apply appropriate styles
					var tdtype = document.createElement('td');				
					tdtype.appendChild(document.createTextNode(properties[prop].type));
					print_r.applyStyles (styleObj.propTableTd, tdname);
					print_r.applyStyles (styleObj.name, z);
					print_r.applyStyles (styleObj.propTableTd, tdstring);
					print_r.applyStyles (styleObj.propTableTd, tdtype);					
					print_r.applyStyles (styleObj.tostring, pre);					
					tr.appendChild(tdname);
					tr.appendChild(tdstring);
					tr.appendChild(tdtype);
					tbodyprops.appendChild(tr);	
										
					} 
				}
				
			}
		}
	};
	this.center = function ()
	{
		
	}
	// this function will be used to rebuild the information stored in the container
	this.refresh = function ()
	{
		this.container.removeChild(this.titleBar);
		this.container.removeChild(this.header);
		this.container.removeChild(this.body);
		this.titleBar = document.createElement('div');
		this.container.appendChild(this.titleBar);
		this.header = document.createElement('div');
		this.container.appendChild(this.header);		
		this.body = document.createElement('div');
		this.container.appendChild(this.body);
		this.parseStrObjRef();
		this.populateTitleBar();
		this.refreshBtn.onclick = refreshThis(this);
		this.closeBtn.onclick = closeThis(this);
		this.applyStyles(styleObj.titleBar, this.titleBar);
		this.populateHeader();
		this.populateBody();
		this.container.style.left = (this.container.offsetLeft + (parseInt(this.container.style.width)/2)) + "px";
		this.container.style.top = (this.container.offsetTop + (parseInt(this.container.style.height)/2)) + "px";
		if (!this.container.style.MarginLeft)
		{
			this.container.style.MarginTop = "";
			this.container.style.MarginLeft = "";
		}		
		
		// make it draggable
		Drag.init(this.titleBar, this.container);
		// internal closure for the refresh button
	function refreshThis(print_r)
	{
		return (function(){
			return print_r.refresh();
		});
	}
	// internal closure for the close button
	function closeThis(print_r)
	{
		return (function(){
			return print_r.close();				
		});
	}
	};
	// similar to above but initializes rather than refreshes
	this.render = function ()
	{
		// Add Container to Document.	
		document.body.appendChild(this.container);
		// populate the refresh  amd close buttons
		this.refreshBtn.onclick = refreshThis(this);
		this.closeBtn.onclick = closeThis(this);
		this.applyStyles(styleObj.titleBar, this.titleBar);
		// Ugly Fix to make DOM DRAG WORK right
		this.container.style.left = (this.container.offsetLeft + (parseInt(this.container.style.width)/2)) + "px";
		this.container.style.top = (this.container.offsetTop + (parseInt(this.container.style.height)/2)) + "px";
		if (!this.container.style.MarginLeft)
		{
			this.container.style.MarginTop = "";
			this.container.style.MarginLeft = "";
		}		
		// start dragging
		Drag.init(this.titleBar, this.container);
		// internal closure for the refresh button
	function refreshThis(print_r)
	{
		return (function(){
			return print_r.refresh();
		});
	}
	// internal closure for the close button
	function closeThis(print_r)
	{
		return (function(){
			return print_r.close();				
		});
	}
	};	
	/*
		Since I could not get a css file to work consistently accross browsers in the 
		Bookmarklet edition, I went with this approach so I would not have so many
		dom.style.***** = "50px"; lines. And also to make it easy to customize
	*/
	this.applyStyles = function (styleObject, domObject)
	{
		for (prop in styleObject)
		{
			try 
			{
				domObject.style[prop] = styleObject[prop];
			} catch (e)
			{
			}
		}
	};	
	// initialize the function
	// parse the string
	this.parseStrObjRef();
	// create the Containers
	this.createContainers();
	// create the title bar
	this.populateTitleBar();
	// write the header
	this.populateHeader();
	// and the meat and potatoes
	this.populateBody();
	// the render function adds the final touches and makes it visible
	this.render();
	
	// internal function for the clickable Elements
	function clickMe (print_r, str)
	{
		return (function(){
			print_r.objRef = eval(str);
			print_r.strObjRef = str;
			print_r.refresh();					
		});
	}
	// Function to help sort the arrays
	function arrSort(a,b)
	{
		var acomp = a['name'].toString(10);
		var bcomp = b['name'].toString(10);
		if (!isNaN(Number(acomp)))
		{
			acomp = Number(acomp);
		}
		if (!isNaN(Number(bcomp)))
		{
			bcomp = Number(bcomp);
		}
		if (acomp < bcomp)
		{
			return -1;
		}
		if (acomp > bcomp)
		{
			return 1;
		}
		return 0;
	}		
}
/*
end Dom Drag
 /*
Main Object