/*************************************************************
* JKow javascript library  
*
* Organization: Universal One (web: http://www.universalone.com.au)
* Author: Uzhiel Bautista (email: uzhiel@universalone.com.au)
* Version: 071211 
*
* This is the first version of the JKow javascript library
* So far it provides objects for:
*   Timer
*   Menus
*   Ajax 
*   DOM ready
*  
*   In the works are: layers and windows
*
*************************************************************/

/****************************** 
* Global namespace 
******************************/
function JKow() {}

JKow.System = {
	browserCheck : function() {},
	browser : ''	
};
JKow.System.browserCheck = function() {
	var result = 'unknown';
	var browsers = {
		'MSIE': { check: function(){ return((navigator.userAgent) && (navigator.userAgent.indexOf('MSIE') != -1)); } },
		'Mozilla': { check: function(){ return((navigator.userAgent) && (navigator.userAgent.indexOf('Gecko') != -1)); } },
		'Safari': { check: function(){ return ((navigator.vendor) && (navigator.vendor.indexOf('Apple') != -1)); } }
	};	
	for (var i in browsers){
		if (browsers[i].check()){
			result =i;
			break;
		}
	}
	return result;
}

/****************************** 
* Initialize system values 
******************************/
function JKow() {}
JKow.System.init = (
	function() { 
		JKow.System.browser = JKow.System.browserCheck();
	}
)();

JKow.DOM = function() {}
JKow.DOM.ContentReadyList = function(){
	this.contentList = [];
	this.checkCount = 0;

	this.addContent = function(elid, fn){
		this.contentList[this.contentList.length] = { 'elid': elid, 'func': fn, 'ready': false };			
	}

	this.checkContent = function(){
		var sender = this;
		for (var i = 0; i < this.contentList.length; ++i){
			++this.checkCount;
			this._checkContent(sender, i);	
		}
	}

	this._checkContent = function(sender, index){
		var _timer = setTimeout(
			function(){
				if ((!sender.contentList[index].ready) && document.getElementById(sender.contentList[index].elid)){
					sender.contentList[index].ready = true;  //mark as ready 
					--sender.checkCount;
					alert(sender.contentList[index].elid + ' ready!');
				} else {
					sender._checkContent(sender, index);
				}

				//test if all ready before execute 
				if (sender.checkCount == 0){
					var $$f = sender.contentList[index].func;
					$$f();
				} else {
					sender._checkContent(sender, index);
				}
			}, 13
		);
	}
}
JKow.DOM.onContentReadyTag = function(tag, fn){
	var _timer = setTimeout(
		function(){
			if(typeof(document.getElementsByTagName(tag)[0]) != 'undefined'){
				clearTimeout(_timer);
				fn();
			} else {
				JKow.DOM.onContentReadyTag(tag, fn);

			}
		}, 10);
}
JKow.DOM.onContentReady = function(element_id, fn){
	var _timer = setTimeout(
		function(){
			if(document.getElementById(element_id)){
				clearTimeout(_timer);
				fn();
			} else {
				JKow.DOM.onContentReady(element_id, fn);

			}
		}, 10);
}
JKow.DOM.onDOMReady = function(fn){
	var _timer = setTimeout(
		function(){
			var bd = document.getElementsByTagName('body')[0];
			if (document.body && bd){
				clearTimeout(_timer);
				fn();
			} else {
				JKow.DOM.onDOMReady(fn);
			}
		},
	13);
}


/****************************** 
* Event handling 
******************************/
JKow.Event = function(){
}
JKow.Event.addEvent = function(element, type, handler){
		if (!handler.$$guid) handler.$$guid = JKow.Event.guid++;
		if (!element.events) element.events = {};
	
		var handlers = element.events[type];
		if (!handlers){
			handlers = element.events[type] = {};
			if (element["on" + type]){
				handlers[0] = element["on" + type];
			}
		}
		handlers[handler.$$guid] = handler;
		var sender = this;
		element["on" + type] = this.handleEvent;
}


/****************************** 
* This is in the scope of the element 
******************************/
JKow.Event.handleEvent = function(event){
		event = event || window.event;
		var handlers = this.events[event.type];
		for (var i in handlers){
			this.$$handleEvent = handlers[i];
			this.$$handleEvent(event);
		}
	}
JKow.Event.guid = 1;

/****************************** 
* Element binding 
******************************/
JKow.ElementBinding = function() {} 
JKow.ElementBinding.bind = function(obj, element_id){
	var result = null;
	var element = document.getElementById(element_id);
	if (element && obj){
		obj.element = element;
		result = element;
	}
	return result;
}

/****************************** 
* Timers 
******************************/
JKow.Timer = function(interval){
	var Instances;

	/* Data */
	this.interval = interval;
	this.interval_id = null;
	this.running = false;

	this.construct = function(){
		if (JKow.Timer.Instances == null){
			JKow.Timer.Instances = new Array();
		}
		this.instance_id = JKow.Timer.Instances.length;
		JKow.Timer.Instances[this.instance_id] = this;
	}

	this.construct();

	/* Event Queue */
	this.onTimerQueue = new Array();

	this.start = function(){
		if (interval > 0){
			this.interval_id = setInterval("JKow.Timer.Instances['" + this.instance_id + "'].onTimer()", this.interval);
			this.running = true;
		}
	}	

	this.stop = function(){
		if (this.running){
			clearInterval(this.interval_id);
			this.running = false;
		}
	}	

	this.addOnTimerHandler = function(fn){ 
		this.onTimerQueue[this.onTimerQueue.length] = function(){fn();};
	} 

	this.onTimer = function(){
		for(var i = 0; i < this.onTimerQueue.length; ++i){
			this.onTimerQueue[i]();
		}	
	}
}


/* The J-Kow Menu */
JKow.Menu = function(){
	this.elements = new Array();
	this.root = new JKow.Menu.Item('root', null);		

	this.get = function(id){
		var result;
		result = this.get_recurse(this.root, id);
		return result;				
	}

	this.get_recurse = function(p, id){
		var result = null;
		if (p != null){
			if (p.children[id] != null){
				result = p.children[id];
			} else {
				for (var k in p.children){
					result = this.get_recurse(p.children[k], id); 
					if (result != null) {
						break;
					}
				}
			}
		}
		return result;
	}

	this.addChild = function(child){
		this.root.addChildren(new Array(child));
	}

}

JKow.Menu.Item = function(id, value, caption){
	/* Data */
	this.id = id;
	this.value = value;
	this.caption = caption;
	this.children = new Array();

	/* Event queues */
	this.onClickQueue = new Array();

	/* Methods */
	this.addChild = function(child) {
		if (child != null){
			this.children[child.id] = child;
		}
	}

	this.addChildren = function(children){
		if (children != null){
			for(var i = 0; i < children.length; ++i){
				this.children[children[i].id] = children[i];
			}
		}	
	}

	/* Event handling */
	this.addOnClickHandler = function(fn){
		this.onClickQueue[this.onClickQueue.length] = function(sender) { fn(sender); };
	}

	this.onClick = function(){
		for (var i = 0; i < this.onClickQueue.length; ++i){
			this.onClickQueue[i](this);
		}
	}
}

JKow.popUp = function(url){
	window.open(url, "new", "width=800,height=600");
}


/****************************** 
* Effects 
******************************/
JKow.Effects = function(){}
JKow.Effects.Resize = function(startstate, currentstate, finalstate, increment){
	this.states = { initial: startstate, current: currentstate, final: finalstate };
	this.increment = increment;
	this.animstate = 'done';
	this.reverse = false;

	this.step = function(el){
		var $s = el.style; var dc = 1; var $states = this.states;
		/* resize y */
		if ($states.final.height > $states.initial.height){
			if (!this.reverse){
				if ($states.current.height < $states.final.height) {
					$states.current.height += this.increment;
					if ($states.current.height < 0){ $states.current.height = 0 }
					$s.height = $states.current.height.toString() + 'px';	
					this.animstate = 'running';
				} else {
					++dc;
				}
			} else {
				if ($states.current.height > $states.initial.height) {
					$states.current.height -= this.increment;
					if ($states.current.height < 0){ $states.current.height = 0 }
					$s.height = $states.current.height.toString() + 'px';	
					this.animstate = 'running';
				} else {
					++dc;
				}
			}
		} else if ($states.final.height < $states.initial.height){
			if (!this.reverse){
				if ($states.current.height <= $states.final.height) {
					$s.height = ($states.current.height -= this.increment).toString() + 'px';	
					this.animstate = 'running';
				} else {
					++dc;
				}
			}
		} else {
			++dc;
		}

		if (dc == 2){
			this.animstate = 'done';
			if (this.reverse){
				$states.current.height = $states.initial.height;
			} else {
				$states.current.height = $states.final.height;
			}
		}
	}
}

JKow.Effects.Accordion = function(){
	this.elements = {};
	this.resizers = {};
	this.eleminfo = {};

	this.addElement = function(el, collapsedstate, currentstate, expandedstate){
		if (el){
			this.elements[el.id] = el;
			this.elements[el.id].style.width = currentstate.width.toString() + 'px';
			this.elements[el.id].style.height = currentstate.height.toString() + 'px';
			this.elements[el.id].style.overflow = 'hidden'; //And so is this
			this.elements[el.id].style.display = 'block'; //This is important
			this.elements[el.id].style.visibility = 'visible';
			this.eleminfo[el.id] = { };
			this.eleminfo[el.id].expanded = false;
			this.resizers[el.id] = new JKow.Effects.Resize( collapsedstate, currentstate, expandedstate, 14);
		}
	}

	this._collapse = function(sender, elid){
		var _timer = setTimeout(
			function(){
				if (sender.resizers[elid].animstate != 'done'){
					sender.resizers[elid].step(sender.elements[elid]);	
					sender._collapse(sender, elid);	
				} else {
					clearTimeout(_timer);	
					sender.eleminfo[elid].expanded = false;
					sender.elements[elid].style.visibility = 'hidden';
					sender.elements[elid].style.display = 'none';
				}
			}, 25);
	}

	this.collapseElement = function(elid){
		if (this.elements[elid]){
			var sender = this;
			this.resizers[elid].animstate = 'running';
			this.resizers[elid].reverse = true;
			this._collapse(sender, elid); 
		}
	}

	this._expand = function(sender, elid){
		var _timer = setTimeout(
			function(){
				if (sender.resizers[elid].animstate != 'done'){
					sender.resizers[elid].step(sender.elements[elid]);	
					sender._expand(sender, elid);	
				} else {
					clearTimeout(_timer);	
					sender.eleminfo[elid].expanded = true;
				}
			}, 25);
	}
	
	this.expandElement = function(elid){
		if (this.elements[elid]){
			var sender = this;
			this.resizers[elid].animstate = 'running';
			this.resizers[elid].reverse = false;
			sender.elements[elid].style.visibility = 'visible';
			sender.elements[elid].style.display = 'block';
			this._expand(sender, elid);
		}	
	}

	this.toggleElement = function(elid){
		if (this.elements[elid]){
			for (var i in this.elements){
				if ((i != elid) && (this.eleminfo[i].expanded)){
					this.collapseElement(i);
				}	
			}
			if (this.eleminfo[elid].expanded){
				this.collapseElement(elid);
			} else {
				this.expandElement(elid);
			}
		}	
	}
}

//primitives

JKow.Bases = function(){
}
JKow.Bases.hexChars = new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
JKow.Bases.decToHex = function(d){
	var r = d % 16;
	var result;

	if ((d - r) <= 0){
		result = JKow.Bases.hexChars[r];
	} else {
		result = JKow.Bases.decToHex((d - r) / 16) + JKow.Bases.hexChars[r];
	}	
	return result;
}
JKow.RGB = function(){
	this.r = 0;
	this.g = 0;
	this.b = 0;

	this.split = function(c){
		/* http://www.phpied.com/files/rgbcolor/rgbcolor.js */
		var res = [ 
			{ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/ },
			{ re: /^(\w{2})(\w{2})(\w{2})$/ }
		];
		for (var i = 0; i < res.length; ++i){
			var rgb = res[i].re.exec(c);
			if (rgb){
				this.r = parseInt(rgb[1]);
				this.g = parseInt(rgb[2]);
				this.b = parseInt(rgb[3]);
				break;
			}
		}
	}

	this.toString = function(){
		var result = 'rgb(' + this.r.toString() + ', ' + this.g.toString()  + ', ' + this.b.toString() + ')';	
		return result;
	}
}
/* wrapper parseInt that removes leading 0 */
JKow.RGB.parseInt = function(s, base){
	if (s.charAt(0) == '0'){
		s = s.charAt(1);
	}
	return parseInt(s, base);
}
JKow.RGB.randomColorRGBString = function(){
	return 'rgb(' + 
		Math.floor(Math.random() * 254).toString() + ', ' +
		Math.floor(Math.random() * 254).toString() + ', ' +
		Math.floor(Math.random() * 254).toString() + ')';
}

JKow.Effects.RGBMorph = function(start, end){
	this.startRGB = start;
	this.endRGB = end;
	this.rinc = 0;
	this.ginc = 0;
	this.binc = 0;
	this.currRGB = null;
	this.state = 'stopped';

	this.reset = function(){
		if (this.startRGB && this.endRGB){
			this.currRGB = new JKow.RGB();
			this.currRGB.r = this.startRGB.r;
			this.currRGB.g = this.startRGB.g;
			this.currRGB.b = this.startRGB.b;

			if (this.startRGB.r < this.endRGB.r){
				this.rinc = 1;
			} else {
				this.rinc = -1;
			}

			if (this.startRGB.g < this.endRGB.g){
				this.ginc = 1;
			} else {
				this.ginc = -1;
			}

			if (this.startRGB.b < this.endRGB.b){
				this.binc = 1;
			} else {
				this.binc = -1;
			}
		}
	}
	this.reset();

	this.step = function(){
		var c = 0;
		if (this.currRGB.r != this.endRGB.r){
			this.currRGB.r += this.rinc; ++c;
		}
		if (this.currRGB.g != this.endRGB.g){
			this.currRGB.g += this.ginc; ++c;
		}
		if (this.currRGB.b != this.endRGB.b){
			this.currRGB.b += this.binc; ++c;
		}
		if (c == 3) this.state = 'done';
	}	

	this.getCurrRGB =function(){
		return this.currRGB;
	}	
}

JKow.Effects.setOpacity = function(el, op){
	var $es = el.style;	
	var op_str = op.toString();
	switch(JKow.System.browser){
		case 'MSIE':
			$es['filter'] = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + (op * 100).toString() + ')';
		break;

		case 'Safari':
			$es['-khtml-opacity'] = op_str;
		break;

		default:
			$es['opacity'] = op_str;
			//$es['-moz-opacity'] = op_str;
	}
}

JKow.Effects.Bounce = function(velocity, accell, constraints){
	this.element = null;
	this.constraints = constraints; 
	this.initialState = {
		velocity : velocity,
		accell : accell
	};
	this.state = this.initialState;

	this.step = function(el){
		var dim = /([0-9]+)(px)$/.exec(el.style.bottom);
		dim[1] = parseInt(dim[1]);	

		if ((dim[1] + this.state.velocity) < this.constraints['min-y']){
			if (Math.floor(Math.abs(this.state.velocity)) == 0){
				this.state.velocity = 0;
				el.style.bottom = Math.floor(dim[1]).toString() + 'px';
				return;
			} else {
				this.state.velocity = (-this.state.velocity);
			}
		} else {
			this.state.velocity += this.state.accell;
		}
		dim[1] += this.state.velocity;
		el.style.bottom = Math.floor(dim[1]).toString() + 'px';
	}
}

JKow.Effects.Slide = function(velocity, accell){
	this.element = null;

	this.initialState = { 
		'velocity' : velocity,
		'accell': accell
       	};
	this.state = {
		'velocity' : this.initialState.velocity,
		'accell': this.initialState.accell
	};

	this.step = function(el){
		var dim = /([0-9]+)(px)$/.exec(el.style.bottom);
		dim[1] = parseInt(dim[1]);	
		if (Math.floor(Math.abs(this.state.velocity)) == 0){
			this.state.velocity = 0;
		} else {
			this.state.velocity += this.state.accell;
			dim[1] += this.state.velocity;
			el.style.bottom = Math.floor(dim[1]).toString() + 'px';
		}
	}
}

/****************************** 
* Windowing 
******************************/
JKow.Wtk = function() {}
JKow.Wtk.setBackgroundImage = function(el, bg){
	var browser = JKow.System.browserCheck();
	if (browser == 'Mozilla'){
		el.style.background = "url(" + bg + ")";	
		el.style.backgroundRepeat = "no-repeat";
	} else if (browser == 'MSIE') {
		el.style.backgroundRepeat = "no-repeat";
		el.style.background = "url('')";	
		el.style['filter'] = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + bg + "', sizingMethod='crop')"; 
	} else if (browser == 'unknown'){
		el.style.background = "url(" + bg + ")";	
	}
}
JKow.Wtk.config = {
	window: 
	{ active_opacity: 0.8, inactive_opacity: 0.5 }
}
JKow.Wtk.Moveable = function(){
	this.oldstate = null;

	this.move = function(el, e){
		var $ = el.style;
		var x, y;

		var xy = JKow.Wtk.getCursor(e);
		x = xy.x;
		y = xy.y;

		if (this.oldstate == null){
			this.oldstate = { top: y, left: x };
		}
		if (this.oldstate.top) $.top = (parseInt($.top) + y - this.oldstate.top).toString() + 'px';
		if (this.oldstate.left) $.left = (parseInt($.left) + x  - this.oldstate.left).toString() + 'px';

		this.oldstate = { top: y, left: x };
	}
}

JKow.Wtk.getCursor = function(event){
	/* IE6 uses documentElement when DOCTYPE is strict */
	var result = {x: null, y: null};
	/*if (event.offsetX){
		result.x = event.offsetX;
	} else */
	if (document.documentElement.scrollLeft){
		result.x= event.clientX + document.documentElement.scrollLeft;
	} else if (event.pageX){
		result.x = event.pageX;
	} else if (window.scrollX){
		result.x= event.clientX + window.scrollX;
	} else if (document.body.scrollLeft){
		result.x= event.clientX + document.body.scrollLeft;
	} else {
		result.x = event.clientX;
	}

	/*if (event.offsetY){
		result.y = event.offsetY;
	} else */
	if (document.documentElement.scrollTop){
		result.y= event.clientY + document.documentElement.scrollTop;
	} else if (event.pageY){
		result.y = event.pageY;
	} else if (window.scrollY){
		result.y= event.clientY + window.scrollY;
	} else if (document.body.scrollTop){
		result.y= event.clientY + document.body.scrollTop;
	} else {
		result.y = event.clientY;
	}
	return result;
}

JKow.Wtk.getWindowDimensions = function(){
	var dim = {};
	if (window.innerWidth && window.innerHeight){
		dim ={'height' : window.innerWidth, 'width': window.innerWidth};
	} else if (document.body.offsetWidth && document.body.offsetHeight){
		dim ={'height' : document.body.offsetWidth, 'width' : document.body.offsetHeight};
	}
	return dim;
}

/* Note Firefox can throw a spaz here if not in quirks mode !*/
JKow.Wtk.Window = function(){
	this.guid = 0;
	this.width = 420;
	this.height = 450;
	this.opacity = 1.0;
	this.element = null;
	this.element_id = null;
	this.children = [];	
	this.titlebar;
	this.ismousedown = false;
	this.clickregions = [];

	this.setSize = function(width, height){
		this.element.style.width = width.toString() + 'px';
		this.element.style.height = height.toString() + 'px';
	}

	this.addClickRegion = function(dim, fn){
		this.clickregions[this.clickregions.length] = {'dim': dim, 'fn': fn};
	}

	this.setElementId = function(elid){
		this.element.id = this.element_id = elid;
	}

	this.enableTitlebar = function(enabled){
		if (!enabled){
			this.titlebar.element.style.visibility = "hidden";
			this.titlebar.element.style.display = "none";
		}
	}

	this.init = function(sender){
		var b = document.getElementsByTagName('body')[0];
		if (b){
			var $ = sender.element.style;	
			$.width = sender.width.toString() + 'px';
			$.height = sender.height.toString() + 'px';
			$.backgroundColor = JKow.RGB.randomColorRGBString(); 
			$.position = 'absolute';
			$.zIndex = sender.guid + 1988;
			$.contentEditable = true;
			var wDim = JKow.Wtk.getWindowDimensions();
			if (wDim){
				//$.top = ((wDim.height / 2) - (sender.height / 2)).toString() + 'px';
				$.top = '250px';
				$.left = ((wDim.width / 2) - (sender.width / 2)).toString() + 'px';
			} else {
				$.top = (Math.random() * 480).toString() + 'px';
				$.left = (Math.random() * 640).toString() + 'px';
			}
			sender.element.setAttribute("class", "jkow wtk window");
			sender.hide();
			b.appendChild(sender.element);
			
			sender.moveable = new JKow.Wtk.Moveable();
			JKow.Effects.setOpacity(sender.element, sender.opacity);

			var sender = sender;
			sender.titlebar = new JKow.Wtk.Window.TitleBar();
			sender.enableTitlebar(false);
			sender.appendChild(sender.titlebar);
			JKow.Event.addEvent(sender.element, 'mousedown', function(event){sender.mouseDown(sender, event);});
			JKow.Event.addEvent(sender.element, 'mouseup', function(event){sender.mouseUp(sender, event);});
			JKow.Event.addEvent(sender.element, 'click', function(event){sender.onClick(sender, event);});
			JKow.Event.addEvent(b, 'mousemove', function(event){sender.mouseMove(sender, event);});
		}
	}

	//constructor
	this.Window = function(){
		this.guid = JKow.Wtk.guid++;
		//save reference to self
		var self = this;
		JKow.Wtk.windows[this.guid] = self;
		this.element_id = 'JKow_Wtk_' + this.guid.toString(); 
		this.element = document.createElement('div');
		this.element.id = this.element_id;
		var sender = this;
		JKow.DOM.onContentReadyTag('body', function() { sender.init(sender); });
	}

	this.onClick = function(sender, event){
		var xy = JKow.Wtk.getCursor(event);
		var $es = sender.element.style;
		for (var i = 0; i < sender.clickregions.length; ++i){
			var $ = sender.clickregions[i];
			if (((xy.x - parseInt($es.left)) >= $.dim.left) &&
			((xy.x - parseInt($es.left)) <= $.dim.right) &&
			((xy.y - parseInt($es.top)) >= $.dim.top) &&
			((xy.y - parseInt($es.top)) <= $.dim.bottom)){
				$.fn();
			}
		}
	}

	this.fadeOut = function(sender){
		if (JKow.System.browser == 'MSIE'){
			return false;	
		}
		var _timer = setTimeout(
			function(){
				sender.opacity -= 0.13;
				if (sender.opacity >= 0.0){
					JKow.Effects.setOpacity(sender.element, sender.opacity);
					sender.fadeOut(sender);
				} else {
					sender.opacity = 0.0;
					JKow.Effects.setOpacity(sender.element, sender.opacity);
					sender.hide();
					clearTimeout(_timer);
				}	
			}, 25);	
	}

	this.fadeIn = function(sender){
		if (JKow.System.browser == 'MSIE'){
			return false;
		}
		var _timer = setTimeout(
			function(){
				sender.opacity += 0.13;
				if (sender.opacity <= 1.0 ){
					JKow.Effects.setOpacity(sender.element, sender.opacity);
					sender.fadeIn(sender);
				} else {
					sender.opacity = 1.0;
					JKow.Effects.setOpacity(sender.element, sender.opacity);
					clearTimeout(_timer);
				}	
			}, 25);
	}

	this.show = function(){
		this.opacity = 0.0;
		if (JKow.System.browser != 'MSIE'){
			JKow.Effects.setOpacity(this.element,this.opacity);
		}
		this.element.style.visibility = 'visible'; 
		this.element.style.display = 'block'; 
		var sender = this;
		this.fadeIn(sender);
	}

	this.hide = function(){
		this.element.style.visbility = 'hidden';
		this.element.style.display = 'none';
	}

	this.mouseMove = function(sender, e){
		//if (sender.titlebar.ismousedown){
		if (this.ismousedown){
			this.moveable.move(sender.element, e);
		}
		//}
	}

	this.mouseUp = function(sender, e){ sender.ismousedown = false; }

	this.mouseDown = function(sender, e){
		var c = 0;
		//reorder z-index of windows
		sender.ismousedown = true;
		for (var i in JKow.Wtk.windows){
			++c;
		}
		if (c > 0){
			var topmost = sender;	
			for (var i in JKow.Wtk.windows){
				var k = JKow.Wtk.windows[i];
				if (parseInt(k.element.style.zIndex) > parseInt(topmost.element.style.zIndex)) {
					topmost = k;
				}
			}
			for (var i in JKow.Wtk.windows){
				var k = JKow.Wtk.windows[i];
				if (k.guid != sender.guid){
					//k.element.style.opacity = 0.3;
				}
			}
			if (topmost.guid != sender.guid){
				//swap with old top most
				var z = sender.element.style.zIndex;
				sender.element.style.zIndex = topmost.element.style.zIndex;
				topmost.element.style.zIndex = z;
				//sender.element.style.opacity = 0.9;
			}
			sender.moveable.oldstate = JKow.Wtk.getCursor(e);
		}
	}

	this.appendChild = function(child){
		child.parent = this;
		this.children[this.children.length] = child;
		child.element.id = 'jkow_wtk_window_' + this.guid.toString();
		child.element.style.zIndex = this.element.style.zIndex + 1;
		this.element.appendChild(child.element);
	}

	this.setContent = function(strContent){
		this.element.innerHTML = strContent;	
	}

	this.setBackgroundImage = function(bg){
		var $es = this.element.style;
		var browser = JKow.System.browser;
		if (browser == 'Mozilla'){
			this.opacity = 1.0;
			JKow.Effects.setOpacity(this.element, 1.0);
			$es.background = "url(" + bg + ")";	
			$es.backgroundRepeat = "no-repeat";
		} else if (browser == 'MSIE') {
			$es.backgroundRepeat = "no-repeat";
			$es.background = "url('')";	
			$es['filter'] = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + bg + "', sizingMethod='scale')"; 
		} else if (browser == 'unknown'){
			$es.background = "url('" + bg + "')";	
		}
	}

	this.Window();
}

JKow.Wtk.Window.TitleBar = function(){
	this.parent;
	this.element;
	this.ismousedown = false;

	//constructor
	this.TitleBar = function(){
		this.element = document.createElement('div');
		this.element.style.height = '25px';
		this.element.style.width = '100%';
		this.element.style.backgroundColor = '#FFFFFF';
		this.element.style.display = 'block';
		this.element.style.visibility = 'visible';
		this.element.style.position = 'relative';
		this.element.style.top = '0px';
		this.element.style.left = '0px';

		var sender = this;
		this.element.onmousedown = function(event){ sender.onMouseDown(sender, event); }; 
		this.element.onmouseup = function(event){ sender.onMouseUp(sender, event); }; 
	}

	this.bindToParent = function(p){ this.parent = p; }
	this.onMouseDown = function(sender, event) { sender.ismousedown = true; }
	this.onMouseUp = function(sender, event) { sender.ismousedown = false; }
	this.onMouseMove = function(sender, event) { return false;}

	this.TitleBar();
}

JKow.Wtk.popupMenuItem = function(menuid, caption){
	this.menuid = menuid; 
	this.caption = caption;
	this.element = false;
	this.hasFocus = false;
	this.initPopupStyle = null;
	this.finalPopupStyle = { height: 90, bottom:130 };
	this.popupElement = null;
	this.animstate = '';
	this.effectstate = { 'velocity': 8, 'accell' : -0.3};
	this.effects = {
		'slide' :  new JKow.Effects.Slide(8, (-0.3)),
		'bounce' :  new JKow.Effects.Bounce(8, (-0.3), {})
	};



	this.animreset = function(){
		var e = document.getElementById('menu_popup_' + this.menuid);
		var initBottom = /([0-9]+)(px)$/.exec(this.initPopupStyle["bottom"]);
		initBottom[1] = parseInt(initBottom[1]);
		if (e){
			e.style.bottom = Math.floor(initBottom[1]).toString() + 'px';
		}
	}

	this.animstep = function(){
		if (this.popupElement){
			var dim;
			switch(this.animstate){
				case 'show':
					var $fx = this.effects.slide;
					if (this.popupElement){
						$fx.state = this.effectstate;
						$fx.step(this.popupElement);
						if ($fx.state.velocity == 0){
							this.animstate = '';
						}
						this.effectstate = $fx.state;
					}
					this.effects.slide = $fx;
				break;

				case 'hide':
					var $fx = this.effects.bounce;
					var initBottom = /([0-9]+)(px)$/.exec(this.initPopupStyle["bottom"]);
					initBottom[1] = parseInt(initBottom[1]);
					$fx.state = this.effectstate;
					$fx.constraints['min-y'] = initBottom[1];
					$fx.step(this.popupElement);	
					if ($fx.state.velocity == 0){
						this.animstate = '';
					}	
					this.effectstate = $fx.state;
					this.effects.bounce = $fx;
				break;

				default:
			}	
		}
	}	

	this.bindToPopupElement = function(elid){
		this.popupElement = document.getElementById(elid);

		if (this.popupElement){
			this.popupElement.parent = this;

			this.initPopupStyle = {
				bottom: this.popupElement.style.bottom,
				width: this.popupElement.style.width
			};


			this.popupElement.onmouseover = function(event){
				this.hasFocus = true;
				this.parent.animstate = 'show';
				this.parent.onMouseOver(this.parent, event);
			};

			this.popupElement.onmouseout = function(event){
				this.hasFocus = false;
				this.parent.onMouseOut(this.parent, event);
			};
		}
	}

	this.bindToElement = function(element){
		this.element = element;
		this.bindToPopupElement('menu_popup_' + this.menuid);
		var sender = this;
		this.element.onmouseover = function(event){ sender.onMouseOver(sender, event); };
		this.element.onmouseout = function(event){ sender.onMouseOut(sender, event); };
	}

	this.onMouseOver = function(sender, event){
		var $s = sender;
		if ($s.popupElement){
			$s.hasFocus = true;	
			if ($s.animstate != 'show'){
				$s.animreset();
				$s.effectstate.velocity = $s.effects.slide.initialState.velocity;
				$s.animstate='show';
			}		
			if ($s.effectstate.velocity < 0){
				$s.effectstate.velocity = (-$s.effectstate.velocity);
			}
			$s.effects.bounce.state.velocity = $s.effectstate.velocity;
		}
	}

	this.onMouseOut = function(sender, event){
		var $s = sender;
		if ($s.popupElement){
			if (!$s.popupElement.hasFocus){
				$s.hasFocus = false;	
				$s.effects.bounce.state.velocity = $s.effectstate.velocity;
				if (Math.floor(Math.abs($s.effects.bounce.state.velocity)) > 0){
					$s.effects.bounce.state.velocity = -(Math.abs($s.effects.bounce.state.velocity));
				}	
				$s.animstate='hide';
			}
		}
	}
}

JKow.Wtk.guid = 1;
JKow.Wtk.windows = {};
