var el = function(e){
	this.version='0.8.4.0';
	this.by="Michael Markie";
	
	// Detect which method of elements that are used for example ID, Class, Tag Name or a Object.
	if(typeof e == "string"){
		// # defines a element ID, so here we check for a # and we also check it is a valid ID.
		if(e.substring(0,1) == "#" && document.getElementById(e.replace('#','')))
			this.e = document.getElementById(e.replace('#',''));
		// . defines a element Class
		else if(e.substring(0,1) == '.' && document.getElementsByClassName(e.replace('.','')))
			this.e = document.getElementsByClassName(e.replace('.',''));
		// No alphanumerics defines a Element Tag name, resulting in a array.
		else if(e.substring(0,1) != "#" && e.substring(0,1) != '.' && document.getElementsByTagName(e))
			this.e = document.getElementsByTagName(e);
	}else if(typeof e == "object")
		this.e=e;

	this.css = function(property,value){
		
		var propVal = [], elem = [];
		// Here we want to see if elem is an array if it isn't we want to turn it into an array with a single item.
		if(!isArray(this.e))
			elem[0] = this.e;
		else
			elem = this.e;

		// Here we check if property is a json object so if it isn't we can put property and value into similar setup with an array.
		if(typeof property == "string")
			propVal[property] = value;
		else
			for(var i in property)
				propVal[i] = property[i];

		for(var i in elem)
			if(typeof elem[i] == "object" && elem[i] != null)
				for(var c in propVal)
					if(elem[i].style){
						// We need to check if we are using css which is not cross browser compatible, so we look for opacity for example and also add the IE filter.
						if(c == "opacity"){
							if(IE){
								elem[i].style['filter']="alpha(opacity="+(propVal[c]*100)+")";
								elem[i].style['zoom']  =1;
							}
							elem[i].style['MozOpacity']  =propVal[c];
							elem[i].style['KhtmlOpacity']=propVal[c];
						}
						if(c == "borderRadius"){
							elem[i].style['MozBorderRadius']   =propVal[c];
							elem[i].style['WebkitBorderRadius']=propVal[c];
						}

						// Now we can set the main property.
						elem[i].style[c] = propVal[c];
					}

		elem=null; propVal=null;
		return this;
	};
	this.style = function(styleCode){
		var style = document.createElement('style');
		style.setAttribute("type", "text/css");
		if(style.styleSheet)
			style.styleSheet.cssText = styleCode;
		else
			style.appendChild(document.createTextNode(styleCode));
			
		document.getElementsByTagName('head')[0].appendChild(style);
		style = null;
		return this;
	};
	this.addClass = function(cls){
		if(isArray(this.e)){
			// If it is a array list loop through the elements and change the CSS values.
			for(var i in this.e){
				if(this.e[i].className)
					this.e[i].className+=" "+cls;
			}
		}else
			this.e.className+=" "+cls;
		return this;
	};
	this.removeClass = function(cls){
		if(isArray(this.e)){
			// If it is a array list loop through the elements and change the CSS values.
			for(var i in this.e){
				if(this.e[i].className){
					var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
					this.e[i].className = this.e[i].className.replace(reg,' ');
				}
			}
		}else{
			var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
			this.e.className = this.e.className.replace(reg,' ');
		}
		return this;
	};
	this.setClass = function(cls){
		this.e.className=cls;
		return this;
	};
	// Add content to the end of a object not overwriting what was previously their.
	this.append = function(text){
		if(isArray(this.e)){
			for(var i in this.e)
				this.e[i].innerHTML+=text;
		}else
			this.e.innerHTML+=text;
		return this;
	};
	// Input content into a object, overwriting what was previously their.
	this.content = function(text){
		if(isArray(this.e)){
			for(var i in this.e)
				this.e[i].innerHTML=text;
		}else
			this.e.innerHTML=text;
		return this;
	};
	this.createElement = function(ele){
		var cElement = document.createElement(ele);
		if(isArray(this.e)){
			for(var i in this.e){
				if(typeof this.e[i] == "object")
					this.e[i].appendChild(cElement);
			}
		}else
			this.e.appendChild(cElement);

		this.e = cElement;
		cElement=null;
		return this;
	};
	this.elert = function(str){
		el().notification.add({content:str,action:'stickie'});
		return this;
	};
	this.childElement = function(){
		if(this.e.children[0])
			this.e = this.e.children[0];
		return this;
	};
	this.setAttribute = function(name,value){
		this.e.setAttribute(name,value);
		return this;
	};
	this.parentElement = function(){
		if(this.e.parentNode)
			this.e = this.e.parentNode;
		return this;
	};
	this.ajax = function(v){
		var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"),
		e = this.e;
		if(xhr){
			xhr.onreadystatechange = function(){
				if(xhr.readyState != 4){
					if(typeof v.loading == "function")
						v.loading();
				}else{
					if(v.format == "xml"){
						var xmlDoc = xhr.responseXML;
					}else if(isset(v.attribute)){
						e[v.attribute]=xhr.responseText;
					}else if(isset(e)){
						if(v.overwrite)
							e.innerHTML=xhr.responseText;
						else
							e.innerHTML+=xhr.responseText;
					}else{
						var returnText = xhr.responseText;
					}

					if(typeof v.complete == "function"){
						v.complete(null,xmlDoc,returnText);
						e=null,xhr=null;
					}
				}
			};
			xhr.open((isset(v.type))?v.type:"GET",v.url,true); 
			xhr.send(null);
		}
		return this;
	};
	this.onClick = function(fn){
		this.e.onclick = fn;
		return this;
	};
	this.animate = function(v){
		// If you have around 3-4 animations running at once it will cause others to slow down so try and keep them minimal.
		if(this.e.style[v.property]){
			
			var px = this.e.style[v.property].match('px'),
			e = this.e;
			v.to = extractNumber(v.to);
			var start = (px == "px")?extractNumber(this.e.style[v.property]):parseFloat(this.e.style[v.property]);
			// Speed up IE animations.
			v.speed = isset(v.speed)?v.speed:((IE)?50:10);
			v.jump  = isset(v.jump)?v.jump:10;
			if(IE) v.jump = (v.jump*2);
			if(start<v.to){
				var animate = setInterval(function(){
					if(start<v.to){
						el(e).css(v.property,start+px);
						start=start+v.jump;
					}else{
						clearInterval(animate);
						el(e).css(v.property,v.to+px);
						if(typeof v.completed == "function")
							v.completed(e);
						px=null,start=null,e=null;
					}
				},v.speed);
			}else if(start>v.to){
				var animate = setInterval(function(){
					if(start>v.to){
						el(e).css(v.property,start+px);
						start=start-v.jump;
					}else{
						clearInterval(animate);
						el(e).css(v.property,v.to+px);
						if(typeof v.completed == "function")
							v.completed(e);
						px=null,start=null,e=null;
					}
				},v.speed);
			}else{
				el(e).css(v.property,v.to+px);
				if(typeof v.completed == "function")
					v.completed(e);
				px=null,start=null,e=null;
			}
		}
		return this;
	};
	// This will hopfully replace the animate function, using css3 transitions for the animation.
	this.css3Animate = function(v){
		// Detect which browser.
		var ua = navigator.userAgent,
			webkit = ua.indexOf('AppleWebKit/') > -1,
			moz = ua.indexOf('Gecko') > -1 && !webkit,
			opera = ua.indexOf('Opera') > -1;
		// If we know this browser works we will use it with css3 calls.
		if(webkit){
			var e = this.e;
			if(!isset(v.speed))
				v.speed = '1';
			// We want to use the right css calls which can vary from browser to browser.
			transprop = webkit?'webkitTransition':(moz?'MozTransition':(opera?'OTransition':'transition')),
			
			e.style[transprop]=v.property+' '+v.speed+'s ease';
			e.style[v.property]=v.to;
			
			// Set a timeout so for the duration of the animation so we know when it finishes, not 100% accurate but as accurate as it can be.
			setTimeout(function(){
				if(typeof v.completed == 'function')
					v.completed(e);
			},v.speed*1000);
		}else{
		// If the browser isn't supported we will fall back on the old animate function.
			return this.animate(v);
		}
	};
	this.ready = function(func){
		var oldonload = window.onload;
		if(typeof window.onload != "function"){
			window.onload = func;
		}else{
			window.onload = function(){
				oldonload();
				func();
			}
		}
	};


	if(this instanceof el)
		return this.el;
	else
		return new el(e);
};


////////////////////////////////////////////////////////////////
//////
///// This is for main functionaily and is not part of the framework.
//// So the framework provides generic functionality and below provides specific functionality such as a lightbox.
///
///////////////////////////////////////////////////////////////


el.libPlugins = function(v){

	////
	/// Lightbox begin
	//
	this.lightbox = function(v){
		var lbFunctions = {
			startContent	: '<div id=\'elLightboxLoading\'></div>',
			overlay     	: '<div id=\'elLightbox\'></div>',
			container   	: '<div id=\"elLightboxContent\"></div>',
			loadingPic		: '',
			tempWidth		: 0,	tempHeight		: 0,
			tempOffsetX		: 0,	tempOffsetY		: 0,
			loadedArray		: [],
			inputContent	: document.getElementById('elLightboxContent'),
			init			: function(v){
				// To keep it backwards compatible.
				if(v.onload){
					globalAnimation = v.animate,
					globalWidth 	= v.width,
					globalHeight 	= v.height;
					lbFunctions.onload(v);
				}
				if(v.open)
					lbFunctions.open(v);
				if(v.close)
					lbFunctions.close(v);
			},
			onload			: function(v){

				globalWidth     = isset(v.width)?extractNumber(v.width):300;
				globalHeight    = isset(v.height)?extractNumber(v.height):250;
				loadingPic      = isset(v.loadPic)?v.loadPic:'';

				document.getElementsByTagName('body')[0].innerHTML += this.container+this.overlay;

				el('#elLightbox').css('opacity','0.5').onClick(function(){ el().lightbox({close:true}); });
				el('#elLightboxContent')
					.css("width",globalWidth+"px")
					.css("height",globalHeight+"px")
					.css("marginLeft","-"+(globalWidth/2)+"px")
					.css("marginTop","-"+(globalHeight/2)+"px");

				el().style([
'#elLightboxLoading{ position:absolute; top:0px; left:0px; width:100%; height:100%; z-index:101; background:#fff url("'+loadingPic+'") no-repeat center; }',
'#elLightboxContent{ position:fixed; _position:absolute; top:50%; left:50%; z-index:100; background:#fff; border:1px solid #000; overflow:hidden; display:none; }',
'#elLightbox{ position:fixed; _position:absolute; top:0px; left:0px; z-index:99; height:100%; _height:'+document.documentElement.clientHeight+'px; width:100%; background:#000; display:none; }'
				].join(''));
			},
			open			:function(v){
				this.findContent(v);
				el('#elLightbox').css('display','block');
				el('#elLightboxContent').css('display','block');
			},
			close			:function(){
				el('#elLightbox').css('display','none');
				el('#elLightboxContent').content().css('display','none');
				el('#elLightboxLoading').css('display','block');
			},
			findContent		:function(v){
				// Our first check is going to check if the content is an ID
				if(document.getElementById(v.content)){
					this.inputContent.innerHTML = this.startContent+document.getElementById(v.content).innerHTML;
					this.loaded(5);
					this.resizeBox(v);
				// If we don't find an ID we check for an image else we assume its a URL, so we use ajax.
				}else{
					var urlCheck = new RegExp("png|jpg|jpeg|gif|bmp|tiff","g");
					// We check to see if content has image file extensions e.g. png, jpg and gif.
					if(urlCheck.test(v.content)){
						el('#elLightboxContent').content(this.startContent).append('<img src="'+v.content+'" id="elLightboxImage" />');
						//We want to check the image has fully loaded before removing the loading screen
						document.getElementById('elLightboxImage').onload=function(){
							lbFunctions.loaded(5);
							lbFunctions.resizeBox(v);
						};
						//In the event of a image not existing we will return an error
						document.getElementById('elLightboxImage').onerror=function(){
							el('#elLightboxContent').content(lbFunctions.startContent).append('Error image cannot be found try again later.');
							lbFunctions.loaded(1); lbFunctions.loaded(2); lbFunctions.loaded(3); lbFunctions.loaded(4); lbFunctions.loaded(5);
						};
					}else{
						el('#elLightboxContent').content(this.startContent).ajax({ url:v.content, complete:function(){
							lbFunctions.loaded(5);
							lbFunctions.resizeBox(v);
						}});
					}
				}
			},
			resizeBox		:function(v){
				this.tempOffsetX = extractNumber(isset(v.offsetX)?v.offsetX:0);
				this.tempOffsetY = extractNumber(isset(v.offsetY)?v.offsetY:0);
				var divNum = 1;
				
				
				//This is a simple fix when occasionally you get whitespace which will act as a childnode so we increase the div number to get the correct div.
				while(this.inputContent.childNodes[divNum] == "[object Text]" && this.inputContent.childNodes[divNum] != "undefined"){
					divNum++;
					if(divNum > 10)
						return;
				}
				
				this.tempWidth   = extractNumber(isset(v.width) ?v.width :computedStyle(this.inputContent.childNodes[divNum],'width'));
				this.tempHeight  = extractNumber(isset(v.height)?v.height:computedStyle(this.inputContent.childNodes[divNum],'height'));
				
				
				// We need to detect if current style returns auto if so we will get the width and height using offsetwidth and height.
				if(this.tempWidth == "0"){
					this.tempWidth = this.inputContent.childNodes[divNum].offsetWidth;
				}
				if(this.tempHeight == "0"){
					this.tempHeight = this.inputContent.childNodes[divNum].offsetHeight;
				}
				
				
				if(globalAnimation == false || v.animate == false){
					el('#elLightboxContent')
						.css('width',this.tempWidth+'px')
						.css('height',this.tempHeight+'px')
						.css('marginLeft','-'+(this.tempWidth/2+this.tempOffsetX)+'px')
						.css('marginTop','-'+(this.tempHeight/2+this.tempOffsetY)+'px');
					this.loaded(1);
					this.loaded(2);
					this.loaded(3);
					this.loaded(4);
				}else{
					var jumpSet = isset(v.jump)?v.jump:10;
						jumpSet = IE?jumpSet+20:jumpSet;
					var jumpSet2= jumpSet/2;
					var speedSet= isset(v.speed)?v.speed:6;
					el('#elLightboxContent')
						.animate({ property:'width',	 to:this.tempWidth,							 jump:jumpSet, speed:speedSet,completed:function(){lbFunctions.loaded(1);}})
						.animate({ property:'height',	 to:this.tempHeight,						 jump:jumpSet, speed:speedSet,completed:function(){lbFunctions.loaded(3);}})
						.animate({ property:'marginLeft',to:'-'+(this.tempWidth/2+this.tempOffsetX), jump:jumpSet2,speed:speedSet,completed:function(){lbFunctions.loaded(2);}})
						.animate({ property:'marginTop', to:'-'+(this.tempHeight/2+this.tempOffsetY),jump:jumpSet2,speed:speedSet,completed:function(){lbFunctions.loaded(4);}});
				}
				this.tempWidth   = null, this.tempHeight  = null,
				this.tempOffsetX = null, this.tempOffsetY = null;
			},
			loaded			:function(which){
				if(which < 6)
					this.loadedArray.push(which);

				if(this.loadedArray.length == 5)
					el('#elLightboxLoading').css('display','none');
			}
		};

		lbFunctions.init(v);

		return this;
	};
	////
	/// Lightbox End
	//

	////
	/// Smooth Scroll Start
	//
	this.smoothScroll = function(){
		currentScrollYPosition = function(){
			if(self.pageYOffset) // All other browsers
				return self.pageYOffset;
			if(document.documentElement && document.documentElement.scrollTop) // IE6 - Standards
				return document.documentElement.scrollTop;
			if(document.body.scrollTop) // IE6, 7 and 8
				return document.body.scrollTop;
			return 0;
		};

		var 
		i=0, c=0,
		startY 	 = currentScrollYPosition(),
		stopY  	 = getElementPosition(this.e).y,
		distance = (stopY > startY)?stopY - startY:startY - stopY,
		speed 	 = Math.round(distance / 200),
		step  	 = Math.round(distance / 25),
		leapY 	 = (stopY > startY)?startY + step:startY - step;

		if(stopY > startY){
			while(i<stopY){
				setTimeout("window.scrollTo(0,"+leapY+");",c*speed);
				leapY += step;
				if(leapY > stopY)
					leapY = stopY;
				c++,
				i+=step;
			}
		}else{
			i=startY;
			while(i>stopY){
				setTimeout("window.scrollTo(0,"+leapY+");",c*speed);
				leapY -= step;
				if(leapY < stopY)
					leapY = stopY;
				c++,
				i-=step;
			}
		}
		return this;
	};
	////
	/// Smooth Scroll End
	//

	////
	/// Location Hash Start
	//
	this.hash = {
		add: function(key,value){
			this.modify(key,value);
		},
		remove: function(key){
			// As the modify function deletes blank values we can just clear the value.
			this.modify(key,'');
		},
		modify: function(key,value){
			// Get the current hash array
			var get = el().hash.get();
			// If the value is empty we assume it'll be deleted so we delete it
			if(value == '')
				delete get[key];
			// Else we're going to add/change the key with the value.
			else
				get[key] = value;
			// Setup the new hash value.
			this.rebuild(get);
		},
		get: function(key){
			// Get the location.hash split it by ,
			var hashes = window.location.hash.replace('#','').split(','), get = [];
			for(var i in hashes){
				// Now split each one by : and add that to the array.
				get[hashes[i].split(':')[0]] = hashes[i].split(':')[1];
			}
			// Return either just the key value if key is set else return the whole shebang.
			return (isset(key))?get[key]:get;
		},
		rebuild: function(arr){
			var str='', c=0;
			for(var i in arr){
				// If they are not empty or set
				if(i != '' && isset(i) && isset(arr[i])){
					str += (c==0) ? i+":"+arr[i] : ","+i+":"+arr[i]+"";
					c++;
				}
			}
			window.location.hash=str;
		}
	};
	////
	/// Location Hash End
	//

	////
	/// Notification Start
	//
	this.notification = {
		boxCount:0,
		add: function(v){
			// Action - stickie or timed, default is timed.
			// content - what will go in the notification

			if(this.boxCount == 0){
				var div = document.createElement('div');
				div.setAttribute('id','noteArea');
				document.body.appendChild(div);
				div = null;

				// Setup the notification box style.
				styleCode = [
					"#noteArea{ width:300px; position:absolute; top:0px; right:10px; text-align:right; z-index:9999; }",
					".noteClose{ float:right; text-decoration:none; color:#FFF; font-size:14px; } ",
					".note{ background:#000; color:#FFF; display:inline-block; width:200px; ",
						"-webkit-border-radius:8px; -moz-border-radius:8px; border-radius:8px; box-shadow: 1px 5px 5px #000; ",
						"-moz-box-shadow: 1px 5px 5px #000; -webkit-box-shadow: 1px 5px 6px #000; padding:4px 10px; ",
						"opacity:0.8; font-size:13px; border:1px solid #FFF; text-align:left; margin:10px 0px 0px 0px; ",
					"}"].join('');
				el().style(styleCode);
			}

			this.boxCount++;

			// Setup the div we use for the notification box.
			var div = document.createElement('div');
			div.setAttribute('class','note');
			div.setAttribute('id','noteid'+this.boxCount);
			div.setAttribute('cache',this.boxCount);
			var a = '<a href="javascript:el().notification.remove(\'noteid'+this.boxCount+'\');" class="noteClose">x</a>';
			// Input the div onto the page.
			document.getElementById('noteArea').appendChild(div);

			var noteBox = document.getElementById('noteid'+this.boxCount);
			if(v.action != "stickie" || typeof v.action == "undefined"){
				var
				onload  = "";
				onload += "setTimeout(function(){";
				onload += 	"el().notification.remove('noteid"+this.boxCount+"');";
				onload += "},4000);";

				var script = document.createElement('script');
				script.setAttribute('type','text/javascript');
				script.text = onload;
				noteBox.appendChild(script);
			}
			// Input content and close button into the div created.
			noteBox.innerHTML=a+v.content;
			noteBox.cache = '1';
		},
		remove: function(id){
			document.getElementById(id).cache='0';
			document.getElementById(id).style.display='none';
			var noteArea = document.getElementById('noteArea');
			var oldnote = document.getElementById(id);
			noteArea.removeChild(oldnote);
		}
	};
	////
	/// Notification End
	//

	////
	/// User Tracking
	//
	this.userTrack = function(v){

		var userTrackFunctions = {
			userInactive:false,
			pageCallback:v.url,
			mouseTrack:[],
			htmlPage: document.getElementsByTagName('html')[0],
			clickTracking: function(){
				this.htmlPage.onclick = function(){
					userTrackFunctions.callPage('?clickTracking=true&x='+(event.clientX+document.body.scrollLeft)+'&y='+(event.clientY+document.body.scrollTop));
				};
			},
			userActivity: function(on,userInactive,userActive){
				this.resetActivity(userInactive,userActive);
				on = on.split(',');
				for(var i in on){
					if(on[i].toLowerCase() == "onclick"){
						document.getElementsByTagName('body')[0].onclick = function(){
							userTrackFunctions.resetActivity(userInactive,userActive);
						};
					}else{
						this.htmlPage[on[i]] = function(){
							userTrackFunctions.resetActivity(userInactive,userActive);
						};
					}
				}
			},
			resetActivity: function(userInactive,userActive){
				if(typeof countdownTime != "undefined"){
					if(this.userInactive){
						if(typeof userActive == "function")
							userActive();
						userTrackFunctions.callPage('?userActivity=true&userActive=true');
					}
					this.userInactive = false;
					clearTimeout(countdownTime);
				}
				countdownTime = setTimeout(function(){
					if(typeof userInactive == "function")
						userInactive();
					userTrackFunctions.userInactive=true;
					userTrackFunctions.callPage('?userActivity=true&userActive=false');
				},2000);
			},
			trackMouse: function(){
				this.htmlPage.onmousemove = function(){
					userTrackFunctions.mouseTrack.push('_'+(event.clientX+document.body.scrollLeft)+','+(event.clientY+document.body.scrollTop));
				};
				setInterval(function(){
					if(userTrackFunctions.mouseTrack.join('') != ""){
						userTrackFunctions.callPage('?trackMouse=true&coordinates='+userTrackFunctions.mouseTrack.join(''));
						userTrackFunctions.mouseTrack=[];
					}
				},1000);
			},
			callPage: function(data,fn){
				if(this.pageCallback != ""){
					el().ajax({ url:this.pageCallback+data,type:"HEAD",completed:function(){
						if(typeof fn == "function")
							fn();
					} });
				}
			}
		};

		if(v.userActivity)
			userTrackFunctions.userActivity(v.userActivity,v.userInactive,v.userActive);
		if(v.clickTracking)
			userTrackFunctions.clickTracking();
		if(v.mouseTrack)
			userTrackFunctions.trackMouse();
		return this;
	};
	////
	/// User Tracking End
	//

	////
	/// Preload Images Start
	//
	this.preloadImages = function(fn){
		var loaded = false;
		loadCheck = function(num1,num2){
			if(num1>=(num2-1)){
				loaded=true;
				if(typeof fn == "function")
					fn();
			}
		};
		var newImg = [];
		for(var i=1; i<arguments.length; i++){
			newImg[i] = new Image();
			newImg[i].src = arguments[i];
		}
		for(var c in newImg){
			newImg[c].onload = function(){
				if(!loaded)
					loadCheck(c,i);
			};
			newImg[c].onerror = function(){
				if(!loaded)
					loadCheck(c,i);
			};
		}
		return this;
	};
	////
	/// Preload Images End
	//
};
el.prototype = new el.libPlugins();

////////////////////////////////////////////////////////////////
///////
////// This sets global variables used in el lib, but is setup as global
///// to be used across the site within other librarys.
//// Was previously stored within global.js
///
///////////////////////////////////////////////////////////////

var
IE  = navigator.userAgent.indexOf('MSIE')   != -1,
IE6 = navigator.userAgent.indexOf('MSIE 6') != -1,
IE7 = navigator.userAgent.indexOf('MSIE 7') != -1,
IE8 = navigator.userAgent.indexOf('MSIE 8') != -1;

isset = function(v){ return typeof v != 'undefined'; };
empty = function(v){ return v == ''; };
isString = function(v){ return v == 'string'; };
isArray = function(v){ if(typeof v != "undefined") return(v == '[object NodeList]' || v == '[object HTMLCollection]' || v.length >= 1) && isset(v); };
inArray = function(needle, haystack, argStrict){
	var key = '',
		strict = !! argStrict;

	if(strict)
		for(key in haystack)
			if(haystack[key] === needle)
				return true;
			else
				for(key in haystack)
					if(haystack[key] == needle)
						return true;
			return false
};

extractNumber = function(value){ var n=parseInt(value); return n==null||isNaN(n)?0:n; };
ComputedStyle = function(e,v){ if(isString(e)) e=document.getElementById(e); return e.currentStyle?e.currentStyle[v]:document.defaultView.getComputedStyle(e,null).getPropertyValue(v); };
computedStyle = function(e,v){ if(isString(e)) e=document.getElementById(e); return e.currentStyle?e.currentStyle[v]:document.defaultView.getComputedStyle(e,null).getPropertyValue(v); };
if(!document.getElementsByClassName){
	document.getElementsByClassName = function(className){
		var children = document.getElementsByTagName('*') || document.all, elements = new Array();
		for(var i in children){
			var	child = children[i];
			if(isset(child)){
				if(child.className){
					var classNames = child.className.split(' ');
					for(var j in classNames){
						if(classNames[j] == className){
							elements.push(child);
							break;
						}
					}
				}
			}
		}
		return elements;
	};
}
var timer = {
	start:function (){
		d = null,
		time = null;
		d = new Date();
		time = d.getTime();
	},
	end: function (){
		d = new Date();
		return (d.getTime() - time);
	}
};
log = {debug:function(m){},info:function(m){},warn:function(m){},error:function(m){}};
getElementPosition = function(v){
	var left = v.offsetLeft,
		top = v.offsetTop;
	while(v.offsetParent && v.offsetParent != document.body){
		v = v.offsetParent;
		left += v.offsetLeft;
		top += v.offsetTop;
	}
	return {
		x: left,
		y: top
	}
};
mousePosition = function(relative){
	var e = e||window.event,
		dp = document.body.parentElement,
		ofY = window.pageYOffset,
		ofX = window.pageXOffset;
	return {
		x:e.clientX+parseInt(ofX?ofX:dp.scrollLeft)-getElementPosition(relative).x,
		y:e.clientY+parseInt(ofY?ofY:dp.scrollTop)-getElementPosition(relative).y
	}
};
scrollPosition = function(){
	var 	e = e||window.event,
			dp = document.body.parentElement,
			ofY = window.pageYOffset,
			ofX = window.pageXOffset;
	return {
		x:e.clientX+parseInt(ofX?ofX:dp.scrollLeft),
		y:e.clientY+parseInt(ofY?ofY:dp.scrollTop)
	}
};
