/*!
 *
 *	JELLY JavaScript Library by Peter Boere --// v. 1.08 //-- 
 *
 * Goals of library: 
 *		One global variable - risk of clashing with other scripts is minimized
 * 	Preserve standard JavaScript API - enhance not reinvent
 *		Powerful and Lightweight - Crossbrowser events, animation, ajax etc. without the bloat
 *
 * Browser support:
 *		A-Grade browsers - as defined by Yahoo! Yui http://developer.yahoo.com/yui/articles/gbs/
 *
 */

var JELLY = function () {
	var jelly = {
		
		/* ----->  WORKING WITH ELEMENTS  <-----
		*/
		addClass: function(el, cn) {
			el.className += el.className ? ' ' + cn : cn;
		},
		removeClass: function(el, cn) {
			var patt = new RegExp('(^|\\s|\\b)' + cn + '(\\s|$)', 'g');
			el.className = el.className.replace(patt, ' ').normalize();
		},
		hasClass: function(el, cn) {
			var patt = new RegExp('(^|\\s)' + cn + '(\\s|$)');
			return patt.test(el.className);
		},
		toggleClass: function(el, cn){
			JELLY.hasClass(el, cn) ? JELLY.removeClass(el, cn) : JELLY.addClass(el, cn);
		},
		createElement: function(type, args) {
			var el = document.createElement(type);
			for (var i in args) {
				switch (i) {
				case 'setHTML' : el.innerHTML = args[i]; break;
				case 'class' : el.className = args[i]; break;
				case 'style' : el.style.cssText = args[i]; break;
				default : el.setAttribute(i, args[i]);
				}
			}
			return el;
		},
		insertElement: function (el, datum, type) {
			type = type || 'bottom';
			switch (type) {
			case 'before' : return datum.parentNode.insertBefore(el, datum);
			case 'after'  : return datum.parentNode.insertBefore(el, datum.nextSibling);
			case 'top'    : return datum.insertBefore(el, datum.firstChild);
			default       : return datum.appendChild(el);
			}
		},
		replaceElement: function (el, replacement) {
			return el.parentNode.replaceChild(replacement, el);
		},
		removeElement: function (el) {
			return el.parentNode.removeChild(el);
		},
		getRelative: function (el, type, opt) {
			switch (type) {
			case 'next'     : return walk(el, 'sibling', {type : 'next', factor : opt});
			case 'previous' : return walk(el, 'sibling', {type : 'previous', factor : opt});
			case 'first'    : return walk(el, 'child',   {type : 'first'});
			case 'last'     : return walk(el, 'child',   {type : 'last'});
			case 'parent'   : return walk(el, 'parent',  {factor : opt});
			}
		},
		getXY: function (el) {
			var xy = [0,0];
			while (el != null)  {
			 xy[0] += el.offsetLeft;
			 xy[1] += el.offsetTop;
			 el = el.offsetParent;
			}
			return xy;
		},
		getStyle: function ( el, prop, parseint ) {
			var value;
			if (prop == 'opacity') { 
				if (el.__opacity == undefined) el.__opacity = 1;
				return el.__opacity;
			}
			if (el.style[prop]) {
				value = el.style[prop];
			} else if (el.currentStyle) {
				value = el.currentStyle[prop]; 
			} else if (document.defaultView && document.defaultView.getComputedStyle) {
				prop = prop.toCssCase();
				var s = document.defaultView.getComputedStyle(el, "");
				value = s ? s.getPropertyValue(prop) : null;
			} else return null;
			if (prop.toLowerCase().indexOf('color') != -1) {
				return value.cssColorToArray();
			}
			return parseint !== false ? parseInt(value, 10) : value;
		},
		setOpacity: function (el, val) {
			if (el.filters) {
				JELLY.setOpacity = function (el, val) {
					if (el.__opacity == undefined) el.__opacity = 1;		
					el.style.filter = (val == 1) ? '' : 'alpha(opacity=' + val * 100 + ')';
					el.__opacity = val;
				};
			} else {
				JELLY.setOpacity = function (el, val) {
					if (el.__opacity == undefined) el.__opacity = 1;		
					el.style.opacity = el.__opacity = val;
				};
				
			}
			JELLY.setOpacity(el, val);
		},
		getByClass: function (cn, els) {
			var arr = [],
				 els = els || document.getElementsByTagName('*'),
			    patt = new RegExp('(^|\\s)' + cn + '(\\s|$)');
			for (var i = 0, len = els.length; i < len; i++) {
				if (patt.test(els[i].className)) arr[arr.length] = els[i];
			}
			return arr;
		},
		Q: function (arg) {
			var A = arg,
				 E = function (str) {return document.getElementById(str);},
				 Arr = function (coll) {
					var i, len=coll.length, arr = [];
					for (i = 0; i < len; i++) arr[i] = coll[i];
				 	return arr;
				 }, 
				 EE = function (tag, node) {
				 	return Arr((node || document).getElementsByTagName(tag));
				 },
				 getClass = JELLY.getByClass;
			if (A.item && typeof A.length != undefined) 
				return Arr(A);	
			else A.normalize();
			if (!A.has(' ')) { 
				if (A.has('#')) return E(A.split('#')[1]);	
				if (!A.has('.')) {
					return EE(A);	
				} else {
					if (A.split('.')[0] != '') { 
						return getClass(A.split('.')[1], EE(A.split('.')[0]));
					} else { 
						return getClass(A.split('.')[1]);
					}
				}
			} else {
				var parts = A.split(' '), 
					 id = parts[0].has('#') ? id = E(parts[0].split('#')[1]) : false;
				if (id) {
					if (!parts[1].has('.')) {
						return EE(parts[1], id);	
					} else { 
						if (parts[1].split('.')[0] != '') {
							return getClass(parts[1].split('.')[1], EE(parts[1].split('.')[0], id));
						} else {
							return getClass(parts[1].split('.')[1], EE('*', id));
						}
					}
				} else {
					var pt1, pt2, uniques = [], returns = [];
					if (parts[0].has('.')) {
						pt1 = parts[0].split('.')[0] ?
							getClass(parts[0].split('.')[1], EE(parts[0].split('.')[0])) : 
							getClass(parts[0].split('.')[1]);
					} else {
						pt1 = EE(parts[0]);
					}
					pt2 = !parts[1].has('.') ? 'tag' : parts[1].split('.')[0]!='' ? 'tag.class' : '.class';
					var len = pt1.length, i=0, c, cn, tn;
					switch (pt2) {
					case 'tag' :
						for (i; i < len; i++) {
							c = EE(parts[1], pt1[i]);
							if (c.length !== 0) returns = returns.concat(c);
						} break;
					case 'tag.class' :
						cn = parts[1].split('.')[1];
						tn = parts[1].split('.')[0];
						for (i; i < len; i++) {
							c = getClass(cn,  EE(tn, pt1[i]));
							if (c.length !== 0) returns = returns.concat(c);
						} break;
					case '.class' :
						cn = parts[1].split('.')[1];
						for (i; i < len; i++) {
							c = getClass(cn, EE('*', pt1[i]));
							if (c.length !== 0) returns = returns.concat(c);
						}
					}
					while (returns[0]) {
						c = returns.pop();
						if (c.__Q_marked == undefined) {
							c.__Q_marked = true; 
							uniques[uniques.length] = c;
						}
					}
					for (i=0; uniques[i]; i++) uniques[i].__Q_marked = undefined;
					return uniques;
				}			
			}
		},
		
		/* ----->  EVENTS  <-----
		*/
		addEvent: function ( obj, type, fn ) {
			var W3C = !!obj.addEventListener, 
				 JScript = !!obj.attachEvent, 
				 mouseEnter = type.has('mouseenter'),
				 mouseLeave = type.has('mouseleave'),
				 host = arguments.callee,
				 wrapper;
			if (JScript && !W3C) {
				wrapper = function (e) {
					e = JELLY.fixEvent(e);
					fn.call(obj, e);
				};
			}
			if (mouseEnter || mouseLeave) {
				wrapper = function (e) {
					e = JELLY.fixEvent(e);
					if (!JELLY.mouseEnterLeave.call(obj, e)) return;
					fn.call(obj, e);
				};
				type = mouseEnter ? 'mouseover' : 'mouseout';
			}
			host.log = host.log || [];
			host.log.push([ obj, type, wrapper || fn ])
			if (W3C) return obj.addEventListener( type, wrapper || fn, false );
			if (JScript) return obj.attachEvent( "on"+type, wrapper );
			return false;
		},
		removeEvent: function ( obj, type, fn ) {
			!!obj.removeEventListener ? 
				obj.removeEventListener(type, fn, false) :
				obj.detachEvent('on'+type, fn);
		},
		purgeEventLog: function () {
			if (JELLY.addEvent.log.length > 1) {
				var arr = JELLY.addEvent.log, i, c;
				for (i = 0; arr[i]; i++) {
					c = arr[i];					
					JELLY.removeEvent(c[0], c[1], c[2])
				}
			}
		}, 
		fixEvent: function (e) {
			e = e || window.event;
			if (window.event && !window.opera) {
				e.target = e.srcElement;
				e.relatedTarget = function () {
					switch (e.type) {
					case 'mouseover' : return e.fromElement;
					case 'mouseout' : return e.toElement;
					}		 
				}();
				e.stopPropagation = function () {e.cancelBubble = true;};
				e.preventDefault = function () {e.returnValue = false;};
				e.pageX = e.clientX + document.documentElement.scrollLeft;
				e.pageY = e.clientY + document.documentElement.scrollTop;
			}
			return e;
		},
		mouseEnterLeave: function (e) { 
			var related, i;
			if (e.relatedTarget) {
				related = e.relatedTarget;
				if (related.nodeType != 1 || related == this) return false;
				var children = this.getElementsByTagName('*');
				for (i=0; children[i]; i++) {
					if (related == children[i]) return false;
				}
			}
			return true;
		},
		stopEvent: function (e) {
			e = JELLY.fixEvent(e);
			e.stopPropagation();
			e.preventDefault();
		},
				
		/* ----->  UTILITIES  <-----
		*/
		getViewport: function () {
			if (typeof window.innerWidth != 'undefined') {
  				return [window.innerWidth,window.innerHeight];
			} else if (typeof document.documentElement != 'undefined' && 
				 typeof document.documentElement.clientWidth != 'undefined'	&& 
				 document.documentElement.clientWidth != 0) {
				return [document.documentElement.clientWidth, 
						  document.documentElement.clientHeight];
			} else {
				return [document.body.clientWidth || 0, 
						  document.body.clientHeight || 0];
			}
		},
		parseQueryString: function (el) {
			el = el || window;
			if (el.href.has('?')) {
				var queries = el.href.split('?')[1].split('&'),
					 i = queries.length-1,
					 pairs = {};
				do {
					var splt = queries[i].split('=');
					pairs[splt[0]] = splt[1];
				} while (i--)
				return pairs;
			} return false;
		},
		extend: function (obj, extentions, overwrite) {
			var i;
			if (overwrite !== false) for (i in extentions) obj[i] = extentions[i];
			else for (i in extentions) if (!obj[i]) obj[i] = extentions[i];
			return obj;
		},
		createClass: function() {
			return function() {
				this.initialize.apply(this, arguments);
			};
		},
		browser: {
			ie: !!window.ActiveXObject,
			ie6: !!(window.ActiveXObject && !window.XMLHttpRequest),
			ie7: !!(window.ActiveXObject && window.XMLHttpRequest)
		},
		local: "for(var i in JELLY){if(i!='local')eval('var '+i+'=JELLY.'+i)};i=undefined;"
	}; 

	function walk(elem, mode, opts) {
		var factor = opts.factor || 1;
		switch (mode) {
		case 'sibling' : 
			do {
				do {
					elem = elem[opts.type + 'Sibling'];
				} while (elem && elem.nodeType != 1); 
			 } while (elem && --factor);
		break;
		case 'child' : 
			if (opts.type == 'first') {
				elem = elem.firstChild;
				while (elem && elem.nodeType != 1) {
					elem = elem.nextSibling;
				}
			} else if (opts.type == 'last') {
				elem = elem.lastChild;
				while (elem && elem.nodeType != 1) {
					elem = elem.previousSibling;
				}  
			};
		break;
		case 'parent' : 
			do {
				elem = elem.parentNode;
			} while (elem && --factor);
		}
		return elem || false;
	}
	
	return jelly;

}(); 


JELLY.extend(Array.prototype, {
		forEach: function(fn, bind){
			for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this);
		}
}, false);
Array.prototype.each = Array.prototype.forEach;

JELLY.extend(Function.prototype, {	
	bind: function(obj) {
		var method = this;
		return function() {
			return method.apply(obj, arguments);
		};
	}
});

JELLY.extend(String.prototype, {
	has: function (test) {
		return this.indexOf(test) != -1 ? true : false;
	},
	trim: function () {
		return this.replace(/^\s+|\s+$/g, '');
	},
	normalize: function () {
		return this.replace(/\s{2,}/g, ' ').trim();
	},
	toCssCase: function () {
		return this.replace(/([A-Z])/g,"-$1").toLowerCase();
	},
	cssToCamelCase: function () {
		return this.replace(/-\D/gi, function(match){
			return match.charAt(match.length - 1).toUpperCase();
		});
	},
	cssRgbToHex: function () {
		var rgb = this.match(/[\d]{1,3}/g), hex = [], i;
		for (i = 0; i < 3; i++){
			var bit = (rgb[i]-0).toString(16);
			hex.push(bit.length == 1 ? '0'+bit : bit);
		}
		return '#'+hex.join('');
	},
	cssHexToArray: function () {
		var hex = this.match(/^#([\w]{1,2})([\w]{1,2})([\w]{1,2})$/), rgb = [], i;
		for (i = 1; i < hex.length; i++) {
			if (hex[i].length == 1) hex[i] += hex[i];
			rgb.push(parseInt(hex[i], 16));
		}
		return rgb;
	},
	cssColorToArray: function () {
		if (this.has('#')) return this.cssHexToArray();
		return this.cssRgbToHex().cssHexToArray();
	}
}, false);

if (JELLY.browser.ie6) try {document.execCommand('BackgroundImageCache', false, true);} catch(e) {};
JELLY.addClass(document.documentElement, 'js');
JELLY.addEvent(window, 'unload', JELLY.purgeEventLog);

/*!
 *
 * AJAX MODULE
 * 
 */
JELLY.Ajax = function (el, options) {
	this.updateElement = el;
	JELLY.extend(this, options || {});
	this.feedbackElement = this.feedbackElement || this.updateElement;
}

JELLY.Ajax.prototype = {
	
	onstart: function () {},
	onsuccess: function () {this.updateElement.innerHTML = this._xhr.responseText;},
	oncomplete: function () {},
	ontimeout: function () {alert('Server Busy');},
	timeout: 12000,
	nocache: false,

	feedback: function (bool) {
		this.inprogress = bool;
		bool ? JELLY.addClass(this.feedbackElement, this.feedbackClass) :
			   JELLY.removeClass(this.feedbackElement, this.feedbackClass);
	},
	
	feedbackClass: 'loading',
		
	getXHR: function () {
		var xhr = false;
		if (window.XMLHttpRequest) {
			xhr = new XMLHttpRequest();
		} else if (window.ActiveXObject) {
			try {
			xhr = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
				 xhr = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}
		return xhr;
	},
	
	httpSuccess: function () {
		return !!(
			this._xhr.readyState == 4 && (
				this._xhr.status == 200 || 
				this._xhr.status == 304 || 
				(this._xhr.status == undefined && /webkit/.test(navigator.userAgent.toLowerCase())))
		);
	},
	
	httpFail: function () {
		if (this._xhr !== null) this._xhr.abort(); 
		this.feedback(false);
		this.ontimeout();
	},
	
	request: function (file, options) {
		var data;
		if (options.formElement) {
			this._xhr.open("POST", file, true);
			this._xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			data = this.serializeFormData(options.formElement);
		} else {
			this._xhr.open("GET", file, true);
		}
		if (this.nocache) this._xhr.setRequestHeader("If-Modifed-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
		this._xhr.send(data || null);
	},
	
	send: function (file, options) {
		if (this.inprogress) return false;
		this._xhr = this.getXHR();
		if (this._xhr) {
			this.feedback(true);
			this.onstart();
			var that = this;
			this._xhr.onreadystatechange = function () {
				if (that.httpSuccess()) {
					clearTimeout(that.timer);
					that.onsuccess();
					that.feedback(false);
					that.oncomplete();
					that._xhr = null;
				} 
			};
			this.timer = setTimeout(function () {that.httpFail.call(that);}, this.timeout);
			this.request(file, options || {});
			return true;
		}
		return false;
	},
	
	serializeFormData: function (form) {
		var data = [], 
			radio_groups = [],
			field, unique, i, j;
		function append(field, value) {
			data[data.length] = (field.name + '=' + encodeURIComponent(value).replace(/%20/g, '+'));
		}
		for (i = 0; i < form.elements.length; i++) {
			field = form.elements[i];
			switch (field.nodeName.toLowerCase()) {
				case 'input' : 
					switch (field.type.toLowerCase()) {
						case 'submit': break;
						case 'checkbox': 
							if (field.checked) append(field, field.value || 'on');
						break;
						case 'radio':
							unique = true;
							for (j = 0; j < radio_groups.length; j++)
								if (radio_groups[j] == field.name) unique = false;
							if (unique) radio_groups[radio_groups.length] = field.name;
						break;
						default: append(field, field.value); 
					}
				break;
				default : append(field, field.value); 
			}
		}
		for (i = 0; i < radio_groups.length; i++) {
			var group = form[radio_groups[i]];
			for (j = 0; j < group.length; j++) {
				if (group[j].checked) {
					append(group[j], group[j].value || 'on');
					break;
				}
			}
		}
		return data.join('&');
	}

};

/*!
 *
 * ANIMATION MODULE  
 * Credits : Moofx, Transition equations by Robert Penner.
 *
 */

JELLY.transitions={linear:function(B,A,D,C){return D*B/C+A},quadIn:function(B,A,D,C){return D*(B/=C)*B+A},quadOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A},quadInOut:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A}return -D/2*((--B)*(B-2)-1)+A},cubicIn:function(B,A,D,C){return D*(B/=C)*B*B+A},cubicOut:function(B,A,D,C){return D*((B=B/C-1)*B*B+1)+A},cubicInOut:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B+A}return D/2*((B-=2)*B*B+2)+A},quartIn:function(B,A,D,C){return D*(B/=C)*B*B*B+A},quartOut:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A},quartInOut:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A}return -D/2*((B-=2)*B*B*B-2)+A},quintIn:function(B,A,D,C){return D*(B/=C)*B*B*B*B+A},quintOut:function(B,A,D,C){return D*((B=B/C-1)*B*B*B*B+1)+A},quintInOut:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B*B+A}return D/2*((B-=2)*B*B*B*B+2)+A},sineIn:function(B,A,D,C){return -D*Math.cos(B/C*(Math.PI/2))+D+A},sineOut:function(B,A,D,C){return D*Math.sin(B/C*(Math.PI/2))+A},sineInOut:function(B,A,D,C){return -D/2*(Math.cos(Math.PI*B/C)-1)+A},expoIn:function(B,A,D,C){return(B==0)?A:D*Math.pow(2,10*(B/C-1))+A},expoOut:function(B,A,D,C){return(B==C)?A+D:D*(-Math.pow(2,-10*B/C)+1)+A},expoInOut:function(B,A,D,C){if(B==0){return A}if(B==C){return A+D}if((B/=C/2)<1){return D/2*Math.pow(2,10*(B-1))+A}return D/2*(-Math.pow(2,-10*--B)+2)+A},circIn:function(B,A,D,C){return -D*(Math.sqrt(1-(B/=C)*B)-1)+A},circOut:function(B,A,D,C){return D*Math.sqrt(1-(B=B/C-1)*B)+A},circInOut:function(B,A,D,C){if((B/=C/2)<1){return -D/2*(Math.sqrt(1-B*B)-1)+A}return D/2*(Math.sqrt(1-(B-=2)*B)+1)+A},elasticIn:function(C,A,G,F,B,E){if(C==0){return A}if((C/=F)==1){return A+G}if(!E){E=F*0.3}if(!B){B=1}if(B<Math.abs(G)){B=G;var D=E/4}else{var D=E/(2*Math.PI)*Math.asin(G/B)}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A},elasticOut:function(C,A,G,F,B,E){if(C==0){return A}if((C/=F)==1){return A+G}if(!E){E=F*0.3}if(!B){B=1}if(B<Math.abs(G)){B=G;var D=E/4}else{var D=E/(2*Math.PI)*Math.asin(G/B)}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A},elasticInOut:function(C,A,G,F,B,E){if(C==0){return A}if((C/=F/2)==2){return A+G}if(!E){E=F*(0.3*1.5)}if(!B){B=1}if(B<Math.abs(G)){B=G;var D=E/4}else{var D=E/(2*Math.PI)*Math.asin(G/B)}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A},backOffset:1.70158,backIn:function(B,A,E,D,C){if(!C){C=JELLY.transitions.backOffset}return E*(B/=D)*B*((C+1)*B-C)+A},backOut:function(B,A,E,D,C){if(!C){C=JELLY.transitions.backOffset}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A},backInOut:function(B,A,E,D,C){if(!C){C=JELLY.transitions.backOffset}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A},bounceIn:function(B,A,D,C){return D-JELLY.transitions.bounceOut(C-B,0,D,C)+A},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A}else{return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A}}}},bounceInOut:function(B,A,D,C){if(B<C/2){return JELLY.transitions.bounceIn(B*2,0,D,C)*0.5+A}return JELLY.transitions.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A}};


JELLY.Tween = JELLY.createClass();
JELLY.Tween.prototype = {

	setOptions: function (options) {
		this.options = JELLY.extend({
			onstart: function(){},
			oncomplete: function(){},
			transition: JELLY.transitions.sineInOut,
			duration: 500,
			unit: 'px',
			wait: false,
			speed: 20
		}, options || {});
	},

	initialize: function (el, options) {
		this.element = typeof el == 'string' ?	document.getElementById(el) : el;
		this.setOptions(options);
	},

	step: function () {
		var time = new Date().getTime();
		if (time < this.time + this.options.duration) {
			this.cTime = time - this.time;
		} else {
			setTimeout(this.options.oncomplete.bind(this, this.element), 10);
			this.clearTimer();
			this.tidyUp();
			return this.callChain();
		}
		this.increase();
	},
	
	increase: function () {
		var i = this.props.length-1, matrix;
		do {
			if (this.values[i].color) {
				matrix = 
					Math.round(this.compute(this.values[i][0][0], this.values[i][1][0])) + ',' +
					Math.round(this.compute(this.values[i][0][1], this.values[i][1][1])) + ',' +
					Math.round(this.compute(this.values[i][0][2], this.values[i][1][2]));
				this.setColor( this.props[i], matrix );
			} else {
				this.setStyle( this.props[i], this.compute( this.values[i][0], this.values[i][1] ) );
			}
		} while (i--)
	},
	
	tidyUp: function () {
		var i = this.props.length-1, matrix;
		do {
			if (this.values[i].color) {
				matrix = [ this.values[i][1][0], this.values[i][1][1], this.values[i][1][2] ].join(',');
				this.setColor( this.props[i], matrix );
			} else {
				this.setStyle( this.props[i], this.values[i][1] );
			}
		} while (i--)
	},

	compute: function (from, to) {
		return this.options.transition(this.cTime, from, (to - from), this.options.duration);
	},

	clearTimer: function () {
		clearInterval(this.timer);
		this.timer = null;
		return this;
	},

	start: function (props, values) {
		if (!this.options.wait) this.clearTimer();
		if (this.timer) return;
		setTimeout(this.options.onstart.bind(this, this.element), 10);
		if (typeof props != 'string') {
			this.props = props;
			this.values = values;
		} else {
			this.props = [props];
			this.values = [values];
		}
		var i = this.values.length-1;
		do {
			this.props[i] = this.props[i].cssToCamelCase();
			if (this.props[i].toLowerCase().indexOf('color') != -1) {
				if (this.values[i].constructor != Array) {	
					this.values[i] = [JELLY.getStyle(this.element, this.props[i]), this.values[i].cssHexToArray()];
				} else this.values[i] = [this.values[i][0].cssHexToArray(), this.values[i][1].cssHexToArray()];
				this.values[i].color = true;
			} else {
				if (this.values[i].constructor != Array) 
					this.values[i] = [JELLY.getStyle(this.element, this.props[i]), this.values[i]]; 
			}
		} while (i--)
		this.time = new Date().getTime();
		this.timer = setInterval(this.step.bind(this), this.options.speed);
		return this;
	},
	
	setStyle: function (p, val) {
		p == 'opacity' ? JELLY.setOpacity(this.element, val) : this.element.style[p] = val + this.options.unit;
	},
	
	setColor: function (p, val) {
		this.element.style[p] = 'rgb(' + val + ')';
	},

	chain: function (fn) {
		this.chains = this.chains || [];
		this.chains.push(fn);
		return this;
	},

	callChain: function () {
		if (this.chains && this.chains.length) {
			var that = this;
			setTimeout( function () {that.chains.shift()()} , 10);
		}
	}

};
/*!
 *
 * SCROLL CLASS   
 *
 */

JELLY.Scroll = JELLY.createClass();
JELLY.Scroll.prototype = JELLY.extend(new JELLY.Tween(), {
																		
	start: function (x, y) {
		if (!this.options.wait) this.clearTimer();
		if (this.timer) return;
		setTimeout(this.options.onstart.bind(this, this.element), 10);
		if (this.element == window) {
			var winpos = this.getWindowScroll();
			if (x.constructor != Array) x = [winpos[0], x];				
			if (y.constructor != Array) y = [winpos[0], y];
			this.increase = function () {
				this.element.scrollTo( this.compute( this.values[0][0], this.values[0][1] ), 
											  this.compute( this.values[1][0], this.values[1][1] ) );
			}
		} else {
			if (x.constructor != Array) x = [this.element.scrollLeft, x];				
			if (y.constructor != Array) y = [this.element.scrollTop, y];
			this.increase = function () {
				this.element.scrollLeft = this.compute( this.values[0][0], this.values[0][1] ); 
				this.element.scrollTop = this.compute( this.values[1][0], this.values[1][1] ); 				
			}
		}
		this.values = [ x, y ];
		this.time = new Date().getTime();
		this.timer = setInterval(this.step.bind(this), this.options.speed);
		return this;
	},

	getWindowScroll: function () {
	  	var pos = [0, 0];
	  	if (typeof window.pageYOffset != 'undefined') {
			pos = [window.pageXOffset, window.pageYOffset];
		} else if (typeof document.documentElement.scrollTop != 'undefined'
				&& (document.documentElement.scrollTop > 0 || document.documentElement.scrollLeft > 0)) {
			pos = [document.documentElement.scrollLeft, document.documentElement.scrollTop];
		}
		return pos;
	},
	
	tidyUp: function () {
		if (this.element == window) {
			this.element.scrollTo(this.values[0][1], this.values[1][1]);
		} else {
			this.element.scrollLeft = this.values[0][1]; 
			this.element.scrollTop = this.values[1][1]; 
		}
	} 
});
