// entrypoint function
//
function $_(e)
{
	return new $_obj(e);
}



/*
Constructor

Parameters:
	mixed - either a DOM object, or the id of a DOM object
*/
$_obj = function (e)
{
	this._ = null;
	if (e)
	{
		if (typeof(e) == "string")
		{
			var re = document.getElementById( e );
			
			if (re != null  &&  typeof(re.appendChild) != "undefined" ) {
				this._ = re;
			} else {
				re = document.getElementsByTagName(e);
				if (re.length == 1)
				{
					this._ = re.item(0);
				} else {
					this._ = re;
				}
			}
		}
		else if (typeof(e.appendChild) != "undefined")
			this._ = e;
		else
			return false;
	}
	
	
	// set up utils
	//
	this.utils =
	{
		cleanNumber : function(str, dec)
		{
			str = str.toString().replace(",",".") - 0;
			if (isNaN(str))
				str = "0";
			
			if (dec>0)
			{
				str = str.toString();
				if (str.lastIndexOf(".")==-1)
					str += ".";

				while (str.lastIndexOf(".") >= str.length-dec)
					str += new String("0");
			}
			else if (dec === 0)
				Math.round(str);

			return str.replace(".",",");
		},
		
		mailto : function(e,to,dom,tl)
		{
			var a = new Array(109,97,105,108,116,111,58), em=to+"&#"+"64;"+dom+"."+tl;
			$_(e).replaceContent("<a href='&#"+a.join(';&#')+";"+em+"'>"+em+"</a>");
		},
		
		pageSize : function ()
		{
			var xScroll, yScroll;
	
			if (window.innerHeight && window.scrollMaxY) {	
				xScroll = document.body.scrollWidth;
				yScroll = window.innerHeight + window.scrollMaxY;
			} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
				xScroll = document.body.scrollWidth;
				yScroll = document.body.scrollHeight;
			} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
				xScroll = document.body.offsetWidth;
				yScroll = document.body.offsetHeight;
			}
			
			var windowWidth, windowHeight;
			if (self.innerHeight) {	// all except Explorer
				windowWidth = self.innerWidth;
				windowHeight = self.innerHeight;
			} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
				windowWidth = document.documentElement.clientWidth;
				windowHeight = document.documentElement.clientHeight;
			} else if (document.body) { // other Explorers
				windowWidth = document.body.clientWidth;
				windowHeight = document.body.clientHeight;
			}	
			
			// for small pages with total height less then height of the viewport
			if(yScroll < windowHeight){
				pageHeight = windowHeight;
			} else { 
				pageHeight = yScroll;
			}
		
			// for small pages with total width less then width of the viewport
			if(xScroll < windowWidth){	
				pageWidth = windowWidth;
			} else {
				pageWidth = xScroll;
			}
			return { pageWidth:pageWidth, pageHeight:pageHeight, windowWidth:windowWidth, windowHeight:windowHeight }; 
		}
		
	};
};



/*
Method: childs

Parameters:
	n - Integer - index

Returns:
	mixed - DOMCore instance if single, childNodes array if plural
*/
$_obj.prototype.childs = function (n)
{
	var ele = this._;
	if (!ele)
		return false;
	
	var c = this._.childNodes.length;
	if (!c)
		return false;
	else if (n!=null && n<c)
		return new $_obj(this._.childNodes[n]);
	else if (c==1)
		return new $_obj(this._.childNodes[0]);
	else
		return this._.childNodes;
}


/*
Method: position

Returns:
	Object - {x:Integer, y:Integer}
*/
$_obj.prototype.position = function ()
{
	var obj = this._;
	
	if (obj)
	{
		var curleft = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curleft += obj.offsetLeft;
				obj = obj.offsetParent;
			}
		}
		else if (obj.x)
			curleft += obj.x;
		
		
		var curtop = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curtop += obj.offsetTop;
				obj = obj.offsetParent;
			}
		}
		else if (obj.y)
			curtop += obj.y;

		return {x:curleft, y:curtop};
	}
	else
	{
		return null;
	}
};



/*
Method: empty
Removes all child nodes
*/
$_obj.prototype.empty = function ()
{
	var ele = this._;
	if (!ele)
		return false;
	
	while (ele.childNodes.length)
		ele.removeChild( ele.childNodes[0] );

	return this;
};



/**
 * append content to this element
 */
$_obj.prototype.appendContent = function ( cont, dom )
{
	var ele = this._;
	if (!ele)
		return false;
	
	if (typeof(cont) == "string" && dom)
		ele.appendChild( document.createTextNode(cont) );
	else if (typeof(cont) == "string")
		ele.innerHTML += cont;
	else if (typeof(cont) == "object")
		ele.appendChild( cont );
	
	return this;
};



// replace content
//
$_obj.prototype.replaceContent = function ( cont, dom )
{
	this.empty();
	this.appendContent(cont,dom);
	
	return this;
};



// get parent
//
$_obj.prototype.parent =  function ()
{
	return new $_obj(this._.parentNode);
};



// show
//
$_obj.prototype.show = function ()
{
	if (this._)
		this._.style['display'] = "block";
	
	return this;
};



// hide
//
$_obj.prototype.hide = function ()
{
	if (this._)
		this._.style['display'] = "none";
	
	return this;
};



// appendElement
//
$_obj.prototype.appendElement = function ( type, attr, cont, returnele )
{
	var ele = this._;
	if (!ele)
		return false;
	
	var ne = document.createElement( type );
	if (!ne)
		return false;

	for (var a in attr)
		ne[a] = attr[a];
	
	if (typeof(cont) == "string")
		ne.innerHTML += cont;
	else if (typeof(cont) == "object")
		ne.appendContent.appendChild( cont );
	
	this.appendContent(ne);
	
	// set new element as object instead of parent object
	//
	if (returnele)
		this._ = ne;
	
	return this;
};



// remove this object
//
$_obj.prototype.remove = function ()
{
	var p = this.parent();
	if (p)
	{
		p._.removeChild( this._ );
		return p;
	} else {
		return false;
	}
};



// style
//
$_obj.prototype.style = function ( part, style )
{
	var ele = this._;
	if (!ele)
		return false;
	
	ele.style[part] = style;

	return this;
};




// ajax methods


$_obj.prototype.loadContent = function (url)
{
	if (!this._)
		return false;
	
	var p = this;
	this.ajax({
		url : url,
		ondata : function (obj)
		{
			p._.innerHTML = obj.xml.getElementsByTagName("response")[0].firstChild.nodeValue;
		}
	});
	
	return false;
};


$_obj.prototype.ajax = function (args)
{
	var a = {
		req : null,
		text : "",
		xml : "",

		request : function (url, method, data, onwait, ondata, onerror)
		{
			this.url = url;
			this.cb_wait = onwait;
			this.cb_data = ondata;
			this.cb_error = onerror;
			this.req = this.getAjax();

			//var nocacheuri = this.url + "&ts=" + new Date().getTime();
			var r = this.req;
			var doneWait = false;
			var p = this;
			
			method = method!="POST" ? "GET" : "POST";
			
			// open ajax
			//
			r.open( method, url, true );
			
			var params = "";
			for (var a in data)
			{
				params += a + "=" + encodeURIComponent(data[a]) + "&";
			}
			
			if (method == "POST")
			{
				r.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
				r.setRequestHeader("Content-length", params.length);
				r.setRequestHeader("Connection", "close");
			}
			else
			{
				r.setRequestHeader("Content-Type", "text/plain; charset=utf-8");
				r.setRequestHeader("Cache-Control", "no-cache");
			}
			
			r.onreadystatechange = function ()
			{
				/*
				0 = uninitialized
				1 = loading
				2 = loaded
				3 = interactive
				4 = complete
				*/
				
				
				if (r.readyState < 4)
				{
					if (!doneWait)
					{
						p.onWait( r );
						doneWait = true;
					}
				}
				else
				{
					switch (r.status)
					{
						case 200: // "OK"
							p.onData( r );
							break;

						case 304: // "Not modified" - shouldn't happen because we are avoiding the browser cache

							break;

						default:
							p.onError( r );
					}
				}
			};
			
			
			r.send( params );
		},
		
		getAjax : function ()
		{
			var oXHR;

			// Returns a new Ajax object (cross-browser) if available, false if not.
			try
			{  
				oXHR = new ActiveXObject('Msxml2.XMLHTTP');
			}
			catch (e)
			{
				try
				{
					oXHR = new ActiveXObject('Microsoft.XMLHTTP');
				}
				catch (e2)
				{
					try
					{
						oXHR = new XMLHttpRequest();
					}
					catch (e3)
					{
						oXHR = false;
					}
				}
			}

			return oXHR;
		},

		onWait : function (oXHR)
		{
			if (this.cb_wait)
				this.cb_wait( this );
		},

		onData : function (oXHR)
		{
			this.text = this.req.responseText;
			this.xml = this.req.responseXML;
			if (this.cb_data)
				this.cb_data( this );
		},

		onError : function (oXHR)
		{
			if (this.cb_error)
				this.cb_error( this );
		}
	};
	
	if (args)
	{
		a.request( args.url, args.method, args.data, args.onwait, args.ondata, args.onerror );
	}
	
	return a;
};
