
// Open New Window:
// Use same syntax as window.open
// onclick="return openWindow(...
// newWindow sets default values if none are chosen then sets the window to focus
// http://www.w3schools.com/htmldom/met_win_open.asp

function openWindow(url,name,specs,replace) {
	var _url = "";
	var _name = "_blank";
	var _replace = false;
	// assign site defaults in _specs, remove fields you don't need
	var _specs = new Array();
		_specs['height'] = 500;
		_specs['width'] = 500;
		_specs['location'] = 'yes';
		_specs['menubar'] = 'no';
		_specs['scrollbars'] = 'yes';
		_specs['status'] = 'yes';
		_specs['titlebar'] = 'yes';
		_specs['toolbar'] = 'no';
	
	if(url) _url = url;
	// cleans up name so it doesn't cause ie6 errors
	if(name) _name = name.replace(/[\s-]*/g,"");
	if(replace) _replace = replace;
	if(specs) {
		var strSpecs = specs.replace(/\s/g,"").split(',');
		for(key in strSpecs) {
			var attr = strSpecs[key].split('=');
			_specs[attr[0]] = attr[1];
		}
	}
	specs = "";
	for(key in _specs) {
		if(specs.length != 0) specs += ",";
		specs += key + '=' + _specs[key];
	}
	
	var win = window.open(_url,_name,specs,_replace);
	win.focus();
	return false;
}


// Submit on Enter Key
// onkeypress="return enterKey(event,'objectID')"
function enterKey(e,id) {
	if(document.getElementById(id)) {
		var key = c2.getKey(e);
		if (key && key == 13) {
			//eval(code);
			var object = document.getElementById(id);
			if(object.tagName == 'A') {
				var href = object.href.replace(window.location,"");
				if(href.length > 1) {
					eval(unescape(object.href.replace(/^javascript:/i,"")));
				}
				else {
					object.onclick();
				}
				return false;
			}
			else if(object.tagName == 'INPUT' || object.tagName == 'BUTTON') {
			    object.click();
				return false;
			}
		}
	}
	return true;
}


// Input Focus and Blur:
// Place the inputFocus function on the onfocus event of an input element and the inputBlur on the onblur event.
// Use 'this' for the object parameter. 'css' and 'defaultValue' parameters are optional.
//		onfocus="inputFocus(this,'text-align:left','First Name')"
// Requires: jQuery

function inputFocus(object, css, defaultValue) {
    var val;
    if(defaultValue) val = defaultValue;
    else val = object.defaultValue;
    if(val == object.value) {
        object.value = "";
    }
    if(css) renderCSS(object, css);
}
function inputBlur(object, css, defaultValue) {
    if(object.value.replace(/\s/g,"").length < 1) {
        var val;
        if(defaultValue) val = defaultValue;
        else val = object.defaultValue;
        object.value = val;
        if(css) renderCSS(object, css);
    }
}
function renderCSS(object, css) {
    var attributes = css.replace(/\s/g,"").split(';');
    for(var x=0;x<attributes.length;x++) {
		if(attributes[x].indexOf(':') > 0) {
			var elem = attributes[x].split(':');
			$(object).css(elem[0],elem[1]);
		}
    }
}


// Filmstrip (coda slider):
//		var slider = new filmstrip();
//		slider.frame = document.getElementById('slider');
//		slider.settings.scrollWheel = true;
//		slider.init();

function filmstrip(frame, next, previous) {
	var self = this;
	this.current = 1;
	this.count = 1;
	this.settings = {direction:0, totalVisible:1, prefix:"filmstrip", ease:"sineInOut", trimEnding:false, disableWrap:false, setRotate:0, scrollWheel:false, pageSlide:false, debug:false};
	this.events = {onBeforeMove:null, onMoveComplete:null};
	this.frame = frame;
	this.next = next;
	this.previous = previous;
	this.anim = {time:0, begin:0, change:0.0, timer:null, duration:50, speed:15, rotate:null};
	this.init = function() {
		if(this.frame.id.length > 0 && this.settings.prefix == "filmstrip") {
			this.settings.prefix = this.frame.id + '_';
		}
		
		var slides = this.frame.getElementsByTagName('li');
		this.count = slides.length;
		for(var x=0;x<this.count;x++) {
			slides[x].id = this.settings.prefix + (x+1);
		}
		
		var wrapper = this.frame.getElementsByTagName('ul')[0];
		if(this.settings.direction == 0) {
			wrapper.style.width = slides[0].offsetWidth * (slides.length + this.settings.totalVisible) + "px";
			//wrapper.style.paddingRight = this.frame.offsetWidth + "px"
		}
		else {
			//wrapper.style.height = slides[0].offsetHeight * (slides.length + this.settings.totalVisible) + "px";
			wrapper.style.paddingBottom = this.frame.offsetHeight + "px"
		}
		
		if(this.settings.scrollWheel) {
			this.initWheel();
		}
		
		this.go(1);
		//if(this.settings.setRotate > 0) {
		//	this.anim.rotate = setTimeout(function() { self.moveNext(); }, this.settings.setRotate);
		//}
		
		if(this.next) {
			this.next.onclick = function() {
				self.moveNext();
				return false;
			};
		}
		if(this.previous) {
			this.previous.onclick = function() {
				self.movePrevious();
				return false;
			};
		}
		
		if(this.settings.debug) {
			if(this.settings.trimEnding && this.settings.pageSlide) alert('Warning:\nsettings.trimEnding and settings.pageSlide are both set to "true".');
		}
	};
	this.go = function(num) {
		clearTimeout(this.anim.rotate);
		
		if(this.events.onBeforeMove) {
			this.events.onBeforeMove(num);
		}
		
		this.current = num;
		
		var position = c2.findElementPos(document.getElementById(this.settings.prefix + this.current));
		var offsetPos = c2.findElementPos(document.getElementById(this.settings.prefix + 1));
		position[this.settings.direction] = position[this.settings.direction] - offsetPos[this.settings.direction];
		
		var scrollOffset = 0;
		if(this.settings.direction == 0) {
			scrollOffset = this.frame.scrollLeft;
		}
		else if(this.settings.direction == 1) {
			scrollOffset = this.frame.scrollTop;
		}
		
		if (this.anim.timer != null) {
			clearInterval(this.anim.timer);
			this.anim.timer = null;
		}
		this.anim.time = 0;
		this.anim.begin = scrollOffset;
		this.anim.change = position[this.settings.direction] - scrollOffset;
		
		this.anim.timer = setInterval(function() { self.scroll(); }, this.anim.speed);
	};
	this.scroll = function() {
		if (this.anim.time > this.anim.duration) {
			clearInterval(this.anim.timer);
			this.anim.timer = null;
			
			if(this.settings.setRotate > 0) {
				this.anim.rotate = setTimeout(function() { self.moveNext(); }, this.settings.setRotate);
			}
			
			if(this.events.onMoveComplete) {
				this.events.onMoveComplete();
			}
		}
		else {
			var move = c2.ease[this.settings.ease](this.anim.time, this.anim.begin, this.anim.change, this.anim.duration);
			if(this.settings.direction == 0) {
				this.frame.scrollLeft = move;
			}
			else if(this.settings.direction == 1) {
				this.frame.scrollTop = move;
			}
			this.anim.time++;
		}
	};
	this.moveNext = function() {
		var num;
		if(this.settings.pageSlide) {
			num = this.current + this.settings.totalVisible;
		}
		else {
			num = this.current + 1;
		}
		if((this.settings.trimEnding && num > this.count - this.settings.totalVisible + 1) || (!this.settings.trimEnding && num > this.count)) {
			if(this.settings.disableWrap) {
				return false;
			}
			else {
				num = 1;
			}
		}
		this.go(num);
	};
	this.movePrevious = function() {
		var num;
		if(this.settings.pageSlide) {
			num = this.current - this.settings.totalVisible;
		}
		else {
			num = this.current - 1;
		}
		if(num < 1) {
			if(this.settings.disableWrap) {
				return false;
			}
			else {
				if(this.settings.trimEnding) {
					num = this.count - this.settings.totalVisible + 1;
				}
				else {
					if(this.settings.pageSlide) {
						if(this.count % this.settings.totalVisible != 0) {
							num = this.count - (this.count % this.settings.totalVisible) + 1;
						}
						else {
							num = this.count - this.settings.totalVisible + 1;
						}
					}
					else {
						num = this.count;
					}
				}
			}
		}
		this.go(num);
	};
	this.initWheel = function() {
		if (this.frame.addEventListener) {
			/** DOMMouseScroll is for mozilla. */
			this.frame.addEventListener('DOMMouseScroll', this.slideEventWheel, false);
		}
		/** IE/Opera. */
		this.frame.onmousewheel = this.slideEventWheel;
	};
	this.slideEventWheel = function(event) {
        var delta = 0;
        if (!event) /* For IE. */
                event = window.event;
        if (event.wheelDelta) { /* IE/Opera. */
                delta = event.wheelDelta/120;
        } else if (event.detail) { /** Mozilla case. */
                delta = -event.detail/3;
        }
        if (delta) {
			if(delta < 0) {
				self.moveNext();
			}
			else {
				self.movePrevious();
			}
		}
        if (event.preventDefault)
			event.preventDefault();
		event.returnValue = false;
	};
}




// Image Slideshow:
//		var ss = new slideshow();
//		ss.frame = document.getElementById('mainSlide');
//		ss.options.slideSpeed = 10000;
//		ss.init();


function slideshow(frame, next, previous, togglePlay) {
	var self = this;
	this.frame = frame;
	this.next = next;
	this.previous = previous;
	this.togglePlay = togglePlay;
	this.options = {slideSpeed : 5000, fadeSpeed : 25, fadeChange : 5};
	this.anim = {paused:false,rotate:null,fade:null,number:0,previous:0,count:0,opacity:0};
	this.init = function() {
	
		this.frame.style.position = "relative";
		
		var slides = this.frame.getElementsByTagName('li');
		this.anim.count = slides.length;
		if(slides.length > 1) {
			for(var x=0;x<slides.length;x++) {
				slides[x].style.position = "absolute";
				slides[x].style.top = "0px";
				slides[x].style.left = "0px";
				if(x > 0) {
					slides[x].style.zIndex = "100";
					slides[x].style.opacity = "0";
					slides[x].style.filter = "alpha(Opacity=0)";
				}
				else {
					slides[0].style.zIndex = "200";
				}
			}
			if(!this.anim.paused) {
				this.callInterval();
			}
		}

		if(this.next) {
			this.next.onclick = function() {
				self.change('++');
				return false;
			};
		}
		if(this.previous) {
			this.previous.onclick = function() {
				self.change('--');
				return false;
			};
		}
		if(this.togglePlay) {
			this.togglePlay.onclick = function() {
				if(!self.anim.paused) {
					clearTimeout(self.anim.rotate);
					self.anim.paused = true;
					this.className = "";
					// uncomment if jQuery
					//$(this).removeClass('slidePause');
				}
				else {
					self.callInterval();
					self.anim.paused = false;
					this.className = "slidePause";
					// uncomment if jQuery
					//$(this).addClass('slidePause');
				}
				return false;
			};
		}

	};
	
	this.callInterval = function() {
		this.anim.rotate = setTimeout(function() { self.change('++'); }, this.options.slideSpeed);
	};
	
	this.state = function(num,state) {
		var node = this.frame.getElementsByTagName('li')[num];
		switch(state) {
			case 1:
				node.style.zIndex = "100";
				node.style.opacity = "0";
				node.style.filter = "alpha(Opacity=0)";
				break;
			case 2:
				node.style.zIndex = "150";
				node.style.opacity = "1";
				node.style.filter = "alpha(Opacity=100)";
				break;
			case 3:
				node.style.zIndex = "200";
				node.style.opacity = (this.anim.opacity / 100);
				node.style.filter = "alpha(Opacity="+this.anim.opacity+")";
				break;
		}
	};
	
	this.bounds = function(num) {
		if(num >= this.anim.count) {
			num = 0;
		}
		if(num < 0) {
			num = this.anim.count - 1;
		}
		return num;
	};

	this.change = function(arg) {
		clearInterval(this.anim.fade);
		clearTimeout(this.anim.rotate);
		
		if(this.anim.previous != this.anim.number) {
			// hide the previous slide
			this.state(this.anim.previous,1);
			// set the previous slide to the current
			this.anim.previous = this.anim.number;
			this.anim.opacity = 50;
		}

		// increment the current slide
		if(arg == '++') {
			this.anim.number = this.anim.number + 1;
		}
		else if(arg == '--') {
			this.anim.number = this.anim.number - 1;
		}
		else {
			this.anim.number = Number(arg);
		}
		this.anim.number = this.bounds(this.anim.number);
		
		// set the slides to the correct states
		this.state(this.anim.previous,2);
		this.state(this.anim.number,3);
		
		this.anim.fade = setInterval(function() {self.fade(); }, this.options.fadeSpeed);
	};

	this.fade = function() {
		var nextNode = this.frame.getElementsByTagName('li')[this.anim.number];
		this.anim.opacity = this.anim.opacity + this.options.fadeChange;
		if(this.anim.opacity >= 100) {
			nextNode.style.opacity = "1";
			nextNode.style.filter = "alpha(Opacity=100)";
			// hide the previous slide
			this.state(this.anim.previous,1);
			
			this.anim.opacity = 0;
			this.anim.previous = this.anim.number;
			clearInterval(this.anim.fade);
			if(this.anim.status == 0) {
				this.anim.rotate = setTimeout(function() { self.change(); }, this.options.slideSpeed);
			}
		}
		else {
			nextNode.style.opacity = (this.anim.opacity / 100);
			nextNode.style.filter = "alpha(Opacity="+this.anim.opacity+")";
		}
	};
}



// Text Limiter:
// requires jQuery for 'adjustStyle'
//		var textarea = new textLimit();
//		textarea.input = document.getElementById('textarea');
//		textarea.limit = 500;
//		textarea.init();

function textLimit() {
	this.limit = 200;
	this.regex = /<[^ ]\/?[^>]+>/gi;
	this.allowOver = false;
	this.input = null;
	this.count = null;
	this.remaining = null;
	this.init = function() {
		var self = this;
		this.input.onkeydown = function(event) {
			if(this.value.length >= self.limit) {
				if(document.selection && document.selection.createRange().text.length > 0) {
					return true;
				}
				else if(self.input.selectionEnd - self.input.selectionStart > 0) {
					return true;
				}
				var key = c2.getKey(event);
				if(key > 46 || key == 13 || key == 32) {
					return false;
				}
			}
		}
		this.input.onkeyup = function() {
			var val = self.clean(this.value);
			if(!self.allowOver && val.length > self.limit) {
				val = val.substr(0, self.limit);
			}
			if(this.value != val) {
				this.value = val;
				self.input.scrollTop = self.input.scrollHeight;
			}
			self.setCount(val.length);
			self.setRemaining(val.length);
		};
		setTimeout(function() {
				self.setCount(self.input.value.length);
				self.setRemaining(self.input.value.length);
			}, 10);
	}
	this.setCount = function(length) {
		if(this.count) {
			this.count.innerHTML = length;
			this.adjustStyle(this.count, length);
		}
	}
	this.setRemaining = function(length) {
		if(this.remaining) {
			this.remaining.innerHTML = this.limit - length;
			this.adjustStyle(this.remaining, length);
		}
	}
	this.adjustStyle = function(object, length) {
		if(length > this.limit) {
			$(object).addClass('error');
		}
		else {
			$(object).removeClass('error');
		}
	};
	this.clean = function(value) {
		return value.replace(this.regex, '');
	}
}



// HTML Truncator:
//		var html = document.getElementById('html').value.truncate(500, '&hellip;');

String.prototype.truncate = function(maxLength, suffix) {
	if(!maxLength) maxLength = 100;
	var html = this.replace(/& /g,"&amp; ").replace(/< /g,"&lt; ").replace(/\n|\t/g,"").replace(/(<script\ .*?>.*?<\/script>)|<!.*?>/ig,"").replace(/  /g," ");
	var re = /(?:(?:<([a-z0-9\/]+)([^<>]*)>)|(&[a-z]+;|#[0-9]+;))([^<&]*)/im;
	var teaser = "";
	if(html.match(re)) {
		teaser = html.substring(0, html.indexOf(html.match(re)[0]));
	}
	else {
		teaser = html;
	}
	var count = teaser.length;
	if(count >= maxLength) {
		teaser = teaser.substring(0, maxLength);
		if(suffix && count != maxLength) {
			teaser += suffix;
		}
	}
	else if(html.length > maxLength) {
		var stack = new Array();
		var startIndex = 0;
		var totalLength = html.length;
		var result, pos, temp;
		while(startIndex < totalLength) {
			result = re.exec(html);
			if (result && result.length > 0 && result[0].length > 0 && count < maxLength) {
				pos = html.indexOf(result[0]);
				startIndex += pos;
				if(result[1] && result[1].indexOf('/') < 0) {
					if(result[2].length == 0 || result[2].lastIndexOf('/') != result[2].length-1) {
						stack.push(result[1]);
					}
					teaser += "<" + result[1] + result[2] + ">";
				}
				else if(result[3]) {
					teaser += result[3];
					count++;
				}
				else {
					var pop = stack.pop();
					if("/" + pop == result[1]) {
						teaser += "<" + result[1] + ">";
					}
					else {
						alert('invalid html: ' + result[0]);
						break;
					}
				}
				temp = result[4];
				if(count + temp.length > maxLength) {
					temp = temp.substring(0, maxLength - count);
					teaser += temp;
					if(suffix) {
						teaser += suffix;
					}
					break;
				}
				else {
					teaser += temp;
					count += temp.length;
				}
				html = html.substr(pos + result[0].length);
				startIndex += result[0].length;
			}
			else if(suffix && count == maxLength && result[4].length > 0) {
				teaser += suffix;
				break;
			}
			else {
				break;
			}
		}
		for(var x=stack.length-1;x>-1;x--) {
			teaser += "</" + stack[x] + ">";
		}
	}
	else {
		teaser = html;
	}
	return teaser;
}

String.prototype.trim = function(str) {
	if(str.length > 0) {
		var s = this;
		if(s.indexOf(str) == 0) {
			s = s.substring(str.length,s.length);
		}
		if(s.lastIndexOf(str) == s.length - str.length) {
			s = s.substring(0, s.length - str.length);
		}
		return s;
	}
	else {
		return this.replace(/^\s+|\s+$/g,"");
	}
}

String.prototype.ltrim = function(str) {
	if(str.length > 0) {
		if(this.indexOf(str) == 0) {
			return this.substring(str.length,this.length);
		}
		else {
			return this;
		}
	}
	else {
		return this.replace(/^\s+/,"");
	}
}

String.prototype.rtrim = function(str) {
	if(str.length > 0) {
		if(this.lastIndexOf(str) == this.length - str.length) {
			return this.substring(0, this.length - str.length);
		}
		else {
			return this;
		}
	}
	else {
		return this.replace(/\s+$/,"");
	}
}


// Form Validation:
// Add classname 'requiredField' or 'requiredEmail' to any form element. Use the title attributes as the required alert messages and class 'hightlight' to adjust the style.
//		var customVal = new formValidation();
//		customVal.form = document.getElementById('form');
//		customVal.init();
// Required: jQuery

function formValidation() {
	var self = this;
	this.form = null;
	this.suffix = "_validate";
	this.event = { beforeSubmit:null, afterSubmit:null, validationFail:null, validationSuccess:null };
	this.customValidation = null;
	this.init = function() {
		$(this.form).find('.requiredField').blur(function() {
			self.checkRequired(this);
		})
		$(this.form).find('.requiredEmail').blur(function() {
			self.checkEmail(this);
		});
		if(this.form) {
			this.form.onsubmit = function() {
				var count = 0;
				if(self.event.beforeSubmit) self.event.beforeSubmit();
				if(self.customValidation) count = self.customValidation();
				var requiredField = $(this.form).find('.requiredField');
				for(var x=0;x<requiredField.length;x++) {
					if(!self.checkRequired(requiredField[x])) {
						count++;
					}
				}
				var requiredEmail = $(this.form).find('.requiredEmail');
				for(var x=0;x<requiredEmail.length;x++) {
					if(!self.checkEmail(requiredEmail[x])) {
						count++;
					}
				}
				if(self.event.afterSubmit) self.event.afterSubmit();
				if(count > 0) {
					if(self.event.validationFail) self.event.validationFail();
					return false;
				}
				else {
					if(self.event.validationSuccess) self.event.validationSuccess();
					return true;
				}
			};
		}
	};
	this.checkRequired = function(field) {
		if(!field.disabled && field.id.length > 0) {
			var reqFieldName = field.id + this.suffix;
			if(field.tagName == "INPUT") {
				if(field.type == "text" || field.type == "password" || field.type == "hidden") {
					if($.trim(field.value).length > 0) {
						$(field).removeClass('highlight');
						if(document.getElementById(reqFieldName)) {
							document.getElementById(reqFieldName).innerHTML = "";
						}
						return true;
					}
					else {
						$(field).addClass('highlight');
						if(field.title.length > 0) {
							if(document.getElementById(reqFieldName)) {
								document.getElementById(reqFieldName).innerHTML = field.title;
							}
							else {
								$(field).after('<span id="'+reqFieldName+'" class="required">'+field.title+'</span>');
							}
						}
						return false;
					}
				}
				if(field.type == "checkbox") {
					if(field.checked) {
						if(document.getElementById(reqFieldName)) {
							document.getElementById(reqFieldName).innerHTML = "";
						}
						return true;
					}
					else {
						if(field.title.length > 0) {
							if(document.getElementById(reqFieldName)) {
								document.getElementById(reqFieldName).innerHTML = field.title;
							}
							else {
								$(field).after('<span id="'+reqFieldName+'" class="required">'+field.title+'</span>');
							}
						}
						return false;
					}
				}
			}
			if(field.tagName == "SELECT") {
				if(field.selectedIndex > 0) {
					$(field).removeClass('highlight');
					if(document.getElementById(reqFieldName)) {
						document.getElementById(reqFieldName).innerHTML = "";
					}
					return true;
				}
				else {
					$(field).addClass('highlight');
					if(field.title.length > 0) {
						if(document.getElementById(reqFieldName)) {
							document.getElementById(reqFieldName).innerHTML = field.title;
						}
						else {
							$(field).after('<span id="'+reqFieldName+'" class="required">'+field.title+'</span>');
						}
					}
					return false;
				}
			}
		}
		else {
			return true;
		}
	};
	this.checkEmail = function(field) {
		if(!field.disabled && field.id.length > 0) {
			var reqFieldName = field.id + this.suffix;
			var emailRegex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/ig;
			if(field.value.match(emailRegex)) {
				$(field).removeClass('highlight');
				if(document.getElementById(reqFieldName)) {
					document.getElementById(reqFieldName).innerHTML = "";
				}
				return true;
			}
			else {
				$(field).addClass('highlight');
				if(document.getElementById(reqFieldName)) {
					document.getElementById(reqFieldName).innerHTML = field.title;
				}
				else {
					$(field).after('<span id="'+reqFieldName+'" class="required">'+field.title+'</span>');
				}
				return false;
			}
		}
		else {
			return true;
		}
	};
}


var c2 = {
	findElementPos: function(elemFind) {
		var elemX = 0;
		var elemY = 0;
		do {
			elemX += elemFind.offsetLeft;
			elemY += elemFind.offsetTop;
		} while ( elemFind = elemFind.offsetParent )
		return Array(elemX, elemY);
	},
	randomInt: function(min, max) {
		return Math.floor(Math.random()*(max+1-min)) + min;
	},
	getQuery: function(param) {
		var p = escape(unescape(param));
		var regex = new RegExp("[?&]" + p + "(?:=([^&]*))?","i");
		var match = regex.exec(window.location.search);
		var value = null;
		if( match != null ){
			value = match[1];
		}
		return value;
	},
	getKey: function(e) {
		if(!e) e = window.event;
		var key = e.which;
		if(!key) key = e.keyCode;
		return key;
	},
	ease: {
		quadIn: function (t, b, c, d) {
			return c*(t/=d)*t + b;
		},
		quadOut: function (t, b, c, d) {
			return -c *(t/=d)*(t-2) + b;
		},
		quadInOut: function (t, b, c, d) {
			if ((t/=d/2) < 1) return c/2*t*t + b;
			return -c/2 * ((--t)*(t-2) - 1) + b;
		},
		cubicIn: function (t, b, c, d) {
			return c*(t/=d)*t*t + b;
		},
		cubicOut: function (t, b, c, d) {
			return c*((t=t/d-1)*t*t + 1) + b;
		},
		cubicInOut: 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;
		},
		quartIn: function (t, b, c, d) {
			return c*(t/=d)*t*t*t + b;
		},
		quartOut: function (t, b, c, d) {
			return -c * ((t=t/d-1)*t*t*t - 1) + b;
		},
		quartInOut: 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;
		},
		quintIn: function (t, b, c, d) {
			return c*(t/=d)*t*t*t*t + b;
		},
		quintOut: function (t, b, c, d) {
			return c*((t=t/d-1)*t*t*t*t + 1) + b;
		},
		quintInOut: 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;
		},
		sineIn: function (t, b, c, d) {
			return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
		},
		sineOut: function (t, b, c, d) {
			return c * Math.sin(t/d * (Math.PI/2)) + b;
		},
		sineInOut: function (t, b, c, d) {
			return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
		},
		expoIn: function (t, b, c, d) {
			return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
		},
		expoOut: function (t, b, c, d) {
			return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
		},
		expoInOut: 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;
		},
		circIn: function (t, b, c, d) {
			return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
		},
		circOut: function (t, b, c, d) {
			return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
		},
		circInOut: 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;
		},
		elasticIn: function (t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			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;
		},
		elasticOut: function (t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			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;
		},
		elasticInOut: function (t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			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;
		},
		backIn: function (t, b, c, d, s) {
			if (s == undefined) s = 1.70158;
			return c*(t/=d)*t*((s+1)*t - s) + b;
		},
		backOut: function (t, b, c, d, s) {
			if (s == undefined) s = 1.70158;
			return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
		},
		backInOut: 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;
		},
		bounceIn: function (t, b, c, d) {
			return c - this.bounceOut (d-t, 0, c, d) + b;
		},
		bounceOut: 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;
			}
		},
		bounceInOut: function (t, b, c, d) {
			if (t < d/2) return this.bounceIn (t*2, 0, c, d) * .5 + b;
			return this.bounceOut (t*2-d, 0, c, d) * .5 + c*.5 + b;
		}
	}
};
