/**
 * @name : Textarea Expander With Animation
 * @author : Swapnil Sarwe
 * @version : 0.2 [BETA]
 * @description : Based on and inspired by James Padolsey's jQuery autoResize
 *              The basic idea is to have textarea expand as the user types in
 *              the content, so that the user never has the scroll bar appear
 *              for the textarea.
 * @see : http://james.padolsey.com/javascript/jquery-plugin-autoresize/
 */
/**
 * @desription: This animation function is inspired Jonathon Snook's book -
 *              "Accelerated DOM Scripting with Ajax, APIs, and Libraries" and
 *              the snippet from James Padolsey's old blog
 *              http://www.qd-creative.co.uk/ for css switcher code
 * @see : http://snook.ca/
 * @see : http://james.padolsey.com/
 */
/**
 * @desription: This easing equations are taken by Robert Penner
 * @see : http://www.robertpenner.com/easing/
 * @see : http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf
 */
var eventStat = true;
function aniMate(options) {
	var Ease = {
		easeInQuad : function(t, b, c, d) {
			return c * (t /= d) * t + b;
		},
		easeOutQuad : function(t, b, c, d) {
			return -c * (t /= d) * (t - 2) + b;
		},
		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;
		},
		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;
		}
	};
	var el = options.element;
	if (typeof el == 'string')
		el = document.getElementById(options.element);
	if (!el)
		return false;

	if (el.style[options.property] === options.to + options.unit) {
		if (options.callBack)
			options.callBack();
		return;
	}
	el.style[options.property] = options.from + options.unit;
	function nudgeProperty(time) {
		eventStat = false;
		change = options.to - options.from;
		if (time <= options.duration) {
			newVal = Ease.easeInOutCirc(time++, options.from, change,
					options.duration)
					+ options.unit;
			el.style[options.property] = newVal;
			setTimeout(function() {
						nudgeProperty(time);
					}, 12)
		} else {
			el.style[options.property] = options.to + options.unit;
			eventStat = true;
			if (options.callBack)
				options.callBack();
		}
	}
	if (eventStat != true) {
		return;
	}
	nudgeProperty(0);
}

/**
 * @desription: addListener function is taken from the Jonathon Snook's book -
 *              "Accelerated DOM Scripting with Ajax, APIs, and Libraries"
 * @see : http://snook.ca/
 */
function addListener(element, event, listener) {
	if (element.addEventListener)
		element.addEventListener(event, listener, false);
	else if (element.attachEvent) {
		element.attachEvent('on' + event, function() {
					listener.call(element)
				});
	}
}

function Xpander(options) {
	makeDuplicate = function(el) {
		var newEl = el.cloneNode(true);
		newEl.removeAttribute('id');
		newEl.removeAttribute('name');
		newEl.style['marginLeft'] = "-9999px";
		return newEl;
	};
	insertAfter = function(target, bullet) {
		target.nextSibling ? target.parentNode.insertBefore(bullet,
				target.nextSibling) : target.parentNode.appendChild(bullet);
	};

	var lastHeight = null;
	activateResize = function(evt) {
		evt = evt || window.event;
		var cloned = this.clone;
		cloned.value = this.value;
		if (!lastHeight) {
			lastHeight = this.clientHeight;
		} else {
			lastHeight = cloned.scrollHeight;
		}
		var newHeight = cloned.scrollHeight + options.xtraSpace;
		if (newHeight == this.clientHeight)
			return;
		var animOptions = {
			element : this,
			property : 'height',
			unit : 'px',
			from : this.clientHeight,
			to : newHeight,
			duration : options.delay,
			callBack : options.callBack
		}
		aniMate(animOptions);
		if (evt.preventDefault) {
			evt.preventDefault();
		} else {
			evt.returnValue = false;
		}
	};
	var tAs = document.getElementsByTagName('textarea');
	var tACount = tAs.length;
	while (tACount) {
		tACount--;
		tAs[tACount].style['overflowY'] = 'hidden';
		var dupA = makeDuplicate(tAs[tACount]);
		tAs[tACount].clone = dupA;
		insertAfter(tAs[tACount], dupA);
		addListener(tAs[tACount], 'keyup', activateResize);
	}
}

