/*  
	Title : MinMax Elements
	Author : Tom Coote
	Wedsite : http://www.tomcoote.co.uk
*/

document.minimize = new MinMaxElements().Minimize;
document.maximize = new MinMaxElements().Maximize;

function MinMaxElements() 
{    
	var that = {}; 

	/* Private Variables */
	var iInterval = 20;


    /* Private Functions */

	function getElementWidth(eObj) {
		if (!eObj) { return 0; }

		if (eObj.style.width !== null && eObj.style.width != '') {
			return parseInt(eObj.style.width,10);
		}

		if (eObj.offsetWidth) {
			return parseInt(eObj.offsetWidth,10);
		}

		if (eObj.clientWidth) {
			return parseInt(eObj.clientWidth,10);
		}
	}

	function getElementHeight(eObj) {
		if (!eObj) { return 0; }

		if (eObj.style.height !== null && eObj.style.height != '') {
			return parseInt(eObj.style.height,10);
		}

		if (eObj.offsetHeight) {
			return parseInt(eObj.offsetHeight,10);
		}

		if (eObj.clientHeight) {
			return parseInt(eObj.clientHeight,10);
		}
	}

	function findPosLeft(obj)
	{
		var curleft = 0;
		if(obj.offsetParent) {
			while(1) {
				curleft += obj.offsetLeft;
				if(!obj.offsetParent) {
					break;
				}
				obj = obj.offsetParent;
			}
		}
		else if(obj.x) {
			curleft += obj.x;
		}
		return curleft;
	}
	function findPosTop(obj)
	{
		var curtop = 0;
		if(obj.offsetParent) {
			while(1) {
				curtop += obj.offsetTop;
				if(!obj.offsetParent) {
					break;
				}
				obj = obj.offsetParent;
			}
		}
		else if(obj.y) {
			curtop += obj.y;
		}
		return curtop;
	}

	function changeOpac(opacity, id) {
		var object = document.getElementById(id).style;
		object.opacity = (opacity / 100);
		object.MozOpacity = (opacity / 100);
		object.KhtmlOpacity = (opacity / 100);
		object.filter = "alpha(opacity=" + opacity + ")";

		if (SupportsAlpha(object)) {
			object.filters.alpha.opacity = opacity;
		}
	}

	function SupportsAlpha(obj) {
		if (obj.filters) {
			if (obj.filters.alpha) {
				return true;
			}
		}
		
		return false;
	}

	/* Public Functions */

	/*
	 * @argument: eMinObj	:	An object containing details of the objects minimized state.
	 *							The object must contain the following variables unless marked as optioanl;
	 *							id		: ID of the element to move
	 *							callback: (Optional) A function that is called when minimize has finished
	 *							width	: (Optional) Width of the element on the page
	 *							height	: (Optional) Height of the element on the page
	 *							x		: (Optional) The x coordinate at which the element must minimize to
	 *							y		: (Optional) The y coordinate at which the element must minimize to
	 *							top		: (Optional) The top (y) coordinate of the element as it currently is on the page
	 *							left	: (Optional) The left (x) coordinate of the element as it currently is on the page
	 */
	that.Minimize = function(eMinObj) {

		if (!eMinObj || !eMinObj.id) { return; }
		fn = eMinObj.callback || function() { };
		eMinObj = eMinObj || { };

		var x = eMinObj.x || 0,
			y = eMinObj.y || 0,
			eObj = document.getElementById(eMinObj.id),
			height = eMinObj.height || getElementHeight(eObj),
			width = eMinObj.width || getElementWidth(eObj),
			top = eMinObj.top || findPosTop(eObj),
			left = eMinObj.left || findPosLeft(eObj),
			PixelsPerX = (x<left) ? (left - x) / width : (x - left) / width,
			PixelsPerY = (y<top) ? (top - y) / height : (y - top) / height,
			SpeedX = (left<top) ? 1 : left/top,
			SpeedY = (top<left) ? 1 : top/left,
			OpacDif = Math.round(((PixelsPerX>PixelsPerY)?PixelsPerX:PixelsPerY)*((PixelsPerX>PixelsPerY)?width:height) / 100),
			iOpacity = 80, 
			bX = (x<left) ? true : false,
			bY = (y<top) ? true : false,
			FactorY = (!bY) ? height/5 : height/10,
			FactorX = (!bX) ? width/5 : width/10;

		if (eObj.style.visibility === 'hidden') { return; }		
		changeOpac(iOpacity, eMinObj.id);

		window.setTimeout(function() {
			eObj.style.overflow = 'hidden';
			eObj.style.width = width;
			eObj.style.height = height;
			eObj.style.top = top;
			eObj.style.left = left;
			eObj.style.position = 'absolute';

			var inter = window.setInterval(	
							function() {
								if (width > 1) {
									width -= PixelsPerX*10;
									eObj.style.width = (width < 1) ? '1px' : width + 'px';
								} else { bFin = true; }
								if (height > 1) {
									height -= PixelsPerY*10;
									eObj.style.height = (height < 1) ? '1px' : height + 'px';
								} else { bFin = true; }
								if (bY && top > y) {
									top -= SpeedY*FactorY;
									eObj.style.top = top + 'px';
								} 
								if (!bY && top < y) {
									top += SpeedY*FactorY;
									eObj.style.top = top + 'px';
								}
								if (bX && left > x) {
									left -= SpeedX*FactorX;
									eObj.style.left = left + 'px';
								}
								if (!bX && left < x) {
									left += SpeedX*FactorX;
									eObj.style.left = left + 'px';
								} 
								if (iOpacity > 0) {
									iOpacity -= OpacDif*2;
									changeOpac((iOpacity<0)?0:iOpacity,eMinObj.id);
								} 

								if ( (bY && top <= y && bX && left <= x) || (bY && top <= y && !bX && left >= x) ||
								     (!bY && top >= y && bX && left >= x) || (!bY && top >= y && !bX && left >= x) ) {
									eObj.style.visibility = 'hidden';
									window.clearInterval(inter);

									fn(eObj);
								}
							}, iInterval)
								}, 300);
	};

	/*
	 * @argument: eMaxObj	:	An object containing details of the objects maximized state.
	 *							The object must contain the following variables unless marked as optioanl;
	 *							id		: ID of the element to move
	 *							callback: (Optional) A function that is called when minimize has finished
	 *							width	: Width the element must maximize to
	 *							height	: Height the element must maximize to
	 *							x		: The x coordinate at which the element must maximize to
	 *							y		: The y coordinate at which the element must maximize to
	 *							top		: (Optional) The top (y) coordinate at where the element should maximise from
	 *							left	: (Optional) The left (x) coordinate at where the element should maximise from
	 */
	that.Maximize = function(eMaxObj) {
		
		if (!eMaxObj || !eMaxObj.id || !eMaxObj.width || !eMaxObj.height || !eMaxObj.x || !eMaxObj.y) { return; }
		fn = eMaxObj.callback || function() { };

		var x = eMaxObj.x,
			y = eMaxObj.y,
			eObj = document.getElementById(eMaxObj.id),
			height = 1,
			width = 1, 
			top = eMaxObj.top || findPosTop(eObj),
			left = eMaxObj.left || findPosLeft(eObj),
			PixelsPerX = (x<left) ? (left - x) / eMaxObj.width : (x - left) / eMaxObj.width,
			PixelsPerY = (y<top) ? (top - y) / eMaxObj.height : (y - top) / eMaxObj.height,
			SpeedX = (x<y) ? 1 : x/y,
			SpeedY = (y<x) ? 1 : y/x,
			OpacDif = Math.round(((PixelsPerX>PixelsPerY)?PixelsPerX:PixelsPerY)*((PixelsPerX>PixelsPerY)?eMaxObj.width:eMaxObj.height) / 100),
			iOpacity = 0, 
			bX = (x<left) ? true : false,
			bY = (y<top) ? true : false,
			FactorY = (!bY) ? eMaxObj.height/10 : eMaxObj.height/5,
			FactorX = (!bX) ? eMaxObj.width/10 : eMaxObj.width/5;

		if (eObj.style.visibility === 'visible') { return; }		
		if (eMaxObj.top && eMaxObj.left) {
			eObj.style.top = eMaxObj.top + 'px';
			eObj.style.left = eMaxObj.left + 'px';
		}

		changeOpac(iOpacity, eMaxObj.id);
		eObj.style.visibility = 'visible';
		eObj.style.overflow = 'hidden';
		eObj.style.position = 'absolute';
		eObj.style.width = '0px';
		eObj.style.height = '0px';

		var inter = window.setInterval(	
						function() {
							if (width < eMaxObj.width) {
								width += PixelsPerX*10;
								eObj.style.width = (width > eMaxObj.width) ? eMaxObj.width + 'px' : width + 'px';
							} 
							if (height < eMaxObj.height) {
								height += PixelsPerY*10;
								eObj.style.height = (height > eMaxObj.height) ? eMaxObj.height + 'px' : height + 'px';
							} 
							if (bY && top > y) {
								top -= SpeedY*FactorY;
								eObj.style.top = top + 'px';
							}
							if (!bY && top < y) {
								top += SpeedY*FactorY;
								eObj.style.top = top + 'px';
							} 
							if (bX && left > x) { 
								left -= SpeedX*FactorX;
								eObj.style.left = left + 'px';
							} 
							if (!bX && left < x) { 
								left += SpeedX*FactorX;
								eObj.style.left = left + 'px';
							} 
							if (iOpacity < 100) {
								iOpacity += OpacDif;
								changeOpac((iOpacity>100)?100:iOpacity,eMaxObj.id);
							} 

							if ( (bY && top <= y && bX && left <= x) || (bY && top <= y && !bX && left >= x) ||
								 (!bY && top >= y && bX && left >= x) || (!bY && top >= y && !bX && left >= x) ) {
								eObj.style.width = eMaxObj.width + 'px';
								eObj.style.height = eMaxObj.height + 'px';
								eObj.style.top = eMaxObj.y + 'px';
								eObj.style.left = eMaxObj.x + 'px';
								changeOpac(100,eMaxObj.id);
								window.clearInterval(inter);

								fn(eObj);
							}
						}, iInterval);
	};

    return that;
}