/**
 * @name 		: 	Textarea Expander
 * @author 		: 	Swapnil Sarwe
 * @link 		: 	http://swapnilsarwe.phpnet.us/
 * @version 	: 	1.00
 * @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.
 * @changes 	: 	The previous version used negative marginLeft to hide the cloned textarea
 which used to use the other element following the textarea to be not visible on the page.
 Absolutely positioned them as in jquery-plugin-autoresize of James Padolsey to fix the issue.
 Also the tab index of -1 has ben added to avoid the focus being taken to the hidden textareas.
 The animation has been given as option rather than having two different JS files,
 you can now just turn on or turn off the animation for expanding the textarea.
 * @options 	: 	animation - true or false will have the text area expand with ease or expand directly.
 * 					xtraSpace - The extra space or height by which the textarea should expand.
 * 					delay	  - The delay in ease for the expansion of the textarea
 * 			    	callBack  - The callback function which executes eveytime the text area expands
 * @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
 */
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) {
		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;
			if (options.callBack) {
				options.callBack();
			}
		}
	}
	
	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) {
		el.style['clear'] = 'left';
		
		var newEl = el.cloneNode(true);
		newEl.removeAttribute('id');
		newEl.removeAttribute('name');
		newEl.style['position'] = "absolute";
		newEl.style['top'] = "0";
		newEl.style['left'] = "-9999px";
		newEl.tabIndex = "-1";
		
		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;
		}
		if (options.animation) {
			var animOptions = {
				element: this,
				property: 'height',
				unit: 'px',
				from: this.clientHeight,
				to: newHeight,
				duration: options.delay,
				callBack: options.callBack
			}
			aniMate(animOptions);
		}
		else {
			this.style['height'] = newHeight + 'px';
		}
		if (evt.preventDefault) {
			evt.preventDefault();
		}
		else {
			evt.returnValue = false;
		}
	};
	var tAs = [];
	if (typeof(options.ids) == 'undefined' || options.ids.length == 0) {
		tAs = document.getElementsByTagName('textarea');
	}
	else {
		tAs = [];
		var n = options.ids.length;
		while (n--) {
			tAs.push(document.getElementById(options.ids[n]));
		}
	}
	var n = tAs.length;
	while (n--) {
		tAs[n].style['overflowY'] = 'hidden';
		var dupA = makeDuplicate(tAs[n]);
		tAs[n].clone = dupA;
		insertAfter(tAs[n], dupA);
		addListener(tAs[n], 'keyup', activateResize);
		/*
		 * Added the below two lines to activate the xpander on focus 
		 * and then focusing on it to trigger the event so that on load the textarea expands
		 */

	}
}
    window.onload = function(){
        Xpander({
            animation: true,
            xtraSpace: 15,
            delay: 10,
            callBack: function(){
                /* Your callback function here */
            }
        });
    };