var DHTML = new function() {
	this.ie = (navigator.userAgent.toLowerCase().indexOf('msie') > -1);
	this.ie6 = (navigator.userAgent.toLowerCase().indexOf('msie 6') > -1);
	this.get = this.bind = function(e) { 
		if (!e) return null;
		if (!(e = DOM.get(e))) return null;

		OO.apply(e, this.Base);
		
		for (var superClass,index = 1;(superClass = arguments[index]);index++) {
			e.inherit(superClass);
		}
		
		e.ooInitSelf(e);
		return e;
	}

	this.clientHeight = function() { return document.documentElement.clientHeight||window.innerHeight; }
	this.clientWidth = function() { return document.documentElement.clientWidth||window.innerWidth; }
	this.hasParent = function(e) { return ((e.parentNode != null) && (e.offsetParent != null)); }
	this.hasParentIE = function(e) { return ((e.parentElement != null) && (e.offsetParent != null)); }
	if (this.ie) this.hasParent = this.hasParentIE;
		
	this.X = this.divX = function(e, x) { res = (this.hasParent(e))?e.offsetLeft - e.offsetParent.scrollLeft:0; if (UTIL.def(x)) DHTML.setLeft(e, x); return res;}
	this.Y = this.divY = function(e, y) { res = (this.hasParent(e))?e.offsetTop - e.offsetParent.scrollTop:0; if (UTIL.def(y)) DHTML.setTop(e, y); return res;}
	this.getWidth = function(e) { return parseInt(e.offsetWidth, 10); }
	this.getHeight = function(e) { return parseInt(e.offsetHeight, 10); }
	this.setWidth = function(e, w) { e.style.width = Math.max(w, 0)+'px'; }
	this.setHeight = function(e, h) { e.style.height = Math.max(h, 0)+'px'; }
	this.hide = function(e) { e.style.visibility='hidden'; }
	this.show = function(e) { e.style.visibility='visible'; }
	this._path = function(start, end, time, period) {
		period = period || 25;
		var time = Math.ceil(time / period);
		var period = Math.PI / (2 * time);
		var result = [];
		end -= start;
		for (var index = 0; index <= time; index++) { result.push(Math.round(end * Math.sin(period * index) + start)); }
		return result;
	}
	
	var div = document.createElement('div');
	
	if (U.def(div.style.pixelLeft)) { 
		this.setLeft = function(e, x) { e.style.right = null; e.style.pixelLeft = x; };
		this.setRight = function(e, x) { e.style.left = null; e.style.pixelRight = x; };
		this.setTop = function(e, y) { e.style.bottom = null; e.style.pixelTop = y; };
		this.setBottom = function(e, y) { e.style.top = null; e.style.pixelBottom = y; };
	} else if (U.def(div.style.left)) {
		this.setLeft = function(e, x) { delete e.style.right; e.style.left = x+'px'; };
		this.setRight = function(e, x) { delete e.style.left; e.style.right = x+'px'; };
		this.setTop = function(e, y) { delete e.style.bottom; e.style.top = y+'px'; };
		this.setBottom = function(e, y) { delete e.style.top; e.style.bottom = y+'px'; };
	}
}

DHTML.Base = function() {
	
	this.Base = { o: 100 };
}


DHTML.Base.prototype = {
	divX: function(x) { return DHTML.divX(this, x); },
	divY: function(y) { return DHTML.divY(this, y);  },
	
	initSelf: function() {
		var oThis = this;
		this.setLeft = function(x) { DHTML.setLeft(oThis, x); };
		this.setRight = function(x) { DHTML.setRight(oThis, x); };
		this.setTop = function(y) { DHTML.setTop(oThis, y); };
		this.setBottom = function(y) { DHTML.setBottom(oThis, y); };
		this.X = this.divX;
		this.Y = this.divY;
		
		if (UTIL.def(this.style.filter)) this.setOpacity = function(o) { this.Base.o = o; this.style.filter = 'alpha(opacity='+o+')'; };
		else if (UTIL.def(this.style.MozOpacity)) this.setOpacity = function(o) { this.Base.o = o; this.style.MozOpacity = Math.min(o / 100, 0.9999); };
		else this.setOpacity = function(o) { this.Base.o = o; this.style.opacity = Math.min(o / 100, 0.9999); };
		
		this.CQ('X,Y,setTop,setBottom,setRight,setLeft,setOpacity');
	},
	
	W: function(w) { r = this.getWidth(); if (U.def(w)) this.setWidth(w); return r; },
	H: function(h) { r = this.getHeight(); if (U.def(h)) this.setHeight(h); return r; },
	
	hScroll: function(l) { result = this.scrollLeft; if (U.def(l)) this.scrollLeft = l; return result; },
	setWidth: function(w) { DHTML.setWidth(this, w); },
	setHeight: function(h) { DHTML.setHeight(this, h); },
	moveTo: function(x, y) { DHTML.moveTo(this, x, y); },
	moveBy: function(x, y) { DHTML.moveBy(this, x, y); },
	sizeTo: function(w, h) { DHTML.sizeTo(this, w, h); },
	setOpacity: function(o) { this.Base.o = o; DHTML.setOpacity(this, o); },

	getWidth: function() { return DHTML.getWidth(this); },
	getHeight: function() { return DHTML.getHeight(this); },
	
	setMargin: function(d, m) { return DHTML.setMargin(this, d, m); },
	setPadding: function(d, p) { return DHTML.setPadding(this, d, p); },

	getOpacity: function() { return this.Base.o; },
	
	fontSize: function(newSize) { var result = parseInt(this.style.fontSize, 10); if (typeof(newSize) != 'undefined') this.style.fontSize = newSize+'px'; return result; },
	
	center: function(h, v, e) { DHTML.center(this, h, v, e); },
	
	pageX: function(r) { return DHTML.pageX(this, r); },
	pageY: function(r) { return DHTML.pageY(this, r); },

	show: function() { DHTML.show(this); },
	hide: function() { DHTML.hide(this); },
	qShow: function() { DHTML.qShow(this); },
	qHide: function() { DHTML.qHide(this); },
	display: function(d) { return DHTML.display(this, d); },
	position: function(p) { return DHTML.position(this, p); },
	zIndex: function(z) { return DHTML.zIndex(this, z); },	

	backgroundImage: function(img) { DHTML.backgroundImage(this, img); },
	backgroundPosition: function(x, y) { DHTML.backgroundPosition(this, x, y) },
	
	classState: function(s, r) { DHTML.classState(this, s, r); },
	
	pagePosition: function() { return DHTML.pagePosition(this); },
	
	containsPoint: function(x, y, t, r, b, l) { return DHTML.containsPoint(this, x, y, t, r, b, l); },
	
	pos: function(s) { var key; for (key in s) this[key](s[key]); },
	matchEle: function(m, o) { DHTML.matchEle(this, m, o); },
	
	nextObject: function() { return DHTML.nextObject(this); },
	previousObject: function() { return DHTML.previousObject(this); },

	removeSelf: function() { DHTML.removeSelf(this); },	
	removeFromParent: function() { DHTML.removeFromParent(this); },	
	clearElement: function() { DHTML.clearElement(this); },	

	disposeSelf: function() { setTimeout(U.FN(DHTML, DHTML.finalCleanup, this), 10); }
}

DHTML.Anim = function() {
	this.Anim = { };
	this.inherit(OO.Timer);
}

DHTML.Anim.prototype = {
	
	initSelf: function() {
		this.animDeferCount = 0;
		this.F = this.fontSize;
		this.SL = this.hScroll;
		this.oX = function(offset) { if (U.def(offset)) { this.divX(this.divX()+offset); if (this._offsetX) this._offsetX(offset); } return 0;};
		this.oY = function(offset) { if (U.def(offset)) { this.divY(this.divY()+offset); if (this._offsetY) this._offsetY(offset); } return 0;};
		this.O = function(o) { r = this.getOpacity(); if (U.def(o)) this.setOpacity(o); return r; };
	},
	
	stopAnimation: function() {
		this.clearTimeout('animate');
		this.clearInterval('animate');
		this.Anim = null;
	},
	
	stopDelay: function() {
		if (!this.Anim.started) {
			this.clearTimeout('animate');
			this.clearInterval('animate');
			this.Anim = null;
		}
	},
	
	animate: function(s, t, d, fn) {
		this.stopAnimation();
		if (d) { this.setTimeout('animate', d, this.animate, s, t, 0, fn); this.animDeferCount++; return; }
		this.Anim = { current: 0, direc: 1, paths: { }, fn: fn };
		var key;
		for (key in s) { 
			this.Anim.paths[key] = DHTML._path(this[key](), s[key], t);  
			if ((key == 'oX') || (key == 'oY')) {
				var total = 0;
				for (index = 0; index < this.Anim.paths[key].length; index++) {
					this.Anim.paths[key][index] -= total;
					total += this.Anim.paths[key][index];
				}
			}
		}
		
		this.setInterval('animate', 25, this._animate);
	},
	
	reverse: function(fn) {
		if (this.Anim) {
			this.Anim.direc = -1;
			this.Anim.fn = fn;
		} else {
			this.stopAnimation();
		}
	},
	
	_animate: function() {
		var val;
		if (!this.Anim) return this.clearInterval('animate');
		this.Anim.started = true;
		for (key in this.Anim.paths) {	
			if (!U.def(val = this.Anim.paths[key][this.Anim.current])) { 
				this.clearInterval('animate');
				if (this.Anim.fn) this.Anim.fn.call(this);
				this.Anim = null;
				return; 
			}
			this[key](val);
		}
		this.Anim.current += this.Anim.direc;
	}
}




var OO = new function() {
	
	this.objectCount = 0;
	
	this.create = function(superClass) {
		var args = [], obj = new OO.Base();
		U.from(arguments, 1, function(i) { args.push(i); } );
		
		obj.inherit(superClass);
		obj.ooInitSelf.apply(obj, args);
	
		return obj;
	}
	
	this.apply = function(obj, fromClass) {
		var args = []; U.from(arguments, 1, function(i) { args.push(i); } );
		
		OO.Base.apply(obj);
		for (key in OO.Base.prototype) obj[key] = OO.Base.prototype[key];
		obj.inherit(fromClass);
		obj.ooInitSelf.apply(obj, args);
	           
		return obj;
	}
	
	this.dispose = function(obj) { if ((obj.ooState != 'deleted') && (obj.ooState != 'deleting')) try { obj.ooDisposeSelf(); } catch(err) { var k,s=[]; if (window.console) for (k in err) s.push(err[k]); if (window.console) { alert('Disposal error: '+s.join(',')); } } return null; }
	this.dispose = function(obj) { if (obj && obj.ooDisposeSelf && (obj.ooState != 'deleted') && (obj.ooState != 'deleting')) obj.ooDisposeSelf(); return null; }
}

OO.Base = function() {
	this.ooState = 'created';
	this.ooInit = [ ];
	this.ooDispose = [ ];
	this.ooSupers = [ OO.Base ];
	this.ooRefs = [];
	this.ooCleanupQ = [];
}

OO.Base.prototype = { 
	ooInitSelf: function() {
		var oThis = this;
		var args = arguments;
	
		this.ooState = 'initialising';
		this.ooInit.forEach( function(fn) { fn.apply(oThis, args); } );
		this.ooState = 'active';
		this.ooIsObject = true;
		this.CQ('CQ,ooInitSelf,ooDisposeSelf,ooSupers,initSelf');
		OO.objectCount++;
	},

	CQ: function() {
		var a,s,i = arguments.length-1;
		if (i>=0) do { 
			a = arguments[i];
			switch (typeof(a)) {
				case 'string'	:	a = a.split(','); while (s=a.pop()) this.ooCleanupQ.push(s); break;
				default			:	this.ooCleanupQ.push(a);
			}
		} while (i--);
	},
	
	CQE: function(list) {
		var a = list.split(',');
		
		for (var i=0,s;(s=a[i]);i++) this.CQ(s, this[s]);
	},
	
	CREF: function(o, r) {
		this.ooRefs.push({o: o, r: r});
	},
	
	ooDisposeSelf: function() {
		if (!this.ooIsObject) return;
		var fn, key, o, cq = this.ooCleanupQ
		
		this.ooState = 'deleting';
		while (fn = this.ooDispose.pop()) fn.apply(this);
		
		if (this._EVENT && this._EVENT.eventList.length) { EVENT.removeEvents.apply(EVENT, this._EVENT.eventList); };
		if (window.EVT && this._hasEVT) EVT.removeObject(this);
		
		for (key in this.prototype) {	try { if (key.CQ) OO.dispose(this[key]); this[key] = null; } catch(e) { }; }
		
		while (cq.length) {
			o = cq.pop();
			if (typeof(o)=='string') this[o] = null;
			else OO.dispose(o)
		}
		while (o = this.ooRefs.pop()) o.o[o.r] = null;
		
		OO.objectCount--;
		
		this.ooState = 'deleted';
	},
	
	inherit: function() {
		var key;
		
		this.ooCleanupQ = this.ooCleanupQ || [];
		for (var superClass,index = 0; (superClass = arguments[index]); index++) {
			if (this.ooSupers.contains(superClass))
				break;
	
			superClass.apply(this);
			for (key in superClass.prototype) {
				this[key] = superClass.prototype[key];
				this[key].ooOwner = superClass;
				this[key].ooFnKey = key;
				this.ooCleanupQ.push(key);
			}
			
			if (superClass.prototype.initSelf) { this.ooInit.push(superClass.prototype.initSelf); }
			if (superClass.prototype.disposeSelf) { this.ooDispose.push(superClass.prototype.disposeSelf); }
			
			this.initSelf = null;
			this.disposeSelf = null;
			this.ooSupers.push(superClass); 
		}
	},
	
	SUPER: function(fArgs) {
		var fn = fArgs.callee, args = [];
		var current = this.ooSupers.indexOf(fn.ooOwner);
		var superFn;
		
		if (current == -1) return;
		
		while (current > 0) {
			if (superFn = this.ooSupers[--current].prototype[fn.ooFnKey]) break; 
		}
		if (!superFn) return;
		
		U.from(arguments, 1, function(i) { args.push(i); } );
		
		return superFn.apply(this, args);
	}
}

OO.Timer = function() {
	this.Timer = { t: { }, i: { } };
}
OO.Timer.prototype = {
	initSelf: function() {
		if (this.timedInit)	this.setTimeout('timedInit', 50, this.timedInit);
	},
	
	disposeSelf: function() {
		var key;
		for (key in this.Timer.t) this.clearTimeout(key);
		for (key in this.Timer.i) this.clearInterval(key);
		
		this.Timer = null;
	},
	
	setTimeout: function(label, period, fn) {
		if (!this.Timer) return;
		var i, oThis = this, args = [];
		if (typeof(fn) == 'string') fn = this[fn];
	
		for (i = 3; i<arguments.length; i++) args.push(arguments[i]);
		this.clearTimeout(label);
		this.Timer.t[label] = setTimeout(function() { if (oThis.Timer) fn.apply (oThis, args); if (oThis.Timer) delete oThis.Timer.t[label]; } , period);
	},
	
	setInterval: function(label, period, fn) {
		var i, oThis = this, args = [];
		if (typeof(fn) == 'string') fn = this[fn];
	
		for (i = 3; i<arguments.length; i++) args.push(arguments[i]);
		this.clearInterval(label);
		this.Timer.i[label] = setInterval(function() { if (oThis.Timer) fn.apply (oThis, args); } , period);
	},
	
	clearTimeout: function(label) {
		if (this.Timer && this.Timer.t[label]) {
			clearTimeout(this.Timer.t[label]);
			delete this.Timer.t[label];
		}
	},
	
	clearInterval: function(label) {
		if (this.Timer.i[label]) {
			clearInterval(this.Timer.i[label]);
			delete this.Timer.i[label];
		}
	}
}