/*
  Easing Equations v1.5
  May 1, 2003
  (c) 2003 Robert Penner, all rights reserved. 
*/


// simple linear tweening - no easing
// t: current time, b: beginning value, c: change in value, d: duration
Math.linearTween = function (t, b, c, d) {
	return c*t/d + b;
};


 ///////////// QUADRATIC EASING: t^2 ///////////////////

// quadratic easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in value, d: duration
// t and d can be in frames or seconds/milliseconds
Math.easeInQuad = function (t, b, c, d) {
	return c*(t/=d)*t + b;
};

// quadratic easing out - decelerating to zero velocity
Math.easeOutQuad = function (t, b, c, d) {
	return -c *(t/=d)*(t-2) + b;
};

// quadratic easing in/out - acceleration until halfway, then deceleration
Math.easeInOutQuad = function (t, b, c, d) {
	if ((t/=d/2) < 1) return c/2*t*t + b;
	return -c/2 * ((--t)*(t-2) - 1) + b;
};


 ///////////// CUBIC EASING: t^3 ///////////////////////

// cubic easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in value, d: duration
// t and d can be frames or seconds/milliseconds
Math.easeInCubic = function (t, b, c, d) {
	return c*(t/=d)*t*t + b;
};

// cubic easing out - decelerating to zero velocity
Math.easeOutCubic = function (t, b, c, d) {
	return c*((t=t/d-1)*t*t + 1) + b;
};

// cubic easing in/out - acceleration until halfway, then deceleration
Math.easeInOutCubic = function (t, b, c, d) {
	if ((t/=d/2) < 1) return c/2*t*t*t + b;
	return c/2*((t-=2)*t*t + 2) + b;
};


 ///////////// QUARTIC EASING: t^4 /////////////////////

// quartic easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in value, d: duration
// t and d can be frames or seconds/milliseconds
Math.easeInQuart = function (t, b, c, d) {
	return c*(t/=d)*t*t*t + b;
};

// quartic easing out - decelerating to zero velocity
Math.easeOutQuart = function (t, b, c, d) {
	return -c * ((t=t/d-1)*t*t*t - 1) + b;
};

// quartic easing in/out - acceleration until halfway, then deceleration
Math.easeInOutQuart = function (t, b, c, d) {
	if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
	return -c/2 * ((t-=2)*t*t*t - 2) + b;
};


 ///////////// QUINTIC EASING: t^5  ////////////////////

// quintic easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in value, d: duration
// t and d can be frames or seconds/milliseconds
Math.easeInQuint = function (t, b, c, d) {
	return c*(t/=d)*t*t*t*t + b;
};

// quintic easing out - decelerating to zero velocity
Math.easeOutQuint = function (t, b, c, d) {
	return c*((t=t/d-1)*t*t*t*t + 1) + b;
};

// quintic easing in/out - acceleration until halfway, then deceleration
Math.easeInOutQuint = function (t, b, c, d) {
	if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
	return c/2*((t-=2)*t*t*t*t + 2) + b;
};



 ///////////// SINUSOIDAL EASING: sin(t) ///////////////

// sinusoidal easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in position, d: duration
Math.easeInSine = function (t, b, c, d) {
	return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
};

// sinusoidal easing out - decelerating to zero velocity
Math.easeOutSine = function (t, b, c, d) {
	return c * Math.sin(t/d * (Math.PI/2)) + b;
};

// sinusoidal easing in/out - accelerating until halfway, then decelerating
Math.easeInOutSine = function (t, b, c, d) {
	return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};


 ///////////// EXPONENTIAL EASING: 2^t /////////////////

// exponential easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in position, d: duration
Math.easeInExpo = function (t, b, c, d) {
	return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
};

// exponential easing out - decelerating to zero velocity
Math.easeOutExpo = function (t, b, c, d) {
	return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
};

// exponential easing in/out - accelerating until halfway, then decelerating
Math.easeInOutExpo = function (t, b, c, d) {
	if (t==0) return b;
	if (t==d) return b+c;
	if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
	return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
};


 /////////// CIRCULAR EASING: sqrt(1-t^2) //////////////

// circular easing in - accelerating from zero velocity
// t: current time, b: beginning value, c: change in position, d: duration
Math.easeInCirc = function (t, b, c, d) {
	return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
};

// circular easing out - decelerating to zero velocity
Math.easeOutCirc = function (t, b, c, d) {
	return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
};

// circular easing in/out - acceleration until halfway, then deceleration
Math.easeInOutCirc = function (t, b, c, d) {
	if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
	return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
};


 /////////// ELASTIC EASING: exponentially decaying sine wave  //////////////

// t: current time, b: beginning value, c: change in value, d: duration, a: amplitude (optional), p: period (optional)
// t and d can be in frames or seconds/milliseconds

Math.easeInElastic = function (t, b, c, d, a, p) {
	if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
	if (a < Math.abs(c)) { a=c; var s=p/4; }
	else var s = p/(2*Math.PI) * Math.asin (c/a);
	return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
};

Math.easeOutElastic = function (t, b, c, d, a, p) {
	if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
	if (a < Math.abs(c)) { a=c; var s=p/4; }
	else var s = p/(2*Math.PI) * Math.asin (c/a);
	return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
};

Math.easeInOutElastic = function (t, b, c, d, a, p) {
	if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
	if (a < Math.abs(c)) { a=c; var s=p/4; }
	else var s = p/(2*Math.PI) * Math.asin (c/a);
	if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
};


 /////////// BACK EASING: overshooting cubic easing: (s+1)*t^3 - s*t^2  //////////////

// back easing in - backtracking slightly, then reversing direction and moving to target
// t: current time, b: beginning value, c: change in value, d: duration, s: overshoot amount (optional)
// t and d can be in frames or seconds/milliseconds
// s controls the amount of overshoot: higher s means greater overshoot
// s has a default value of 1.70158, which produces an overshoot of 10 percent
// s==0 produces cubic easing with no overshoot
Math.easeInBack = function (t, b, c, d, s) {
	if (s == undefined) s = 1.70158;
	return c*(t/=d)*t*((s+1)*t - s) + b;
};

// back easing out - moving towards target, overshooting it slightly, then reversing and coming back to target
Math.easeOutBack = function (t, b, c, d, s) {
	if (s == undefined) s = .5;
	return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
};

// back easing in/out - backtracking slightly, then reversing direction and moving to target,
// then overshooting target, reversing, and finally coming back to target
Math.easeInOutBack = function (t, b, c, d, s) {
	if (s == undefined) s = 1.70158; 
	if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
	return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
};


 /////////// BOUNCE EASING: exponentially decaying parabolic bounce  //////////////

// bounce easing in
// t: current time, b: beginning value, c: change in position, d: duration
Math.easeInBounce = function (t, b, c, d) {
	return c - Math.easeOutBounce (d-t, 0, c, d) + b;
};

// bounce easing out
Math.easeOutBounce = function (t, b, c, d) {
	if ((t/=d) < (1/2.75)) {
		return c*(7.5625*t*t) + b;
	} else if (t < (2/2.75)) {
		return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
	} else if (t < (2.5/2.75)) {
		return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
	} else {
		return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
	}
};

// bounce easing in/out
Math.easeInOutBounce = function (t, b, c, d) {
	if (t < d/2) return Math.easeInBounce (t*2, 0, c, d) * .5 + b;
	return Math.easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
};


//trace (">> Penner easing equations loaded");

var cleverCode = {};

cleverCode.domReady = function(f){
	if(cleverCode.domReady.done){
		return f();
	}
	if(cleverCode.domReady.timer){
		cleverCode.domReady.ready.push(f);
	}else{
		window.onload = cleverCode.isDOMReady;
		cleverCode.domReady.ready = [f];
		cleverCode.domReady.timer = setInterval(cleverCode.isDOMReady, 14);
	}
};

cleverCode.isDOMReady = function(){
	if(cleverCode.domReady.done){
		return false;
	}
	if(document && document.getElementById && document.getElementsByTagName && document.body){
		cleverCode.domReady.done = true;
		clearInterval(cleverCode.domReady.timer);
		cleverCode.domReady.timer = null;
		for(var i = 0; i < cleverCode.domReady.ready.length; i++){
			cleverCode.domReady.ready[i]();
		}
		cleverCode.domReady.ready = null;
	}
};

cleverCode.stopDefault = function(e){
	if(e && e.preventDefault){
		e.preventDefault();
	}else{
		window.event.returnValue = false;
	}
	return false;
};

cleverCode.stopBubble = function(e){
	if(e && e.stopPropogation){
		e.stopPropogation();
	}else{
		window.event.cancelBubble = true;
	}
};

cleverCode.getElementsByClass = function(classname, parent){
	var domset = [];
	var arr = document.getElementsByTagName("*");
	var reg = new RegExp("(^| )" + classname + "( |$)");
	for(var i = 0; i < arr.length; i++){
		if(reg.test(arr[i].className)){
			domset.push(arr[i]);
		}
	}
	return domset;
};

cleverCode.$ = function(selector){
	var parent = (this == cleverCode) ? document : this;
	switch(selector.charAt(0)){
		case "#":
			var el = selector.substr(1, selector.length);
			var domset = document.getElementById(el);
			domset.$ = cleverCode.$;
			break;
		case ".":
			var domset = [];
			var el = selector.substr(1, selector.length);
			var arr = cleverCode.getElementsByClass(el, parent);
			for(var i = 0; i < arr.length; i++){
				arr[i].$ = cleverCode.$;
				domset.push(arr[i]);
			}
			break;
		default:
			var domset = [];
			var arr = parent.getElementsByTagName(selector);
			for(var i = 0; i < arr.length; i++){
				domset.push(arr[i]);
				domset[i].$ = cleverCode.$;
			}
			break;
	};
	return domset;
};

cleverCode.hasClass = function(el, theClass){
	var pattern = new RegExp("(^| )" + theClass + "( |$)");
	if(pattern.test(el.className)){ return true; }
	return false;
};

cleverCode.addClass = function(el, theClass){
	if(!cleverCode.hasClass(el, theClass)){
		if(el.className == ""){
			el.className = theClass;
		}else{
			el.className += " " + theClass;
		}
	}
};

cleverCode.removeClass = function(el, theClass){
	var pattern  = new RegExp("(^| )" + theClass + "( |$)");
	el.className = el.className.replace(pattern, "$1");
	el.className = el.className.replace(/ $/, "");
};

cleverCode.validateForm = function(form){
	var vSet = {
		email:{
			"test":function(obj){
				var reg = /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Follow this format: username@domain.com"
		},
		reemail:{
			"test":function(obj){
				var res = (cleverCode.$("#email2").value == cleverCode.$("#email1").value) ? true : false;
				return (!(obj.value == "") && res);
			},
			"msg": "Emails do not match."
		},
		phone:{
			"test":function(obj){
				var reg = /^[2-9]\d{2}(\.|-)?\d{3}(\.|-)?\d{4}$/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Please enter a valid 10 digit phone number."
		},
		password:{
			"test":function(obj){
				var reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).{4,8}$/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Requires one lowercase letter, one uppercase letter, and one number. Must be 6 - 13 characters long with no spaces."
		},
		repassword:{
			"test":function(obj){
				var res = (cleverCode.$("#password2").value == cleverCode.$("#password1").value) ? true : false;
				return (!(obj.value == "") && res);
			},
			"msg": "Passwords do not match."
		},
		website:{
			"test":function(obj){
				var reg = /(www\.)?([^\.]+)\.(\w{2,4}$)/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Please type a valid website address."
		},
		user:{
			"test":function(obj){
				var reg = /^[a-zA-Z0-9]+$/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Please use only letters."
		},
		text:{
			"test":function(obj){
				var reg = /^[a-zA-Z]+$/;
				return (!(obj.value == "") && (reg.test(obj.value)));
			},
			"msg": "Please use only letters."
		}
	};
	for(var i = 0; i < form.elements.length; i++){
		if(form.elements[i].type != "submit"){
			var fel = form.elements[i];
			fel.parentNode.$=cleverCode.$;
			fel.onfocus = function(){
				cleverCode.addClass(this.parentNode, "highlight")
			};
			fel.onblur = function(){
				cleverCode.removeClass(this.parentNode, "highlight")
			};
			fel.onkeyup = function(){
				for(var j in vSet){
					var success = vSet[j].test(this);
					if(cleverCode.hasClass(this, j) && success){
					var tmp = this.parentNode.$("label")[0].$("#" + this.id + "_error").innerHTML = "";
						if(cleverCode.hasClass(this, "required")){
							cleverCode.addClass(this, "valid");
							cleverCode.removeClass(this, "invalid");
						}
					}else if(cleverCode.hasClass(this, j) && !success){
						var tmp = this.parentNode.$("label")[0].$("#" + this.id + "_error").innerHTML = vSet[j].msg;
						if(cleverCode.hasClass(this, "required")){
							cleverCode.removeClass(this, "valid");
							cleverCode.addClass(this, "invalid");
						}
					}
				}
			};
		}else{
			form.onsubmit = function(e){
				var passed = true;
				for(var k = 0; k < form.elements.length; k++){
					if(form.elements[k].type != "submit"){
						var fel = form.elements[k];
						for(var l in vSet){
							if(cleverCode.hasClass(fel, l)){
								passed = (vSet[l].test(fel)) ? passed : false;
							}
						}
					}
				}
				return (passed) ? true : cleverCode.stopDefault(e);
			};
		}
	};
};
	
cleverCode.serialize = function(obj){
	var ser = [];
	for(var p in obj){
		ser.push(p + "=" + encodeURIComponent(obj[p]));
	}
	return ser.join("&");
};

cleverCode.ajax = function(options){
	var options = {
		url: options.url || "",
		timeout: options.timeout || 7000,
		onSuccess: options.onSuccess || function(){},
		onError: options.onError || function(){},
		data: options.data || {},
		type: options.type || "text"
	};
	
	options.data = cleverCode.serialize(options.data);
	
	if(typeof XMLHttpRequest === "undefined"){
		XMLHttpRequest = function(){
			return new ActiveXObject("Msxml2.XMLHTTP");
		};
	}
	var xhr = new XMLHttpRequest();
	xhr.open ("GET", options.url + "?" + options.data, true);
	
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4){
			if(xhr.status === 200 || xhr.status === 304){
				var result = (options.type === "text") ? xhr.responseText : xhr.responseXML;
				options.onSuccess(result);
			}else{
				options.onError();
			}
			xhr = undefined;
		}
	};
	
	xhr.send(null);
	setTimeout(function(){
		if(xhr){ xhr.abort(); }
	},
	options.timeout);
};

cleverCode.getStyle = function(elem, name){
  if(elem.styel[name]){
    return elem.style[name];
  }else if(elem.currentStyle){
    return elem.currentStyle[name];
  }else if(document.defaultView){
    name = name.replace( /([A-Z])/g, "-$1" );
    name = name.toLowerCase();
    var el = document.defaultView.getComputedStyle(elem, "");
    return el.getPropertyValue(name);
  }else{
    return null;
  }
};

cleverCode.animate = function(options){
  var options = {
    change: options.change || 0,
    start: options.start || 0,
    duration: options.duration || 600,
    easing: options.easing || "easeOutCirc",
    property: options.property || null,
    tag: options.tag ||null
  };
  
  if(!options.tag || !options.property){ return false; };
  
  var i = 0;
  var anim = setInterval(function(){
    i += 15;
    options.tag.style[options.property] = Math[options.easing](i, options.start, options.change, options.duration) + "px";
    if(i >= options.duration){
      if(options.property == "height" || options.property == "width"){
        if(options.start + options.change <= 0){
          options.tag.style.display = "none";
          options.tag.style[options.property] = options.start + "px";
        }
      }
      clearInterval(anim);
      anim = null;
    }
  }, 15);
};

cleverCode.slideUp = function(options){
  options = {
    duration: options.duration || 600,
    easing: options.easing || "easeOutCirc",
    tag: options.tag || null
  };
  
  options.tag.style.display = "block";
  var h = parseInt(options.tag.clientHeight);
  
  cleverCode.animate({
    tag: options.tag,
    start: h,
    change: -h,
    duration: options.duration,
    property: "height",
    easing: options.easing
  });
};

cleverCode.slideDown = function(options){
  options = {
    duration: options.duration || 600,
    easing: options.easing || "easeOutCirc",
    tag: options.tag || null
  };
  
  options.tag.style.display = "block";
  var h = parseInt(options.tag.clientHeight);
  options.tag.style.height = "0px";
  
  cleverCode.animate({
    tag: options.tag,
    start: 0,
    change: h,
    duration: options.duration,
    property: "height",
    easing: options.easing
  });
};

cleverCode.slideToggle = function(options){
  if(!options.tag.slideState){
    options.tag.slideState = "down";
  }  if(options.tag.slideState == "down"){    options.tag.slideState = "up";    cleverCode.slideUp(options);  }else{    options.tag.slideState = "down";    cleverCode.slideDown(options);  }
};

cleverCode.accordion = function(options){
  options = {
    tag: options.tag,
    duration: options.duration || 600,
    easing: options.easing || "easeOutCirc"
  };
  
  var content = cleverCode.$(options.tag);
  content.style.display = "none";
  content.slideState = "up";
  cleverCode.slideDown({
    tag: content,
    duration: options.duration,
    easing: options.easing
  });
};