var goldenrod
if (!goldenrod) goldenrod = {}



goldenrod.Dom = new function() {

	var self = this;
	self.NAME = "goldenrod.Dom";
	
	
	/**************************************************************************************************
	*Point - A class constructor - for holding x and y coordinates
	*
	*x - The horizontal coordinate or an array of two elements. (Note: typeof null yields 'object')
	*y - The vertical coordinate
	**************************************************************************************************/
	self.Point = function(x,y) {
	
		if(x instanceof Array){
			this.x = x[0];
			this.y = x[1];
		}
		else {
			if(x == null) this.x = 0; else this.x = x;
			if(y == null) this.y = 0; else this.y = y;
		}
	}
	
	self.Point.prototype.getPointX = function() {
		return this.x
	}
	
	self.Point.prototype.getPointY = function() {
		return this.y
	}
	
		
	self.Point.prototype.setPointX = function(x) {
		this.x = x
	}
	
	self.Point.prototype.setPointY = function(y) {
		this.y = y
	}
	
	self.Point.prototype.add = function(point) {
		if(point instanceof Point){
			this.x += point.x;
			this.y += point.y;
		}
		else if(point instanceof Array){
			this.x += point[0];
			this.y += point[1];
		}
	}
	
	self.Point.prototype.copy = function(point) {
		if(point instanceof Point){
			this.x = point.x;
			this.y = point.y;
		}
	}
	
	self.Viewport = new self.Point()

	
	
	/**************************************************************************************************
	*Rectangle - A class constructor - All parameters are optional. The default value is the string "auto"
	*
	*Left - The left coordinate 
	*Top - The top coordinate
	*Width - The width
	*Height - The height
	**************************************************************************************************/
	self.Rectangle = function(x,y,w,h) {
		if(x == null) this.Left = self.auto; else this.Left = x;
		if(y == null )this.Top = self.auto; else this.Top = y;
		if(w == null) this.Width = self.auto; else this.Width = w;
		if(h == null) this.Height = self.auto; else this.Height = h;
		this.adjustRB();
	
	}
	

	
	self.Rectangle.prototype.adjustWH = function(){
		this.Width = self.auto; this.Height = self.auto
		if ((this.Right != self.auto) && (this.Left != self.auto)) this.Width = this.Right - this.Left;
		if ((this.Bottom != self.auto) && (this.Top != self.auto)) this.Height = this.Bottom - this.Top;
	}

	self.Rectangle.prototype.adjustRB = function(){
		this.Right = self.auto; this.Bottom = self.auto
		if ((this.Left != self.auto) && (this.Width != self.auto)) this.Right = this.Left + this.Width;
		if ((this.Top != self.auto) && (this.Height != self.auto)) this.Bottom = this.Top + this.Height;
	}
	self.Rectangle.ZERO = new self.Rectangle(0,0,0,0);
	self.Rectangle.AUTO = new self.Rectangle();

	self.Rectangle.prototype.copy = function(rectangle) {
		this.Left = rectangle.Left;
		this.Top = rectangle.Top;
		this.Width = rectangle.Width;
		this.Height = rectangle.Height;
		this.Right = rectangle.Right;
		this.Bottom = rectangle.Bottom;
	}
	
	self.Rectangle.prototype.add = function(rectangle) {
		if( (typeof this.Left == "number") && (typeof rectangle.Left == "number") )
			this.Left += rectangle.Left;
		if( (typeof this.Top == "number") && (typeof rectangle.Top== "number") )
			this.Top += rectangle.Top;
		if( (typeof this.Width == "number") && (typeof rectangle.Width == "number") )
			this.Width += rectangle.Width;
		if( (typeof this.Height == "number") && (typeof rectangle.Height == "number") )
			this.Height += rectangle.Height;
		if( (typeof this.Right == "number") && (typeof rectangle.Right == "number") )
			this.Right += rectangle.Right;
		if( (typeof this.Bottom == "number") && (typeof rectangle.Bottom == "number") )
			this.Bottom += rectangle.Bottom;
	}
	
	self.Rectangle.prototype.isIn = function(xy) {
		var returnValue = true;
		var x = xy[0], y=xy[1];
		if( (x < this.Left) || (x >= this.Right) || (y < this.Top) || y >= this.Bottom)
			returnValue = false;
		return returnValue;
	}

	
	/**************************
	goldenrod.Dom.ELEMENT_NODE = 1;
	goldenrod.Dom.TEXT_NODE = 3;
	goldenrod.Dom.DOCUMENT_NODE = 9;
	goldenrod.Dom.COMMENT_NODE = 8;
	goldenrod.Dom.DOCUMENT_FRAGMENT_NODE = 11;
	goldenrod.Dom.ATTRIBUTE_NODE = 2;
	***********************************/

	self.DPI_X;
	self.DPI_Y;
	self.bcheck = false;
	self.bodycheck = false;
	self.offsetWH_hasborder;
	
	self.absScrollCheck = false;	//If false an absolutely position element scrolls with its offsetParent.
									//If true it scrolls with it's parent (Quirks Mode)
	
	self.scrollBase;
	self.root = document.documentElement;
	
	self.bodyStyleArray = ['visibility',
						'marginLeft', 'marginTop', 'marginRight', 'marginBottom',
						'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 
						'borderLeftWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth'];
	
	self.toPixelRatio;
	self.toPointRatio;
	self.unit_search_pattern = /px|in|pt/;
	//self.scroll_bar_size = .25;
	self.scroll_bar_pixel;
	self.a;
	self.b;
	self.offsetParentBase;
	
	
	self.featureTEST = function(){
		var _0px= '0px', i;
		var body = document.body;
		var bodyStyle = self.getStyle(body);
		
		/*---------------Save body's style-----------------------*/
		var bodyStyleSave = [];
		for(i=0; i<self.bodyStyleArray.length; i++){
			if(self.bodyStyleArray[i] in bodyStyle){
				bodyStyleSave[i] = bodyStyle[self.bodyStyleArray[i]];	
			}
			else {
				bodyStyleSave[i] = 'null';
			}
			
		}
		/*---------------Neutralize body's style----------------*/	
		for(i=0; i<self.bodyStyleArray.length; i++){
			if(i==0) i==i; //body.style[self.bodyStyleArray[i]] = 'hidden';
			else body.style[self.bodyStyleArray[i]] = _0px;
		}
		
		var div_1_Style = [
					['position', 'absolute'],
					['left', '0px'],
					['top', '0px'],
					['width', '100pt'],
					['height', '100pt'],
					['border', '10px solid black'],
					['display', 'block']
			]
			
		var div_2_Style = [
					['position', 'absolute'],
					['left', '0px'],
					['top', '0px'],
					['width', '72pt'],
					['height', '72pt'],
					['border', '0px solid black'],
					['display', 'block']
			]
		var div_1 = document.createElement('div');
		for(i=0; i<div_1_Style.length; i++){
			div_1.style[div_1_Style[i][0]] = div_1_Style[i][1];
		}
		
		var div_2 = document.createElement('div');
		for(i=0; i<div_2_Style.length; i++){
			div_2.style[div_2_Style[i][0]] = div_2_Style[i][1];
		}
		div_1.appendChild(div_2)
		
		body.appendChild(div_1);
		self.offsetParentBase = div_1.offsetParent;
		
		
		self.DPI_Y = div_2.offsetHeight;
		self.DPI_X = div_2.offsetWidth;
		
		self.toPixelRatio = self.DPI_X/72;
		self.toPointRatio = 7200/self.DPI_X;
		
		/*-----------------------------------------------------------------
			It seems there are two way that browsers define offsetLeft.
			In this test case 'div_2' is positioned at the upper left
			corner of the contents area of div_1.
			The offset is a measure from the top left point of an element to 
			a reference point in it's containing parentOffset elt. The top left
			point of an element is always the outer corner - even if the element has 
			a border. 
			
			However the reference point on the offsetParent element is sometimes 
			the outer top corner and other times the top left of the containing box
			inside of the border.
			
			div_2.offsetLeft is either 0 or 10 depending on what point
			of the containing elements geometery is used as an origin.
			
		-------------------------------------------------------------------*/
		switch(div_2.offsetLeft){
			case 0 :	//In this case we need to add the border to get an offset to the parent elements corner.
				self.bcheck = true;
				break;
			case 10 :	//In this case the offset of to the parent elements corner.
				self.bcheck = false;
				break;
			default : 
				alert('feature_test: Unexpected value of div_2.offsetLeft - ' + div_2.offsetLeft);
		}
		
		//if(div_2.offsetLeft != 10) self.bcheck = true;
		
		body.style.margin = '10px';
		switch(body.offsetLeft){
			case 0 :
				self.bodycheck = false;
				break;
			case 10 :
				self.bodycheck = true;
				break;
			default : 
				alert('feature_test: Unexpected value of body.offsetLeft (when body has margin:10px) - ' + body.offsetLeft);
		}
		//if(body.offsetLeft == 10) self.bodycheck = true;
		/*-------------Determine if offsetWidth and offsetHeight include an elements border or not----------*/
		div_1.style.width = '100px';
		div_1.style.height = '100px';
		switch(div_1.offsetWidth){
			case 120 :
				self.offsetWH_hasborder = true;
				break;
			case 100 :
				self.offsetWH_hasborder = false;
				break;
			default :
				alert('feature_test: Unexpected value of div_1.offsetWidth\r\n' +
						'when width is 100px and border is 10px - ' + div_1.offsetWidth);
		}
		
		/*-------------Determine Scroll Bar Width----------*/
		div_1_Style = [
					['position', 'static'],
					['left', 'auto'],
					['top', 'auto'],
					['width', '100px'],
					['height', '100px'],
					['border', '0px solid black'],
					['display', 'block'],
					['overflow', 'auto']
			]
			
		div_2_Style = [
					['position', 'static'],
					['left', 'auto'],
					['top', 'auto'],
					['width', '10px'],
					['height', '150px'],
					['border', '0px solid black'],
					['display', 'block']
			]
		for(i=0; i<div_1_Style.length; i++){
			div_1.style[div_1_Style[i][0]] = div_1_Style[i][1];
		}
		
		for(i=0; i<div_2_Style.length; i++){
			div_2.style[div_2_Style[i][0]] = div_2_Style[i][1];
		}	
		
		self.a = div_1.offsetWidth - div_1.scrollWidth;
		self.b = div_1.offsetWidth - div_1.clientWidth;
		self.scroll_bar_pixel = self.b;
		
		/*-------------Determine Scroll Behaviour for absolutely positioned elements---------*/
		div_2_Style = [
					['position', 'absolute'],
					['left', '0px'],
					['top', '0px'],
					['width', '10px'],
					['height', '150px'],
					['border', '0px solid black'],
					['display', 'block']
			]
				
		for(i=0; i<div_2_Style.length; i++){
			div_2.style[div_2_Style[i][0]] = div_2_Style[i][1];
		}	
		
		self.absScrollCheck = self.hasScrollBar(div_1)[0];
		
		
		div_1.style.height = 2 * (self.getViewportHeight()) + 'px';
		div_1.style.width =  2 * (self.getViewportWidth()) + 'px';
		body.scrollTop = 10;
		if(body.scrollTop == 10){
			self.scrollBase = body;
			body.scrollTop = 0;
		}
		else {
			self.root.scrollTop = 10;
			if(self.root.scrollTop == 10)self.scrollBase = self.root;
			self.root.scrollTop = 0;
		}
		
		/*----------------Clean Up-------------------------------*/
		body.removeChild(div_1);
		
		/*--------------Restore Body's style---------------*/
		for(i=0; i<self.bodyStyleArray.length; i++){
			if(self.bodyStyleArray[i] in body.style){
				if(bodyStyleSave[i] != 'null')
					body.style[self.bodyStyleArray[i]] = bodyStyleSave[i];	
			}
			else alert(self.bodyStyleArray[i] + " is not a property of body.style");
		}
	}
	
	self.isAnOffsetParent = function(elt, eltBase){
		var result = false;
		if(typeof eltBase == 'string') eltBase = document.getElementById(eltBase);
		
		if(elt && elt.nodeType && (elt.nodeType == 1) ){
			if(eltBase == undefined){
				return true;
			}
			else if( (eltBase == document.body) || (eltBase == self.root)){
				result = true;
			}
			else if(eltBase && eltBase.nodeType && (eltBase.nodeType == 1) ){
				var offsetParent = elt;
				while( (offsetParent = offsetParent.offsetParent) ){
					if(offsetParent == eltBase)break;
				}
				if(offsetParent!=null) result=true;
			}	
		}
		return result;
	}

	self.calcBorder = function(elt, xy){
		var eltStyle = self.getStyle(elt), n;
		if(elt.clientLeft != undefined){	//clientTop may exist but equal 0 so we need this test.
			xy[0] += elt.clientLeft;
		}
		else if(!isNaN(n = self.getPixel(eltStyle.borderLeftWidth))){
			xy[0] += n;	
		}
		if(elt.clientTop != undefined){
			xy[1] += elt.clientTop;
		}
		else if(!isNaN(n = self.getPixel(eltStyle.borderTopWidth))){
			xy[1] += n;	
		}
	}
	
	self.getOffsetParentBase = function(elt){
		var offsetParent = elt;
		var base = elt;
		while(offsetParent = offsetParent.offsetParent){
			base = offsetParent;
		}
		return base;
	}
	
	self.getscrollParent = function(elt){
		var returnValue = null;
		if(typeof elt == "string") elt = document.getElementById(elt);
		
		if( (elt.nodeType == 1) && (elt != document.body) && (elt != self.root) ){
			var position = self.getStyle(elt, 'position');
			if(position != 'fixed'){
				if( (position != 'absolute') || (self.absScrollCheck) ){
					returnValue = elt.parentNode;
				}
				else returnValue = elt.offsetParent;
			}
		}
		return returnValue;	
	}
	
	self.getBorderDim = function(node) {
		if(typeof node == "string") node = document.getElementById(node);
		var returnValue = false;
		if(node) {
			var nodeStyle = self.getStyle(node);
			var borderDim = [
				self.getPixel(nodeStyle.borderLeftWidth),
				self.getPixel(nodeStyle.borderTopWidth),
				self.getPixel(nodeStyle.borderRightWidth),
				self.getPixel(nodeStyle.borderBottomWidth),
				
			];
			returnValue = borderDim;
		}
		return returnValue;
	}
	
	self.hasScrollBar = function(node) {
		if(typeof node == "string") node = document.getElementById(node);
		var returnValue = false;
		if(node && node.nodeType == 1){
			returnValue = [false, false];
			var nodeStyle = self.getStyle(node, 'overflow');
			if(nodeStyle == 'auto' || nodeStyle == 'scroll'){
				var b = self.getBorderDim(node);
				if(node.clientWidth <= node.offsetWidth - b[0] - b[2] - self.scroll_bar_pixel) returnValue[0] = true;
				if(node.clientHeight <= node.offsetHeight - b[1] - b[3] - self.scroll_bar_pixel) returnValue[1] = true;
			}
		}
		return returnValue;
	}
	
	self.getPixel = function(s){
	
		if(s == self.auto) return NaN;
	
		var x = parseFloat(s);
		if(isNaN(x)) {
			//alert("goldenrod.Dom.getPixel encountered a string that does not start with a number. " + s);
			return NaN;
		}
		
		var unit = s.slice(s.search(self.unit_search_pattern))
	
			switch(unit) {
				case "px" : 
				break;
		
				case "pt":
				x = x*self.toPixelRatio;
				break;
		
				case "in": 
				x = x*self.DPI_X
				break;
			}
		return x;
	}
	
	self.getPoint = function(s){
		if(s == self.auto) return NaN;
	
		var x = parseFloat(s);
		if(isNaN(x)) {
			//alert("goldenrod.Dom.getPoint encountered a string that does not start with a number." + s);
			return NaN;
		}
		var unit = s.slice(s.search(self.unit_search_pattern))
	
			switch(unit) {
				case "px" : 
				x = self.toPoint(x);
				break;
		
				case "pt": 
				break;
		
				case "in": 
				x = self.toPoint(x*self.DPI_X);
				break;
			}
		return x;
	}
	
	self.toPoint = function(x) {
		return Math.round( x*self.toPointRatio ) / 100
	}
	/*********************************************************************************************
	*Dom.setDimension - Always set the style property to a point value.

	x - A number which is the value to be set
	elt - An HTML element or the "id" string of an element
	dim - The string of the style property to be set
	unit - a flag that tells the function what units is the value x
			if this parameter is omited pixels are assumed.
	**********************************************************************************************/

	self.setDimension = function(x, elt, dim,  unit){
	
		var value;
		if(unit == null) unit = self.setDimension.pixel
		if(typeof elt == "string") elt = document.getElementById(elt);
		if(elt) {
			switch(unit) {
			case self.setDimension.pixel : 
			value = self.toPoint(x);
			break;
		
			case self.setDimension.point : 
			value = x;
			break;
		
			case self.setDimension.inch : 
			value = self.toPoint(x*self.DPI_X);
			break;
			}
	
	
	
			try {	//In case this is an illegal value
				elt.style[dim] = value + "pt"
			} 
			catch(e) {
				;
			}	
		}
		
	}
	
	self.setDimension.pixel = 0;
	self.setDimension.point = 1;
	self.setDimension.inch = 2;

	
	/*********************************************************************************************
	*Dom: - Shift Key down Constants Masks
	**********************************************************************************************/
	self.NoKey = 0;
	self.Shift = 1;		//Shift = 1st bit
	self.Control = 2;	//Control = 2nd bit
	self.Alt = 4;		//Alt = 3rd bit


	self.shiftkeyState;

	/****************************************************************************************
	*Dom.set_shiftkeyState() -  is passed an event Object.
	*
	*
	*****************************************************************************************/
	self.set_shiftkeyState = function(e) {
		self.shiftkeyState = 0;
		if(!e) return;
		if(e.shiftKey) self.shiftkeyState = (self.shiftkeyState | self.Shift);
		if(e.ctrlKey)  self.shiftkeyState = (self.shiftkeyState | self.Control);
		if(e.altKey)  self.shiftkeyState = (self.shiftkeyState | self.Alt);
	}

	
	/****************************************************************************************
	*Dom.getTarget() is passed an event Object.
	*
	*Internet Explorer has is own interface. To get the element on which the event occured use
	*the scrElement property of the event Object.
	*
	*Otherwise the W3C standard uses the target property.
	*****************************************************************************************/
	self.getTarget = function(e) {
		if(e.target) return e.target;  //This is the W3 way to get the target
		else if(e.srcElement) return e.srcElement; //This is the IE way to get the target
		else {goldenrod.myAlert("No way to determine the target node"); return undefined;}
	}
		
	self.getcurrentTarget = function(e) {
		if(e.currentTarget) return e.currentTarget;
	}

		
	/****************************************************************************************
	Dom.getStyle(node) is passed a node Object (also work with an element object)
	*
	*If nodeType does not equal 1 (Element Node) the function returns "undefined".
	*
	*In Internet Explorer - we can get the style using the "currentStyle" property of the "node" Object.
	*
	*In other browsers we use the "getComputedStyle" method of the "window" Object. 
	*
	*I realize that we do not
	*need am element node to have an "id" because and elementnode is also an element!
	*
	*
	*If both node.currentStyle and window.getComputedStyle are undefined we issue an alert and 
	*return "undefined"
	*****************************************************************************************/		
	self.getStyle = function(node, /*optional*/ parameter) {
		//dump_properties("node ", node);
		var style = undefined;
		var id, elt;
		if(node){
			if(node.nodeType == 1) {
				if( node.currentStyle) {
					style = node.currentStyle;
				}
				else if(window.getComputedStyle ) {
					style = window.getComputedStyle(node, null);
				}
				else {
					goldenrod.myAlert("goldenrod.Dom.getStyle: No way to get style information on the target node");
					return;
				}
			}
			else {
				goldenrod.myAlert("goldenrod.Dom.getStyle: This node is not an Element node.");
				return;
			}
			
			if(parameter) {return style[parameter]}
			else return style;
		}	
	}

	/*----------------------------------------------------------------------------------------
	Dom.getStyleSheetInfo(sheet, selectorText)
		If sheet is a string we search for the style sheet with that file name.
		Otherwise we assume that sheet is a stylesheet.
		The selectorText is a substring of the sought after selector that must occur at the
		end of the selector.
		If the search fails we return false.
		Otherwise we return the style object of that selector - if there are
		more than one matching selector in the stylesheet the style of the 
		last matching selector found in the stylesheet is returned.
	------------------------------------------------------------------------------------------*/
	self.getStyleSheetInfo = function(sheet /*selectorText1, selectorText2, ...*/){
		var returnValue = false;
		var i, j, ss, rules, rule, selText, style=[], sText;
		if( typeof sheet == 'string'){
			ss = document.styleSheets;
			for(i = 0; i < ss.length; i++){
				if(ss[i].href && ss[i].href.search(sheet) != -1 ) break;
			}
			if(i == ss.length) {
				alert("Dom.getStyleSheetInfo: No stylesheet found.");
				return returnValue;
			}
			else sheet = ss[i]; 
		}
		
		rules = sheet.cssRules ? sheet.cssRules : sheet.rules;	//This is for IE that uses rules
		for(i = 0; i < rules.length; i++) {
			rule = rules.item ? rules.item(i) : rules[i];	//This is also for IE that uses the item method.
			if ( !(selText = rule.selectorText) ) continue;
			for(j = 1; j<arguments.length; j++){
				sText = arguments[j].toUpperCase();
				if(j > style.length )style[j-1] = false;
				selText = selText.slice(-sText.length).toUpperCase();
				if(selText.slice(-sText.length) == sText) style[j-1] = rule.style;
			}
		}
		return style;
	}
	
	/****************************************************************************************
	Dom.getStyleOpacity(style) is passed a style Object.
	*
	*If no opacity is found we return "undefined"
	*
	*IE - Has nothing set of opacity unless a value has been explicitly written. Otherwise the filter property
	is defined but is a zero length string - "".
	*****************************************************************************************/		
	self.getStyleOpacity = function(style) {
		//dump_properties("node ", node);
		var opacity = undefined;
		var name = "";
		if(style.opacity !== undefined) {
			opacity = (style.opacity * 100); name = "opacity";
		}
		else if (style.MozOpacity !== undefined) {
			opacity = (style.MozOpacity * 100);
			name = "MozOpacity"
		}
		else if (style.KhtmlOpacity !== undefined) {
			opacity = (style.KhtmlOpacity * 100);
			name = "KhtmlOpacity"
		}
		else if (style.filter !== undefined) {
			if(style.filter == "" ) opacity = 100;
			else {
				opacity = myString.parseInt(style.filter);
				if(opacity == NaN) opacity = undefined;
			}
												
		}//parse filter string for a number
		return opacity;
	}


	/****************************************************************************************
	Dom.setStyleOpacity(style, opacity) is passed an interger between 1 and 100.
	*
	*If no opacity is found we return "undefined"
	*****************************************************************************************/		
	self.setStyleOpacity = function(elt, opacity) {
		
		var styleObject = elt.style;
		opacity = Math.round(opacity);
		styleObject.opacity = (opacity / 100);	//If the property doesnot exist it is created.
    	styleObject.MozOpacity = (opacity / 100); 
    	styleObject.KhtmlOpacity = (opacity / 100); 
    	styleObject.filter = "alpha(opacity=" + opacity + ")";
		
		/***********Maybe some code for IE******************
		styleObject.filter = "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + opacity + ")"; 
		************/
		return true;
	}

	/****************************************************************************************
	Dom.getStyleClipFull(style, box) 
	*
	*box  - A rectangle Object 
	*returns a rectangle that will reveal the whole element - in points
	*****************************************************************************************/		
	self.getStyleClipFull = function(style, box) {
	
		//Initialize Current Element Clip Box to what "auto" means (may have to be adjusted)
		box.Left = 0;
		box.Top = 0;
	
		//Note: In IE the border width must be set explicitly for the default value is a text string - "medium"
		box.Width = self.getPoint(style.width) + self.getPoint(style.borderLeftWidth) + 
					self.getPoint(style.borderRightWidth) + self.getPoint(style.paddingLeft) + 
					self.getPoint(style.paddingRight);; 
		box.Height = self.getPoint(style.height) + self.getPoint(style.borderTopWidth) + 
					 self.getPoint(style.borderBottomWidth) +
					 self.getPoint(style.paddingTop) + self.getPoint(style.paddingBottom);
	
				 
		box.Right = box.Width;
		box.Bottom = box.Height;
	
	}
	



	/****************************************************************************************
	Dom.getStyleClip(style, box) 
	*
	*box  - A rectangle Object with point values
	*****************************************************************************************/		
	self.getStyleClip = function(style, box) {
		var returnvalue = true, m, n, i;
		//Initialize Current Element Clip Box to what "auto" means (may have to be adjusted)
		self.getStyleClipFull(style, box);
	
		if(self.isIE) {
			if( (style.clipTop) && (style.clipTop != self.auto) ) box.Top = self.getPoint(style.clipTop);
			if( (style.clipRight) && (style.clipRight != self.auto) ) box.Right = self.getPoint(style.clipRight);
			if( (style.clipLeft) && (style.clipLeft != self.auto) ) box.Left = self.getPoint(style.clipLeft);
			if( (style.clipBottom) && (style.clipBottom != self.auto) ) box.Bottom = self.getPoint(style.clipBottom);
		}
		
		
		//Save Current Element Clip Box we assume clip box values are in pixels "px"
		else if( (style.clip != self.auto) && (style.clip != "rect(0pt, 0pt, 0pt, 0pt)") ) {
			self.pattern.lastIndex = 0; i=0;
			//alert("We are about to parse this string: " + style.clip);
			while( ((m = self.pattern.exec(style.clip)) != null) ) {
				//alert("m[0] = " + m[0]);
				n = self.getPoint(m[0]);
				if( !isNaN(n) ) {
			
					switch (i) {
						case 0: {
							box.Top = n;
							break;
						}
					
						case 1: {
							box.Right = n;
							break;
						}

						case 2: {
							box.Bottom = n;
							break;
						}
					
						case 3: {
							box.Left = n;
							break;
						}
						
					}
					i++;				
				}
				else {alert("goldenrod.Dom.getStyleClip - parameter is Nan")}
	
			}
		}	
		
		box.adjustWH();	
		//dump_properties("clip box = ", box)	
		return returnvalue;
	}

	/****************************************************************************************
	Dom.setStyleClip(elt, box) 
	*
	*box  - A rectangle Object 
	*****************************************************************************************/		
	self.setStyleClip = function(elt, box) {
		var returnvalue = true, j, i, value;
		var inlinestyle, styles_list, clipString, top, right, bottom, left;
		if( (top = box.Top) != self.auto  ) top = top + "pt ";
		if( (right = box.Right) != self.auto  ) right = right + "pt ";
		if( (bottom = box.Bottom) != self.auto  ) bottom = bottom + "pt ";
		if( (left = box.Left) != self.auto  ) left = left + "pt";
		clipString = "rect(" + top + ", " + right + ", " + bottom + ", " + left + ")";
		//alert("goldenrod.Dom.setStyleClip: clipString = " + clipString);
		//alert("goldenrod.Dom.isIS = " + self.isIE)
		if(self.isIE){	//This does not work - must set the style attribute
			if(self.IEengine<8)
				clipString = "rect(" + top + " " + right + " " + bottom + " " + left + ")";
			for(clip in elt.style) elt.style.clip = clipString;
		}
		
		else {
			for(clip in elt.style) elt.style.clip = clipString;
		}
		
		return returnvalue;
	}
	
	/****************************************************************************************
	Dom.getColor - colorvalue is the browers encoding of a color value - can be "#FFFFFF" or "#FFF" or rgb(255, 255, 255)
					This function will convert this value or an interger.
	*****************************************************************************************/	
	self.getColor = function(colorvalue) {
	
	}
	
	/****************************************************************************************
	Dom.setColor - n is an interger and this will be convert to the string "#FFFFFF"
	*****************************************************************************************/	
	self.setColor = function(n) {
		
	}


	/****************************************************************************************
	Dom.getViewportHeight - Height of browser viewport 
	*****************************************************************************************/	
	self.getViewportHeight = function() {
			
    	var height = window.innerHeight; // Safari, Opera
        var mode = window.document['compatMode'];
        
        if ( (mode || self.isIE) && !self.isOpera ) { // IE, Gecko
        	height = (mode == 'CSS1Compat') ?
            	document.documentElement.clientHeight : // Standards
                document.body.clientHeight; // Quirks
     	}
		return height;
	}
		
	/****************************************************************************************
	Dom.getViewportWidth - Width of browser viewport 
	*****************************************************************************************/	
	self.getViewportWidth = function() {
    	var width = window.innerWidth;  // Safari
        var mode = window.document['compatMode'];
            
        if (mode || self.isIE) { // IE, Gecko, Opera
        	width = (mode == 'CSS1Compat') ?
            	document.documentElement.clientWidth : // Standards
                document.body.clientWidth; // Quirks
      	}
        return width;
	}
	
	/****************************************************************************************
	Dom.getVerticalScroll - Document coordinate in upper part of viewport 
							We try all three methods and take the one that yields a non zero value.
	*****************************************************************************************/	
	self.getVerticalScroll = function() {
	
		var a=0, b=0, c=0;
		
		if(document.documentElement && 
				( document.documentElement.clientHeight !== undefined) ) {
					
			a = document.documentElement.scrollTop;		
		}
		if(document.body.clientHeight !== undefined) {
			b = document.body.scrollTop;
		}
		if(window.innerHeight !== undefined) {
			c = window.pageYOffset;
		}
		
		if(a < b) a=b;
    	if(a < c) a=c;
		return a;
	}
		
	/****************************************************************************************
	Dom.getHorizontalScroll - Document coordinate in left part of viewport
							  We try all three methods and take the one that yields a non zero value.
	*****************************************************************************************/	
	self.getHorizontalScroll = function() {
		
		var a=0, b=0, c=0;
		
		if(document.documentElement && 
				( document.documentElement.clientWidth !== undefined) ) {
					
			a = document.documentElement.scrollLeft;		
		}
		if(document.body.clientWidth !== undefined) {
			b = document.body.scrollLeft;
		}
		if(window.innerWidth !== undefined) {
			c = window.pageXOffset
		}
		if(a < b) a=b;
    	if(a < c) a=c;
		return a;
    	
	}
	
	/*---------------------------------------------------------------------------------------
	Dom.getDocumentCoord_noScroll - Given an element we calculate the location of its visible upper left 
						   corner relative to the upper left corner of the base elt.
						   The base element must be an offsetParent of elt.
						   It does not take into account scrolling.
						   The base elt is optional. If missing we use the offsetParent
						   base which was irectly calculated by feature test.  It is either the body element
						   or the html element and depends on the browser version.
	----------------------------------------------------------------------------------------*/	
	self.getDocumentCoord_noScroll = function(elt, eltBase){
	
		if(self.isAnOffsetParent(elt, eltBase)){
			
			if(!eltBase){
				eltBase = self.offsetParentBase;
			}
			else if(typeof eltBase == 'string')eltBase = document.getElementById(eltBase);
			
			var xy= [];
			xy[0] = elt.offsetLeft;
			xy[1] = elt.offsetTop
			var offsetParent = elt;
			while( (offsetParent = offsetParent.offsetParent) ){
				if(self.bcheck){
					self.calcBorder(offsetParent, xy)
				}	
				if(  (offsetParent != eltBase) || 
					( ( (eltBase == document.body) || (eltBase == self.root) ) && self.bodycheck ) ){
					xy[0] += offsetParent.offsetLeft;
					xy[1] += offsetParent.offsetTop;
				}
				else break;
			}
			
			if( (elt.offsetParent == document.body) ){
				xy[0] += self.root.clientLeft;
				xy[1] += self.root.clientTop;
			}
		}
		else{
			xy = null;
		}
		return xy;
	}
	
	
	/*---------------------------------------------------------------------------------------
	Dom.getDocumentCoord - Given an element we calculate the location of its visible upper left 
						   corner relative to the upper left corner of the base elt.
						   The base element must be an offsetParent of elt.
						   It does not take into account the scrolling of the page as a whole.
						   The base elt is optional. If missing we use the offsetParent
						   base which is directly calculated by feature test.  It is either the body element
						   or the html element and depends on the browser version.
	----------------------------------------------------------------------------------------*/	
	self.getDocumentCoord = function(elt, eltBase){
		
		var xy=[];	
		if(xy = self.getDocumentCoord_noScroll(elt, eltBase)){
			
			if(!eltBase){
				eltBase = self.offsetParentBase;
			}
			else if(typeof eltBase == 'string')eltBase = document.getElementById(eltBase);
			
			
			/*-----------------------------------------------------------------------------------------
				Note: When Dom.absScrollCheck is true, absolutely positioned elements scroll with
				the parentNode. When Dom.absScrollCheck is false, absolutely positioned elements scroll with
				the offsetParent. 
			-------------------------------------------------------------------------------------------*/
			var scrollParent = elt;
			
			while(scrollParent = self.getscrollParent(scrollParent)){
				if( (scrollParent != eltBase) && (scrollParent != document.body) && (scrollParent != self.root) ){
					if(scrollParent.scrollLeft) xy[0] -= scrollParent.scrollLeft;
					if(scrollParent.scrollTop)  xy[1] -= scrollParent.scrollTop;	
				}
				else {
					break;
				}
			}
		}
		else{
			xy = null;
		}
		return xy;
	}
	
	
	/*---------------------------------------------------------------------------------------
	Dom.getWindowCoord - Given an element we calculate the location of its visible upper left 
						   relative to the upper left corner of the viewport(browser window).
	----------------------------------------------------------------------------------------*/	
	self.getWindowCoord = function(elt){
		var xy = self.getDocumentCoord(elt);
		if(xy && (self.getStyle(elt, 'position') != 'fixed') ){
			xy[0] -= self.getHorizontalScroll()
			xy[1] -= self.getVerticalScroll();
		}
		return xy;
	}
	
	/*---------------------------------------------------------------------------------------
	Dom.scrollIntoView - Given an element we scroll it into view. If the element left(top) edge is
							off to the left(top) it is brought in to the left(top) edge of the parent.
							otherwise if the elements right(bottom)	edge is off to the right(bottom)
							it is brought into the right(bottom)of the parent.
							
							We pass all the way up the document tree and finally scroll the whole
							docment in the viewport window if necessary.
	----------------------------------------------------------------------------------------*/	
	self.scrollIntoView = function(elt){
		if(elt && ( elt.nodeType == 1) && (elt != document.body) && (elt != self.root) ){
			var eltLocation, eltArea, baseLocation, baseWidth, baseHeight, baseArea, hasScrollBar;
			eltLocation = self.getDocumentCoord(elt);
			eltArea = new self.Rectangle(eltLocation[0], eltLocation[1], 
										elt.offsetWidth, elt.offsetHeight);
	
			var scrollParent = elt, scrollBase;
			while(scrollParent = self.getscrollParent(scrollParent)){
				if(scrollParent != document.body && scrollParent != self.root)
					hasScrollBar = self.hasScrollBar(scrollParent);
				else hasScrollBar = [true, true];
				if(hasScrollBar[0] || hasScrollBar[1]){
					if( (scrollParent == document.body) || (scrollParent == self.root) ){
						eltArea.Top -= self.getVerticalScroll(); 
						eltArea.Left -= self.getHorizontalScroll()
						scrollBase = self.scrollBase;
						baseWidth = self.getViewportWidth();
						baseHeight = self.getViewportHeight();
						
					}
					else {
						scrollBase = scrollParent;
						baseWidth = scrollParent.clientWidth;
						baseHeight = scrollParent.clientHeight;
					}
					baseLocation = self.getDocumentCoord(scrollParent);
					baseLocation[0] += scrollParent.clientLeft;
					baseLocation[1] += scrollParent.clientTop;
					
					baseArea = new self.Rectangle(	baseLocation[0], 
													baseLocation[1], 
													baseWidth, 
													baseHeight)
					
					
					var scrollAdj_UR = [eltArea.Left - baseArea.Left, eltArea.Top - baseArea.Top];
					var scrollAdj_LL = [eltArea.Right - baseArea.Right, eltArea.Bottom - baseArea.Bottom]
					
					if(hasScrollBar[1]){
						if(scrollAdj_UR[0]<0) {
							scrollBase.scrollLeft += scrollAdj_UR[0];
							eltArea.Left -= scrollAdj_UR[0];
						}
						else if(scrollAdj_LL[0]>0) {
							scrollBase.scrollLeft += scrollAdj_LL[0];
							eltArea.Left -= scrollAdj_LL[0];
						}
					}
					if(hasScrollBar[0]){
						if(scrollAdj_UR[1]<0) {
							scrollBase.scrollTop += scrollAdj_UR[1];
							eltArea.Top -= scrollAdj_UR[1];
						}
						else if(scrollAdj_LL[1]>0) {
							scrollBase.scrollTop += scrollAdj_LL[1];
							eltArea.Top -= scrollAdj_LL[1];
						}
					}
				}
			}
		}
	}

	
	/*---------------------------------------------------------------------------------------
	Dom.eltBox - We calculate the box of an element in window Coordinates - all scrolling accounted
	----------------------------------------------------------------------------------------*/	
	self.eltBox = function(elt) {
		
		var returnValue = undefined;
		var point = [];
		
		if((elt.offsetHeight !== undefined) && (elt.offsetWidth !== undefined) ) {
			point = self.getWindowCoord(elt);
			returnValue = new self.Rectangle(point[0], point[1], elt.offsetWidth, elt.offsetHeight);
		}
		return returnValue;
		
	}
	
	
	
	/****************************************************************************************
	Dom.isIn - We calculate if a point relative to the viewPort is in the visible boundaries of 
					and element
	*****************************************************************************************/	
	self.isIn = function(xy, elt) {
		
		var box, returnValue = undefined;
		if(box = self.eltBox(elt)) {
				returnValue = box.isIn(xy)
		}
		return returnValue;
	}
	
	
	/*********************************************************************************************
	*Constants
	*
	*The DOM constants are set so that:
	*	If goldenrod.Dom.browser is 0 - we are in the old model
	*	If goldenrod.Dom.browser is 1 - we are in IE
	*	If goldenrod.Dom/browser is greater than 1 - we have addlistener capability.
	**********************************************************************************************/
	self.OLD = 0;	
	self.IE = 1;
	self.IEengine = null;
	self.isIE = false;
	self.DOM = 2;
	self.MOZ = 3;
	self.Opera = 4;
	self.Google = 5;
	self.Safari = 6;
	self.Win64 = false;
	self.isOpera = false;
	self.browser;
	self.leftButton = 0;
	self.auto = "auto";
	//self.pattern = /auto|[0-9]+|-[0-9]+/g;

	self.pattern = /auto|-?[0-9]+\.?[0-9]*(px|in|pt)/g; //auto or zero or one minus sign followed by one or more 
													//digits followed by an optional decimal point followed
													//by zero or more digits followed by px or in or pt

	/*********************************************************************************************
	*Dom.set_handler() - This function uses the appropriate method for registering an event handler
	**********************************************************************************************/
	self.set_handler = function( eventname, elt, handler, capture){

		var capturestate;

		if( capture == null ) capturestate = true; else capturestate = false;

		switch (self.browser) {
	
			case self.IE: {  elt.attachEvent("on" + eventname, handler);
				if (capturestate) {
					if(elt == document) {
						elt.body.setCapture();
					}
					else {
						elt.setCapture(); 
						goldenrod.myAlert("goldenrod.Dom.set_hanlder: setCapture() on " + elt.tagName + ".");
					}	
				}
				break;
			}
			
			case self.OLD: {
				break;
			}
			
			default : {
				elt.addEventListener(eventname, handler, capturestate);
				break;
			}
		}
	}

	/*********************************************************************************************
	*Dom.propagationHandler() - This function uses the appropriate method for both stopping event
	* propagation and preventing the default action.
	
	If defaultFlag is missing or false we will prevent the default action.
	If defualtFlag is true we allow the default action.
	**********************************************************************************************/
	self.propagationHandler = function(e, defaultFlag) {
		if(e){
			switch (self.browser) {
		
				case self.IE: {
					e.cancelbubble = true;
					if(!defaultFlag) e.returnValue = false;
					break;
				}
				
				case self.OLD: {
					break;
				}
				
				default : {
					e.stopPropagation();
					if(!defaultFlag) e.preventDefault();
					break;
				}
			}
		}
	}
	
	/*********************************************************************************************
	*Dom.currentTarget(e) - This function returns the currrent target however it does not adapt to IE
		correctly - and so should not be used.
	**********************************************************************************************/
	self.currentTarget = function(e) {
		if(!e) return;
		var r;
		switch (self.browser) {
	
			case self.IE: {
				r = e.srcElement;
				break;
			}
			
			case self.OLD: {
				r = undefined;
			}
			
			default : {
				r = e.currentTarget;
				break;
			}
		}
		return r;
	}

	/*********************************************************************************************
	*Dom.clickHandler() - This is a generic click handler which will do nothing if a shift key is depressed
	**********************************************************************************************/
	self.clickHandler = function(e) {
	
		if(self.isIE) e = window.event;
		self.set_shiftkeyState(e);
		if(self.shiftkeyState) {
			return false;
		}
		window.location = this.href;
	}

	var _hasClass = function(elt, classname) {
		
		if(typeof elt == "string") elt = document.getElementById(elt);
		var pattern = new RegExp("\\b" + classname + "\\b");	//The slash b matches a word boundary
		if(elt.className) {
			return (elt.className.search(pattern) != -1 );	
		}
		else return false;
		
	};
	
	self.CSSClass = {
		
		/****
		hasClass : function(elt, classname) {
	
				if(typeof elt == "string") elt = document.getElementById(elt);
				var pattern = new RegExp("\\b" + classname + "\\b")
				return (elt.className.search(pattern) != -1 );
			},
		****/
		hasClass : _hasClass,
		
		/*classname can be a list of class name (words) separated by spaces*/
		addClass : function(elt, classname) {
	
				if(typeof elt == "string") elt = document.getElementById(elt);
				if(classname){
					var separator = /\b/;
					var i, singleClass, a = classname.split(separator);
					for(i=0; i<a.length; i++){
						if( !_hasClass(elt, a[i]) ){
							singleClass = ' ' + a[i];
							elt.className += singleClass;
						}
					}
				}
			},
	
		/*classname can be a list of class name (words) separated by spaces*/
		removeClass : function(elt, classname) {
	
				if(typeof elt == "string") elt = document.getElementById(elt);
				if(classname && elt.className){
					var separator = /\b/;
					
					var i, j, singleClass, a = classname.split(separator), b = elt.className.split(separator);
					for(i=0; i<a.length; i++){
						for(j=0; j<b.length; j++){
							if(a[i] == b[j]){
								b.splice(j,1);	/*remove b[j] from the b array.*/
								j--;
							}
						}
					}
					separator = " ";
					elt.className = b.join(separator);
				}
			}
	
	};

	/*********Dom.Location - is an object that contains location manipulators functions*/
	self.Location = {
	
		replaceHash : function(hash) {
			if(hash){
				var theUrl = window.location.href;
				var newUrl = theUrl.split('#', 2);
				window.location.replace(newUrl[0] + hash);
			}
		}
	};
	
	
	/*********Dom.Location - is an object that contains location manipulators functions*/
	self.clientTools = {
	
		insertAfter : function(childElt, newChildElt){
			var parent = childElt.parentNode;
			var children = parent.childNodes;
			var j = Number.MAX_VALUE;
			for(var i = 0; i<children.length; i++){
				if(children[i] == childElt) j = i;
				if(i > j && children[i].nodeType == 1)break;
			} 
			var theChild = children[i]; /*This might be undefined or null?*/
			if(!theChild)theChild = null; /*If so - make sure it is in fact null*/
			parent.insertBefore(newChildElt, theChild);
		},
		
		mouseOver : function(e){
			e = e || event;
			self.propagationHandler(e);
			var elt = this.parentNode.removeChild(this);
			elt.style.display = 'none';
			
		},
		
		makeHoverBox : function(elt, position, text, className) {
			var returnValue = false;
			if(elt.nodeType == 1 && elt.id && !document.getElementById(elt.id + '_hoverBox')){
				var div = document.createElement('div');
				div.innerHTML = text;
				div.className = className;
				div.id = elt.id + '_hoverBox';
				div.style.position = 'absolute';
				div.style.visibility = 'hidden';
				//div.onmouseover = self.clientTools.mouseOver;

				self.clientTools.insertAfter(elt, div);	/*Insert div immediately after elt*/
				var elt_xy = self.getDocumentCoord(elt, div.offsetParent);
				div.style.left = elt_xy[0] + Math.round((elt.offsetWidth * position[0])/100) + 'px';
				div.style.top = elt_xy[1] + Math.round((elt.offsetHeight * position[1])/100) + 'px';
				div.style.visibility = 'visible';
				returnValue = div;
			}
			return returnValue;
		},
		
		removeHoverBox : function(elt){
			var returnValue = false;
			if(elt.nodeType == 1 && elt.id){
				var hoverBox = document.getElementById(elt.id + '_hoverBox');
				if(hoverBox){
					hoverBox.style.display = 'none';
					var parent = hoverBox.parentNode;
					returnValue = parent.removeChild(hoverBox)
				}
			}
			return returnValue;
		}
	};
	
	
	
	/*********Dom.Cookie - is an object that contain cookie handler functions*/
	self.Cookie = {
	
		getValue : function(name) {
			var returnValue = "", start, end, allcookies = document.cookie;
			
			var pos = allcookies.indexOf(name);
			if (name && pos != -1) {
				start = pos + name.length;
				end = allcookies.indexOf(";", start);
				if(end == -1) end = allcookies.length;
				returnValue = allcookies.substring(start, end);
			}
			return returnValue
		}
		
	};
	
	/*********Dom.NewWindow - is an object that will facilitate open new browser windows*/
	self.NewWindow = {
	
		Create : function(location, name, features, isSame) {
			return window.open(location, name, features, isSame);
		}
		
	};
	
	/*--------------------------------------------------------------------------------------------
	Dom.browserCheck() - This function initializes the "browser" flag. and the "leftButton" value.
						It is implemented as the code body of this constructor function: Note the
						invocation operator "()" immediately after this annonymous function 
						definition.
	---------------------------------------------------------------------------------------------*/
	self.Init = function() {
		
			
		//alert("Inside goldenrod.Dom.browserCheck")
		self.browser = self.OLD;
		
		if (document.addEventListener) {
			self.browser = self.DOM;
			self.leftButton = 0;
		}
		else if(document.attachEvent) {
			self.browser = self.IE;
			self.isIE = true;
			self.leftButton = 1;
		}
		
		if( navigator && (navigator['appName'] == "Microsoft Internet Explorer") && 
			(navigator['platform'] == "Win64") ) {
			self.Win64 = true;
		}
		
		if (window.navigator.appName == "Microsoft Internet Explorer") {
   		// This is an IE browser. What mode is the engine in?
   			if (document.documentMode) // IE8
      			self.IEengine = document.documentMode;
   			else { // IE 5-7
      			self.IEengine = 5; // Assume quirks mode unless proven otherwise
      			if (document.compatMode) {
         			if (document.compatMode == "CSS1Compat")
            			self.IEengine = 7; // standards mode
      			}
   			}
		// the engine variable now contains the document compatibility mode.
		}
		
		
		if(navigator && (navigator['appName'] == "Opera")) {
			self.browser = self.Opera;
			self.isOpera = true;
		}
		else if(navigator && (navigator['appCodeName'] == "Mozilla") && (!self.isIE) ){
			self.browser = self.MOZ;
		}
		
	return arguments.callee;	
		
	}();
	
};


