function Map()
{
	this.keys=new Array();
	this.values=new Array();
	this.hash=new Array();
}

Map.prototype.getHash=function(key,create)
{
	var strKey=key.toString();
	var hash=this.hash[strKey];
	if (hash==null && create)
	{
		hash=new Array();
		this.hash[strKey]=hash;
	}
	return(hash);
}

Map.prototype.getPosition=function(key)
{
	var hash=this.getHash(key);
	if (hash!=null)
	{
		for (var i=0;i < hash.length; i++)
		{
			if (this.keys[hash[i]]==key)
			{
				return(hash[i]);
			}
		}
	}
	return(null);
}

Map.prototype.put=function(key, value)
{
	if (key==null || value==null)
	{
		throw "can not be null"
	}
	this.remove(key);
	
/*	var nPosition=this.getPosition(key);
	if (nPosition!=null)
	{
		this.keys[nPosition]=key;
		this.values[nPosition]=value;
		return;
	}*/

	var hash=this.getHash(key,true);
	hash[hash.length]=this.keys.length;

	this.keys[this.keys.length]=key;
	this.values[this.values.length]=value;
}

Map.prototype.get=function(key)
{
	var nPosition=this.getPosition(key);
	if (nPosition!=null)
	{
		return(this.values[nPosition]);
	}
	return(null);
}

Map.prototype.remove=function(key)
{
	var hash=this.getHash(key);
	if (hash!=null)
	{
		var nPosition=null;
		for (var i=0; i < hash.length; i++)
		{
			if (this.keys[hash[i]]==key)
			{
				nPosition=hash[i];
			}
			hash.splice(i,1);
			if (hash.length==0)
			{
				delete this.hash[key];
			}
		}
		if (nPosition != null)
		{
			var obj=this.values[nPosition];
			delete this.keys[nPosition];
			delete this.values[nPosition];
			//this.keys.splice(nPosition,1);
			//this.values.splice(nPosition,1);
			return(obj);
		}
	}

	return(null);
}

Map.prototype.getKeys=function()
{
	var keys=new Array();
	for (var i=0;i < this.keys.length; i++)
	{
		var key=this.keys[i];
		if (key!=null)
		{
			keys[keys.length]=this.keys[i];
			if (this.getPosition(key)==null)
			{
				var hash=this.getHash(this.keys[i]);
				alert("should not happen '"+i+" "+this.keys[i]+"' "+hash);
			}
		}
	}
	return(keys);
}

Map.prototype.size=function()
{
	return(this.keys.length);
}

function Utils()
{
	this.timeouts=new Array();
	this.timeoutCount=0;
}

Utils.prototype.callWithParamArray=function(object, func, array, start)
{
	var params=new Array();
	for (var i=start;i < array.length; i++)
	{
		params[params.length]="array["+i+"]";
	}
	var funccall="func.call(object"+((array.length > start)?",":"")+params.join(",")+")"
	eval(funccall);
}

Utils.prototype.objectTimeout=function(time, object, func)
{
	var id=""+(this.timeoutCount++);
	var array=new Array();
	array[array.length]=object;
	array[array.length]=func;
	array[array.length]=arguments;
	this.timeouts[id]=array;
	setTimeout("var array=utils.timeouts["+id+"];utils.callWithParamArray(array[0],array[1],array[2],3)",time);
}
Utils.prototype.getWidth=function(node)
{
	if (node.clientWidth)
	{
		return(node.clientWidth);
	}
	else
	{
		return(node.offsetWidth);
	}
}
Utils.prototype.getHeight=function(node)
{
	if (node.clientHeight)
	{
		return(node.clientHeight);
	}
	else
	{
		return(node.offsetHeight);
	}
}
Utils.prototype.importNode=function(doc,node,children)
{
	if(!doc.importNode)
	{
		var newNode;

		if(node.nodeType == 1)
		{
			newNode = doc.createElement(node.nodeName);
			for(var i = 0; i < node.attributes.length; i++)
			{
				newNode.setAttribute(node.attributes[i].name, node.attributes[i].value);
			}
			newNode.style.cssText = node.style.cssText;
		}
		else if(node.nodeType == 3)
		{
			newNode = doc.createTextNode(node.nodeValue);
		}
		else
		{
			return;
		}

		if(children)
		{
			for (var i=0;i < node.childNodes.length; i++)
			{
				var child=this.importNode(doc,node.childNodes[i],children);
				if (child)
				{
					newNode.appendChild(child);
				}
			}
		}
		return newNode;
	}
	else
	{
		return(doc.importNode(node,true));
	}
}

/*Utils.prototype.getDocumentFromString=function(xml)
{
	if (window.ActiveXObject)
	{
		var doc=new ActiveXObject("Microsoft.XMLDOM");
		doc.async="false";
		doc.loadXML(xml);
		return(doc);
	}
	else
	{
		var parser=new DOMParser();
		var doc=parser.parseFromString(xml,"text/xml");
		return(doc);
	}
}*/

Utils.prototype.removeComments=function(str)
{
	var nStart=str.indexOf("\<\!\-\-");
	if (nStart != -1)
	{
		var nEnd=str.indexOf("\-\-\>",nStart);
		if (nEnd!=-1)
		{
			nEnd+=3;
			return(str.substring(0,nStart)+utils.removeComments(str.substring(nEnd)));
		}
	}
	return(str);
}
Utils.prototype.reflow=function()
{
	document.body.style.display="none";
	utils.objectTimeout(1,null,function()
	{
		document.body.style.display="block";
	});	
}

var utils=new Utils();

var DOMUtils=function()
{
}
DOMUtils.prototype.getDocumentFromURL=function(strURL,callback)
{
	if (window.ActiveXObject)
	{
		var doc=new ActiveXObject("Microsoft.XMLDOM");
		doc.async="true";
		doc.load(strURL);
		doc.onreadystatechange=function()
		{
			if (this.readyState==4)
			{
				callback(doc);
			}
		}
	}
	else if (document.implementation && document.implementation.createDocument)
	{
		var doc=document.implementation.createDocument("","",null);
		doc.load(strURL);
		doc.onload=function()
		{
			callback(doc);
		}
	}
}
DOMUtils.prototype.getDocumentFromString=function(xml)
{
	if (window.ActiveXObject)
	{
		var doc=new ActiveXObject("Microsoft.XMLDOM");
		doc.async="false";
		doc.loadXML(xml);
		return(doc);
	}
	return(new DOMParser().parseFromString(xml,"text/xml"));
}
DOMUtils.prototype.normalize=function(ele)
{
	var defaultNamespace=ele.getAttribute("xmlns");
	for (var i=0; i < ele.childNodes.length; i++)
	{
		var child=ele.childNodes[i];
		if ((typeof child.getAttribute)=="unknown" | (typeof child.getAttribute)=="function")
		{
			var childNamespace=child.getAttribute("xmlns");
			if (childNamespace==null)
			{
				var attrib=doc.createAttribute("xmlns");
				attrib.value=defaultNamespace;
				child.setAttributeNode(attrib);
			}
			this.normalize(child);
		}
	}
}
DOMUtils.prototype.serialize=function(doc)
{
	if (doc.xml)
	{
		this.normalize(doc.documentElement);
		return(doc.xml);
	}
	return(new XMLSerializer().serializeToString(doc));
}
DOMUtils.prototype.getChildNode=function(ele,index)
{
	if (typeof index=="function")
	{
		for (var i=0;i < ele.childNodes.length; i++)
		{
			var child=ele.childNodes[i];
			var ret=index(child);
			if (ret)
			{
				return(ret);
			}
		}
	}
	else
	{
		if (typeof index=="undefined")
		{
			index=0;
		}
		var count=0;
		for (var i=0;i < ele.childNodes.length; i++)
		{
			if (ele.childNodes[i].nodeName!="#text")
			{
				count++;
				if (count > index)
				{
					return(ele.childNodes[i]);
				}
			}
		}
	}
}
var domUtils=new DOMUtils();

