//set up the RD object
if(!window.RD){
	window.RD = {};
}

if(!RD.XHTML){
	RD.XHTML = {};
}

RD.XHTML.XMLHttpRequestHandler = function(aUrl, aAction, aCallbackObj, aCallbackFunction, aContentType, aEnc, aAsync, aContentLength){
	aAction = aAction?aAction:"GET";
	aCallbackObj = aCallbackObj?aCallbackObj:window;
	aAsync = (aAsync != null)?aAsync:true;
	var vXmlHttp = null;
	var vErrorMsg = String.empty;

	if(window.XMLHttpRequest){
		vXmlHttp = new XMLHttpRequest();
	}
	else{
		  try {
			  vXmlHttp=new ActiveXObject("Microsoft.XMLHTTP")
		  }
		  catch(err){
			  try{
				  vXmlHttp=new ActiveXObject("Msxml2.XMLHTTP")
			  }
			  catch(err){
				  vErrorMsg = e.message;
			  }
		  }
	}

	if(vXmlHttp){
		try{
			vXmlHttp.open(aAction, aUrl, aAsync);
		
			if(aAction.toLowerCase() == "post"){
				if(aEnc){ vXmlHttp.setRequestHeader("Content-Encoding", aEnc); }
				if(aContentType){ vXmlHttp.setRequestHeader("Content-Type", aContentType); }
				if(aContentLength){ vXmlHttp.setRequestHeader("Content-Length", aContentLength); }
			}
	
			if(aAsync){
				vXmlHttp.onreadystatechange = function(){
					RD.XHTML.XMLHttpRequestStateChange(vXmlHttp, aCallbackObj, aCallbackFunction);
				};
			}

			vXmlHttp.send(null);
		}
		catch(e){
			//this will catch file not found errors
			vErrorMsg = e.message;
			vXmlHttp.abort();
		}

		if(!aAsync){
			RD.XHTML.XMLHttpRequestStateChange(vXmlHttp, aCallbackObj, aCallbackFunction);
		}
	}
};

RD.XHTML.XMLHttpRequestStateChange = function(aXmlHttp, aCallbackObj, aCallbackFunction){
	var vStatus = {
		success:false
	};
	
	if(aXmlHttp.readyState==4){
		if(aXmlHttp.status == 200){
			vStatus.success = true;
			vStatus.responseXML = aXmlHttp.responseXML;
			vStatus.responseText = aXmlHttp.responseText;
			vStatus.contentType = aXmlHttp.getResponseHeader("Content-Type");
		}
		else{
			vStatus.success = false;
			vStatus.responseXML = aXmlHttp.responseXML;
			vStatus.responseText = aXmlHttp.responseText;
			vStatus.contentType = aXmlHttp.getResponseHeader("Content-Type");
		}
	}
	
	if(aXmlHttp.readyState==0 || aXmlHttp.readyState==4){
		if(typeof(aCallbackObj) == "string"){
			eval(aCallbackObj)(vStatus);
		}
		else{
			if(aCallbackObj.operationComplete){
				aCallbackObj.operationComplete(vStatus);
			}
			else if(aCallbackFunction){
				aCallbackObj[aCallbackFunction](vStatus);
			}
			else if(aCallbackObj != window){
				aCallbackObj(vStatus);
			}
		}
	}
};

RD.XHTML.XMLHttpRequestHandler.pingUrl = function(aUrl){
	RD.XHTML.XMLHttpRequestHandler(aUrl, "GET", RD.XHTML.XMLHttpRequestHandler.pingUrl_Callback, null, null, null, false);
	
	return RD.XHTML.XMLHttpRequestHandler._pingUrlStatus;
};

RD.XHTML.XMLHttpRequestHandler.pingUrl_Callback = function(aStatus){
	RD.XHTML.XMLHttpRequestHandler._pingUrlStatus = aStatus.success;
};

//AIM.submit(this, {'onStart' : startCallback, 'onComplete' : completeCallback})

RD.XHTML.XMLHttpPostLocalFile = {};

RD.XHTML.XMLHttpPostLocalFile.frame = function(aFrameId, aCallbackObject, aCallbackFunction){
	aFrameId = aFrameId?aFrameId:RD.XHTML.getUniqueId();
/*
	var vIframe = RD.XHTML.NodeHelper.createNode("iframe", null,{
		id:vIframeId
		,src:"about:blank"
		,style:"display:block"
	});

	vIframe.onload = RD.XHTML.XMLHttpPostLocalFile.loaded(vIframe);
*/
	//unfortunately we can't use dom methods to create this because the onload event doesn't fire correctly :(
	var vDiv = document.createElement("div");
	vDiv.style.cssText = "display:none;";
	vDiv.innerHTML = "<iframe style=\"display:block\" src=\"about:blank\" id=\"" + aFrameId + "\" name=\"" + aFrameId + "\" onload=\"RD.XHTML.XMLHttpPostLocalFile.loaded('" + aFrameId + "');\"></iframe>";
	document.body.appendChild(vDiv);

	var vIframe = $(aFrameId);

	vIframe._callbackObject = aCallbackObject;
	vIframe._callbackFunction = aCallbackFunction;
	
	return aFrameId;
};

RD.XHTML.XMLHttpPostLocalFile.submit = function(aForm, aCallbackObject, aCallbackFunction){
	var vFrameId = RD.XHTML.XMLHttpPostLocalFile.frame(null, aCallbackObject, aCallbackFunction);
	aForm.setAttribute("target", vFrameId);

	return true;
};

RD.XHTML.XMLHttpPostLocalFile.loaded = function(aIframeId){
	var vIframe = $(aIframeId);
	var vDocument = null;
	
	if(vIframe.contentDocument){ 
		vDocument = vIframe.contentDocument;
	}
	else if(vIframe.contentWindow){ 
		vDocument = vIframe.contentWindow.document;
	}
	else{  
		vDocument = vIframe.document;
	}
	
	if(vDocument.location.href != "about:blank"){ 
		if(vIframe._callbackObject && vIframe._callbackFunction){
			vIframe._callbackObject[vIframe._callbackFunction]();
		}
		
		var vTimerObj = RD.XHTML.Timer.getManager();
		this._timerId = vTimerObj.addCallback(this);
		this._callId = vTimerObj.setTimeout(this._timerId, "remove", 1000, vIframe);
	}
};

RD.XHTML.XMLHttpPostLocalFile.remove = function(aIframe){
	var vDiv = aIframe.parentNode;
	vDiv.parentNode.removeChild(vDiv);
};

RD.XHTML.XMLHttpLoadScript = function(aUrl, aCallbackObject, aCallbackFunction){
	this._callbackObject = aCallbackObject;
	this._callbackFunction = aCallbackFunction;
	getURL(aUrl, this, true);
	
	return this;
};

RD.XHTML.XMLHttpLoadScript.prototype.operationComplete = function(aStatus){
	eval(aStatus.responseText);
	if(this._callbackObject && this._callbackFunction){
		this._callbackObject[this._callbackFunction](aStatus);
	}
};

//
//	Helper Methods
//
RD.XHTML.getUniqueId = function(){
	window._uniqueId = window._uniqueId?window._uniqueId:new Date().getTime() + Math.round(Math.random()*1000);
	window._uniqueId++;

	return window._uniqueId.toString();
};

RD.XHTML.toggleNodeDisplay = function(aNode){
	if(typeof(aNode) == "string"){
		aNode = $(aNode);
	}
	
	if(aNode){
		aNode.style.display = (aNode.style.display == "none")?String.empty:"none";
	}
};

RD.XHTML.S4 = function(){
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
RD.XHTML.getGuId = function(){
	var vGuId = [];
	vGuId.push(RD.XHTML.S4() + RD.XHTML.S4());
	vGuId.push(RD.XHTML.S4());
	vGuId.push(RD.XHTML.S4());
	vGuId.push(RD.XHTML.S4() + RD.XHTML.S4() + RD.XHTML.S4());

   return vGuId.join("-");
}

RD.XHTML.getCdataSectionNodeList = function(aNode, aGetFirstOnly){
	var vCdataSections = [];
	var vChildNode = null;
	for(var n=0;n<aNode.childNodes.length;n++){
		var vChildNode = aNode.childNodes.item(n);
		if(vChildNode.nodeName.toLowerCase() == "#cdata-section"){
			vCdataSections.push(vChildNode);
			if(aGetFirstOnly){
				break;
			}
		}
		else if(vChildNode.childNodes && vChildNode.childNodes.length > 0){
			var vTempCdataSections = RD.XHTML.getCdataSectionNodeList(vChildNode);
			vCdataSections.concat(vTempCdataSections);
		}
	}
	
	return vCdataSections;
};

RD.XHTML.getFirstCdataSection = function(aNode){
	var vCdataSection = null;
	var vCdataSections = RD.XHTML.getCdataSectionNodeList(aNode, true);
	
	if(vCdataSections.length > 0){
		vCdataSection = vCdataSections[0];
	}
	return vCdataSection;
};

//document events
RD.XHTML.mousemove = function(evt){
	//evt = evt?evt:window.event;
	if(window._pMouse){
		window._pMouse.setLoc(evt);
	}
	if(RD.XHTML.Cursor && RD.XHTML.Stage && RD.XHTML.Main){
		var vCursor = RD.XHTML.Cursor.getManager();
		var vStage = RD.XHTML.Stage.getManager();
		if( vStage.pState != RD.XHTML.Main.PREVIEW && vCursor.pSelCursor != vCursor.pDefault && vCursor.pSelCursor != "disabled" && vCursor.pSelCursor != "sprite"){
			var vInfo0 = {pRect:new RD.XHTML.Rect(window._pMouse.x, window._pMouse.y, 1, 1)};
			var vPoint = RD.XHTML.GetABSPos(vStage.pContentNode);
			var vInfo1 = {pRect:new RD.XHTML.Rect(vPoint.x, vPoint.y+vStage.pTopHeight-vStage.pBdrWidth, vStage.pInfo.pRect.width, vStage.pInfo.pRect.height-vStage.pTopHeight-vStage.pBdrWidth)};
			var vHitTest = RD.XHTML.InfoHitTest(vInfo0, vInfo1);
			if(!vHitTest){
				vCursor.hide();
			}
			else{
				vCursor.pOffset.x = -10;
				vCursor.pOffset.y = -10;
				vCursor.show();
			}
		}

		RD.XHTML.Cursor.getManager().mousemove(evt, false);
	}
	//RD.XHTML.Debug.getManager().write([window._pMouse.toString()]);
};

RD.XHTML.mouseup = function(evt){
	if(window._pMouse){
		window._pMouse.isDown = false;
	}
	RD.XHTML.MsgInputs(evt, this);
};

RD.XHTML.mousedown = function(evt){
	if(window._pMouse){
		window._pMouse.isDown = true;
		window._pMouse.setLoc(evt);
	}
	
	RD.XHTML.MsgInputs(evt, this);

	if(RD.XHTML.ContextMenu && evt.button == 2 && !evt.target.getAttributeNS(null, "buildContext")){
		RD.XHTML.ContextMenu.resetMenu(evt);
	}
};

RD.XHTML.click = function(evt){
	RD.XHTML.MsgInputs(evt, this);
};

RD.XHTML.MsgInputs = function(evt){
	if(RD.XHTML.SelectBox && RD.XHTML.SelectBox.currentSelectBox && RD.XHTML.SelectBox.currentSelectBox[evt.type]){
		RD.XHTML.SelectBox.currentSelectBox[evt.type](evt, RD.XHTML.SelectBox.currentSelectBox);
	}
	if(RD.XHTML.TextBox && RD.XHTML.TextBox.focusedBox && RD.XHTML.TextBox.focusedBox[evt.type]){
		RD.XHTML.TextBox.focusedBox.blur(evt, RD.XHTML.TextBox.focusedBox);
	}
	if(RD.XHTML.Menubar && RD.XHTML.Menubar.openMenu && RD.XHTML.Menubar.openMenu[evt.type]){
		RD.XHTML.Menubar.openMenu[evt.type](evt, RD.XHTML.Menubar.openMenu);
	}
	if(RD.XHTML.ToolBox && RD.XHTML.ToolBox.openTool && RD.XHTML.ToolBox.openTool[evt.type]){
		RD.XHTML.ToolBox.openTool[evt.type](evt, RD.XHTML.ToolBox.openTool);
	}
};
/*
RD.XHTML.mouseover = function(evt){
	window._pMouse.setLoc(evt);
}

RD.XHTML.mouseout = function(evt){
	window._pMouse.setLoc(evt);
}

RD.XHTML.click = function(evt){
	window._pMouse.setLoc(evt);
}
*/

RD.XHTML.stripTag = function(aString, aTagName){
	var vSpace = "[ \\t\\u00A0]*";

	var vReg = "\<" + vSpace + aTagName + ".*?\>([\\d\\D\\n\\r]*)\<\/" + vSpace  + aTagName + "\>";
	var vMyRE = new RegExp(vReg, "gi");

	var vDelim = "!~!";
	aString = aString.replace(vMyRE, 
									function(){
											return RegExp.$1 + vDelim;
									});
	if(aString.indexOf(vDelim) > -1){
		vMatch = aString.split(vDelim);
		vMatch.pop();
	}

	return vMatch?vMatch:[];
};

RD.XHTML.toSource = function(aVariable){
	var vSource = null;
	if(aVariable){
		if(typeof(aVariable) == "object"){
			vSource = [];
			if(aVariable.constructor == Array){
				for(var n=0;n<aVariable.length;n++){
					vSource.push(RD.XHTML.toSource(aVariable[n]));
				}
				vSource = "[" + vSource.join(",") + "]";
			}
			else{
				for(var vProp in aVariable){
					if(typeof(aVariable[vProp]) == "string"){
						vSource.push(vProp + ':"' + aVariable[vProp] + '"' );
					}
					else{
						vSource.push(vProp + ":" + RD.XHTML.toSource(aVariable[vProp]));
					}
				}
				
				vSource = "{" + vSource.join(",") + "}";
			}
		}
		else{
			vSource = aVariable;
		}
	}
	else{vSource = aVariable;}

	return vSource;
};

RD.XHTML.convertStringToObjectType = function(aString){
	var vType = null;

	if(aString != "null"){
		vType = aString;
		if(aString.indexOf(".") > -1){
			vType = parseFloat(aString);
		}
		else{
			if(aString == "true" || aString == "false"){
				vType = (aString == "true")?true:false;
			}
			else{
				vType = parseInt(aString, 10);
			}
		}
	}
	
	return vType;
};

//sometimes we need to store an event's properties for later use...
RD.XHTML.GetEvent = function(evt){
	evt = evt?evt:new Object();
	var vEvent = new Object();
	vEvent.clientX = evt.clientX?evt.clientX:0;
	vEvent.clientY = evt.clientY?evt.clientY:0;
	vEvent.type = evt.type;
	vEvent.target = evt.target?evt.target:null;
	vEvent.getShiftKey = evt.getShiftKey?function(){return evt.getShiftKey();}:function(){return false;};
	vEvent.stopPropagation = evt.stopPropagation?function(){evt.stopPropagation();}:function(){};

	return vEvent;
};

RD.XHTML.GetAbsPosition = function(aNode, aStopAtNode){
	aStopAtNode = aStopAtNode?aStopAtNode:document.body;
	var vPoint = new RD.XHTML.Point();
	//loop through and compute all position transformations
	while(aNode && aNode != aStopAtNode){
		if(aNode.offsetLeft){
			vPoint.x += aNode.offsetLeft;
		}
		if(aNode.offsetTop){
			vPoint.y += aNode.offsetTop;
		}
		
		aNode = aNode.offsetParent;
	}
	
	return vPoint;
};

RD.XHTML.NodeHelper = function() {
	return this;
};

RD.XHTML.NodeHelper.VERSION = 1.4;


RD.XHTML.NodeHelper.createNode = function(aType, aParentNode, aAttributes, aText, aDocument){
	aDocument = aDocument?aDocument:window.document;
	
	aType = aType.toLowerCase();
	var vNode = null;

	if(aType == "cdatasection"){
		aText = (aText != null)?aText:String.empty;
		vNode = aDocument.createCDATASection(aText);
	}
	else{
		if(aType != "text"){
			//have to handle radio buttons special for IE (of course)
			if(aType == "input" && aAttributes["type"] == "radio" && isIE()){
				var vName = aAttributes["name"] ? aAttributes["name"] : String.empty;
				vNode = document.createElement("<input type=\"radio\" name=\"" + vName + "\" >");
			}
			if(isNull(vNode)){
				vNode = aDocument.createElement(aType);
			}

			var vProperty;
			for (var a in aAttributes) {
				vProperty = isNull(aAttributes[a])?String.empty:aAttributes[a];
				//some dimensions are too big, so place in try catch
				try{
					switch(a){
						case "disabled":
							if(aAttributes[a]){
								vNode[a] = vProperty;
							}
						case "style":
						case "cssText":
							vNode.style.cssText = vProperty;
							break;
						case "class":
						case "className":
						case "classname":
							vNode.className = vProperty;
							break;
						case "onclick":
						case "onmouseover":
						case "onmouseout":
						case "onmousedown":
						case "onmouseup":
						case "onchange":
							if(isIE()){
								vNode["_" + a] = vProperty;
								vNode[a] = function(evt){
									evt = evt?evt:window.event;
									eval(this["_on" + evt.type])
								};
							}
							else{
								vNode[a] = vProperty;
								vNode.setAttribute(a, vProperty);
							}
							break;
						default:
							vNode[a] = vProperty;
							vNode.setAttribute(a, vProperty);
							break;
					}
				}
				catch(e){
					var vError = new Array("Error setting " + vNode.nodeName + " attributes:\n");
					vError.push("\t" + a + ":" + vProperty + "\n");
					/*for(var a2 in aAttributes){
						vError.push("\t" + a2 + ":" + aAttributes[a2] + "\n");
					}*/
					alert(vError.join(String.empty));
				}
			}
		}
		
		if(aText){
			if(!vNode){
				vNode = aDocument.createTextNode(aText);
			}
			else{
				vNode.appendChild(aDocument.createTextNode(aText));
			}
		}
	}

	if(vNode && aParentNode){
		aParentNode.appendChild(vNode);
	}
	
	return vNode;
};

RD.XHTML.NodeHelper.insertFirstChild = function(aParentNode, aChildNode){
	if(aParentNode.firstChild){
		aParentNode.insertBefore(aChildNode, aParentNode.firstChild);
	}
	else{
		aParentNode.appendChild(aChildNode);
	}
};

RD.XHTML.NodeHelper.insertAfter = function(aInsertChildNode, aCurrentChildNode){
	if(aCurrentChildNode == aCurrentChildNode.parentNode.lastChild){
		aCurrentChildNode.parentNode.appendChild(aInsertChildNode);
	}
	else{
		aCurrentChildNode.parentNode.insertBefore(aInsertChildNode, aCurrentChildNode.nextSibling);
	}
};

RD.XHTML.NodeHelper.getElementsByTagName = function(aParentNode, aTagName, aDeep){
	return $$(aParentNode, aTagName, aDeep);
};

RD.XHTML.NodeHelper.getFirstElementNode = function(aNode){
	var vElementNode = aNode;
	
	if(vElementNode && vElementNode.nodeType != 1){
		for(var n=0;n<aNode.childNodes.length;n++){
			vElementNode = this.getFirstElementNode(aNode.childNodes.item(n));
			if(vElementNode && vElementNode.nodeType == 1){
				break;
			}
		}
	}
	
	return vElementNode;
};

RD.XHTML.NodeHelper.appendWhiteSpaceToElementNodes = function(aNode, aLevel, aXmlDocument){
	aLevel = aLevel?aLevel:0;
	aNode = this.getFirstElementNode(aNode);

	var vTextArray = ["\n\t"];
	for(var n=0;n<aLevel;n++){
		vTextArray.push("\t");
	}
	
	var vStartText = vTextArray.join(String.empty);
	var vEndText = vStartText.substr(0, vStartText.length-1);
	
	var vNode = null;
	var vNodeHelper = RD.XHTML.NodeHelper;
	var vLength = aNode.childNodes.length;

	for(var n=0;n<vLength;n++){
		if(aNode.childNodes[n].nodeType == 1){//element node
			
			vNode = vNodeHelper.createNode("text", null, {},vStartText, aXmlDocument);
			aNode.insertBefore(vNode, aNode.childNodes[n]);
			vLength++;
			n++;
			
			if(aNode.childNodes[n].childNodes.length){
				this.appendWhiteSpaceToElementNodes(aNode.childNodes[n], aLevel + 1, aXmlDocument);
			}
		}
	}
	
	if(aNode.childNodes.length && aNode.lastChild.nodeType == 1){
		vNodeHelper.createNode("text", aNode, {},vEndText, aXmlDocument);
	}
};

RD.XHTML.NodeHelper.getAbsolutePosition = function(aNode, aStopAtNode, aDocument){
	aDocument = aDocument?aDocument:document;
	aStopAtNode = aStopAtNode?aStopAtNode:aDocument.body;
	var vPoint = new RD.XHTML.Point();
	//loop through and compute all position transformations
	while(aNode != aStopAtNode){
		if(aNode.offsetLeft){
			vPoint.x += aNode.offsetLeft;
		}
		if(aNode.offsetTop){
			vPoint.y += aNode.offsetTop;
		}
		
		aNode = aNode.parentNode;
	}
	
	return vPoint;
};

RD.XHTML.NodeHelper.getElementsByNodeType = function(aParentNode, aNodeType, aDeep){
	aDeep = (aDeep != null)?aDeep:true;
	aNodeType = (aNodeType != null)?aNodeType:1;
	var vChildNodes = [];
	var vChildNode = null;
	for(var n=0;n<aParentNode.childNodes.length;n++){
		vChildNode = aParentNode.childNodes.item(n);
		if(vChildNode.nodeType == aNodeType){
			vChildNodes.push(vChildNode);
		}
		
		if(aDeep && vChildNode.childNodes.length > 0){
			vChildNodes.concat(RD.XHTML.NodeHelper.getElementsByNodeType(vChildNode, aNodeType));
		}
	}
	
	return vChildNodes;
};

RD.XHTML.NodeHelper.getNodeIndexByNodeType = function(aNode){
	var vIndex = -1;
	if(aNode && aNode.nodeName){
		var vSiblingNodes = $$(aNode.parentNode, aNode.tagName);
		
		for(var n=vSiblingNodes.length-1;n>=0;n--){
			if(aNode == vSiblingNodes.item(n)){
				vIndex = n;
				break;
			}
		}
	}
	
	return vIndex;
};

RD.XHTML.EventHandler = function(){
	this.init();
	
	return this;
};

//ammended version of Kevin Lindsey's EventHandler object
//edited to be functional on NN4+ (can't throw exceptions using keyword "throw")
RD.XHTML.EventHandler.VERSION = 1.0;
RD.XHTML.EventHandler.HELD_TME = 500; //time is in ms
RD.XHTML.EventHandler.HOVER_TME = 600; //time is in ms
RD.XHTML.EventHandler.DBL_CLICK_SPD = 300; //time is in ms

//this is used for double clicks
RD.XHTML.EventHandler.DBL_CLICK = function(evt){
	var vHandler = this.getEventHandler?this.getEventHandler(evt, "dblclick"):null;
	vHandler = vHandler?vHandler:this;
	vHandler._clickCount = vHandler._clickCount?vHandler._clickCount:0;
	vHandler._clickCount++;

	var vTarget = evt.target;
	if(vHandler._clickCount == 1){
		var vTimerObj = RD.XHTML.Timer.getManager();
		vHandler._oldTarget = vTarget;

		if(!vHandler._timerId){
			vHandler._timerId = vTimerObj.addCallback(vHandler);
		}

		vHandler._callId = vTimerObj.setTimeout(vHandler._timerId, "clearDblClick", this._dblClickSpeed, evt);
	}

	if(vHandler._clickCount == 2){
		//call dblclick if user has clicked on same target twice
		if(vTarget == vHandler._oldTarget){
			this.dblclick(evt);
		}
		vHandler.clearDblClick(evt);
	}
};

//this is used for holding the mouse down on a node
RD.XHTML.EventHandler.MOUSE_HELD = function(evt){
	var vTimerObj = RD.XHTML.Timer.getManager();
	if(!this._timerId){
		this._timerId = vTimerObj.addCallback(this);
	}

	evt = RD.XHTML.GetEvent(evt);
	this._callId = vTimerObj.setTimeout(this._timerId, "mouseheld", RD.XHTML.EventHandler.HELD_TME, evt);
};

//this is used for hovering the mouse over a node
RD.XHTML.EventHandler.MOUSE_HOVER = function(evt){
	var vTimerObj = RD.XHTML.Timer.getManager();
	if(!this._timerId){
		this._timerId = vTimerObj.addCallback(this);
	}

	evt = RD.XHTML.GetEvent(evt);
	this._callId = vTimerObj.setTimeout(this._timerId, "mousehover", RD.XHTML.EventHandler.HOVER_TME, evt);
};

RD.XHTML.EventHandler.prototype.constructor = RD.XHTML.EventHandler;

RD.XHTML.EventHandler.prototype.init = function(){
	this._timerId = null;
	this._callId = null;
	this._isEnabledMouseHeld = false;
	this._isEnabledMouseHover = false;
	this._isEnabledDblClick = false;
};

RD.XHTML.EventHandler.prototype.enableDblClick = function(aDblClickSpeed){
	this._clickCount = 0;
	this._oldTarget = null;
	this._dblClickSpeed = aDblClickSpeed?aDblClickSpeed:RD.XHTML.EventHandler.DBL_CLICK_SPD;
	this._isEnabledDblClick = true;
};

RD.XHTML.EventHandler.prototype.enableMouseHeld = function(){
	var vHandler = null;//this.getEventHandler?this.getEventHandler(evt, "mouseheld"):null;
	vHandler = vHandler?vHandler:this;
	vHandler._isEnabledMouseHeld = true;
};

RD.XHTML.EventHandler.prototype.enableMouseHover = function(){
	var vHandler = null;//this.getEventHandler?this.getEventHandler(evt, "mousehover"):null;
	vHandler = vHandler?vHandler:this;
	vHandler._isEnabledMouseHover = true;
};

RD.XHTML.EventHandler.prototype.clearDblClick = function(evt){
	var vHandler = this.getEventHandler?this.getEventHandler(evt, "dblclick"):null;
	vHandler = vHandler?vHandler:this;
	RD.XHTML.Timer.getManager().clearTimeout(vHandler._timerId, vHandler._callId);

	vHandler._clickCount = 0;
	vHandler._oldTarget = null;
};

RD.XHTML.EventHandler.prototype.clearMouseHeld = function(){
	if(this._callId){
		RD.XHTML.Timer.getManager().clearTimeout(this._timerId, this._callId);
	}
};

RD.XHTML.EventHandler.prototype.clearMouseHover = function(){
	if(this._callId){
		RD.XHTML.Timer.getManager().clearTimeout(this._timerId, this._callId);
	}
};

RD.XHTML.EventHandler.prototype.handleEvent = function( evt ){
	evt = evt?evt:window.event;

	this.handleCustomEvent(evt);

	if( !this[evt.type]){
		if(window._alertErrors){
			alert( "Unsupported event type: " + evt.type );
			//throw new Error( "Unsupported event type: " + evt.type );
		}
	}
	else{this[evt.type](evt);}
};

RD.XHTML.EventHandler.prototype.handleCustomEvent = function( evt ){
	switch(evt.type){
		case "mousedown":
			this.clearMouseHover();
			if(this._isEnabledMouseHeld && this.getEventHandler(evt, "mouseheld")){
				RD.XHTML.EventHandler.MOUSE_HELD.call(this, evt);
			}
			break;
		case "click":
			if(evt.detail == 2){
				this.clearDblClick(evt);
				this.dblclick(evt);
			}//some browsers (safari) don't seem to like the built in dblclick much, so also set up the custom dblclick
			else if(this._isEnabledDblClick && this.getEventHandler(evt, "dblclick")){
				RD.XHTML.EventHandler.DBL_CLICK.call(this, evt);
			}
			break;
		case "mouseover":
			if(this._isEnabledMouseHover && this.getEventHandler(evt, "mousehover")){
				RD.XHTML.EventHandler.MOUSE_HOVER.call(this, evt);
			}
			break;
		case "mouseout":
			this.clearMouseHover();
			break;
		case "mouseup":
			this.clearMouseHeld();
			break;
	}
};

/*
function RD.XHTML.GetUrlRequestHandler(){
	if(!RD.XHTML.GetUrlRequestHandler.Manager){
		RD.XHTML.GetUrlRequestHandler.Manager = this;
		this._calls = new Object();
	}

	return RD.XHTML.GetUrlRequestHandler.Manager;
}

RD.XHTML.GetUrlRequestHandler.getManager = function(){
	return new RD.XHTML.GetUrlRequestHandler();
};

RD.XHTML.GetUrlRequestHandler.prototype.constructor = RD.XHTML.GetUrlRequestHandler;
RD.XHTML.GetUrlRequestHandler.Manager = null;

RD.XHTML.GetUrlRequestHandler.prototype.getURL = function(vRequestHanderId, aCallback, aUrl){
    var vCallId = RD.XHTML.getUniqueId();
	var vCallObj = this._calls[aTimerId];
	vCallObj._callbacks[vCallId] = new Object();
	vCallObj._callbacks[vCallId]._callback = aCallback;

	getURL(aUrl, this);
	
    return vCallId;
};

RD.XHTML.GetUrlRequestHandler.prototype.addCallback = function(aCallback){
	var vRequestHanderId = RD.XHTML.getUniqueId();
	this._calls[vRequestHanderId] = new Object();
	this._calls[vRequestHanderId]._callObj = aCallback;
	this._calls[vRequestHanderId]._callbacks = new Object();
	
	return vRequestHanderId;
};

RD.XHTML.GetUrlRequestHandler.prototype.operationComplete = function(status){
	if(status.success){
		this.makeCall();
	}
};

RD.XHTML.GetUrlRequestHandler.prototype.makeCall = function(aRequestHanderId, aCallId){
	var vCallObj = this._calls[aRequestHanderId];
    if(!vCallObj && !vCallObj._callbacks[aCallId]){
		return;
	}

	vArgs = vCallObj._callbacks[aCallId]._args;

	var vCall = new Array("vCallObj._callObj[vCallObj._callbacks[aCallId]._callback](");
	
	for(var n=2;n<vArgs.length;n++){
		vCall.push("vArgs[" + n + "]");
		if(n<vArgs.length-1){
			vCall.push(",");
		}
	}
	
	vCall = vCall.join(String.empty) + ")";

	eval(vCall);
};
*/

RD.XHTML.Timer = function(){
	if(!RD.XHTML.Timer.Manager){
		RD.XHTML.Timer.Manager = this;
		this._callbacks = {};
	}

	return RD.XHTML.Timer.Manager;
}

RD.XHTML.Timer.getManager = function(){
	return new RD.XHTML.Timer();
}

RD.XHTML.Timer.prototype.constructor = RD.XHTML.Timer;
RD.XHTML.Timer.Manager = null;

RD.XHTML.Timer.prototype.constructor = RD.XHTML.Timer;

RD.XHTML.Timer.prototype.addCallback = function(aCallback){
	var vTimerId = -1;
	for(var vKey in this._callbacks){
		if(this._callbacks[vKey].callbackObject == aCallback){
			vTimerId = vKey;
			break;
		}
	}
	
	if(vTimerId == -1){
		var vCallback = {
			callbackObject:aCallback
			,calls:{}
		}
		vTimerId = RD.XHTML.getUniqueId();
		this._callbacks[vTimerId] = vCallback;
	}

	return vTimerId;
};


RD.XHTML.Timer.prototype.setInterval = function(aTimerId, aCallback, aMSec){
	var vCallback = this._callbacks[aTimerId];
	var vCallId = -1;

	if(vCallback){
		var vCallId = RD.XHTML.getUniqueId();
		vCallback.calls[vCallId] = {
			args:arguments
			,callback:aCallback
		};

		vCallback.calls[vCallId].windowTimerId = window.setInterval("RD.XHTML.Timer.getManager().makeCall("+aTimerId+", "+vCallId+");", aMSec);
	}

    return vCallId;
};

RD.XHTML.Timer.prototype.setTimeout = function(aTimerId, aCallback, aMSec){
    var vCallback = this._callbacks[aTimerId];
	var vCallId = -1;

	if(vCallback){
		var vCallId = RD.XHTML.getUniqueId();
		vCallback.calls[vCallId] = {
			args:arguments
			,callback:aCallback
		};

		vCallback.calls[vCallId].windowTimerId = window.setInterval("RD.XHTML.Timer.getManager().callOnce("+aTimerId+", "+vCallId+");", aMSec);
	}

    return vCallId;
};

RD.XHTML.Timer.prototype.clearTimeout = function(aTimerId, aCallId){
	var vCallback = this._callbacks[aTimerId];

	if(this._callbacks[aTimerId]){
		var vCall = this._callbacks[aTimerId].calls[aCallId];
		if(vCall){
			window.clearTimeout(vCall.windowTimerId);
			
			this._callbacks[aTimerId].calls[aCallId] = null;
			delete this._callbacks[aTimerId].calls[aCallId];
		}
	}
};

RD.XHTML.Timer.prototype.clearInterval = function(aTimerId, aCallId){
	var vCallback = this._callbacks[aTimerId];

	if(this._callbacks[aTimerId]){
		var vCall = this._callbacks[aTimerId].calls[aCallId];
		if(vCall){
			window.clearInterval(vCall.windowTimerId);
			
			this._callbacks[aTimerId].calls[aCallId] = null;
			delete this._callbacks[aTimerId].calls[aCallId];
		}
	}
};

RD.XHTML.Timer.prototype.makeCall = function(aTimerId, aCallerId){
	var vCallback = this._callbacks[aTimerId];
	if(vCallback){
		var vCallbackObject = vCallback.callbackObject;
		var vCall = vCallback.calls[aCallerId];
		
		var vCallString = new Array();
		vCallString.push("vCallbackObject[vCall.callback](");
		for(var n=3; n<vCall.args.length; n++){
			vCallString.push("vCall.args["+n+"]");
			if(n<vCall.args.length-1){
				 vCallString.push(",");
			}
		}
		vCallString.push(")");
	
		eval(vCallString.join(String.empty));
	}
	else{
		this.clearInterval(aTimerId, aCallerId);
	}
};

RD.XHTML.Timer.prototype.callOnce = function(aTimerId, aCallId){
	this.makeCall(aTimerId, aCallId);
	this.clearTimeout(aTimerId, aCallId);
};

RD.XHTML.Rect = function( aX, aY, aWidth, aHeight ){
	this.x=aX?parseFloat(aX):0;
	this.y=aY?parseFloat(aY):0;
	this.width=aWidth?aWidth:0;
	this.height=aHeight?aHeight:0;
	this.width=(this.width.toString().indexOf("%") > -1)?this.width:parseFloat(this.width);
	this.height=(this.height.toString().indexOf("%") > -1)?this.height:parseFloat(this.height);
	
	return this;
};

RD.XHTML.Rect.prototype.constructor = RD.XHTML.Rect;

RD.XHTML.Rect.add = function(aRect_A, aRect_B){
	return new RD.XHTML.Rect(
				(aRect_A.x+aRect_B.x), 
				(aRect_A.y+aRect_B.y),
				(aRect_A.width+aRect_B.width),
				(aRect_A.height+aRect_B.height)
			);
};

RD.XHTML.Rect.subtract = function(aRect_A, aRect_B){
	return new RD.XHTML.Rect(
				(aRect_A.x-aRect_B.x), 
				(aRect_A.y-aRect_B.y),
				(aRect_A.width-aRect_B.width),
				(aRect_A.height-aRect_B.height)
			);
};

RD.XHTML.Rect.prototype.duplicate = function(){
	return new RD.XHTML.Rect(this.x, this.y, this.width, this.height);
};

RD.XHTML.Rect.prototype.toSASize = function(){
	return new RD.XHTML.Size(this.width, this.height);
};

RD.XHTML.Rect.prototype.toSAPoint = function(){
	return new RD.XHTML.Point(this.x, this.y);
};

RD.XHTML.Rect.prototype.toString=function(){
	return "rect(" + this.x + "," + this.y + "," + this.width + "," + this.height + ")";
};

RD.XHTML.Size = function( aWidth, aHeight ){
	this.width=aWidth?aWidth:0;
	this.height=aHeight?aHeight:0;
	this.width=(this.width.toString().indexOf("%") > -1)?this.width:parseFloat(this.width);
	this.height=(this.height.toString().indexOf("%") > -1)?this.height:parseFloat(this.height);
	
	return this;
};

RD.XHTML.Size.prototype.constructor = RD.XHTML.Size;

RD.XHTML.Size.add = function(aSize_A, aSize_B){
	return new RD.XHTML.Size(
				(aSize_A.width+aSize_B.width), 
				(aSize_A.height+aSize_B.height)
			);
};

RD.XHTML.Size.subtract = function(aSize_A, aSize_B){
	return new RD.XHTML.Size(
				(aSize_A.width-aSize_B.width),
				(aSize_A.height-aSize_B.height)
			);
};

RD.XHTML.Size.prototype.subtract = function(aValue){
	this.add(-aValue);
};

RD.XHTML.Size.prototype.add = function(aValue){
	this.width += aValue;
	this.height += aValue;
};

RD.XHTML.Size.prototype.duplicate = function(){
	return new RD.XHTML.Size(this.width, this.height);
};

RD.XHTML.Size.prototype.toString = function(){
	return "size(" + this.width + "," + this.height + ")";
};

//
//
//   constructor
//
//
RD.XHTML.Vector2D = function(x, y) {
    if ( arguments.length > 0 ) {
        this.x = x;
        this.y = y;
    }
};


//
//
//   length
//
//
RD.XHTML.Vector2D.prototype.length = function() {
    return Math.sqrt(this.x*this.x + this.y*this.y);
};


//
//
//   dot
//
//
RD.XHTML.Vector2D.prototype.dot = function(that) {
    return this.x*that.x + this.y*that.y;
};


//
//
//   cross
//
//
RD.XHTML.Vector2D.prototype.cross = function(that) {
    return this.x*that.y - this.y*that.x;
}


//
//
//   unit
//
//
RD.XHTML.Vector2D.prototype.unit = function() {
    return this.divide( this.length() );
};


//
//
//   unitEquals
//
//
RD.XHTML.Vector2D.prototype.unitEquals = function() {
    this.divideEquals( this.length() );

    return this;
};


//
//
//   add
//
//
RD.XHTML.Vector2D.prototype.add = function(that) {
    return new RD.XHTML.Vector2D(this.x + that.x, this.y + that.y);
};


//
//
//   addEquals
//
//
RD.XHTML.Vector2D.prototype.addEquals = function(that) {
    this.x += that.x;
    this.y += that.y;

    return this;
};


//
//
//   subtract
//
//
RD.XHTML.Vector2D.prototype.subtract = function(that) {
    return new RD.XHTML.Vector2D(this.x - that.x, this.y - that.y);
};


//
//
//   subtractEquals
//
//
RD.XHTML.Vector2D.prototype.subtractEquals = function(that) {
    this.x -= that.x;
    this.y -= that.y;

    return this;
};


//
//
//   multiply
//
//
RD.XHTML.Vector2D.prototype.multiply = function(scalar) {
    return new RD.XHTML.Vector2D(this.x * scalar, this.y * scalar);
};


//
//
//   multiplyEquals
//
//
RD.XHTML.Vector2D.prototype.multiplyEquals = function(scalar) {
    this.x *= scalar;
    this.y *= scalar;

    return this;
};


//
//
//   divide
//
//
RD.XHTML.Vector2D.prototype.divide = function(scalar) {
    return new RD.XHTML.Vector2D(this.x / scalar, this.y / scalar);
};


//
//
//   divideEquals
//
//
RD.XHTML.Vector2D.prototype.divideEquals = function(scalar) {
    this.x /= scalar;
    this.y /= scalar;

    return this;
};


//
//
//   perp
//
//
RD.XHTML.Vector2D.prototype.perp = function() {
    return new RD.XHTML.Vector2D(-this.y, this.x);
};


//
//
//   perpendicular
//
//
RD.XHTML.Vector2D.prototype.perpendicular = function(that) {
    return this.subtract(this.project(that));
};


//
//
//   project
//
//
RD.XHTML.Vector2D.prototype.project = function(that) {
    var percent = this.dot(that) / that.dot(that);

    return that.multiply(percent);
};


//
//
//   toString
//
//
RD.XHTML.Vector2D.prototype.toString = function() {
    return this.x + "," + this.y;
};


//
//
//   fromPoints
//
//
RD.XHTML.Vector2D.fromPoints = function(p1, p2) {
    return new RD.XHTML.Vector2D(
        p2.x - p1.x,
        p2.y - p1.y
    );
};

RD.XHTML.Point = function( aX, aY ){
	this.init(aX, aY);
	
	return this;
};

RD.XHTML.Point.prototype.constructor = RD.XHTML.Point;

RD.XHTML.Point.add = function(aPoint_A, aPoint_B){
	return new RD.XHTML.Point(
				(aPoint_A.x+aPoint_B.x), 
				(aPoint_A.y+aPoint_B.y)
			);
};

RD.XHTML.Point.min = function(aPoint_A, aPoint_B){
	return new RD.XHTML.Point(
				Math.min(aPoint_A.x, aPoint_B.x), 
				Math.min(aPoint_A.y, aPoint_B.y)
			);
};

RD.XHTML.Point.max = function(aPoint_A, aPoint_B){
	return new RD.XHTML.Point(
				Math.max(aPoint_A.x, aPoint_B.x), 
				Math.max(aPoint_A.y, aPoint_B.y)
			);
};

RD.XHTML.Point.subtract = function(aPoint_A, aPoint_B){
	return new RD.XHTML.Point(
				(aPoint_A.x-aPoint_B.x), 
				(aPoint_A.y-aPoint_B.y)
			);
};

RD.XHTML.Point.prototype.init = function(aX, aY){
	this.x=aX?parseFloat(aX):0;
	this.y=aY?parseFloat(aY):0;
};

RD.XHTML.Point.prototype.duplicate = function(){
	return new RD.XHTML.Point(this.x, this.y);
};

RD.XHTML.Point.prototype.toPointString=function(){
	return this.x + "," + this.y;
};

RD.XHTML.Point.prototype.toString=function(){
	return "point(" + this.x + "," + this.y + ")";
};

RD.XHTML.Mouse = function( evt ){
	if(!RD.XHTML.Mouse.Manager){
		if(!evt){

		}

		RD.XHTML.Mouse.Manager = this;
	}

	RD.XHTML.Mouse.Manager.setLoc(evt);
	
	return RD.XHTML.Mouse.Manager;
};

RD.XHTML.Mouse.Manager = null;

RD.XHTML.Mouse.getManager = function(evt){
	return new RD.XHTML.Mouse(evt);
};

RD.XHTML.Mouse.prototype = new RD.XHTML.Point();
RD.XHTML.Mouse.prototype.constructor = RD.XHTML.Mouse;
RD.XHTML.Mouse.superclass = RD.XHTML.Point.prototype;

RD.XHTML.Mouse.prototype.setLoc=function(evt){
	RD.XHTML.Mouse.superclass.init.call(this);
	if(evt){
		var vPoint = RD.XHTML.GetEvtPos(evt);
		this.x = vPoint.x;
		this.y = vPoint.y;
	}
};

RD.XHTML.ToolTip = function( aArgs ){
	if(!RD.XHTML.ToolTip.Manager){
		if(!aArgs){
			aArgs = {
				parentNode:SVG_ROOT,
				fontSize:10.5,
				fill:"#FFFFE1",
				fontColor:"#000",
				stroke:"#000",
				padding:2
			};
		}

		this.init( aArgs );
		
		RD.XHTML.ToolTip.Manager = this;
	}

	return RD.XHTML.ToolTip.Manager;
};

RD.XHTML.ToolTip.prototype.constructor = RD.XHTML.ToolTip;
RD.XHTML.ToolTip.Manager = null;
RD.XHTML.ToolTip.getManager = function(){
	return new RD.XHTML.ToolTip();
};

RD.XHTML.ToolTip.prototype.init = function(aArgs){
	this.pFontSize = aArgs.fontSize?aArgs.fontSize:11;
	this.pLoc = aArgs.loc?aArgs.loc:new RD.XHTML.Point(0, 22);
	this.pPadding = aArgs.padding?aArgs.padding:8;
	this.pHtPadding = aArgs.paddingHeight?aArgs.paddingHeight:this.pPadding;
	this.pWtPadding = aArgs.paddingWidth?aArgs.paddingWidth:this.pPadding+1;
	this.pFontFamily = "Arial,Tunga,Tahoma,Monospace";
	this.pTipNode = RD.XHTML.NodeHelper.createNode("g", aArgs.parentNode, {display:"none"});

	var vRect = RD.XHTML.NodeHelper.createNode("rect", this.pTipNode, {x:this.pLoc.x, y:this.pLoc.y, width:10, height:10, fill:aArgs.fill, stroke:aArgs.stroke, "stroke-width":1});
	vRect.setAttributeNS( null, "pointer-events", "none" );
	
	var textbox = RD.XHTML.NodeHelper.createNode(
		"text", 
		this.pTipNode,{
			x:this.pLoc.x, 
			y:this.pLoc.y, 
			"text-rendering":"optimizeLegibility", 
			"font-size":this.pFontSize + "px", 
			fill:aArgs.fontColor, 
			"text-anchor":"middle", 
			"dominant-baseline":"mathematical" 
		},
		"Error"
		);

	textbox.setAttributeNS( null, "pointer-events", "none" );
};

RD.XHTML.ToolTip.prototype.show = function(aLabel, aLoc){
	if(this.pTipNode != this.pTipNode.parentNode.lastChild){
		this.pTipNode.parentNode.appendChild(this.pTipNode);
	}

	//var vIndex = this.getIndex(aNode);
	aLabel = aLabel?aLabel:"Display Tip Here"
	this.setTip( aLabel, aLoc );
	this.pTipNode.setAttributeNS(null, "display", "all");
	//RD.XHTML.Debug.getManager().write([(new Date),'showing'])
};

RD.XHTML.ToolTip.prototype.setLabel = function(aIndex, aLabel){
	this.pTools[aIndex].pLabel = aLabel;
};

RD.XHTML.ToolTip.prototype.setTip = function( aLabel, aLoc ){
	//set pos of rect
	aLoc = aLoc?aLoc:RD.XHTML.Mouse.getManager().duplicate();
	aLoc.x += this.pLoc.x;
	aLoc.y += this.pLoc.y;
	this.pTipNode.firstChild.setAttributeNS(null, "x", aLoc.x);
	this.pTipNode.firstChild.setAttributeNS(null, "y", aLoc.y);

	//set text attributes
	var vText = this.pTipNode.lastChild;
	vText.firstChild.data = aLabel;
	
	var vTextLen = vText.getComputedTextLength();
	var vWidth = vTextLen + (2 * this.pWtPadding);
	var vHeight = this.pFontSize + (2 * this.pHtPadding);
	
	//set size of rect
	this.pTipNode.firstChild.setAttributeNS(null, "width", vWidth);
	this.pTipNode.firstChild.setAttributeNS(null, "height", vHeight);
	
	//set pos of text
	vText.setAttributeNS(null, "x", aLoc.x + vWidth*0.5);
	vText.setAttributeNS(null, "y",  aLoc.y + vHeight*0.5);
};

RD.XHTML.ToolTip.prototype.hide = function(){
	this.pTipNode.setAttributeNS(null, "display", "none");
	//RD.XHTML.Debug.getManager().write([(new Date),'hiding'])
};

RD.XHTML.Color = function(aRGB, aHex, aHSB){
	if(aRGB || aHex || aHSB){
		this.init(aRGB, aHex, aHSB);
	}
	
	return this;
};

//store wc3 16 color name mappings
RD.XHTML.Color._colorNames = {
	black:"#000000"
	,silver:"#C0C0C0"
	,gray:"#808080"
	,grey:"#808080"//do this one for ppl who misspell gray ;p
	,white:"#FFFFFF"
	,maroon:"#800000"
	,red:"#FF0000"
	,purple:"#800080"
	,fuchsia:"#FF00FF"
	,green:"#008000"
	,lime:"#00FF00"
	,olive:"#808000"
	,yellow:"#FFFF00"
	,navy:"#000080"
	,blue:"#0000FF"
	,teal:"#008080"
	,aqua:"#00FFFF"
};

RD.XHTML.Color.prototype.constructor = RD.XHTML.Color;

RD.XHTML.Color.prototype.init = function(aColor){
	var vRGB = {r:0, g:0, b:0};
	var vHSB = null;
	var vHex = null;
	if(aColor){
		if(typeof(aColor) == "object"){
			//if hsb
			if(aColor.h != null && aColor.s != null && aColor.v != null){
				vRGB = this.HSBToRGB(aColor.h,aColor.s,aColor.v );
				vHSB = aColor;
			}
			else{
				vRGB = aColor;
				vHSB = this.RGBToHSB(aColor.r,aColor.g,aColor.b );
			}
		}
		else{
			//check to see if it is a color keyword
			var vHex = RD.XHTML.Color._colorNames[aColor.toLowerCase()];

			vHex = vHex?vHex:aColor;
			vHex = vHex.replace(/\#/, String.empty);
			if(!vHex.length || vHex.length > 6){
				vHex = "ffffff";
			}
			   
			var vLength = vHex.length;
			for (var n=vLength-1;vHex.length<6; n++){
				vHex += vHex.charAt(vLength-1);
			}
			vHex = "#" + vHex;
			vRGB = this.hexToRGB(vHex);
		}
	}

	this.r = vRGB.r;
	this.g = vRGB.g;
	this.b = vRGB.b;
		
	this.pHex = vHex?vHex:this.RGBToHex(vRGB);
	vHSB = vHSB?vHSB:this.RGBToHSB(vRGB.r, vRGB.g, vRGB.b);

	
	this.h = vHSB.h;
	this.s = vHSB.s;
	this.v = vHSB.v;
};

RD.XHTML.Color.prototype.toString = function(){
	return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
};

RD.XHTML.Color.prototype.getInverse = function(aRGB){
	var vColor = "rgb(" + Math.abs(this.r-255) + ", " + Math.abs(this.g-255) + ", " + Math.abs(this.b-255) + ")";
	if(!aRGB){
		vColor = this.RGBToHex(vColor);
	}
	
	return vColor;
};

RD.XHTML.Color.prototype.getDec = function(aHex){
	var vValue = null;
	
	switch (aHex.toUpperCase()){
		case "A":vValue = 10;break;
		case "B":vValue = 11;break;		
		case "C":vValue = 12;break;
		case "D":vValue = 13;break;
		case "E":vValue = 14;break;	
		case "F":vValue = 15;break;
		default:vValue = eval(aHex);break;
	}
	
	return vValue;
};

RD.XHTML.Color.prototype.getHex = function(aDec){
	aDec = parseInt(aDec, 10);
	var vValue = null;
	
	switch(aDec){
		case 10:vValue = "A";break;
		case 11:vValue = "B";break;		
		case 12:vValue = "C";break;
		case 13:vValue = "D";break;
		case 14:vValue = "E";break;	
		case 15:vValue = "F";break;
		default:vValue = aDec.toString();break;
	}
	
	return vValue;
};


///******************************************************************
//		***function hexToRGB (aHex)***
//	converts a hexidecimal value to an RGB object and returns the object
//	**seems to be something wrong with the conversion**
//	**works with browsers 4+
//
///******************************************************************
RD.XHTML.Color.prototype.hexToRGB = function(aHex){
	aHex = aHex.toUpperCase();
   var vRGB = new Object();
   var vStart = 0;
   var vEnd = aHex.length;

   aHex = aHex.replace(/\#/, String.empty);

   a = this.getDec(aHex.substring(0, 1));
   b = this.getDec(aHex.substring(1, 2));
   c = this.getDec(aHex.substring(2, 3));
   d = this.getDec(aHex.substring(3, 4));
   e = this.getDec(aHex.substring(4, 5));
   f = this.getDec(aHex.substring(5, 6));
  
   
   vRGB.r = (a * 16) + b;
   vRGB.g = (c * 16) + d;
   vRGB.b = (e * 16) + f;

   return vRGB;
};

///******************************************************************
//		***function RGBToHex (vDec)***
//
//
//	**works with browsers 4+
//
///******************************************************************
RD.XHTML.Color.prototype.RGBToHex = function(aRGB){
	var vRGB = new Object();
	
	//can accept an RD.XHTML.Color object or an RGB string ie rgb(r,g,b)
	if(typeof(aRGB) == "object"){
		vRGB.r = aRGB.r;
		vRGB.g = aRGB.g;
		vRGB.b = aRGB.b;
	}
	else{
		if(aRGB.substr(0, 1) == "#"){
			return aRGB;
		}
		else if(aRGB.length == 6){
			return "#" + aRGB;
		}
	
		vDec=String(aRGB);
		clArray=aRGB.split('(')
		clArray2=clArray[1].split(',')
		clArray[0]=clArray2[0];
		clArray[1]=clArray2[1];
		clArray[2]=clArray2[2].split(')')[0];
		
		vRGB.r=clArray[0];
		vRGB.g=clArray[1];
		vRGB.b=clArray[2];
	}
	
	var vHex = new Array();
	vHex.push(this.getHex(Math.floor(vRGB.r / 16)));
	vHex.push(this.getHex(vRGB.r % 16));
	vHex.push(this.getHex(Math.floor(vRGB.g / 16)));
	vHex.push(this.getHex(vRGB.g % 16));
	vHex.push(this.getHex(Math.floor(vRGB.b / 16)));
	vHex.push(this.getHex(vRGB.b % 16));

	return "#" + vHex.join(String.empty).toUpperCase();
}

RD.XHTML.Color.prototype.HSBToRGB = function (h,s,v){
	var vRGB = new Object();
	vRGB.r = 0;
	vRGB.g = 0;
	vRGB.b = 0;

	h /= 360;
	s *= 0.01;
	v *= 0.01;
	
	if(s==0){
		vRGB.r= Math.round(255*v); 
		vRGB.g= Math.round(255*v); 
		vRGB.b= Math.round(255*v);
		return vRGB;
	}
	else if (v == 0){
		return vRGB;
	}
	else{
		if (h < 1.0 / 6){       // vRGB.r domain; vRGB.g ascends
			var domnOffset = h;

			vRGB.r = v;
			vRGB.b = v * (1.0 - s);
			vRGB.g = vRGB.b + (v - vRGB.b) * domnOffset * 6;
		}
		else if (h < 2.0/6){         // yellow domain; vRGB.r descends
			domnOffset = h - 1.0/6;
			vRGB.g = v;
			vRGB.b = v * (1.0 - s);
			vRGB.r = vRGB.g - (v - vRGB.b) * domnOffset * 6;
		}   
		else if (h < 3.0/6){         // vRGB.g domain; vRGB.b ascends
			domnOffset = h - 2.0/6;
			vRGB.g = v;
			vRGB.r = v * (1.0 - s);
			vRGB.b = vRGB.r + (v - vRGB.r) * domnOffset * 6;
		}
		else if (h < 4.0 / 6){       // cyan domain; vRGB.g descends
			domnOffset = h - 3.0/6;
			vRGB.b = v;
			vRGB.r = v * (1.0 - s);
			vRGB.g = vRGB.b - (v - vRGB.r) * domnOffset * 6;
		}
		else if (h < 5.0 / 6){       // vRGB.b domain; vRGB.r ascends
			domnOffset = h - 4.0/6;
			vRGB.b = v;
			vRGB.g = v * (1.0 - s);
			vRGB.r = vRGB.g + (v - vRGB.g) * domnOffset * 6;
		}
		else{                     // magenta domain; vRGB.b descends
			domnOffset = h - 5.0/6
			vRGB.r = v;
			vRGB.g = v * (1.0 - s);
			vRGB.b = vRGB.r - (v - vRGB.g) * domnOffset * 6;
		}
	}
	
	vRGB.r = Math.round(vRGB.r * 255);
	vRGB.g = Math.round(vRGB.g * 255);
	vRGB.b = Math.round(vRGB.b * 255);

	return vRGB;
};

RD.XHTML.Color.prototype.RGBToHSB = function(r,g,b){
	var vHSB = new Object();
	vHSB.h = 0;
	vHSB.s = 0;
	vHSB.v = 0;
	
	r /= 255;
	g /= 255;
	b /= 255;
	
	var vMin = Math.min3( r, g, b );
	var vMax = Math.max3( r, g, b );
	
	vHSB.h = 0;
	vHSB.v = vMax;
	vHSB.s = 0;
	
	if (vMax > 0) {
		vHSB.s = (vMax - vMin) / vMax;
	}

	if (vHSB.s > 0){
		var vDiff = vMax - vMin;
		rc = (vMax - r) / vDiff;
		gc = (vMax - g) / vDiff;
		bc = (vMax - b) / vDiff;
		if (r == vMax) {
			vHSB.h = (bc - gc) / 6;
		}
		if (g == vMax) {
			vHSB.h = (2 + rc - bc) / 6;
		}
		if (b == vMax) {
			vHSB.h = (4 + gc - rc) / 6;
		}
	}

	if (vHSB.h < 0) {
		vHSB.h += 1;
	}
	
	vHSB.h = Math.round(vHSB.h * 360);
	vHSB.s = Math.round(vHSB.s * 100);
	vHSB.v = Math.round(vHSB.v * 100);

	return vHSB;
};

RD.XHTML.Debug = function(){
	if(!RD.XHTML.Debug.Manager){
		var vId = "RD.XHTML.debug_0";
		this.init( vId );
		
		RD.XHTML.Debug.Manager = this;
	}

	var vLayer = $("debug_text_nodes_" + RD.XHTML.Debug.Manager.pId);
	if(vLayer != SVG_ROOT.lastChild){
		SVG_ROOT.appendChild(vLayer);
	}
	
	return RD.XHTML.Debug.Manager;
}

RD.XHTML.Debug.Manager = null;
RD.XHTML.Debug.getManager = function(){
	return new RD.XHTML.Debug();
}

RD.XHTML.Debug.prototype.init = function( aId ){
	this.pId = aId;
	this.pTextNodes = new Array(2);
	//this.pStartLoc = new RD.XHTML.Point(800,10);
	this.pStartText = "Debug Info";
	this.pEnabled = false;
	this.pForeColor = "#000";
	
	this.createTextNodes();
};

RD.XHTML.Debug.prototype.setEnabled = function( aEnabled ){
	var vDisplay = aEnabled?"inline":"none";
	this.pEnabled = aEnabled;
	
	$("debug_text_nodes_" + this.pId).setAttributeNS(null, "display", vDisplay);
};

RD.XHTML.Debug.prototype.setForeColor = function( aForeColor ){
	this.pForeColor = aForeColor;
	$("debug_text_nodes_" + this.pId).setAttributeNS(null, "fill", this.pForeColor);
};

RD.XHTML.Debug.prototype.write = function( aTextArry ){
	for(var n=0;n<this.pTextNodes.length;n++){
		if(n<aTextArry.length){
			if(aTextArry[n] != null){
				this.pTextNodes[n].firstChild.data = this.pStartText + " " + n + ": " + aTextArry[n];
			}
		}
		else{
			break;
		}
	}
};

RD.XHTML.Debug.prototype.createTextNodes = function( ){
	var trans = "translate(" + (-10) + "," + 0 + ")";
	var vLayer = RD.XHTML.NodeHelper.createNode("g", SVG_ROOT, {
		transform:trans,
		id:"debug_text_nodes_" + this.pId,
		fill:this.pForeColor,
		display:"none"
	});
	
	var vOffsetY = 0;
	for(var n=0;n<this.pTextNodes.length;n++){
		this.pTextNodes[n] = RD.XHTML.NodeHelper.createNode(
				"text",
				vLayer,{
				x:800, 
				y:10 +vOffsetY,
				"text-anchor":"end",
				"dominant-baseline":"hanging"
			}
			,this.pStartText + " " + n + ": "
		);
		vOffsetY += 20;
	}
};
