/*******************************************************************************
 * This notice must be untouched at all times.
 * 
 * This javascript library is a cross browser DHTML library.
 * 
 * domHelpers.js v. 0.7 The latest version is available at
 * http://www.dulac.ca/webmastery/
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version. This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at
 * http://www.gnu.org/copyleft/gpl.html for more details.
 * 
 * changes: 0.7 - fixed domParseXML() IE bug and 
 *  
 ******************************************************************************/
function domGetElement4Ie4(s) {
	return document.all[s];
}

function domGetElementsByTag4Ie4(s) {
	return document.tags[s];
}

function domGetElement4Ns4(s) {
	return domGetElement4NsHelper(s, self.document.layers);
}

function cleanValue(s) {
	if (document.layers) {
		return parseInt(s);
	} else {
		return s;
	}
}

function domGetElement4NsHelper(s, layerArr) {
	var i;
	
	for (i = 0; i < layerArr.length; i++) {
		// check to see if Netscape assigned block
		if (document.layers[i].id.substring (0, 3) != "_js")
		{
			if (layerArr[i].id == s) {
				layerArr[i].style = layerArr[i];
				return layerArr[i];
			}
			
			// check internal layers within this layer
			if (layerArr[i].document.layers.length > 1) {
				var returnValue = indexNSObjs (layerArr[i].document.layers);
				if (returnValue != null) {
					return returnValue;
				}
				
			}
		}
	}
	return null;
}

/* I *think* this is right */
function getElementsByTag4Ns4(s) {
	return document.tags[s];
}

if (!document.getElementById && document.all) {
	document.getElementById = domGetElement4Ie4;
}
if (!document.getElementsByTagName && document.tags) {
	document.getElementsByTagName = domGetElementsByTag4Ie4;
}

if (!document.getElementById && document.layers) {
	document.getElementById = domGetElement4Ns4;
}




function domSetWidthAndHeight (obj, w, h) 
{
	
	// IE style
	if (obj.style.pixelWidth && obj.style.pixelHeight)
	{
		obj.style.pixelWidth += (2 * h_incr);
		obj.style.pixelHeight += (2 * w_incr);
	}
	// W3C style
	else if (obj.offsetWidth && obj.offsetHeight) 
	{
		obj.offsetWidth -= w_incr / 2;
		obj.offsetHeight += h_incr / 2;
	}
	// NS4 style
	else if (obj.style.width && obj.style.height) 
	{
		obj.width -= w_incr / 2;
		obj.height += h_incr / 2;
	}
}

// 
function
domSetVisibility (obj, value)
{
	// IE, NS4 and W3C
	if (obj.style.visibility != null) {
		
		// NS4 needs this
		if (document.layers && value == "visible") {
			value = "inherit";
		} 
		
		obj.style.visibility = value;
	}
}

function
domGetVisibility (obj)
{
	// IE, NS4, W3C
	if (obj.style.visibility != null) {
		
		// I've seen "hide" once a while ago in NS4 a long time ago.
		if (obj.style.visibility == "hidden" || obj.style.visibility == "" ||
				obj.style.visibility == "hide") {
			return "hidden";
		} else {
			return "visible";
		}
		
	} else {
		return error;
	}
}

function
domGetLeft (obj)
{
	// W3C
	if (obj.offsetLeft != null)
		return obj.offsetLeft; 
	// IE
	else if (obj.style.pixelLeft != null) {
		return obj.style.pixelLeft;
	} // NS4
	else if (obj.style.left != null)
		return parseInt (obj.style.left);
	else
		return error;
}

function
domGetTop (obj)
{
	// W3C
	if (obj.offsetTop != null) 
		return obj.offsetTop;
	// IE
	else if (obj.style.pixelTop != null)
		return obj.style.pixelTop;
	// NS4
	else if (obj.style.top != null)
		return parseInt (obj.top);
	else 
		return error;
}

// element's absolute left position: works on relatively positioned objects!
function domGetAbsoluteLeft (obj)
{
	// IE
	if (obj.offsetLeft != null) 
		return obj.offsetLeft;
	// NS4
	else if (obj.style.pageX != null) 
		return obj.style.pageX;
	// W3C
	else if (document.defaultView != null && 
			document.defaultView.getComputedStyle != null) {
		return parseInt(document.defaultView.
				getComputedStyle(obj, "").
				getPropertyValue("left"));
	} else { 	// old Opera doesn't have this object
		return error;
	}
}

// element's absolute top position: works on relatively positioned objects!
function domGetAbsoluteTop (obj)
{
	if (obj.offsetTop != null) 
		return obj.offsetTop;
	else if (obj.pageY != null) 
		return obj.style.pageY;
	else if (document.defaultView != null && 
			document.defaultView.getComputedStyle != null) {
		return parseInt(document.defaultView.
				getComputedStyle(obj, "").
				getPropertyValue("top"));
	} else {
		return -1;
	}
}

function domSetTop (obj, top)
{
	
	// IE
	if (obj.style.pixelTop != null) {
		obj.style.pixelTop = top;
		
		// NS4, W3C
	} else if (obj.style.top!=null) {
		
		/*
		 * This handles a difference between the Mozilla implementation of the
		 * DOM as well as the Opera version (Mozilla demands a px at the end of
		 * the DOM, Opera doesn't).
		 */
		
		/* If .style.top is JUST a number, then just set it to top */
		if (parseInt(obj.style.top).toString() == obj.style.top.toString()) {
			obj.style.top=top;
			
			/* Otherwise, set .style.top to be top + "px" */
		} else {
			obj.style.top=top + "px";
		}
	}
}

// set element's left position
function domSetLeft (obj, left)
{
	// IE
	if  (obj.style.pixelLeft != null) {
		obj.style.pixelLeft = left;
		// NS4, W3C
	} else if (obj.style.left != null) {
		/* See notes for domSetTop() */
		/* If .style.left is JUST a number, then just set it to top */
		if (parseInt(obj.style.left).toString() == obj.style.left.toString()) {
			obj.style.left=left;
		} else {
			obj.style.left=left+ "px";
		}
	}
}

// set Left and Top at the same time
function domMoveTo (obj, newleft, newtop) 
{
	domSetLeft(obj, newleft);
	domSetTop (obj, newtop);
}

// move relative to current location
function domMoveBy (obj, left, top)
{
	domSetLeft (obj, left + parseInt (domGetLeft (obj)));
	domSetTop (obj, top + parseInt (domGetTop (obj)));
}

// get element's width
function domGetWidth (obj)
{
	// IE
	if (obj.offsetWidth != null)
		// was obj.style.pixelWidth, but changed because it was inaccurate
		return obj.offsetWidth;	
	// NS4
	else if (obj.style.clip != null && obj.style.clip.width != null)
		return obj.clip.width;
	else if (obj.style.width != null ) 
		return parseInt (obj.style.width);
}

// get element's height
function domGetHeight (obj)
{
	// IE
	if (obj.offsetHeight != null)
		return obj.offsetHeight;	// was obj.style.pixelHeight
	// NS4
	else if (obj.style.clip != null  && obj.style.clip.height != null)
		return obj.style.clip.height;
	// W3C
	else if (obj.style != null && obj.style.width != null)
		return parseInt (obj.style.height);
	
}

// set element's width
function domSetWidth (obj, width)
{
	// IE
	if (obj.style.pixelWidth != null) 
		obj.style.pixelWidth = width;
	// W3C
	else if (obj.style.width != null) 
		obj.style.width = width;	
	// NS4
	else if (obj.clip != null && obj.clip.width != null)
		obj.style.clip.width = width;
	
}

// set element's height
function domSetHeight (obj, height)
{
	
	// IE
	if (obj.style.pixelHeight != null)
		obj.style.pixelHeight = height;
	// W3C
	else if (obj.style.height != null) 
		obj.style.height = height;
	else if (obj.style.clip != null && obj.style.clip.height != null) 
		obj.style.clip.height = height;
}

// clip object
function
domSetClipRect (obj, top, right, bottom, left)
{
	if (top == null)
		top = domGetClipTop (obj);
	if (left == null)
		left = domGetClipLeft (obj);
	if (bottom == null)
		bottom = domGetClipBottom (obj);
	if (right == null)
		right = domGetClipRight (obj);
	
	// NS4
	if (obj.style.clip.left != null )
	{
		obj.clip.left = left;
		obj.clip.right = right;
		obj.clip.top = top;
		obj.clip.bottom = bottom;
	}
	// IE, W3C
	else if (obj.style.clip != null)
	{
		var strng = "rect(" + top + "px," + right +
		"px," + bottom + "px," + left + "px)";
		obj.style.clip = strng;
	}
}

function convert(s) {
	return parseInt(s);
}

// needed by IE, W3C DOMS for the domGetClip*() functions
function
domGetClipEntry (obj, indx)
{
	var strng = obj.style.clip;
	//(document.all)?obj.css1.style.clip:document.getElementById(obj.name).style.clip;
	strng = strng.slice (5, strng.length - 1);
	var rectNull =  (strng == "" );
	var entries = strng.split (" ");
	if (indx == "top")
		if (entries[0] == "auto" || rectNull)
			return domGetTop (obj);
		else
			return convert (entries[0]);
	else if (indx == "left")
		if (entries[3] == "auto" || rectNull)
			return domGetLeft (obj);
		else
			return convert (entries[3]);
	else if (indx == "bottom")
		if (entries[2] == "auto")
			return domGetHeight (obj);
		else if (rectNull)
			return domGetTop(obj) + domGetHeight(obj);
		else
			return convert (entries[2]);
	else if (indx == "right")
		if (entries[1] == "auto" )
			return domGetWidth ();
		else if (rectNull) 
			return domGetWidth(obj) + domGetLeft(obj);
		else
			return convert (entries[1]);
	
}



// get current clip
function domGetClip (obj, side)
{
	switch (side) {
	case "top":
	case "right": 
	case "bottom":
	case "left":
		// NS4
		if (obj.style.clip != null) {
			
			if (obj.style.clip[side] != null) 
				return obj.style.clip[side];
			// IE, W3C
			else 
				return domGetClipEntry (obj, side);
		}
		break;
	}
	return error;
}

// get current clip bottom
function domGetClipWidth (obj)
{
	if (obj.style.clip != null && obj.style.clip.width != null) 
		return obj.style.clip.width;
	else
		return domGetClip(obj, "right") - domGetClip(obj, "left");
}

// get current clip bottom
function domGetClipHeight (obj)
{
	if (obj.style.clip != null && obj.style.clip.height != null) 
		return obj.style.clip.height;
	else 
		return domGetClip(obj, "bottom") - domGetClip(obj, "top");
}


function
domSetInnerHTML(obj, html_string)
{
	// IE ... and other browsers that support innerHTML
	if (obj.innerHTML != null)
	{
		obj.innerHTML = html_string;
	}
	// W3C method ... this *should* work
	else if (document.createRange) 
	{
		var rng = document.createRange();
		
		if (rng.setStartBefore && rng.createContextualFragment && 
				obj.removeChild && obj.appendChild) {
			rng.setStartBefore(obj);
			htmlFrag = rng.createContextualFragment(content);
			while (obj.hasChildNodes())
				obj.removeChild(obj.lastChild);
			obj.appendChild(htmlFrag);
		}
	}
	else if (obj.document != null && obj.document.open != null)
	{
		
		/*
		 * this NS 4.x way is *almost* as trivial ... note you cannot do this with
		 * relatively positioned <div>'s or <layers>'s - it will puke.
		 */
		obj.document.open ();
		obj.document.write (html_string);
		obj.document.close ();
	}
}

function domGetInnerHTML(obj) {
	if (obj.innerHTML) {
		return obj.innerHTML;
	}
}

// change source
function
domSetIframeSrc(obj, sourcefile, width)
{
	// IE, W3C
	if (obj.src != null)
	{
		obj.src = sourcefile;
	}
	else if (obj.load != null && obj.style.clip != null 
			&& obj.style.clip.bottom != null) 
	{
		var clipbottom;
		domHide (obj);
		clipbottom = domGetClip (obj, "bottom");
		obj.style.load (sourcefile, width);
		obj.style.clip.bottom = clipbottom;
		this.objShow ();
	}
}


function domSetBackgroundColor (c)
{
	if (obj.style.backgroundColor != null)
		obj.style.backgroundColor = c;
	else if (obj.style.bgColor != null)
		obj.style.bgColor = c;
}

function domGetOpacity(obj) {
	// Mozilla
	if (obj.style.MozOpacity != null) {
		return parseFloat(obj.style.MozOpacity) * 100;
		// Possibly the W3C DOM
	} else if (obj.style.opacity != null) {
		return parseFloat(obj.style.opacity);
		// IE .. Can't do object sniffing .. have to do browser sniffing (ugh).
	} else if (is && is.ie && is.win) {
		var filter=obj.style.filter;
		
		var ptr=filter.indexOf("opacity=");
		
		if (ptr < 0) {
			return "";
		} else {
			ptr += filter.substring(ptr).indexOf('=');
			
			if (ptr <0) {
				return "";
			}
			ptr ++;
			return parseFloat(filter.substring(ptr));
		}
	}
}


function domSetOpacity(obj, percentage){ 
	// Mozilla
	if (obj.style.MozOpacity != null) {
		obj.style.MozOpacity=(percentage/100).toString();
		// Possibly the W3C DOM
	} else if (obj.style.opacity != null) {
		obj.style.opacity='100%';
		// IE .. Can't do object sniffing .. have to do browser sniffing (ugh).
	} else if (is && is.ie && is.win) {
		obj.style.filter = 'alpha(opacity=' +  percentage.toString() + ')';
	} 
}


// ideas for domGetWindowWidth() and domGetWindowHeight() are from
// http://www.quirksmode.org
function
domGetWindowWidth ()
{
	// all except IE
	if (window.innerWidth != null) 
		return window.innerWidth;
	// IE6 Strict mode
	else if (document.documentElement && 
			document.documentElement.clientWidth )
		return document.documentElement.clientWidth;
	// IE strictly less than 6
	else if (document.body != null)
		return document.body.clientWidth;
	else 
		return document.body.offsetWidth;
}

function
domGetWindowHeight ()
{
	// all except IE
	if (window.innerHeight != null)
		return window.innerHeight;
	// IE6 Strict mode
	else if (document.documentElement && 
			document.documentElement.clientHeight )
		return document.documentElement.clientHeight;
	// IE strictly less than 6
	else if (document.body != null)
		return document.body.clientHeight;
	else 
		return document.body.offsetHeight;
}

function domSetWindowWidth(n) {
	if (window.innerWidth != null)
		window.innerWidth = n;
	else 
		window.resizeTo(n, domGetWindowHeight());
}

function domSetWindowHeight(n) {
	if (window.innerHeight != null)
		window.innerHeight = n;
	else 
		window.resizeTo(domGetWindowWidth(), n);
}

function domGetMouseX (e)
{	
	if (!e) {
		return;
	}
	// NS4
	if (e.pageX != null) {
		return e.pageX;
		// IE
	} else if (window.event != null && window.event.clientX != null 
			&& document.body != null && 
			document.body.scrollLeft != null)
		return window.event.clientX + document.body.scrollLeft;
	// W3C
	else if (e.clientX != null) 
		return e.clientX;
	else 
		return error;
}

function domGetMouseY (e)
{
	// NS4
	if (e.pageY != null )
		return e.pageY;
	// IE
	else if (window.event != null  && window.event.clientY != null  && 
			document.body != null  &&
			document.body.scrollTop != null )
		return window.event.clientY + document.body.scrollTop; 
	// W3C
	else if (e.clientY != null) {
		return e.clientY;
	}
}

function domScrollX ()
{
	// NS4, mozilla
	if (window.pageXOffset != null) 
		return window.pageXOffset;
	// IE strict mode
	else if (document.documentElement != null 
			&& document.documentElement.scrollLeft !="0px" 
				&& document.documentElement.scrollLeft !=0) 
		return document.documentElement.scrollLeft;
	// IE, compatibility mode
	else if (document.body != null && document.body.scrollLeft != null) 
		return document.body.scrollLeft;
	// W3C
	else if (window.scrollX != null) 
		return window.scrollX;
	else
		return error;
}

function domScrollY()
{
	// NS4, mozilla
	if (window.pageYOffset != null)
		return window.pageYOffset;
	// IE strict
	else if (document.documentElement != null
			&& document.documentElement.scrollTop !="0px" 
				&& document.documentElement.scrollTop !=0) 
		return document.documentElement.scrollTop;
	else if (document.body && document.body.scrollTop != null) 
		return document.body.scrollTop;
	else if (window.scrollY != null) 
		return window.scrollY;
	else
		return error;
}

function domGetScrollX() {
	return domScrollX();
}

function domGetScrollY() {
	return domScrollY();
}


function domGetSelectedText ()
{
	// IE
	if (document.selection != null && document.selection.createRange != null)
	{
		var sel = document.selection.createRange ();
		sel.expand ("word");
		return sel.text;
	}
	// W3C
	else if (document.getSelection != null)
		return document.getSelection ();
}

/* a debugging function ... very useful. */
function domGetProperties (obj, objName, style, CRs, onlyNames, search)
{
	var result = ""
		var count=0;
	
	if (!obj) {
		return result;
	}
	
	for (var i in obj)
	{
		if (search && 
				i.toString().toLowerCase().indexOf(search.toLowerCase())  == -1 ){
			; // do nothing
		} else {
			result += objName + "." + i.toString() 
			if (!onlyNames) 
				result += " = " + obj[i];
			count++;
			if (CRs || count%3==0)
				result+= "\n";
			else 
				result+= ", ";
		}
	}
	return result
}


function domGetBody () {
	// IE
	if (document.body) 
		return document.body;
	else if (document.getElementByTagName) 
		return document.getElementsByTagName ("body").item (0);
}


function domMouseEvent(func) {
	
	if (oldNSdom){
		document.captureEvents(Event.MOUSEMOVE);
	}
	
	document.onmousemove = func;
	window.onmousemove = func;
	window.onmouseover=func;
	
}


/*
 * The code of the functions domGetStyleOfClass and domGetStyleClassProperty
 * were taken from javascript.faqts:
 * http://www.faqts.com/knowledge_base/view.phtml/aid/1939 - I assume they are
 * in the public domain.
 */

function domGetStyleOfClass (className) {
	
	// document.all and document.layers checked first.
	
	var re = new RegExp("\\." + className + "$", "gi");
	if (document.all) {
		for (var s = 0; s < document.styleSheets.length; s++)
			for (var r = 0; r < document.styleSheets[s].rules.length; r++)
				if (document.styleSheets[s].rules[r].selectorText.search(re) 
						!= -1) {
					return document.styleSheets[s].rules[r].style;
				}
	} else if (document.layers) {
		return document.classes[className].all;
	} else if (document.getElementById) {
		for (var s = 0; s < document.styleSheets.length; s++)
			for (var r = 0; r < document.styleSheets[s].cssRules.length; r++)
				if (document.styleSheets[s].cssRules[r].selectorText.search
						(re) != -1) {
					document.styleSheets[s].cssRules[r].sheetIndex = s;
					document.styleSheets[s].cssRules[r].ruleIndex = s;
					return document.styleSheets[s].cssRules[r].style;
				}
	}
	return null;
}


function domGetStyleClassProperty (className, propertyName) {
	var styleClass = getStyleClass(className);
	if (styleClass)
		return styleClass[propertyName];
	else 
		return null;
}

/*
 * domAddEvent, domRemoveEvent and domEventTarget from
 * http://www.scottandrew.com/index.php/articles/cbs-events . Added
 * functionality for Netscape 4 from info at
 * http://www.quirksmode.org/js/events_netscape4.html
 * 
 * Examples of usage: domAddEvent(window, "load", myFunction, false);
 * domAddEvent(docunent, "keydown", keyPressedFunc, false);
 * domAddEvent(document, "keyup", keyPressFunc, false);
 */
function domAddEvent(obj, evType, fn, useCapture){
	if (obj.addEventListener != null) {
		if (window.opera) {
			obj.addEventListener(evType, fn, !useCapture);
		} else {
			obj.addEventListener(evType, fn, useCapture);
		}
		return true;
	} else if (obj.attachEvent != null){
		var r = obj.attachEvent("on"+evType, fn);
		
		
		/*
		 * if (typeof(r) == "undefined") { alert(r); obj["on" + evtype] = fn; }
		 */
		
		return r;
	} else {
		
		//alert('Handler could not be attached');
		obj["on" + evType]= fn;
	}
	
	/*
	 * // Fix for NS4 var objName = obj.toString(); var myIndex =
	 * objName.indexOf("[object "); if (myIndex >= 0 ){ var eventObjName =
	 * objName.substring(8, objName.length-1); } else { // guess
	 * eventObjName='window'; }
	 * 
	 * if( document.captureEvents ) { var s = eventObjName.toLowerCase() +
	 * ".captureEvents( Event." + evType.toUpperCase() + ");"; eval(s); }
	 * 
	 * var fnName = fn.toString(); var fnIndex = fnName.indexOf("function"); if
	 * (fnIndex >= 0) { fnName = fnName.substring(fnIndex + 9).split('(')[0]; }
	 * 
	 * s=eventObjName.toLowerCase() + ".on" + evType;
	 * 
	 * if (window.onload != "undefined") { s += "=" + fnName; eval(s); } }
	 *  
	 */
	
}


// Netscape 4 you can't release a particular event .. its all or nothing.
function domRemoveEvent(obj, evType, fn, useCapture){
	if (obj.removeEventListener){
		obj.removeEventListener(evType, fn, useCapture);
		return true;
	} else if (obj.detachEvent){
		var r = obj.detachEvent("on"+evType, fn);
		return r;
	} else {
		window.status = ("Handler could not be removed");
	}
}

function domEventTarget(e) {
	if (e.toElement) {
		return e.toElement;
	} else if (e.currentTarget) {
		return e.currentTarget;
	} else {
		return null;
	}
}

function domGetElementsByClass(obj, cls) {
	var argv = domGetElementsByClass.arguments;
	var argc = argv.length;

	var tagName = (argc >2)?argv[2]:'*';


	var a, b, c, i, ii, j, o, classList;
	
	if (!obj) {
		b = document.getElementsByTagName("body").item(0);
	} else {
		b=obj;
	}
	a = b.getElementsByTagName(tagName);
	o = new Array();
	j = 0;
	for (i = 0; i < a.length; i++) {
		if (typeof(a[i].className) == 'string') {
		for (ii=0, classList = a[i].className.split(' '); 
		ii < classList.length; ii++) {
			
			if (classList[ii] == cls) {
				o[j] = a[i];
				j++;
			}
		}
		}
	}
	return o;
}

// wdvlDocumentWidth and wdvlDocumentHeight are based on ideas from
// http://www.quirksmode.org/viewport/compatibility.html
function domGetDocumentWidth() {
	var test1 = document.body.scrollWidth;
	var test2 = document.body.offsetWidth;
	if (test1 > test2) // all but Explorer Mac
	{
		return document.body.scrollWidth;
	}
	else // Explorer Mac;
		//would also work in Explorer 6 Strict, Mozilla and Safari
	{
		return document.body.offsetWidth;
	}
}

function domGetDocumentHeight() {
	var test1 = document.body.scrollHeight;
	var test2 = document.body.offsetHeight;
	if (test1 > test2) // all but Explorer Mac
	{
		return document.body.scrollHeight;
	}
	else // Explorer Mac;
		//would also work in Explorer 6 Strict, Mozilla and Safari
	{
		return document.body.offsetHeight;
	}
}


function domGetStyle(obj ,styleProp)
{
	var x = obj; // document.getElementById(el);
	var y;
	var sniffer;
	
	if (window.getComputedStyle) {
		sniffer = window.getComputedStyle(x,null).
		getPropertyValue(styleProp);
		
		if (sniffer) {
			y = window.getComputedStyle(x,null).
			getPropertyValue(styleProp);
		} else { 
			y = window.getComputedStyle(x,null).
			getPropertyValue(convertToWikiWord(styleProp));
		}
	} else if (x.currentStyle) {
		y = eval('x.currentStyle.' + styleProp);
	} else {
		y = x;
	}
	
	return y;
}

function domConvertToWikiWord(s) {
	var i;
	var r="";
	
	for (i=0; i<s.length; i++) {
		if (s.substring(i, i+1) == '-') {
			i++;
			r+= s.substring(i, i+1).toUpperCase();
		} else {
			r+= s.substring(i, i+1);
		}
	}
	
	return r;
}

/* a debugging function ... very useful. */
function
domShowProps (obj, objName, style, CRs, onlyNames, search)
{
	if (is && is.ie && is.major == 7) {
		return "IE 7 doesn't support domShowProps() currently";
	}
	var result = ""
		var count=0;
	
	if (!obj) {
		return result;
	}
	for (var i in obj)
	{
		if (search &&
				i.toString().toLowerCase().indexOf(search.toLowerCase())  == -1 ){
			; // do nothing
		} else {
			result += objName + "." + i.toString()
			if (!onlyNames)
				result += " = " + obj[i];
			count++;
			if (CRs || count%3==0)
				result+= "\n";
			else
				result+= ", ";
		}
	}
	return result
}

// can be used for keydown, keyup and keypress events
function domGetKey(e)
{
	var tmp;
	
	if (e.which)
		tmp = e.which;
	else if (e.keyCode) 
		tmp = e.keyCode;
	else if (e.event.keyCode) 
		tmp = window.event.keyCode;
	return tmp;
}

function domCharToUnicode(num) {
	var q,r;
	var s='';
	q=Math.floor(num);
	for (i=0; i<4; i++) {
		r=q%16;
		q=Math.floor(q/16);
		
		if (0 <=r && r<=9)
			rStr=r.toString();
		else
			rStr='abcdef'.charAt(r-10);
		
		s=rStr+s;
		
	}
	return eval("\"\\u"+s+"\"");
}

/*
 * domGetElementsBySelector(selector): from Version 0.4 - Simon Willison, March
 * 25th 2003 -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6,
 * Internet Explorer 5 on Windows -- Opera 7 fails - returns an array of element
 * objects from the current document matching the CSS selector. Selectors can
 * contain element names, class names and ids and can be nested. For example:
 * 
 * elements = document.getElementsBySelect('div#main p a.external')
 * 
 * Will return an array of all 'a' elements with 'external' in their class
 * attribute that are contained inside 'p' elements that are contained inside
 * the 'div' element which has id="main"
 * 
 * New in version 0.4: Support for CSS2 and CSS3 attribute selectors: See
 * http://www.w3.org/TR/css3-selectors/#attribute-selectors
 *  
 */

function domGetAllChildren(e) {
	// Returns all children of element. Workaround required for IE5/Windows. Ugh.
	return e.all ? e.all : e.getElementsByTagName('*');
}

domGetElementsBySelector = function(selector) {
	// Attempt to fail gracefully in lesser browsers
	if (!document.getElementsByTagName) {
		return new Array();
	}
	// Split selector in to tokens
	var tokens = selector.split(' ');
	var currentContext = new Array(document);
	for (var i = 0; i < tokens.length; i++) {
		token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
		if (token.indexOf('#') > -1) {
			// Token is an ID selector
			var bits = token.split('#');
			var tagName = bits[0];
			var id = bits[1];
			var element = document.getElementById(id);
			if (tagName && element.nodeName.toLowerCase() != tagName) {
				// tag with that ID not found, return false
				return new Array();
			}
			// Set currentContext to contain just this element
			currentContext = new Array(element);
			continue; // Skip to next token
		}
		if (token.indexOf('.') > -1) {
			// Token contains a class selector
			var bits = token.split('.');
			var tagName = bits[0];
			var className = bits[1];
			if (!tagName) {
				tagName = '*';
			}
			// Get elements matching tag, filter them for class selector
			var found = new Array;
			var foundCount = 0;
			for (var h = 0; h < currentContext.length; h++) {
				var elements;
				if (tagName == '*') {
					elements = getAllChildren(currentContext[h]);
				} else {
					elements = currentContext[h].getElementsByTagName(tagName);
				}
				for (var j = 0; j < elements.length; j++) {
					found[foundCount++] = elements[j];
				}
			}
			currentContext = new Array;
			var currentContextIndex = 0;
			for (var k = 0; k < found.length; k++) {
				if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
					currentContext[currentContextIndex++] = found[k];
				}
			}
			continue; // Skip to next token
		}
		// Code to deal with attribute selectors
		if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
				var tagName = RegExp.$1;
		var attrName = RegExp.$2;
		var attrOperator = RegExp.$3;
		var attrValue = RegExp.$4;
		if (!tagName) {
			tagName = '*';
		}
		// Grab all of the tagName elements within current context
		var found = new Array;
		var foundCount = 0;
		for (var h = 0; h < currentContext.length; h++) {
			var elements;
			if (tagName == '*') {
				elements = getAllChildren(currentContext[h]);
			} else {
				elements = currentContext[h].getElementsByTagName(tagName);
			}
			for (var j = 0; j < elements.length; j++) {
				found[foundCount++] = elements[j];
			}
		}
		currentContext = new Array;
		var currentContextIndex = 0;
		var checkFunction; // This function will be used to filter the elements
		switch (attrOperator) {
		case '=': // Equality
			checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
			break;
		case '~': // Match one of space seperated words
			checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
			break;
		case '|': // Match start with value followed by optional hyphen
			checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
			break;
		case '^': // Match starts with value
			checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
			break;
		case '$': // Match ends with value - fails with "Warning" in Opera 7
			checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
			break;
		case '*': // Match ends with value
			checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
			break;
		default :
			// Just test for existence of attribute
			checkFunction = function(e) { return e.getAttribute(attrName); };
		}
		currentContext = new Array;
		var currentContextIndex = 0;
		for (var k = 0; k < found.length; k++) {
			if (checkFunction(found[k])) {
				currentContext[currentContextIndex++] = found[k];
			}
		}
		// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+'
		// '+attrValue);
		continue; // Skip to next token
	}
	// If we get here, token is JUST an element (not a class or ID selector)
	tagName = token;
	var found = new Array;
	var foundCount = 0;
	for (var h = 0; h < currentContext.length; h++) {
		var elements = currentContext[h].getElementsByTagName(tagName);
		for (var j = 0; j < elements.length; j++) {
			found[foundCount++] = elements[j];
		}
	}
	currentContext = found;
}
return currentContext;
}

/* That revolting regular expression explained
 *  /^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
 *   \---/  \---/\-------------/    \-------/
 *     |      |         |               |    
 *     |      |         |           The value
 *     |      |    ~,|,^,$,* or =            
 *     |   Attribute             
 *    Tag
 */


function domEventTarget(e) {
	if (e.target) {
		return e.target;
	} else if (e.srcElement) {
		return e.srcElement;
	}
}

function domShowDebugInfo (s) {
	var d = document.getElementById('debug');
	
	if (d) {
		domSetInnerHTML(d, '<pre>' + s + '</pre>');
	}
}

function domGetFirstChildWhere(obj, name, value) {
	var i;
	var childNodes = obj.childNodes;
	
	for (i=0; i<childNodes.length; i++) {
		var node=childNodes[i];
		if (node[name] && node[name] == value) {
			return node;
		}
	}
	return null;
}

function domGetNumChildrenWhere(obj, name, value) {
	var returnNum=0;
	var i;
	var childNodes = obj.childNodes;
	
	for (i=0; i<childNodes.length; i++) {
		var node=childNodes[i];
		if (node[name] && node[name] == value) {
			returnNum ++;
		}
	}
	
	return returnNum;
	
}

/*
 * Grabbing data from a URL. Input is one parameter, url. It returns a request
 * object. Based on code from
 * http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
 */
function domOpenXMLDoc(url, processReqChange) //, method, data, isAsync)
{
	// We must add the date at the end. It seems Internet Explorer doesn't
	// grab things it has already unless you change the url slightly.
	// There must be another way around this, but this is fine for now.
	var theDate = new Date().getTime();
	var argv = domOpenXMLDoc.arguments;
	var argc = domOpenXMLDoc.arguments.length;
	var httpMethod = (argc > 2) ? argv[2] : 'GET';
	var data = (argc > 3) ? argv[3] : null;
	var isAsync = (argc > 4) ? argv[4] : true;
	
	
	if (url.indexOf('?') == -1) {
		url += "?";
	} else {
		url += "&amp;";
	} 
	
	
	/* url += "_dOmEpOcH=" + theDate; */
	
	var req;
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
		req = new XMLHttpRequest();
		
		// This function must be defined by your app.
		req.onreadystatechange = processReqChange;
		req.open(httpMethod, url, isAsync);
		
		if (httpMethod = "POST") {
			req.send(data);
		}
		
		
		
		// branch for IE/Windows ActiveX version
	} else if (window.ActiveXObject) {
		req = new ActiveXObject("Microsoft.XMLHTTP");
		if (req) {
			if (isAsync) {
				req.onreadystatechange = processReqChange;
			}
			req.open(httpMethod, url, isAsync);
			
			if (httpMethod = "POST") {
				req.send(data);
			}
		}
		// the browser doesn't suipport XML HttpRequest. Return null;
	} else {
		req=null;
	}
	
	return req;
}

function domGetFrameSrc(id) {
	if (frames && frames[id] && frames[id].document && 
			frames[id].document.body) {
		
		return frames[id].document.body.innerHTML;
	} else if (document.getElementById(id).contentWindow) {
		return document.getElementById(id).contentWindow.document.body.innerHTML;
	}
}

function domSetFrameSrc(id, value) {
	if (frames && frames[id] && frames[id].document && 
			frames[id].document.body) {
		
		frames[id].document.body.innerHTML = value;
	} else if (document.getElementById(id).contentWindow) {
		document.getElementById(id).contentWindow.document.body.innerHTML = value;
	}
}

function domGetFrameDocument(obj) {
	
	if (obj.contentWindow &&
			obj.contentWindow.document) {
		return obj.contentWindow.document;
	} else if (obj.document) {
		return obj.document; 
	} else {
		return null;
	}
}

function domParseXML(xmlString) {
	var myDocument;
	
	if (document.implementation && document.implementation.createDocument){
		// Mozilla, create a new DOMParser
		var parser = new DOMParser();
		myDocument = parser.parseFromString(xmlString, "text/xml");
	} else if (window.ActiveXObject){
		// Internet Explorer, create a new XML document using ActiveX
		// and use loadXML as a DOM parser.
		myDocument = new ActiveXObject("Microsoft.XMLDOM")
		myDocument.async="false";
		myDocument.loadXML(xmlString);
	}
	
	return myDocument;
}

function domGetTextContent(tag) {
	if (tag && tag.firstChild && tag.firstChild.nodeValue) {
		return tag.firstChild.nodeValue;
	} else {
		return "";
	}
}



function domUncommentThisHTML(s) {
	if (s.indexOf('-->')!= -1 && s.indexOf('<!--') != -1) {
		return s.replace("<!--", "").replace("-->", "");
	} else {
		return s;
	}
	
}

function domCommentThisHTML(s) {
	
	if (s.indexOf('-->')!= -1 || s.indexOf('<!--') != -1) {
		return s;
	} else {
		return "<!-- " + s + "-->";
	}
}

function domGetAttributeValue(obj, attrName) {
	var i;
	var attributes = obj.attributes;
	for (i=0; i<attributes.length; i++) {
		var attr = attributes[i]
							  if (attr.nodeName == attrName) {
							  	return attr.nodeValue;
							  }
	}
	return null;
}

function domDumpDebug(s) {
	var debugDiv = document.getElementById('debug');
	
	if (debugDiv){
		domSetInnerHTML(debugDiv, '<pre>' + s + '</pre>')
		
	}
}

function domGetInnerXML(obj) {

	var innerXML;
	if (obj.xml) {
		return obj.firstChild.xml;
	} else {
		// tricky.  Let's create a new node on the page, and suck out 
		// the innerHTML
		var clone = document.importNode(obj, true);
		
		var body =  document.getElementsByTagName('body')[0];

		var sandbox = document.createElement('DIV');
		sandbox.style.display = 'none';
		sandbox.id = 'dOmSaNdBoX';

		var cloneChildNodes = clone.childNodes;

		for (var i=0; i<cloneChildNodes.length; i++) {
			sandbox.appendChild(cloneChildNodes[i]);
		}

		body.appendChild(sandbox);

		var domSandbox = document.getElementById('dOmSaNdBoX');
		innerXML = domGetInnerHTML(domSandbox);

		// now .. destroy the muthuh!
		body.removeChild(domSandbox);
		
	}
	return innerXML;
}

function domParseXMLDataIsland(obj) {
         return domParseXML(domUncommentThisHTML(domGetInnerHTML(obj)))
}

function domXMLParseError(xmlObj) {
        var parseError = xmlObj.getElementsByTagName('parsererror')[0];
        var sourceText = xmlObj.getElementsByTagName('sourcetext')[0];
        if (parseError) {
                return domGetTextContent(parseError);
        } else if (domGetAllChildren(xmlObj).length == 0) {
                return "Error parsing XML";
        } else {
                return null;
        }


}



/*
* Sound routines
*/

function logIfPresent(s) {
	try {
		Logger.info(s);
	} catch (e) {

	}
}

function domErrorString(error) {
	var errorString = "";

	errorString += error.message + ". ";

	if (error.fileName) {
		errorString += error.fileName 
		if (error.lineNunber) {
			errorString += ", " + error.lineNumber;
		}
	}

	if (error.stack) {
		errorString += "\n\nStack info: " + error.stack;
	}

	return errorString;
}

function domMediaRewind(obj){ 
	var failed= true;

	try {
		obj.Rewind();
		failed = false;
	} catch (e) {
	}

	if (!failed) {
		return;
	}

	try {
		obj.DoRewind();
	} catch (e) {
	}

	if (!failed) {
		return;
	}

	try {
		obj.rewind();
	} catch (e) {
	}
	
}

function domMediaPlay(obj, fromBeginning) {
	var failed = true;

	if (fromBeginning) {
		domMediaRewind(obj);
	}
	
	try {
		// Quicktime
		obj.Play();
		failed = false;
	} catch (e) {
	}

	if (!failed) {
		logIfPresent("Play();");
		return;
	}

	try {
		// Real
		obj.DoPlay();
		failed = false;
	} catch (e) {
	}

	if (!failed) {
		logIfPresent("DoPlay();");
		return;
	}

	try {
		// Windows Media 
		obj.play();
		failed = false;
		logIfPresent("play();");
	} catch (e) {
	}
	logIfPresent("Exiting ... ");
	return;
}

function domMediaStop(obj) {
	var failed = true;

	try {
		obj.Stop();
		failed = false;
	} catch (e) {
	}

	if (!failed) {
		return;
	}

	try {
		obj.DoStop();
	} catch (e) {
	}

	if (!failed) {
		return;
	}

	try {
		obj.stop();
	} catch (e) {
	}
	return;
}

function domMediaGetVolume(obj) {
	var answer = null;
	try {
		answer = obj.Volume;
	} catch (e) {
	}

	if (answer)
		return answer;

	try {
		answer= obj.get_volume();
	} catch (e) {
	}

	if (answer) 
		return answer;

	try {
		answer= obj.GetVolume();
	} catch (e)  {
	}

	return answer;
}


function domMediaSetVolume(obj, value) {
	var done=false;

	try {
		obj.Volume = value;
		done = true;
	} catch (e) {
	}

	if (done)
		return;

	try {
		obj.set_volume(value);
		done = true;
	} catch (e) {
	}

	if (done) 
		return;

	try {
		obj.SetVolume(value);
		done = true;
	} catch (e)  {
	}
}

/* 
domMediaHTML(url, mediaType, width, height, loop, autoStart, showControls,
	attributes) {

	var r;
   if (attributes == null) {
	attributes = '';
   }
   
   if (mediaType == 'real') {
	r = '<object ' + attributes + 
	  ' classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA">' +
	  '<param name="loop" value="' + loop==true + '" />' +
	  '<param name="autostart" value="' + autostart==true + '" />' +
	  '<param name="controls" value="' + showControls== true + '" />' +
	  '<param name="src" value="' + url + '" />' +
	  '<embed ' + attributes + 'src="' + url + '" ' +
	  'loop="' + loop == true + '" type="audio/x-pn-realaudio-plugin" ' +
	  'controls="' + showControls == true + '" autostart="' + autoStart==true +
	  '">' +
	  '</embed>' +
	  '</object>';
	} else if (mediaType == 'quicktime') {
	r = 
	  '<object ' + attributes + 
	  ' classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B' " +
	  ' codebase='http://www.apple.com/qtactivex/qtplugin.cab'> ' +
	  '<param name='src' value="' + url + '"> ' +
	  '<param name='autoplay' value="' + autoStart==true + '"> ' +
	  '<param name='controller' value="' + showControls==true + '"> ' +
	  '<param name='loop' value="' + loop == true '"> ' +
	  '<embed src="' + url + '" autoplay="' + autoStart + '"  ' +
	  'controller="' + showControls==true +'" ' +
	  'loop="' + true +'"  ' +
	  'pluginspage='http://www.apple.com/quicktime/download/'> ' +
	  '</embed> ' +
	  '</object> ';
	} else if (mediaType == 'windows') {
	r =
	  '<object id="mediaPlayer" width='320' height='285' ' + 
	  'classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" ' + 
	  'codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"' + 
	  'standby="Loading Microsoft Windows Media Player components..." type="application/x-oleobject">' + 
	  '<param name="fileName" value="'  + url + '">' + 
	  '<param name="animationatStart" value="true">' + 
	  '<param name="autoStart" value="">' + 
	  '<param name="showControls" value='true'>' + 
	  '<param name="loop" value='true'>' + 
	  '<embed type="application/x-mplayer2"' + 
	  'pluginspage="http://microsoft.com/windows/mediaplayer/en/download/"' + 
	  'id="mediaPlayer" name="mediaPlayer" displaysize="4" autosize="-1" ' + 
	  'bgcolor="darkblue" showcontrols='true' showtracker="-1" ' + 
	  'showdisplay="0" showstatusbar="-1" videoborder3d="-1" width='320' height='285'' + 
	  'src='http://servername/path/to/media.file' autostart='true' designtimesp="5311" loop='true'>' + 
	  '</embed>' + 
	  '</object>' + 
	}

*/
