/* elementary.js 
 * cross browser api for easing javascript development
*/


var Switcher = function(){
	document.getElementById("iswitch-link").style.display = "none";
	document.getElementById("iswitch-drop").style.display = "block";
	
}

var Toggled = null;
var unToggled = null;
function ToggleLayer(layer,unlayer){
	Toggled = new Element(layer);
	if (unlayer) unToggled = new Element(unlayer);
	if(Toggled.element.style.display == "block"){
		var lay = new Animation(Toggled.element.id, {alpha:100});			
		lay.effect({alpha:0.01, duration:0.2, fps:1/50, trans:physics.easeOut}, function(){
				Toggled.hide('none');
		});
		if(unlayer){
			var unlay = new Animation(unToggled.element.id, {alpha:0.01});
			unToggled.show('block');				
			unlay.effect({alpha:99.9, duration:0.1, fps:1/50, trans:physics.easeOut});	
		}
	}else{		
		var lay = new Animation(Toggled.element.id, {alpha:0.01});
		Toggled.show('block');				
		lay.effect({alpha:99.9, duration:0.2, fps:1/50, trans:physics.easeOut});
		
		if(unlayer && unToggled.element){
			var unlay = new Animation(unToggled.element.id, {alpha:100});			
			unlay.effect({alpha:0.01, duration:0.1, fps:1/50, trans:physics.easeOut}, function(){
					unToggled.hide('none');
			});
		}
	}
}


var Window = {
	construct:function(){
		
  	   //without scrolling...
	  if( typeof( window.innerWidth ) == 'number' ) {
		//moz, opera
		this.width = window.innerWidth;
		this.height = window.innerHeight;
	  } else if( document.documentElement &&
		( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//ie
		this.width = document.documentElement.clientWidth;
		this.height = document.documentElement.clientHeight;
	  }
	
	  //with scrolling..
	  if( document.body ) {
		//dom
			this.scrollheight = document.body.scrollHeight;
			this.scrollwidth = document.body.scrollWidth;
	   } else if(document.documentElement && document.documentElement.scrollHeight){
	    //ie
	   		this.scrollheight =  document.documentElement.scrollHeight;
			this.scrollwidth =  document.documentElement.scrollWidth;		
	  } 
	  
	  //srolling offset
	  if (window.innerHeight){
	 	  	this.scrolledy = window.pageYOffset;
			this.scrolledx = window.pageXOffset;
	  } else if (document.documentElement && document.documentElement.scrollTop) {
			this.scrolledy = document.documentElement.scrollTop;
			this.scrolledx = document.documentElement.scrollLeft;
	  }else if (document.body){
		  this.scrolledy = document.body.scrollTop;
		  this.scrolledy = document.body.scrollLeft;
	  }	
	}
}
Window.construct();
addWindowEventListener("resize",Window.construct);

function Tooltip(){
    var This = this;
	this.ie = navigator.appName.indexOf("xplorer") > 0 ? true : false;
	
	var el = new Element("middle");
	//var tip = el.append("div", "", 'class="tooltip"');
		//el = document.getElementById("wrap").appendChild(el);  
	
	
	this.tip = new Animation("tooltip",{alpha:0.01});
	this.over = false;
	this.timer = null;
	
	this.show = function(message, e){
		this.timer = window.setTimeout(tooltip.open, 1000, message, e);
		This.message = message;
		This.ev = e;
		var ein = new EventInfo(e, true);  
		y = ein.ymouse-17
		This.tip.element.setPosition(ein.xmouse - el.getRealLeft() + 5, y - 5);
	}
	
	this.open = function(){
	   if(this.timer) window.clearTimeout(this.timer);	   
	   var ei = new EventInfo(This.ev, true);
	   This.tip.element.setContent(This.message);
	   This.tip.element.show('block');
	   This.tip.effect({alpha:99.9,duration:0.3});
	   
	ei.source.onmousemove = function(e){   
		    var ein = new EventInfo(e, true);  
			y = ein.ymouse-17
			This.tip.element.setPosition(ein.xmouse - el.getRealLeft() + 5, y - 5);
	   } 
	}                
	
	this.hide = function(e){		
		this.over = false;	 
		this.close();
		//this.timer = window.setTimeout(tooltip.close, 500);
	}
	
	this.close = function(){
		
		if(this.over) return;
		This.tip.effect({alpha:0.01,duration:0.3}, function(){ 
			This.tip.element.hide('none');
		}); 		
		window.clearTimeout(this.timer);
	}
}


function addWindowEventListener(eventName, callback, bubble){
	if(window.addEventListener){          
		window.addEventListener(eventName, callback, bubble);
	} else {
		document.attachEvent('on' + eventName, callback);
	}                                                  
}


function WaitClear(){
	//window.setTimeout(ClearNotifications, 2000);	
}

var ClearNotifications = function(){	
	var mid = document.getElementById("middle");
	var ps = mid.getElementsByTagName("p");
	for(var p = 0; p < ps.length; p++){
		if(ps[p].className == "notify" || ps[p].className == "error"){
		//	ps[p].innerHTML = "";
		}		
	}	
}

addWindowEventListener('load',WaitClear);

var Valid = function(frm){
	var match = "";
	var password = "";	
	for(var e = 0; e < frm.elements.length; e++){
		if(frm.elements[e].getAttribute("notempty") && frm.elements[e].value == ""){
			var name = frm.elements[e].getAttribute("name");
				name = name.replace(/_/g,' ');
				name = name.replace(/\[|\]/g,' ');
			var notify = frm.elements[e].getAttribute("notempty") == "true" ? name + " is required." :  frm.elements[e].getAttribute("notempty") + " is required.";
			var msg = document.createElement("p");
				 msg.className = "error";
				 msg.innerHTML = notify;
				
			frm.elements[e].parentNode.insertBefore(msg, frm.elements[e].previousSibling);
			frm.elements[e].focus();
			return false;
		}else if(frm.elements[e].getAttribute("valid-email")){
			
			var valid = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
			if (!frm.elements[e].value.match(valid)) {				
				var name = frm.elements[e].getAttribute("name");
					name = name.replace(/_/g,' ');
					name = name.replace(/\[|\]/g,' ');
				var notify = frm.elements[e].getAttribute("valid-email") == "true" ? name + " must be a vaild email address." :  frm.elements[e].getAttribute("valid-email") + " must be a vaild email address.";
				var msg = document.createElement("p");
					 msg.className = "error";
					 msg.innerHTML = notify;
					
				frm.elements[e].parentNode.insertBefore(msg, frm.elements[e].previousSibling);
				frm.elements[e].focus();
				return false;
			}
			
		}else if(frm.elements[e].getAttribute("type") == "password"){
			if(!match){
				match = frm.elements[e].value;
				password = frm.elements[e];
			}else{
				if(frm.elements[e].value != match){
					var msg = document.createElement("p");
						msg.className = "error";
						msg.innerHTML = "Your passwords do not match. Please re-enter";
					password.parentNode.appendChild(msg, frm.elements[e]);		
					password.focus();
					password.select();
					return false;
				}
			}
		}
	}
	return true;
}


/** remote call wraper a call to the controler method or "action", and returns the resulting object **/
var RemoteCall = {
	handlers:null,
	make:function(controller, action, object, string){
		if(!string) string = true;
		var req = new Request(RemoteCall.handlers, string);
			req.send(WEB_HOME + "remote/?name="+controller+"&action="+action+"&obj=" + object);
	}
}

var RenderToLayer = null;
var PostRenderAction = null;
var RenderUrlToLayer = function(url, layer, after){
	RenderToLayer = layer;
	if(after) PostRenderAction = after;
	Handlers = {
		onData:function(string){
			document.getElementById(RenderToLayer).innerHTML = string;
			if(PostRenderAction) PostRenderAction();
		},
		onError:function(er){
			alert("Error rending layer from URL: " + er)
		}
	}
	document.getElementById(RenderToLayer).innerHTML = '<p class="loading"><span>Loading...</span></p>';
	var req = new Request(Handlers, false);
		req.send(WEB_HOME + url);
}

/** allows for editable block elements, id attribute must be present to work correctly. **/
var TextEditor = {
	elements:false,
	control:false,
	action:false,
	active:false,
	appended:false,
	original_value:false,
	make:function(element, control, action, field, appended){
		if(!TextEditor.elements){
			TextEditor.elements = new Array();
			TextEditor.field = field;
			TextEditor.appended = appended;
			//addWindowEventListener('mouseup',TextEditor.cancel)
		} 
		var obj = new Element(element, { onclick:TextEditor.click, onrollover:TextEditor.over, onrollout:TextEditor.out});
		TextEditor.elements.push(obj); 
		this.control = control;
		this.action = action;
		
	},
	click:function(e){
		TextEditor.cancel();
		var inst = TextEditor.getinstance(this);
		var cont = inst.getContent();
			inst.setContent("");
			var field = inst.append("input",false,'type="text" value="'+cont+'"');
			inst.append("input",false,'type="button" class="button" style="clear:both;" value="save" onclick="TextEditor.save(this)"');
			inst.append("input",false,'type="button" class="button" value="cancel" onclick="TextEditor.cancel(this)"');
			inst.append("br",false,'style="clear:both;"');		
		TextEditor.active = inst;
		TextEditor.original_value = field.value;
		field.focus(); field.select();		
		DisableDrag = true;	
	},
	over:function(e){
		this.style.backgroundColor = "#FFFFD7";
		this.style.cursor = "pointer";
	},
	out:function(e){
		this.style.backgroundColor = "transparent";
	},
	getinstance:function(source){
		for(var e = 0; e < TextEditor.elements.length; e++){
			if(TextEditor.elements[e].id == source.getAttribute("id"))
				return TextEditor.elements[e];
		}
	},
	cancel:function(){
		if(TextEditor.active){
			var value = TextEditor.active.element.firstChild.value;
			TextEditor.active.setStyleProperty('backgroundColor','#FFF');			
			TextEditor.active.setContent(TextEditor.original_value);
			TextEditor.active = null;
			DisableDrag = false;	
		}
	},
	onData:function(result){
		if(result.okay){
			TextEditor.active.setStyleProperty('backgroundColor','#FFF');			
			TextEditor.active.setContent(result.saved.name);
			TextEditor.active = null;
			DisableDrag = false;	
		}
	},
	save:function(){
		if(TextEditor.active){
			var id = TextEditor.active.element.id;
			if(TextEditor.appended){
				id = id.substring(0, id.indexOf(TextEditor.appended));
			}
			
			var value = TextEditor.active.element.firstChild.value;
			var save = '{"id":"'+id+'","'+TextEditor.field+'":"'+value+'"}';
			
			RemoteCall.handlers = TextEditor;
			RemoteCall.make(TextEditor.control, TextEditor.action, save);
			
			TextEditor.active.setContent("Saving...");
			
		}
	},
	revert:function(){
		
	}	
}


/** assign observer objects to keypress events.. **/
var KeyEventObservers = {
	list:null,
	add:function(key, handler){ 
		if(KeyEventObservers.list == null){
			 KeyEventObservers.list = new Object();
			 addWindowEventListener('keydown',KeyEventObservers.onkeydown, false);
			 addWindowEventListener('keyup',KeyEventObservers.onkeyup, false);
		}
		if(!KeyEventObservers.list[key]) KeyEventObservers.list[key] = new Array();
		KeyEventObservers.list[key].push(handler);			
	},
	onkeydown:function(e){
		if( ! KeyEventObservers.list[KeyMap.lookup(e.keyCode)]) return true;
		var observers = KeyEventObservers.list[KeyMap.lookup(e.keyCode)];
	    for(var o = 0; o < observers.length; o++){
			if(observers[o].down) observers[o].down(e);
		}
		return true;
	},
   	onkeyup:function(e){ 
		if( ! KeyEventObservers.list[KeyMap.lookup(e.keyCode)]) return true;
		var observers = KeyEventObservers.list[KeyMap.lookup(e.keyCode)];
	    for(var o = 0; o < observers.length; o++){
			if(observers[o].up) observers[o].up(e);
		}
		return true;
	}
}

var KeyMap = {
	names:['shift','ctl','up','down','left','right','tab'],
	//note: safari shift, ctl, and alt don't fire events!
	safari:[16,17,38,40,37,39,9],
	moz:[16,17,38,40,37,39,9],
	ie:[16,17,38,40,37,39,9],
	mac:[16,224,38,40,37,39,9],
	lookup:function(test){	
		var code = internet_explorer ? KeyMap.ie : KeyMap.moz;
		if(macintosh) code = KeyMap.mac;
		if(safari) code = KeyMap.safari;
		for(var i = 0; i < code.length; i++){
			if(code[i] == test)
				return KeyMap.names[i];
		}
		return "all";
	}
}

var Message = {
	display:function(type, msg){
		document.getElementById("message").className = type;
		document.getElementById("message").innerHTML = msg;
		document.getElementById("message").style.display = "block";
		window.setTimeout(ClearNotifications, 2000);
	},
	clear:function(){
		//document.getElementById("message").style.display = "none";
		document.getElementById("message").innerHTML = ""; 	
	}
}


/* form helper scripts */
function ReplaceSelect(name, wrapper, listener){
	var sel = wrapper.getElementsByTagName("select")[0];
	var bef = wrapper.getElementsByTagName("label");	
	wrapper.removeChild(sel);
	var ni = document.createElement("input");
		ni.setAttribute("name", name);
		ni.setAttribute("type", "text");
	if(bef.length > 1)
		wrapper.insertBefore(ni, bef[1]);
	else
		wrapper.appendChild(ni);
		
	if(listener)
		listener.call();
}



function addslashes(str) {
str=str.replace(/\\/g,'\\\\');
str=str.replace(/\'/g,'\\\'');
str=str.replace(/\"/g,'\\"');
str=str.replace(/\0/g,'\\0');
return str;
}
function stripslashes(str) {
str=str.replace(/\\'/g,'\'');
str=str.replace(/\\"/g,'"');
str=str.replace(/\\0/g,'\0');
str=str.replace(/\\\\/g,'\\');
return str;
}




//dependencies - "not so clean" code, this is old and should all be replaced but it works- well.  

var internet_explorer = navigator.appName.indexOf("xplorer") > 0;
var macintosh = navigator.platform.indexOf("Mac") >= 0;
var safari = navigator.appVersion.indexOf("fari") > 0;


function Request(handlers, evaluate){
  this.onData = handlers.onData;
  this.onError = handlers.onError ? handlers.onError : false;
  this.onLoading = handlers.onLoading ? handlers.onLoading : false;
  this.evaluate = evaluate;
  this.lastRequest = ""; 
  var xmlhttp=false;
  var This = this;
  try { 
  	xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 	} catch (e) {
 		 try {
  	 		xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  		  } catch (E) {
   			xmlhttp = false;
  		 }
 	}
   if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
  		xmlhttp = new XMLHttpRequest();
    }
   this.stateChange = function( ){
		if ( xmlhttp.readyState == 4) {
        	if (xmlhttp.status == 200) {
		    	var response = (xmlhttp.responseText) ? xmlhttp.responseText : ""; 
				if(This.evaluate){
					var result;
					var str = 'result = ' + response + ';';
					try{
						eval(str);
					}catch(e){
						This.onError(response);
						//alert("Request Runtime error: " + e+ "\nReturned Response:\n\n" + response);
					}
					response = result;					
				}
				This.onData(response, This);
       		} else {
            	var e = xmlhttp.statusText;
				if(This.onError) This.onError(e, This);
        	}
	   }
   } 
   this.send = function( url, requestHeaders ) {
	  if(xmlhttp){		
	    	if(This.onLoading) This.onLoading();
  			xmlhttp.open("POST", url , true);
			xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
 			xmlhttp.onreadystatechange = This.stateChange;
			This.lastRequest = url;
			xmlhttp.send(null);
	   }else{
		   if(This.onError) This.onError("Sorry, your browser does not support remote requests.");
	   }
   }
}
function Element(id, io){	
	var This = this;
	if(typeof(id) == 'string'){
		if(!document.getElementById(id)){
			//alert("Can't find element with id: " + id);
			This.element = false;
		}
		This.element = document.getElementById(id);
		This.id = id;	
	}else{
		This.element = id;
		try{		
			This.id = This.element.getAttribute('id');
		}catch(e){
			This.id = null;
		}
	}
	if(!io) io = {};
	var units = io.units ? io.units : 'px';
	this.x = io.x ? io.x : false;
	this.y = io.y ? io.y : false; 
	this.width = io.width ? io.width : false; 
	this.height = io.height ? io.height : false; 
	this.alpha = (io.alpha != undefined) ? io.alpha : false;
	this.center = (io.center) ? io.center : false;
	this.contentElement = false;
	if(io.contentElement)  
		this.contentElement = document.getElementById(io.contentElement); 	
	this.setDimensions = function(w,h){
		if(isNum(w)) { this.element.style.width = (w + units); this.width = w;   }
		if(isNum(h)) { this.element.style.height = (h + units); this.height = h; }
		if(This.center){
			var cx = (This.width-w) * This.center.x;
			var cy = (This.height-h) * This.center.y;
			This.setPosition( This.x + cx, This.y + cy);
		}
	}
	this.setWidth = function(w){
		if(isNum(w)) this.element.style.width = (w + units); this.width = w;
	}
	this.setHeight = function(h){
		if(isNum(h)) this.element.style.height = (h + units); this.height = h;
	}
	
	this.setPosition = function(x,y){
	  if(isNum(y)) { this.element.style.top = y + units;  this.y = y;   }
	  if(isNum(x)) { this.element.style.left = x + units; this.x = x;  }
	  //if(this.center) this.setDimenions(this.width, this.height);
	}
	this.setOpacity = function(a){ 
		if(isNum(a)){
			this.element.style.opacity = (a/100);		
			this.element.style.filter = "Alpha(Opacity=" + a + ")";  
			this.alpha = a;
		}
	}	
	this.setStyleProperty = function(property, value){
		eval("this.element.style." + property + "=\"" + value + "\"");
	}
	this.setClass = function(name){
		this.element.className = name;	
	}
	this.addClass = function(name){
		if(this.element.className.toString().indexOf(name) < 0)
			this.element.className = this.element.className + " " + name;
	}
	this.removeClass = function(name){
		var cc = this.element.className.toString();
		var e = cc.substring(0,cc.indexOf(name));
		var b = cc.substring(cc.indexOf(name) + name.length, cc.length);
		this.element.className = b + " " + e;
	}	
	this.hide = function(disp){
		this.element.style.visibility = 'hidden';
		if(disp) this.element.style.display = disp;
	}	
	this.show = function(disp){
		this.element.style.visibility = 'visible';
		if(disp) this.element.style.display = disp;
	}	
	this.getRealHeight = function(){
		return this.element.offsetHeight;
	}
	this.getRealWidth = function(){
		return this.element.offsetWidth;
	}
	this.getRealTop = function(){
		if(internet_explorer){
			var top = 0;
	   	 	var obj = This.element;
				if (obj.offsetParent)
				{
					while (obj.offsetParent)
					{
						if(obj.offsetParent.getAttribute("id")) top += obj.offsetTop;
						//if(obj.offsetParent.scrollTop) top -= obj.offsetParent.scrollTop;
						obj = obj.offsetParent;
					}
				}
				else if (obj.y)
					top += obj.y;
			return top;
		}else{
			return this.element.offsetTop;
		}  
	}
	this.getRealLeft = function(){
		if(this.ie){
			var left = 0;
			var obj = this.element;
				if (obj.parentNode)
				{
					while (obj.parentNode)
					{
						if(obj.offsetParent.getAttribute("id")) left += obj.parentNode.offsetLeft
						obj = obj.parentNode;
					}
				}
				else if (obj.x)
					left += obj.x;
			return left; 
		} else {
			return this.element.offsetLeft;
		}     
	}
	this.getRelativeTop = function(){
		var top = 0;
   	 	var obj = This.element;
			if (obj.offsetParent)
			{
				while (obj.offsetParent)
				{
					top += obj.offsetTop
					obj = obj.offsetParent;
				}
			}
			else if (obj.y)
				top += obj.y;
		return top;
	}
	this.getRelativeLeft = function(){	
		var left = 0;
		var obj = this.element;
			if (obj.offsetParent)
			{
				while (obj.offsetParent)
				{
					left += obj.offsetLeft
					obj = obj.offsetParent;
				}
			}
			else if (obj.x)
				left += obj.x;
		return left; 	  
	}
	this.getTop = function(){
		return this.element.offsetTop;
	}
	this.getLeft = function(){
		return this.element.offsetLeft;
	}
	this.getContent = function(cont){
		if(this.contentElement) return this.contentElement.innerHTML;
		return this.element.innerHTML;	
	}
	this.setContent = function(cont){
		if(this.contentElement) this.contentElement.innerHTML = cont;
		else this.element.innerHTML = cont;	
	}
	this.insertContent = function(cont, pos){
		var bCont = this.getContent();
		if(pos=='before') this.setContent(cont + bCont);
		else this.setContent(bCont + cont);
	}
	this.getChildren = function(tag){
		if(this.element)
			return this.element.getElementsByTagName(tag);
		else
			return new Array();
	}
	this.append = function(type, content, attributes){
		var ne;	
		if(!internet_explorer){ 
			ne = document.createElement(type);
			if(attributes){
				var atts = attributes.split('" ');
				for(var a=0; a < atts.length; a++){
					var data = atts[a].split('="');
					var value = data[1].indexOf('"') > 0 ? data[1].substring(0,data[1].length-1) : data[1];
					ne.setAttribute(data[0], value);
				}
			}
		}else{
			var make = '<' + type + ' ' + attributes + '>';
			ne = document.createElement(make);
		}
		if(content) ne.innerHTML = content;	
		this.element.appendChild(ne);
		return ne;
	}
	this.prepend = function(type, content){
			var ne = document.createElement(type);   
		    this.element.insertBefore(ne, This.element.firstChild); 
			if(content) ne.innerHTML = content; 
			return ne;
	}
	this.remove = function(node){
		this.element.removeChild(node);
	}
	this.insert = function(node, before){
		this.element.insertBefore(node, before);
	}
	this.setHandlers = function(io){   
		if(io.onclick) this.element.onclick = io.onclick;
		if(io.onrollover) this.element.onmouseover = io.onrollover;
		if(io.onrollout) this.element.onmouseout = io.onrollout;
		if(io.onpress) this.element.onmousedown = io.onpress;
		if(io.onrelease) this.element.onmouseup = io.onrelease;
		if(io.ondouble) this.element.ondblclick = io.ondouble;
		if(io.onmove) this.element.onmousemove = io.onmove;
	}	
	if(this.width || this.height)
		this.setDimensions(this.width, this.height);
	if(this.x || this.y)
		this.setPosition(this.x, this.y);
	if(this.alpha)
		this.setOpacity(this.alpha);
	if(io)
		this.setHandlers(io);
	function isNum(num){ if(num==0) return true; if(!num) return false; else return typeof(num) == 'number' };	
}
function Animation(el, io){
	var This = this;
	this.element = new Element(el, io);
	var next = function(){ };
	var args = false;  
	this.cancel = function(){ this.time.reset(); this.time.stop(); } 
	this.update = function() { 
		var t = This.trans( This.time.getTime() / This.dur );
		if(isNum(da)){
			var na  = oa + (t * da);
			This.element.setOpacity(na);
		}
		if(isNum(dx) || isNum(dy)){
			var nx  = ox + t * dx;  	     
			var ny  = oy + t * dy;
			This.element.setPosition(nx, ny);
		}
		if(isNum(dw)){
			var nw  =  ow + (t * dw);  	     
		
			if(This.element.center){
				var cx = (This.element.width - nw) * This.element.center.x;
				This.element.setPosition( This.element.x + cx, This.element.y);
			}
			This.element.setWidth(nw);
		}
		if(isNum(dh)){
			var nh  =  oh + (t * dh);
			if(This.element.center){
				var cy = (This.element.height - nh) * This.element.center.y;
				This.element.setPosition( This.element.x, This.element.y + cy);			
			}
			This.element.setHeight(nh);			
		}
		if(observer) observer();
		if(t == 1){
			if(_effect.y && isNum(_effect.y)) This.element.element.style.top = _effect.y + 'px';
			if(_effect.x && isNum(_effect.x)) This.element.element.style.left = _effect.x + 'px';
			This.complete = true;
			try{ 
				 next(args);
				 next = new function(){};
			}catch(e){ }
		}
	}
	var _effect;
	var oa; var ox; var oy; var ow; var oh; 
	var da; var dx; var dy; var dw; var dh;
	this.effect = function(fect, after, afterArgs){
		if(This.complete){
			_effect = fect;
			if(fect.duration) This.dur = fect.duration;
			if(fect.fps) This.fps = fect.fps;
			if(fect.trans) This.trans = fect.trans;
			if(after) next = after;
			if(afterArgs) args = afterArgs;
			if(isNum(fect.alpha)){   oa = This.element.alpha;     da = fect.alpha - oa; }
			if(isNum(fect.width)){  ow = This.element.width;   dw = fect.width - ow;  }
			if(isNum(fect.height)){  oh = This.element.height;  dh = fect.height - oh; }
			if(isNum(fect.x)){	 ox = This.element.x;       dx = fect.x - ox;  }
			if(isNum(fect.y)){	  oy = This.element.y;	    dy = fect.y - oy; }
			This.complete = false;
			this.time.reset();
			this.time.start(This.dur, This.fps);  
		}
	}	
	var observer = false
	this.setUpdateObserver= function(obj){ observer = obj; }
	this.linear = function(x){ return x; }
	if(!io) io = { };
	this.time = new Timer(this.dur, this.fps, this.update);
	this.trans = (!io.trans) ? this.linear : io.trans;
	this.fps = (io.fps) ? io.fps : (1/24);
	this.dur = (io.duration) ? io.duration : 1;
	this.complete = true;
	function isNum(val) { 
		if(val==0) 
			return true; 
		else if(typeof(val) == 'number');
		 	return true;
		return false; }
}  
function Timer(duration, updateInterval, listener){
  	this.update = (updateInterval) ? updateInterval : (1/24);
	this.duration = (duration) ? duration : 1;
	this.listeners = new Array();
	if(listener) this.listeners.push(listener);
	var time = 0;  var timer = null;
	var self = this; var check;
	this.addListener = function(listenerObj){
		this.listeners.push(listenerObj);
	}	
	this.start = function(duration, interval){
		if(duration) this.duration = duration;
		if(interval) this.update = interval;
		check = this.update;
		run();
	}	
	this.stop = function(nocall){ 
		window.clearTimeout(timer);
		time = this.duration; 
		for(var l=0; l < self.listeners.length; l++)
			self.listeners[l].call(this, self); 		
	}							 
	this.getTime = function(){ return time; }
	this.reset = function() {  
		window.clearTimeout(timer); 
		time = 0; 
		check = 0; 
		timer = null; 
	}
    function run(){
		if(time <= self.duration){
			if(time >= check){
				for(var l=0; l < self.listeners.length; l++)
						self.listeners[l].call(this, self);
				check += self.update;	
			}
			time+= 0.01;			
			loop();
			return;	
		}
	  self.stop();
	}	
	function loop(){
		timer = window.setTimeout(run, 10);
	}
};
function Physics(){
	this.linear = function(x){ return x; }
	this.easeIn = function(x){ return Math.pow(x,2); }
	this.easeOut = function(x){ return 1 - Math.pow((x-1), 2); }
	this.sineWave = function(x){ return Math.sin(x*Math.PI/2); }
	this.spring = function(x){
		if(x < 0.65)
			return 1.1 * Math.sin(x * (Math.PI/1.5666) ); 
		else if(x < 1)
			return 1 + 0.1 * Math.sin(3.3 * (x +0.21) * Math.PI);	
		else
			return 1;		
	}	
	this.snap = function(x){ 
		if(x < 1)
			return 1.1 * Math.sin(x * (Math.PI/1.5666) );  
		else
			return 1;
	}
}
var physics = new Physics();
function EventInfo(e, cancel){
		if (!e) var e = window.event;			
		if (e.target) this.source = e.target;
		else if (e.srcElement) this.source = e.srcElement;
		if (this.source.nodeType == 3)
			this.source = this.source.parentNode;			
		if (e.pageX || e.pageY) {
			this.xmouse = e.pageX;
			this.ymouse = e.pageY;
		}
		else if (e.clientX || e.clientY) {
			this.xmouse = e.clientX + document.body.scrollLeft;
			this.ymouse = e.clientY + document.body.scrollTop;
		}		
		if(cancel){
			e.cancelBubble = true;
			if (e.stopPropagation) e.stopPropagation();
		}	
}

/**
/*  Generic cookie functions
**/
function cookies(){

	this.set = function(name, value, expires, path, domain, secure) {
  		var xtime = new Date(expires);
  		var curCookie = name + "=" + escape(value) +
      		((expires) ? "; expires=" + xtime.getUTCDate() : "") +
      		((path) ? "; path=" + path : "") +
      		((domain) ? "; domain=" + domain : "") +
      		((secure) ? "; secure" : "");
 		 document.cookie = curCookie;
	};

	this.get = function(name) {
  		var dc = document.cookie;
  		var prefix = name + "=";
  		var begin = dc.indexOf("; " + prefix);
  		if (begin == -1) {
   		 begin = dc.indexOf(prefix);
   		 if (begin != 0) return null;
  		} else
    		begin += 2;
  		var end = document.cookie.indexOf(";", begin);
  		if (end == -1)
    		end = dc.length;
  		return unescape(dc.substring(begin + prefix.length, end));
	};

	this.remove = function(name, path, domain) {
  		if (this.get(name)) {
    		document.cookie = name + "=" +
    		((path) ? "; path=" + path : "") +
    		((domain) ? "; domain=" + domain : "") +
    		"; expires=Thu, 01-Jan-70 00:00:01 GMT";
  		}
	};

	this.fixDate = function(date) {
  		var base = new Date(0);
  		var skew = base.getTime();
  		if (skew > 0)
    		date.setTime(date.getTime() - skew);
	};

}
var Cookies = new cookies();

String.prototype.html_entity_encode = function(quote_style){
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: nobbler
	    // +    tweaked by: Jack
	    // +   bugfixed by: Onno Marsman
	    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +    bugfixed by: Brett Zamir (http://brett-zamir.me)
	    // +      input by: Ratheous
	    // -    depends on: get_html_translation_table
	    // *     example 1: htmlentities('Kevin & van Zonneveld');
	    // *     returns 1: 'Kevin &amp; van Zonneveld'
	    // *     example 2: htmlentities("foo'bar","ENT_QUOTES");
	    // *     returns 2: 'foo&#039;bar'

	    var hash_map = {}, symbol = '', tmp_str = '', entity = '';
	    tmp_str = this.toString();

	    if (false === (hash_map = get_html_translation_table('HTML_ENTITIES', quote_style))) {
	        return false;
	    }
	    hash_map["'"] = '&#039;';
	    for (symbol in hash_map) {
	        entity = hash_map[symbol];
	        tmp_str = tmp_str.split(symbol).join(entity);
	    }

	    return tmp_str;
}

function get_html_translation_table (table, quote_style) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: noname
    // +   bugfixed by: Alex
    // +   bugfixed by: Marco
    // +   bugfixed by: madipta
    // +   improved by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Frank Forte
    // +   bugfixed by: T.Wild
    // +      input by: Ratheous
    // %          note: It has been decided that we're not going to add global
    // %          note: dependencies to php.js, meaning the constants are not
    // %          note: real constants, but strings instead. Integers are also supported if someone
    // %          note: chooses to create the constants themselves.
    // *     example 1: get_html_translation_table('HTML_SPECIALCHARS');
    // *     returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
    
    var entities = {}, hash_map = {}, decimal = 0, symbol = '';
    var constMappingTable = {}, constMappingQuoteStyle = {};
    var useTable = {}, useQuoteStyle = {};
    
    // Translate arguments
    constMappingTable[0]      = 'HTML_SPECIALCHARS';
    constMappingTable[1]      = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';

    useTable       = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';

    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: "+useTable+' not supported');
        // return false;
    }

    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }

    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';


    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }
    
    return hash_map;
}

