// CodeThatSDK - JavaScript SDK
// Version: 1.0.1
// Copyright (c) 2003 by CodeThat.Com
// http://www.codethat.com/

function Undef (o) { return typeof(o) == 'undefined' || o === '' || o == null }
function Def (o) { return !Undef(o) }
function Und (o) { return typeof(o) == 'undefined' }

/*
Object that represents the user-agent abilities
and partially the user-agent name/version.
*/
function UA () {
	var n = navigator.userAgent.toLowerCase(), v = parseInt(navigator.appVersion)
	var ns = navigator.appName == "Netscape";
	this.DOM = document.getElementById ? true : false; //DOM1+ browser (MSIE 5+, Netscape 6/Mozilla, Opera 5+)
//	this.opera = this.opera5 = window.opera && this.DOM; //Opera 5+
//	this.opera6 = this.opera && window.print; //Opera 6+
	this.opera = n.indexOf('opera') != -1;
	this.opera5 = n.indexOf("opera 5") > 0 || n.indexOf("opera/5") >= 0; //Opera 5
	this.opera6 = n.indexOf("opera 6") > 0 || n.indexOf("opera/6") >= 0; //Opera 6
	this.opera7 = n.indexOf("opera 7") > 0 || n.indexOf("opera/7") >= 0; //Opera 7
	this.oldOpera = this.opera5 || this.opera6; //only supported old versions
	this.ie3down = n.indexOf('msie') != -1 && v < 4 && !this.opera;
	this.ie4up = !this.ie3down && document.all && document.all.item && !this.opera; //MSIE 4+
	this.ie5up = this.DOM && this.ie4up; //MSIE 5+
	this.ie6 = this.ie5up && n.indexOf('msie 6.') > 0;
	this.ie = this.ie4up || this.ie5up; //identifies only supported versions
//	this.nn4 = document.layers; //Netscape 4.*
	this.nn4 = ns && !this.DOM && !this.opera;
	this.moz = this.nn6up = this.DOM && ns && !this.opera; //Mozilla or Netscape 6+
	this.hj = n.indexOf('hotjava') != -1;
	this.aol = n.indexOf('aol') != -1;
	this.aol4up = this.aol && this.ie4up;
	this.supp = this.supported = this.oldOpera || this.opera7 || this.ie || this.moz || this.nn4 || this.DOM
}

var ua = new UA();

/*
CEvent
The constructor function that creates an object with
main event properties
Parameters:
	e	: event object
*/
function CEvent (e) {
	this._e = e;
	this.x = ua.nn4 || ua.moz ? e.pageX
		: ua.oldOpera ? e.clientX
		: ua.ie || ua.opera ? e.clientX + document.body.scrollLeft : null;
	this.y = ua.nn4 || ua.moz ? e.pageY
		: ua.oldOpera ? e.clientY
		: ua.ie || ua.opera ? e.clientY + document.body.scrollTop : null;
	this.offsetX = ua.nn4 || ua.moz ? e.layerX : e.offsetX;
	this.offsetY = ua.nn4 || ua.moz ? e.layerY : e.offsetY;
	this.screenX = e.screenX;
	this.screenY = e.screenY;
	this.target = ua.ie ? e.srcElement : e.target;
	this.key = ua.nn4 ? e.which : e.keyCode;
	this.alt = ua.nn4 ? e.modifiers & Event.ALT_MASK : e.altKey;
	this.ctrl = ua.nn4 ? e.modifiers & Event.CONTROL_MASK : e.ctrlKey;
	this.shift = ua.nn4 ? e.modifiers & Event.SHIFT_MASK : e.shiftKey;
	this.spec = this.alt || this.ctrl || this.shift;
	var b = ua.nn4 || ua.moz ? e.which : e.button;
	this.b_left = b == 1;
	this.b_mid = ua.nn4 || ua.moz ? b == 2 : b == 4;
	this.b_right = ua.nn4 || ua.moz ? b == 3 : b == 2
}

/*
CTimer
constructor function that creates timer events
Parameters:
oPar		: parent object that must share getObjPath and sig_stop methods
id		: id used by the parent to identify object
sig	(bool)	: if true, the sig_stop method is called for parent
oSend		: object to call onTimer() method
n		: number of times to call onTimer
pause		: interval between onTimer calls
scr_bef		: script to evaluate before timer starts
scr_betw	: script to evaluate every step
scr_aft		: script to evaluate after timer ends
*/
function CTimer (oPar, id, sig, oSend, n, pause, scr_bef, scr_betw, scr_aft) {
	this._par = oPar;
	this._id = id;
	this._sig = sig;
	this._o = oSend;
	this._n = n;
	this._pause = pause || 100;
	this._scr = [scr_bef, scr_betw, scr_aft];
}

{//to avoid window variables definition

var CTp = CTimer.prototype;

CTp.run = function () {
	if (Undef(this._o)) return;
	this._i = 0;
	if (Def(this._scr[0])) eval(this._scr[0]);
	this._to = setTimeout(this+'.step()', this._pause);
};

CTp.step = function () {
	with (this) {
		if (this._o) _o.onTimer();
		if (Def(this._scr[1])) eval(_scr[1]);
		_i++;
		if (_i < _n)
			this._to = setTimeout(this+'.step()', _pause);
		else
			finish()
	}
};

CTp.stop = function () {
	clearTimeout(this._to);
	this.finish()
};

CTp.finish = function () {
	if (Def(this._scr[2])) eval(this._scr[2]);
	if (this._sig)
		this._par.sig_stop(this._id)
};

CTp.toString = function () {
	return this._par.getObjPath(this._id)
}

}

function CSlideAnimation (oPar, id, sig, oCL, aP, step, pause, scr_bef, scr_betw, scr_aft) {
	var dx, dy, n;
	this.base = CTimer;
	this._l = oCL;
	this._x = oCL.getLeft();
	this._y = oCL.getTop(); 
	dx = aP[0] - this._x;
	dy = aP[1] - this._y;
	n = Math.floor(Math.sqrt(dx*dx + dy*dy)/step);
	this._st_x = dx/n;
	this._st_y = dy/n;
	this.base(oPar, id, sig, this, n, pause, scr_bef, scr_betw, scr_aft)
}

CSlideAnimation.prototype = new CTimer;

CSlideAnimation.prototype.onTimer = function () {
	with (this) {
		_x += _st_x;
		_y += _st_y;
		_l.moveTo(_x, _y)
	}
};

function CClipAnimation (oPar, id, sig, oCL, aP, n, pause, scr_bef, scr_betw, scr_aft) {
	this.base = CTimer;
	this._l = oCL;
	this._c = oCL.getClip();
	this._st_t = (aP[0]-this._c[0])/n;
	this._st_r = (aP[1]-this._c[1])/n;
	this._st_b = (aP[2]-this._c[2])/n;
	this._st_l = (aP[3]-this._c[3])/n;
	this.base(oPar, id, sig, this, n, pause, scr_bef, scr_betw, scr_aft)
}

CClipAnimation.prototype = new CTimer;

CClipAnimation.prototype.onTimer = function () {
	var c = this._c;
	c[3] += this._st_l;
	c[0] += this._st_t;
	c[1] += this._st_r;
	c[2] += this._st_b;
	this._l.clip(c[3], c[0], c[1]-c[3], c[2]-c[0])
};
/*
Function CAniCollection - the constructor function that creates a collection
for manipulating animation objects
Constructor parameters:
	id	: id that is used to identify a collection globally
*/
function CAniCollection (id) {
	this._id = id;
	this._c = 0;
	this._a = [];
	this.slideAni = CSlideAnimation;
	this.clipAni = CClipAnimation;
	this.SLIDE = 'slideAni';
	this.CLIP = 'clipAni'
}

{

var CCp = CAniCollection.prototype;

CCp.add = function (sType, autoDel, oCL, aCoords, nPar, pause, scr_bef, scr_betw, scr_aft) {
	var id = 's'+this._c++;
	var o = new this[sType](this, id, autoDel, oCL, aCoords, nPar, pause, scr_bef, scr_betw, scr_aft);
	this._a[id] = o;
	return id
};

CCp.remove = function (t_id) {
	delete this._a[t_id]
};

CCp.run = function (t_id) {
	if (Undef(this._a[t_id])) return;
	this._a[t_id].run()
};

CCp.stop = function (t_id) {
	if (Undef(this._a[t_id])) return;
	this._a[t_id].stop()
};

CCp.sig_stop = function (t_id) {
	setTimeout(this._id+".remove('"+t_id+"')", 1)
};

CCp.getObjPath = function (t_id) {
	return this._id+'._a.'+t_id
}

}

/*
CCodeThat
constructor function that creates main CodeThat object
Object properties:
	_id	: id to identify the object globally
	_c	: internal count for id creation
	Ani	: collection for animation
*/
function CCodeThat(id) {
	this._id = id;
	this.Ani = new CAniCollection(this._id+'.Ani');
	this._c = 0;
	this.pre = {}; //list of preloaded images
	this.sz = []; //list of onload handlers
	this.ld = [] //list of onresize handlers
/*	this.debug = window.open('','DEBUG');
	this.debug.document.write('<HTML><BODY><PRE><BR>'); */
}

{

var CTp = CCodeThat.prototype;
/*
CTp.debugtxt = function (text) {
	this.debug.document.writeln(text)
}
*/
/*
Function findLayer
Finds and returns the LAYER/DIV object by name or name/parent pair
Parameters
	name	: the name of the layer to find
	parent	: the parent layer object (important for NN)
Returns		: reference to the layer object
*/
CTp.findLayer = function(name, parent) {
	return this.findElement(name, parent)
};

/*
Function findElement
Finds and returns the object by name or name/parent pair
Parameters
	name	: the name of the object to find
	parent	: the parent layer object (important for NN)
Returns		: reference to the layer object
*/
CTp.findElement = function (name, parent) {
	if (ua.DOM)
		return document.getElementById(name);
	else if (ua.ie4up)		
		return document.all[name];
	else {
		var set = Undef(parent) ? document : parent.document;
		if (Undef(set[name]))
		{
			var i, el, len = set.layers.length;
			if (len == 0) return
			else {
				for (i=0; i<len; i++)
				{
					el = this.findElement(name, set.layers[i]);
					if (Def(el)) return el;
				}
			}
		} else return set[name];
	}
};

/*
Function regEventHandler
Sets the event handler
Parameters:
	e	: string that represents an event ("click", "mousemove", "dblclick", "mouseover" etc.)
	h	: reference to the function that handles the event or the code string (the event object is referenced as 'ev')
	obj	: the object to register the handler for (if omitted, the document object is used)
*/

CTp.regEventHandler = function (e, h, obj) {
	if (Undef(obj)) obj = document;
	e = e.toLowerCase();
	if (ua.nn4) {
		var name = e.toUpperCase();
		obj.captureEvents(Event[name]);
	}
	var f = typeof(h) == "function" ?
			function (e) { var ev = ua.nn4 || ua.moz ? e : window.event; if (Def(ev)) ev = new CEvent(ev); return h(ev) } :
			typeof(h) == "string" ?
				new Function("e", "var ev=ua.nn4||ua.moz?e:window.event;if (Def(ev)) ev=new CEvent(ev);"+h) :
				null;
/*	if (ua.DOM && Def(obj.addEventListener))
		obj.addEventListener(e, f, false)
	else*/
		obj["on"+e] = f;
};

CTp.clearEventHandler = function (e, obj) {
	if (Undef(obj)) obj = document;
	e = e.toLowerCase();
	if (ua.nn4) {
		var name = e.toUpperCase();
		obj.releaseEvents(Event[name]);
	}
/*	if (ua.DOM && Def(obj.removeEventListener))
		obj.removeEventListener(e,obj["on"+e],false)
	else */obj["on"+e] = null;
};

/*
Function setResizeHandler
sets the resize handler
Parameters:
	h	: function object, the resize event handler, when called,
			the new size of the window is passed to it as (x,y)
	b	: boolean that specifies whether to set the onload event
			(intended to properly set the resize handler for old Operas),
			if true, the onload event is NOT set, and the resize handler
			begins to work instantly
*/

CTp.setResizeHandler = CTp.setOnResize = function (h, b) {
	var s = this.sz, id = this._id;
	if (!s.length) {
		if (ua.oldOpera) {
			var _h = new Function(id+".saveWinSize();"+id+".checkSize()");
			b ? _h() : this.setOnLoad(_h)
		} else {
			s[0] = window.onresize;
			window.onresize = new Function(id + '.onresize()')
		}
	}
	s[s.length] = h
};

CTp.setOnLoad = function (h) {
	var l = this.ld;
	if (!l.length) {
		l[0] = window.onload;
		window.onload = new Function(this._id + '.onload()')
	}
	l[l.length] = h
};

CTp.checkSize = function () {
	if (this.getWinHeight() != this._oldWH || this.getWinWidth() != this._oldWW) {
		this.saveWinSize();
		this.onresize()
	}
	this._resTO = setTimeout(this._id+'.checkSize()', 2000)
};

CTp.call = function (a) {
	for (var i=a.length-1;i>=0;i--)
		if (Def(a[i])) a[i]()
};

CTp.onload = function () {
	this.call(this.ld)
};

CTp.onresize = function () {
	this.call(this.sz)
};

CTp.saveWinSize = function () {
	this._oldWH = this.getWinHeight();
	this._oldWW = this.getWinWidth()
};

CTp.getWinHeight = function () { return ua.ie4up ? document.body.clientHeight : self.innerHeight };
CTp.getWinWidth = function () { return ua.ie4up ? document.body.clientWidth : self.innerWidth };

/*
Function cancelEvent
Cancels the event
Parameters:
	e	: CEvent object
*/
CTp.cancelEvent = function (e) {
/*	if (ua.DOM) e._e.preventDefault()
	else */if (!ua.nn4) e._e.cancelBubble = true
};

CTp.newID = function () {
	return 'CodeThat'+this._c++
};

CTp.readCookie = function (name) {
	var CookieString = document.cookie;
	var CookieSet = CookieString.split (';');
	var SetSize = CookieSet.length;
	var CookiePieces;
	var ReturnValue = "";
	var x = 0;

	for (x = 0; x < SetSize && ReturnValue == ""; x++) {
		CookiePieces = CookieSet[x].split ('=');
		if (CookiePieces[0].substring (0,1) == ' ') {
			CookiePieces[0] = CookiePieces[0].substring (1, CookiePieces[0].length);
		}

		if (CookiePieces[0] == name) {
			ReturnValue = CookiePieces[1];
		}
	}
	return ReturnValue
};

CTp.writeCookie = function (name, val, exp) {
	var expDate = new Date();
	if(exp) {
		expDate.setTime (expDate.getTime() + exp);
		document.cookie = name + "=" + val + "; expires=" + expDate.toGMTString();
	} else {
		document.cookie = name + "=" + val;
	}
};

/* CTp.preload = function () {
	var i, im = [], a = arguments;
	for(i=0; i<a.length; i++) {
		im[i] = new Image();
		im[i].src = a[i]
	}
	return a.length == 1 ? im[0] : im
}*/

CTp./*smart*/preload = function () {
	var i, im = [], a = arguments;
	for(i=0; i<a.length; i++) {
		if (Undef(a[i]))
			im[i] = null
		else if (Def(this.pre[a[i]]))
			im[i] = this.pre[a[i]]
		else {
			im[i] = new Image();
			im[i].src = a[i];
			this.pre[a[i]] = im[i]
		}
	}
	return a.length == 1 ? im[0] : im
}

}

//create global window.CodeThat object
var CodeThat = new CCodeThat('CodeThat');/*
CLayer
The constructor function that creates a layer representation
Constructor parameters
1st way:	int, int	: width, height	: layer's width and height
2nd way:	string		: id		: layer's id (this must be a string),
						if the page has been loaded, it's used to find the layer in the document
3rd way:	w/o parameters	: 		: an empty layer object will be created
Returns		: none

Layer's properties:
_lr		: LAYER/DIV object
_st		: layer's style object
_id		: id that is used to find the layer in the document
_classID	: CSS class ID
_w		: width of the layer (in pixels)
_h		: height of the layer (in pixels)
_top		: top-left corner Y coordinate
_left		: top-left corner X coordinate
_rel	(bool)	: if true, then relative positioning
_HTML		: layer's content
_clip	(array)	: clipping layer's area [top, right, bottom, left]
_bgColor	: background color
_bgImg		: background image
_z		: z-index
_alpha		: transparence level (0-100)
_visible (bool)	: visibility
_cursor		: cursor style
_ex (bool)	: specifies if a layer has been created in the document or not
_ev (array) : specifies the list of assigned event handlers
*/
function CLayer () {
	var a = arguments;
	this._ex = false;
	if (a.length == 2 && typeof(a[0]) == 'number') //width and height
	{
		this._w = parseInt(a[0]);
		this._h = parseInt(a[1])
	}
	else if (a.length >= 1 && typeof(a[0]) == 'string') //object's id
		this.assignLayer(CodeThat.findLayer(a[0], a[1]))
	this._id = this._id || CodeThat.newID();
	this._HTML = '';
	this._ev = [];
}

{

var CLp = CLayer.prototype;

CLp.assignLayer = function (oLayer) {
	if (Undef(oLayer)) oLayer = this._id;
	if (typeof(oLayer) == 'string') oLayer = CodeThat.findLayer(oLayer);
	this._lr = oLayer;
	this._st = this._lr.style || this._lr;
	this._ex = true;
	this.getID();
};

CLp.setHTML = function (sHTML) {
	this._HTML = sHTML;
	if (this._ex) {
		if (ua.nn4) {
			var d = this._lr.document;
			d.open();
			d.write(sHTML);
			d.close()
		} else if (!ua.oldOpera)
			this._lr.innerHTML = sHTML;
	}
};

CLp.appendHTML = function (sHTML) {
	this.setHTML(this._HTML+sHTML);
}

CLp.clear = function () {
	this.setHTML('')
};

CLp.setVisible = function (vis) {
	this._visible = vis;
	if (this._ex)
		this._st.visibility = vis ? ua.nn4 ? "show" : "visible" : ua.nn4 ? "hide" : "hidden"
};

CLp.show = function () {
	this.setVisible(true)
};

CLp.hide = function () {
	this.setVisible(false)
};

CLp.showAt = function (x,y) {
	this.moveTo(x,y);
	this.show()
};

CLp.setZIndex = function (zindex) {
	this._z = zindex;
	if (this._ex)
		this._st.zIndex = zindex
};

CLp.setWidth = function (width) {
	this._w = width;
	if (this._ex) {
		var h = this._h || this.getHeight();
		if (ua.nn4) {
			this._lr.resizeTo(this._w, h)
			this._st.clip.width = this._w
		}
		else if (ua.opera) this._st.pixelWidth = this._w
		else this._st.width = this._w
		if (!ua.nn4 && !this._clip)
			this._st.clip = "rect(0px "+this._w+"px "+h+"px 0px)"
	}
};

CLp.setHeight = function (height) {
	this._h = height;
	if (this._ex) {
		var w = this._w || this.getWidth();
		if (ua.nn4) {
			this._lr.resizeTo(w, this._h);
			this._st.clip.height = this._h
		}
		else if (ua.opera) this._st.pixelHeight = this._h
		else this._st.height = this._h;
		if (!ua.nn4 && !this._clip)
			this._st.clip = "rect(0px "+w+"px "+this._h+"px 0px)"
	}
};

CLp.resize = CLp.setSize = function (width, height) {
	this._h = height;
	this._w = width;
	if (this._ex) {
		this.setHeight(height);
		this.setWidth(width);
	}
};

CLp.setTop = function (y) {
	this._top = y;
	if (this._ex) {
		if (ua.nn4) this._st.y = y
		else if (ua.opera) this._st.pixelTop = y
		else this._st.top = y;
	}
};

CLp.setLeft = function (x) {
	this._left = x;
	if (this._ex) {
		if (ua.nn4) this._st.x = x
		else if (ua.opera) this._st.pixelLeft = x
		else this._st.left = x
	}
};

CLp.moveTo = CLp.setPos = function (x,y) {
	this._left = x; this._top = y;
	if (this._ex) {
		if (ua.nn4) this._lr.moveTo(x,y)
		else {
			this.setTop(y);
			this.setLeft(x)
		}
	}
};

CLp.setRel = function (rel) {
	if (!this._ex)
		this._rel = rel;
}

CLp.moveRel = function (dx,dy) {
	this.moveTo(this.getLeft()+dx, this.getTop()+dy)
};

CLp.slide = function (x, y, step, time, scr_bef, scr_betw, scr_aft) {
	var s = CodeThat.Ani.add(CodeThat.Ani.SLIDE, true, this, [x, y], step, time, scr_bef, scr_betw, scr_aft);
	CodeThat.Ani.run(s);
};

CLp.slideRel = function (dx, dy, step, time, scr_bef, scr_betw, scr_aft) {
	var s = CodeThat.Ani.add(CodeThat.Ani.SLIDE, true, this, [this.getLeft()+dx, this.getTop()+dy], step, time, scr_bef, scr_betw, scr_aft);
	CodeThat.Ani.run(s);
};

CLp.setCSS = function (classID) {
	this._classID = classID;
	if (this._ex && !(ua.oldOpera || ua.nn4))
		this._lr.className = classID
};

CLp.setID = function (id) {
	if (!this._ex)
		this._id = id || CodeThat.newID();
};

CLp.setBgColor = function (color) {
	this._bgColor = color;
	if (this._ex) {
		if (ua.ie || ua.moz || ua.opera7) this._st.backgroundColor = color
		else if (ua.nn4) this._st.bgColor = color
		else if (ua.opera) this._st.background = color
	}
};

CLp.setBgImage = function (url) {
	this._bgImg = url;
	if (this._ex) {
		if (ua.ie || ua.moz || ua.opera7) this._st.backgroundImage = 'url('+url+')'
		else if (ua.nn4 || ua.opera) this._st.background.src = url
	}
};
/*
CLp.setCursor = function (cursor) {
	this._cursor = cursor || "default";
	if (this._ex && (!ua.oldOpera || ua.NN4))
		this._lr.cursor = this._cursor
};
*/
CLp.clip = function (x, y, width, height) {
	this._clip = [y, x+width, y+height, x];
	if (this._ex && this._clip) {
		if (ua.nn4) {
			var area = this._st.clip;
			area.top = y;
			area.left = x;
			area.width = width;
			area.height = height;
		} else if (ua.ie || ua.moz || ua.opera7) {
			this._st.clip = 'rect('+this._clip[0]+'px '+this._clip[1]+'px '+this._clip[2]+'px '+this._clip[3]+'px)';
		}
	}
};

CLp.noclip = function () {
	delete this._clip;
	if (this._ex) {
		if (ua.nn4) {
			var area = this._st.clip;
			area.top = 0;
			area.left = 0;
			area.width = this.getWidth();
			area.height = this.getHeight();
		} else if (ua.ie || ua.moz || ua.opera7)
			this._st.clip = 'rect(auto auto auto auto)';
	}
}

CLp.clipSlide = function (l, t, r, b, n, time, scr_bef, scr_betw, scr_aft) {
	var s = CodeThat.Ani.add(CodeThat.Ani.CLIP, true, this, [t, r, b, l], n, time, scr_bef, scr_betw, scr_aft);
	CodeThat.Ani.run(s);
};

CLp.clipMove = function (l, t, n, time, scr_bef, scr_betw, scr_aft) {
	var c = this.getClip();
	var dx = l-c[3], dy = t-c[0];
	var s = CodeThat.Ani.add(CodeThat.Ani.CLIP, true, this, [t, c[1]+dx, c[2]+dy, l], n, time, scr_bef, scr_betw, scr_aft);
	CodeThat.Ani.run(s);
};

CLp.addEventHandler = function(evt, code) {
	if (this._ex) return;
	var e = this._ev;
	e[e.length] = [evt, code];
};

CLp.setTransparence = CLp.setAlpha = function (a) {
	this._alpha = a;
	if (this._ex && this.ie)
		this._st.filter = 'Alpha(Opacity="'+this._alpha+'")'
};

CLp.object = function () { return this._lr };

CLp.getHTML = function () { return this._HTML };

CLp.getVisible = function () {
	if (this._ex) {
		var v = this._st.visibility;
                this._visible = Def(v) ? v == "show" || v == "visible" : v;
	}
	return this._visible
};

CLp.getZIndex = function () {
	if (this._ex)
		this._z = this._st.zindex;
	return this._z
};

CLp.getWidth = function () {
	if (this._ex) {
		if (ua.nn4) {
			if (Undef(this._w))
				this._w = this._lr.document.width
		} else this._w = ua.oldOpera ? this._st.pixelWidth : this._lr.offsetWidth;
	}
	return this._w
};

CLp.getHeight = function () {
	if (this._ex) {
		if (ua.nn4) {
			if (Undef(this._h))
				this._h = this._lr.document.height
		} else this._h = ua.oldOpera ? this._st.pixelHeight : this._lr.offsetHeight;
	}
	return this._h
};

CLp.getSize = function () {
	return [this.getWidth(), this.getHeight()]
};

//call only if width property has not been set yet (quick solution)
CLp.getContentWidth = function () {
	return this._ex ?
		ua.nn4 ? this._lr.document.width :
		ua.oldOpera ? this._st.pixelWidth :
		ua.ie ? this._lr.scrollWidth :
			this._lr.offsetWidth :
		this._w
}

//call only if height property has not been set yet (quick solution)
CLp.getContentHeight = function () {
	return this._ex ?
		ua.nn4 ? this._lr.document.height :
		ua.oldOpera ? this._st.pixelHeight :
		ua.ie ? this._lr.scrollHeight :
			this._lr.offsetHeight :
		this._h
}

CLp.getTop = function () { //relative to the parent element
	if (this._ex)
		this._top = ua.nn4 ? this._st.y : this._lr.offsetTop
	return this._top
};

CLp.getLeft = function () { //relative to the parent element
	if (this._ex)
		this._left = ua.nn4 ? this._st.x : this._lr.offsetLeft
	return this._left
};

CLp.getPos = function () {
	return [this.getLeft(), this.getTop()]
};

CLp.getAbsoluteTop = function () { //relative to the main document
	if (this._ex) {
		if (ua.nn4) return this._st.pageY
		else {
			var t = 0; var o = this._lr;
			do {
				t += o.offsetTop
			} while (Def(o = o.offsetParent));
			return t
		}
	}
	else return this._top
};

CLp.getAbsoluteLeft = function () { //relative to the main document
	if (this._ex) {
		if (ua.nn4) return this._st.pageX
		else {
			var l = 0; var o = this._lr;
			do {
				l += o.offsetLeft
			} while (Def(o = o.offsetParent));
			return l
		}
	}
	else return this._left
};

CLp.getAbsolutePos = function () { //relative to the main document
	return [this.getAbsoluteLeft(), this.getAbsoluteTop()]
};

CLp.getCSS = function () {
	if (this._ex && !(ua.oldOpera || ua.nn4))
		this._classID = this._lr.className;
	return this._classID
};

CLp.getClip = function () {
	var c = this._clip;
	if (this._ex && Undef(c))
	{
		var cl = this._st.clip;
		if (cl) {
			if (ua.nn4) {
				c[0] = cl.top || 0;
				c[1] = cl.right || this.getWidth();
				c[2] = cl.bottom || this.getHeight();
				c[3] = cl.left || 0;
			} else {
				var n1, n2 = cl.indexOf('(');
				n1 = cl.indexOf(' ', n2);
				c[0] = parseInt(cl.substring(n2+1, n1));
				n2 = cl.indexOf(' ', n1);
				c[1] = parseInt(cl.substring(n1+1, n2));
				n1 = cl.indexOf(' ', n2);
				c[2] = parseInt(cl.substring(n2+1, n1));
				c[3] = parseInt(cl.substr(n1+1));
			}
		}
	}
	return c;
}

CLp.getID = function (id) {
	if (this._ex)
		this._id = this._lr.id;
	return this._id
};

CLp.getSource = function () {
	var src = '';
	var c, t = this;
	if (Def(t._clip)) c = t._clip
	else if (Def(t._h) && Def(t._w))
		c = [0, t._w, t._h, 0];
	var l = t._left; if (!t._rel && !l) l=0;
	var tp = t._top; if (!t._rel && !t) t=0;
	if (ua.nn4) {
		src = (t._rel ? "<ilayer" : "<layer")+ (Def(t._id) ? " id="+t._id : "") +
			(Def(t)?" top="+tp:"") + (Def(l)?" left="+l:"") +
			(Def(t._w) ? " width="+t._w : "") +
			(Def(t._classID) ? " class="+t._classID : "") + (Def(t._z) ? " z-index="+t._z : "") +
			' visibility=' + (t._visible ? "inherit" : "hide") +
			(c  ? ' clip="'+ c[3]+','+c[0]+','+c[1]+','+c[2]+'"' : "") +
			(Def(t._bgColor) ? " bgcolor="+t._bgColor : "") +
			(Def(t._bgImg) ? ' background="'+t._bgImg+'"' : "");
	} else {
		src = "<div" + (Def(t._id) ? " id="+t._id : "") +
			(Def(t._classID) ? " class="+t._classID : "")+
			' style="position:'+(t._rel?'relative':'absolute')+';overflow:hidden'+ ';visibility:'+(!t._visible ? 'hidden':'inherit') +
			(Def(t) ? ";top:"+tp+"px" : "") +(Def(l) ? ";left:"+l+"px" : "") +
			(Def(t._w) ? ";width:"+t._w+"px" : "") + (Def(t._h) ? ";height:"+t._h+"px" : "") +
			(Def(t._z) ? ";z-index:"+t._z : "") +
			(Def(t._bgColor) ? ";background-color:"+t._bgColor : "") +
			(Def(t._bgImg) ? ";background-image:url("+t._bgImg+")" : "") +
//			(Def(t._cursor) ? ";cursor:"+t._cursor : "") + 
			(c ? ";clip:rect("+c[0]+"px "+c[1]+"px "+c[2]+"px "+c[3]+"px)" : "")+
			(Def(t._alpha) && ua.ie4up ? ';filter:Alpha(Opacity='+t._alpha+')':'')+ '"';
	}
	var e = t._ev;
	for (var i=0; i<e.length; i++)
		src += ' '+ e[i][0] + '="' + e[i][1] + '"';
	src +=	">" + t.getHTML() + '</'+(ua.nn4 ? (t._rel?'i':'')+"layer>" : "div>");
	return src
};

CLp.create = function () { //for now only on page-creation stage (restricted by Opera5/6)
	if (this._ex) return;
	document.write(this.getSource());
//	this.assignLayer(CodeThat.findLayer(this._id));
	this.assignLayer();
};

}/*
CNode
The object represents XML node

Node's properties:
type		: String representing node type. May be "ELEMENT", "DOCUMENT",
"PARAMETER", "CHARDATA"
name            : String node name is used only for elements and parameters
parent		: Parent node object. For document it is set to null.
parameters	: Array with parameters (attributes) for node. Used only for
elements.
subitems	: Array with subnodes. Used only for elements.
value		: String with node value. Used for parameters and character data nodes.
*/
function CNode(type, name, parent) {
	this.type = type;
	this.name = name;
	this.parent = parent;
	this.parameters = new Array();
	this.subitems = new Array();
	this.value = new String();

}

{
var CNp = CNode.prototype;

CNp.getParameter = function (name) { // Returns parameter value
	// Try to find parameter with given name
	for(var i = 0;i<this.parameters.length;++i) {
		if(this.parameters[i].name == name) {
			return this.parameters[i].value;
		}
	}
	return null;
};

CNp.getValue = function () { // Returns self value
	return this.value;
};
}

/*
CXMLTree
object that represents the XML tree document

Properties:
str 		: XML tree string
tree		: XML root node
*/
function CXMLTree (str) {
	this.str = str;
	this.tree = new CNode("DOCUMENT","",null);
	this.parse(this.str,0,this.tree);
}

{
CXp = CXMLTree.prototype;

CXp.parse = function (s,begin,tag) {
	var close = false;
	var index = begin;

	// Is str a valid string?
	if(typeof(s)!="string" || s==null) {
		//Error!
		return null;
	}

	while(!close)
	{

		// Find something after whitespaces
		index = this.skipWhitespaces(s,index);
		// Exit loop at end of the string
		if(index > s.length-1) {
			break;
		}
		// Is it a start of a new tag?
		if(s.charAt(index)=='<') {
			++index;
			// Is it a processing instruction or document type?
			if(s.charAt(index)=='?') {
				index = s.indexOf('>',index) + 1;
				// Just ignore...

			}
			else
			// Is it a close tag?
			if(s.charAt(index)=='/') {
				//Set close tag.
				close = true;
				//We may check the closing tag here, but it is neccessory.
				index = s.indexOf('>',index) + 1;

			}
			else
			// Is it a comment?
			if(s.substr(index,3)=='!--') {
				index = s.indexOf('-->',index) + 3;
			}
			else
			// Is it a char data?
			if(s.substr(index,8)=='![CDATA[') {
				index+=8;
				// This is character data
				var end = s.indexOf(']]>',index);
				// Add char node to current node
				var charnode = new CNode("CHARDATA","",tag)
				charnode.value = s.substr(index, end - index);
				tag.subitems[tag.subitems.length] = charnode;
				index = end+3;

			}
			else
			// Is it a doctype or something else?
			if(s.charAt(index)=='!') {
				index = s.indexOf('>',index) + 1;
				// Just ignore...

			}
			else {
				// This is probably a simple tag
				var tagname = this.getCharname(s,index);
				// Is it a valid tag name?
				if(tagname==null || tagname.length==0) {
					// Error!
					return null;
				}
				else {
					index+=tagname.length;
			                index = this.skipWhitespaces(s,index);

					var newtag = new CNode("ELEMENT",tagname,tag)
					// While not and of tag process parameters
					while(s.charAt(index)!='/'&&s.charAt(index)!='>') {


						var paramname = this.getCharname(s,index);
						var param = new CNode("PARAMETER",paramname,newtag);
						newtag.parameters[newtag.parameters.length] = param;
						index+=paramname.length;

						index = this.skipWhitespaces(s,index);
						// Expect '=' here
						if(s.charAt(index)!='=') {
							// Error!
						}
						++index;
						index = this.skipWhitespaces(s,index);
						// Expect '"' here
						if(s.charAt(index)!='\"') {
							// Error!
						}
						++index;
						var paramend = s.indexOf("\"",index);
						param.value = this.processValue(s.substr(index, paramend - index));
						index = this.skipWhitespaces(s,paramend + 1);


					}

					tag.subitems[tag.subitems.length] = newtag;
					//Go to the end of the tag
					index = s.indexOf('>',index) + 1;
					// Is it a close tag?
					if(s.charAt(index-2)=='/') {
						// Yes just go ahead

					}
					else {
						// No, we should handle tag body recursively
						index = this.parse(s,index,newtag);
					}
				}

			}
		}
		else {
			// This is probably character data
			var end = s.indexOf('<',index);
			// Add char node to current node
			var charnode = new CNode("CHARDATA","",tag)
			charnode.value = this.processValue(s.substr(index, end - index));
			tag.subitems[tag.subitems.length] = charnode;
			index = end;
		}
	}
	return index;
}

CXp.skipWhitespaces = function (str,begin) {
	var i = begin;
	// Loop while we have whitespace
	while(	i<str.length &&
		(str.charAt(i)=='\n'
		||str.charAt(i)=='\r'
		||str.charAt(i)=='\t'
		||str.charAt(i)==' '))
		++i;
	return i;
}
CXp.getCharname = function (str,begin) {
	var i = begin;
	// Loop while we have whitespace
	while(	i<str.length &&
		!(str.charAt(i)=='\n'
		||str.charAt(i)=='\r'
		||str.charAt(i)=='\"'
		||str.charAt(i)=='\''
		||str.charAt(i)=='\t'
		||str.charAt(i)=='/'
		||str.charAt(i)=='>'
		||str.charAt(i)=='<'
		||str.charAt(i)=='='
		||str.charAt(i)==' '))
		++i;
	return str.substr(begin,i-begin);
}
CXp.processValue = function (str) {
	// Replace standart entities
	var arraytmp = new Array();
	arraytmp = str.split("&lt;");
	str = arraytmp.join("<");
	arraytmp = str.split("&gt;");
	str = arraytmp.join(">");
	arraytmp = str.split("&quot;");
	str = arraytmp.join("\"");
	arraytmp = str.split("&apos;");
	str = arraytmp.join("\'");
	arraytmp = str.split("&amp;");
	str = arraytmp.join("&");
	return str;

}

/*
Method toObject
Converts document structure to object structure

Call parameters: none
Returns: object structure representing XML document.
Example:
<menu type="tree">
	<style>
		<border>
			<width>3</width>
			<color>black</color>
		</border>
	</style>
	<item>Item1</item>
	<item><text>Item2</text></item>
</menu>

will be converted to this object:
{ 
"menu" :{
	"type":"tree",
	"style": { "border":{ "width":"3", "color":"black" } },
	"item":["Item1",{"text":"Item2"}]
}
}
*/
CXp.toObject = function (node) {
	node = node || this.tree;
        var i, o;
	if (node.parameters.length==0 && node.subitems.length==1 && node.subitems[0].type == 'CHARDATA')
		o = node.subitems[0].value
	else	{
		o = {};
		for(i=0;i<node.parameters.length;++i) {
			var par = node.parameters[i];
			o[par.name] = par.value
		}
		for(i=0;i<node.subitems.length;++i) {
			var val, it = node.subitems[i];
			if (it.type == 'CHARDATA')
				o.__value = it.value
			else {
				val = this.toObject(it);
				if (Undef(o[it.name]))
					o[it.name] = val
				else {
					if (o[it.name].constructor != Array)
						o[it.name] = [o[it.name]]; //make array
					o[it.name][o[it.name].length] = val //push is not available up to MSIE 5.5
				}
			}
		}
	}
	return o;
}

}
