function saveOrigClasses () {
	var elems = document.getElementsByTagName("*");
	for (var ix=0;ix<elems.length;ix++) {
		var cls = elems[ix].getAttribute("class");
		elems[ix].setAttribute("orgClass", cls);
	}
}
function brightenMe (me) {
	var cls = me.getAttribute("orgClass");
	me.setAttribute("class", cls);
	me.setAttribute("hilightState", "bright");
}

function dimMe (me) {
	var cls = me.getAttribute("orgClass");
	cls = cls + " " + "dim";
	me.setAttribute("class", cls);
	me.setAttribute("hilightState", "dim");
}

function asIwas (me) {
	var orgClass = me.getAttribute("orgClass");
	me.setAttribute("class", orgClass);
	me.setAttribute("hilightState", "bright");
}

function expandMe (me) {
	var cls = me.getAttribute("orgClass");
	me.setAttribute("displayState", "expanded");
	me.setAttribute("class", cls);
}

function collapseMe (me) {
	me.setAttribute("displayState", "collapsed");
	me.setAttribute("class", "collapse");
}

function toggleHilight (elemId) {
	var me = document.getElementById(elemId);
	var state = me.getAttribute("hilightState");
	if (state == null || state == "bright")
		dimMe (me);
	else
		brightenMe (me);
}

function toggleExpand (elemId) {
	var me = document.getElementById(elemId);
	var state = me.getAttribute("displayState");
	if (state == null || state == "expanded")
		collapseMe (me);
	else
		expandMe (me);
}

function backToNormal () {
	var elems = document.getElementsByTagName("*");
	for (var ix=0;ix<elems.length;ix++) {
		asIwas(elems[ix]);
	}
}
function focusOnMe (attr, val) {
	var elems = document.getElementsByTagName("*");
	for (var ix=0;ix<elems.length;ix++) {
		if (notContainedInBody(elems[ix]) || elems[ix].getAttribute(attr) == null) {
			continue;
		}
		if (elems[ix].getAttribute(attr) == val)
			brightenMe(elems[ix]);
		else
			dimMe(elems[ix]);
	}
}

function notContainedInBody (elem) {
	var nodeName = elem.nodeName;
	return (nodeName == "HTML" || nodeName == "BODY" || nodeName == "STYLE"
		|| nodeName == "SCRIPT" || nodeName == "HEAD" || nodeName == "LINK");

}
function showDocHier() {
	var res = showElemHier(document, "Document", 1);
	alert(res);
}
function showElemHier(node, res, nlevel) {
	var elems = node.childNodes;
	for (var ix=0;ix<elems.length;ix++) {
		res = res + "\n";
		for (var t=0;t<nlevel;t++) {
			res = res + "\t";
		}
		res = res + elems[ix].toString();
		res = showElemHier(elems[ix], res, nlevel+1);
	}
	return res;
}
function alertArray (arr) {
	var ret = unravelArray (arr, false);
	alert (ret);
}
function unravelArray (arr, deep) {
	var ret = "Array: " + arr.toString() + "\n";
	for (var ix=0;ix<arr.length;ix++) {
		ret += arr[ix].nodeName + "\n";
		if (deep) {
			
		}
	}
	return ret;
}

function getElementsByAttribute (attr) {
	var elems = document.getElementsByTagName("*");
	var ret;
	var jx = 0;
	for (var ix=0;ix<elems.length;ix++) {
		if (elems[ix].getAttribute(attr) != null) {
			alert (elems[ix].id + " has attr " + attr);
			ret[jx++] = elems[ix];
		}
	}
	
	return ret;
}
function tabOpen1 (id, attr) {
	var p1 = document.getElementById("p1");
	var p2 = document.getElementById("p2");
	if (id == "p1") {
		p1.setAttribute("class", "tabOpen");
		p2.setAttribute("class", "tab");
	} else {
		p2.setAttribute("class", "tabOpen");
		p1.setAttribute("class", "tab");
	}
}
function tabOpen (id, tabGroup) {
	var tabs = getElementsByAttribute(tabGroup);
	var openTab = document.getElementById(id);
	openTab.setAttribute("class", "openTab");
	for (var ix=0;ix<tabs.length;ix++) {
		if (tabs[ix] != openTab) {
			tabs[ix].setAttribute("class", "tab");
		}
	}
}

function hideDelay (id, delay) {
        window.setTimeout("hide('"+id+"')", delay);
}
        
function hide (id) {
        var elem = document.getElementById(id);
        elem.style.display = "none";
}
function showDelay (id, delay) {
        window.setTimeout("show('"+id+"')", delay);
}
function show (id) {
        var elem = document.getElementById(id);
        elem.style.display = "block";
}
function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.parentNode;
    }
    return { top: _y, left: _x };
}

/** 
 * @param {Function} func the callback function 
 * @param {Object} opts an object literal with the following 
 * properties (all optional): 
 * bind: the object to bind the function to (what the "this" keyword will refer to) 
 * args: an array of arguments to pass to the function when it is called, these will be 
 * appended after any arguments passed by the caller 
 * suppressArgs: boolean, whether to supress the arguments passed 
 * by the caller. This default is false. 
 */ 
function callback(func,opts) { 
	var cb = function() { 
		var args = opts.args ? opts.args : []; 
		var bind = opts.bind ? opts.bind : this; 
		var fargs = opts.supressArgs === true ? [] : toArray(arguments);
		func.apply(bind,fargs.concat(args)); 
	} 
	return cb; 
} 
/* A utility function for callback() */ 
function toArray(arrayLike) { 
	var arr = []; 
	for(var i = 0; i < arrayLike.length; i++){ 
		arr.push(arrayLike[i]); 
	} 
	return arr; 
}


