function dom_getAncestorByClass(node, classname, alert_if_not_found) {
	if (typeof(alert_if_not_found)=== 'undefined') {
		alert_if_not_found = true;
	}
	n = node;
	while (true) {
		n = n.parentNode;
		if (typeof(n)== 'undefined' || n==null) { // stop when there's no parent node.
			break;
		} else if (typeof(n.className)!= 'undefined') { // skip text nodes
			//alert("dom_getAncestorByClass n.className="+n.className+"\n n.className.indexOf(classname)="+n.className.indexOf(classname));
			if (n.className.indexOf(classname) != -1) {
				//alert("GOT IT!")
				return n;
			}
		}
	}
	if (alert_if_not_found) {
		dom_alert_node(node, "dom_getAncestorByClass not found. classname="+classname);
	}
	return null;
}

function dom_getAncestorByName(node, name, alert_if_not_found) {
	if (typeof(alert_if_not_found)=== 'undefined') {
		alert_if_not_found = true;
	}
	name	= name.toUpperCase();
	n		= node;
	while (true) {
		n = n.parentNode;
		//alert("dom_getAncestorByName n.nodeName="+n.nodeName);
		if (typeof(n)== 'undefined' || n==null) { // stop when there's no parent node.
			break;
		} else if (n.nodeName==name) {
			return n;
		}
	}
	if (alert_if_not_found) {
		dom_alert_node(node, "dom_getAncestorByName not found. name="+name);
	}
	return null;
}

function dom_getElementByName(node, tagname) {
	tagname=tagname.toUpperCase();
	for (var i=0; i<node.childNodes.length; i++){
		n = node.childNodes[i];
		//alert(n.nodeName);
		if (typeof(n.className)!= 'undefined') { // skip text nodes
			if (n.nodeName.toUpperCase()==tagname) {
				return n;
			}
		}
	}
	alert("dom_getElementByName not found. tagname="+tagname+" node="+node.innerHTML);
}

function dom_getElementsByName(node, tagname) {
	result = new Array();
	tagname=tagname.toUpperCase();
	for (var i=0; i<node.childNodes.length; i++){
		n = node.childNodes[i];
		if (typeof(n.className)!= 'undefined') { // skip text nodes
			if (n.nodeName.toUpperCase()==tagname) {
				result.push(n);
			}
		}
	}
	return result;
}

function dom_getElementByClass(node, classname, alert_if_not_found) {
	if (typeof(alert_if_not_found)=== 'undefined') {
		alert_if_not_found = true;
	}
	for (var i=0; i<node.childNodes.length; i++){
		n = node.childNodes[i];
		//common_alert_node(n)
		if (typeof(n.className)!= 'undefined') { // skip text nodes
			if (n.className.indexOf(classname) != -1) {
				return n;
			}
		}
	}
	if (alert_if_not_found) {
		alert("dom_getElementByClass not found. class="+classname+" node="+node.innerHTML);
	}
	return null;
}

function dom_getChildByClass(node, classname, alert_if_not_found) {
	if (typeof(alert_if_not_found)=== 'undefined') {
		var start = true;
		alert_if_not_found = true;
	} else {
		start = false;
	}
	//dom_alert_node(node, "dom_getChildByClass "+classname+" "+node.className.indexOf(classname))
	// check children
	for (var i in node.childNodes){
		var n = node.childNodes[i];
		//if (typeof(n.className)!= 'undefined') { // skip text nodes
		if (n.nodeType==1) {
			if (n.className.indexOf(classname) != -1) {
				//common_alert_node(n, "found it!")
				return n;
			}
		}
	}
	// let children check their children
	for (var j in node.childNodes){
		var n = node.childNodes[j];
		//common_alert_node(n, "search child "+(j+1)+" of "+node.childNodes.length)
		if (n.nodeType==1) {
			var r = dom_getChildByClass(n, classname, alert_if_not_found);
			if (r!=null) {
				return r;
			}
		}
		
		//if (typeof(n.className)!='undefined') {
		//	return r;
		//}
	}
	if (alert_if_not_found && start) {
		dom_alert_node(node, "dom_getChildByClass not found. class="+classname);
	}
	// not found
	return null;
}

function dom_getElementsByClass(node, classname) {
	result = new Array();
	// array or string
	if (typeof(classname)=="object") {names = classname}
	else {names = new Array(classname);}
	 
	for (var i=0; i<node.childNodes.length; i++){
		n = node.childNodes[i];
		if (typeof(n.className)!= 'undefined') { // skip text nodes
			
			for (var j=0; j<names.length; j++){
				if (n.className.indexOf(names[j]) != -1) {
					result.push(n);
				}
			}
		}
	}
	return result;
}

function dom_getPreviousByClass(node, classname, alert_if_not_found, strict) {
	//dom_alert_node(node, "dom_getPreviousByClass. classname="+classname)
	if (typeof(alert_if_not_found)=== 'undefined') {
		alert_if_not_found = true;
	}
	if (typeof(strict)=== 'undefined') {
		strict = true;
	}
	n = node;
	while (true) {
		n = n.previousSibling;
		if (n===null) { // stop when there's no previous node.
			break;
		} else if (typeof(n.className)!= 'undefined') { // skip text nodes
			if (n.className.indexOf(classname) != -1) {
				return n;
			} else if (strict) { // stop if we find another class
				break;
			}
		}
	}
	if (alert_if_not_found) {
		dom_alert_node(node, "dom_getPreviousByClass not found. classname="+classname)
	}
	return null;
}

function dom_getNextByClass(node, classname, alert_if_not_found, strict) {
	//dom_alert_node(node, "dom_getNextByClass. classname="+classname)
	if (typeof(alert_if_not_found)=== 'undefined') {
		alert_if_not_found = true;
	}
	if (typeof(strict)=== 'undefined') {
		strict = true;
	}
	n = node;
	while (true) {
		//dom_alert_node(n, "dom_getNextByClass. this is n");
		n = n.nextSibling;
		if (n===null) { // stop when there's no next node.
			break;
		} else if (typeof(n.className)!= 'undefined') { // skip text nodes
			if (n.className.indexOf(classname) != -1) {
				return n;
			} else if (strict) { // stop if we find another class
				break;
			}
		}
	}
	if (alert_if_not_found) {
		dom_alert_node(node, "dom_getNextByClass not found. classname="+classname)
	}
	return null;
}

function dom_alert_node(node, text) {
	//atts="";for (a=0; a<node.attributes.length; a++) {atts += '\n'+node.attributes[a].nodeName;} alert(atts);
		// --> node.attributes has no properties
	if (typeof(text)!='undefined') {
		s = text+"\n\n";
	} else {
		s = "";
	}
	if (node==null) {
		alert("node=null "+text);
	}
	s+="<"+node.nodeName+" class=\""+node.className+"\" id=\""+node.id+"\">\n\n";
	if (typeof(node.innerHTML)=='undefined') {
		s+="(no innerHTML)\n";
	} else if (node.innerHTML.length<100000) { // 1000
		s+="innerHTML:\n"+node.innerHTML+"\n\n";
	} else {
		s+="innerHTML:\n"+node.innerHTML.substring(0,1000)+"[...]\n\n";
	}
	if (typeof(node.childNodes)!='undefined') {
		s+="childNodes.length="+node.childNodes.length+"\n";
	}
	if (typeof(node.nodeValue)!='undefined') {
		s+="value="+node.nodeValue+"\n";
	}
	t=node.nodeType;
	if (t==1) {s+="nodeType=ELEMENT_NODE\n";}
	if (t==2) {s+="nodeType=ATTRIBUTE_NODE\n";}
	if (t==3) {s+="nodeType=TEXT_NODE\n";}
	if (t==4) {s+="nodeType=CDATA_SECTION_NODE\n";}
	if (t==5) {s+="nodeType=ENTITY_REFERENCE_NODE\n";}
	if (t==6) {s+="nodeType=ENTITY_NODE\n";}
	if (t==7) {s+="nodeType=PROCESSING_INSTRUCTION_NODE\n";}
	if (t==8) {s+="nodeType=COMMENT_NODE\n";}
	if (t==9) {s+="nodeType=DOCUMENT_NODE\n";}
	if (t==10) {s+="nodeType=DOCUMENT_TYPE_NODE\n";}
	if (t==11) {s+="nodeType=DOCUMENT_FRAGMENT_NODE\n";}
	if (t==12) {s+="nodeType=NOTATION_NODE\n";}
	//if (node.nodeType==3) { // text
	//}
	alert(s);
}

function dom_string_to_dom(xml_string) {
	if (typeof ActiveXObject != 'undefined') {
		var dom = new ActiveXObject("Microsoft.XMLDOM");
		dom.async = false;
		dom.loadXML(xml_string);
	}
	else {
		parser = new DOMParser();
		dom = parser.parseFromString(xml_string, "text/xml");						
	}
	return dom;
}
