/*
Author/Owner: 	Daniel Peel.
Contact: 		mintpants@tiscali.co.uk.
Copyright: 		This script may not be reproduced or used in any way without the consent of the owner.
Details: 		Monster Element Explode.
					- explode
					- implode
					- implode to target
					- puff/disapear
					- puff
					
Created:		01.10.07
Updated: 		23.01.08 - 	Converted the original divExplode function into a class with new features:  
								implode = reverses the explode animation.
								clone target = clones the target to create a smoother looking animation.
						
						 -	Removed the validating of target dimensions to determine if it had reached its end state (to clear
						   	intervalId). Script now runs the animation a set number of cycles which should help reduce memory load.
				24.01.08 - 	Added a cleanup function to kill objects to prevent memory leaks.
							Added a setup method to allow an implode without an explode previously all the setup was tied to the
							explode.
				21.02.08 -	Removed opacity effects for now
				21.02.08 -  Changed the way a hidden element explodes if the element has content the explode doesnt look correct
							so content will always be added at the end of the explosion
				21.02.08 -	Added the ability to have a transparent exploded div with the child data opaque 
				25.02.08 -	Added a callback function to do something once the explode or implode has finished.
							Added the ability too choose where on the screen the explosion ends



*/


//******************************************************************************************************************//
//												     DIV ANIMATE OBJECT                                             //
//******************************************************************************************************************//
function divAnimate(trigger, targetId, args)	{
	
	this.args = augment({
	
	//additional pixels that position the target such as parent margins
	
		eSpaceX: false,
		eSpaceY: false,
		
		endPos: 'center'})
		
	//Target details
	this.target = document.getElementById(targetId);
		
	//The final width and height of the target
	this.target.finalWidth = this.target.getAttribute("finalWidth");
	this.target.finalHeight =  this.target.getAttribute("finalHeight");
	
	//The end position
	this.endPos = this.args.endPos;
	
	//Find the target position
	this.target.pos = findPosition(this.target);
	
	//precentage of movement per cycle default 25%
	this.percentage = 25;
		
	//Number of cycles based on this.percentage default is 4
	this.cycles = 100/this.percentage;
	
	
	if(typeof(trigger) != 'object')
	{
		trigger = document.getElementById(trigger);
	}
	
	this.trigger = trigger;
	
	//Trigger position
	this.trigger.pos = findPosition(this.trigger);
	
}

divAnimate.prototype.finalPos = function()	{
	
	switch(this.endPos) {
		
		case 'top_left':
			this.finalXPos = 0;
			this.finalYPos = 0;
		break;
		
		case 'top_center':
			this.finalXPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).horCent;
			this.finalYPos = 0;	
		break;
		
		case 'top_right':
			this.finalXPos = innerWin.Width - this.target.finalWidth;
			this.finalYPos = 0;
		break;
		
		case 'middle_left':
			this.finalXPos = 0;
			this.finalYPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).verCent;
		break;
		
		case 'center':
			//determine the the final position of the target based upon the window center and the targets finalWidth, Height	
			this.finalXPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).horCent;
			this.finalYPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).verCent;		
		break;
		
		case 'middle_right':
			this.finalXPos = innerWin.Width - this.target.finalWidth;
			this.finalYPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).verCent;	
		break;
		
		case 'bottom_left':
			this.finalXPos = 0;
			this.finalYPos = innerWin.Height - this.target.finalHeight;	
		break;
		
		case 'bottom_center':
			this.finalXPos = divScreenCenter(this.target.finalWidth, this.target.finalHeight).horCent;
			this.finalYPos = innerWin.Height - this.target.finalHeight;	
		break;
		
		case 'bottom_right':
			this.finalXPos = innerWin.Width - this.target.finalWidth;
			this.finalYPos = innerWin.Height - this.target.finalHeight;	
		break;
	}
		
	return this;
	
}

divAnimate.prototype.eSpace = function()	{
		
		/* Because the target is removed from the DOM tree to be positioned absolutely 
		any target margins or target.parents padding affecting the targets position
		are removed and the target moves a little bit looking unsightly.
	
		Since the margins or padding could be any number of levels up its best to adjust this manually 
		*/
		
		//Adjust
		if(this.args.eSpaceX)
		{
			this.target.style.left = parseInt(this.target.style.left, 10) - this.args.eSpaceX + "px";
		}
		
		if(this.args.eSpaceY)
		{
			this.target.style.top = parseInt(this.target.style.top, 10) - this.args.eSpaceY + "px";
		}		
		
		return this;		
}
		

divAnimate.prototype.movement = function()	{
	
	
	//********************** HORIZONTAL MOVEMENT *********************/
	
	//Determine if the target needs to move left or right and caluclate the pixel movement per cycle
	if(this.target.pos[0] < this.finalXPos)
	{
		this.moveHor = "right";
		this.pxPerCycleX = ((this.finalXPos - parseInt(this.target.style.left, 10))/100) * this.percentage;
	}
	else
	{
		this.moveHor = "left";
		this.pxPerCycleX = ((parseInt(this.target.style.left, 10) - this.finalXPos)/100) * this.percentage;
	}
	
	
	
	//************************ VERTICAL MOVEMENT ********************/
	
	//Determine if the target needs to move up or down and the pixels per y movement
	if(this.target.pos[1] < this.finalYPos)
	{
		this.moveVer = "down";
		this.pxPerCycleY = ((this.finalYPos - parseInt(this.target.style.top, 10))/100) * this.percentage;
	}
	else
	{
		this.moveVer = "up";
		this.pxPerCycleY = ((parseInt(this.target.style.top, 10) - this.finalYPos)/100) * this.percentage;
		
	}	
}


divAnimate.prototype.resizing = function()	{
	
	//************************** RESIZING ***************************/
		
	/* Resizing is calculated after the element is displayed otherwise 
	
	we dont have access to its offset properties
	
	*/	
	
	this.pxPerCycleWidth = ( (this.target.finalWidth - this.target.offsetWidth)/100) * this.percentage;	
	this.pxPerCycleHeight = ( (this.target.finalHeight - this.target.offsetHeight)/100) * this.percentage;	
	
	
}
divAnimate.prototype.eXpand = function()	{
	
	//ParseInt or parseFloat?? parseFloat would be more accurate but might it be slower?
	
	//*******************************************************************************************//
	//										 RESIZE WIDTH	    								 //		
	
	this.target.style.width = (this.target.offsetWidth + this.pxPerCycleWidth) + "px"; 			
	
	//									    END RESIZE WIDTH                                    //		
	//******************************************************************************************//	
	
	
	
	
	//******************************************************************************************//
	//											MOVE X		                                    //
	if(this.moveHor == "right")
	{
		this.target.style.left = (parseFloat(this.target.style.left, 10) + this.pxPerCycleX ) + "px";
	}
	else
	{
		this.target.style.left = (parseFloat(this.target.style.left, 10) - this.pxPerCycleX ) + "px";
		
	}
	//									     END MOVE X           							    //		
	//******************************************************************************************//	
	
	
	
	
	//******************************************************************************************//
	//										RESIZE HEIGHT								        //			
			
	this.target.style.height = (this.target.offsetHeight + this.pxPerCycleHeight) + "px"; 			
	
	//									   END RESIZE HEIGHT								    //		
	//******************************************************************************************//	
	
	
	
	
	//******************************************************************************************//
	//										    MOVE Y                                          //		
	if(this.moveVer == "down")
	{
		this.target.style.top = (parseFloat(this.target.style.top, 10) + this.pxPerCycleY) + "px";		
	}
	else
	{
		this.target.style.top = (parseFloat(this.target.style.top, 10) - this.pxPerCycleY) + "px";
		
	}
	//									      END MOVE Y                                        //		
	//******************************************************************************************//
	
}

divAnimate.prototype.shrink = function()	{
	//*******************************************************************************************//
	//										   RESIZE WIDTH	    								 //		

	this.target.style.width = (this.target.offsetWidth - this.pxPerCycleWidth) + "px"; 			
	
	//									    END RESIZE WIDTH                                    //		
	//******************************************************************************************//	
	
	
	
	//******************************************************************************************//
	//											MOVE X		                                    //
	if(this.moveHor == "right")
	{
		this.target.style.left = (parseFloat(this.target.style.left, 10) - this.pxPerCycleX ) + "px";		
	}
	else
	{
		this.target.style.left = (parseFloat(this.target.style.left, 10) + this.pxPerCycleX ) + "px";		
	}
	//									     END MOVE X           							    //		
	//******************************************************************************************//	
	
	
	
	//******************************************************************************************//
	//										RESIZE HEIGHT								        //			
		
	this.target.style.height = (this.target.offsetHeight - this.pxPerCycleHeight) + "px"; 			
	
	//									   END RESIZE HEIGHT								    //		
	//******************************************************************************************//	
	
	
	
	//******************************************************************************************//
	//										    MOVE Y                                          //		
	if(this.moveVer == "down")
	{
		this.target.style.top = (parseFloat(this.target.style.top, 10) - this.pxPerCycleY) + "px";
	}
	else
	{
		this.target.style.top = (parseFloat(this.target.style.top, 10) + this.pxPerCycleY) + "px";
	}
	//									      END MOVE Y                                        //		
	//******************************************************************************************//
}

divAnimate.prototype.startCallBack = function()	{
	
	//If you want to do something once the animation has finished
	//This must be defined before you initiate the animation method
}
//********************* CALLBACK MACROS *************************//
divAnimate.prototype.positionContent = function(content)	{

//position content over a transparent wrapper
content.style.position = 'absolute';

content.style.top = Math.ceil((parseInt(this.target.style.height, 10) - parseInt(content.style.height, 10))/2) + (parseInt(this.target.style.top, 10)) + "px";

content.style.left = Math.ceil((parseInt(this.target.style.width, 10)-parseInt(content.style.width, 10))/2) + (parseInt(this.target.style.left, 10)) + "px";

content.style.zIndex = 12;

content.style.display = 'block';

return;
}//End positionContent Macro

divAnimate.prototype.appendFChild = function(content)	{
	
	this.target.appendChild(content);
	
	content.style.visibility = 'block';
}

divAnimate.prototype.placeChild = function(content, holder)	{
	
	if( typeof(holder) != 'object')
	{
		holder = document.getElementById(holder)
	}
	
		holder.appendChild(content);
}
			


divAnimate.prototype.endCallBack = function()	{
	//If you want to do something once the animation has finished
	//This must be defined before you initiate the animation method
}

	

divAnimate.prototype.doExplode = function()	{
	
	//*********** ANIMATE DIVS MOVEMENT ********//
	this.eXpand();	
	
	//************* INCREASE OPACITY ***********/
	
	//this.incOpac();
	
	//Increment cycle counter
	this.cycle++;
	
	
	if(this.cycle == this.cycles)
	{	
		clearInterval(this.intervalId);
		
		this.startCallBack();
	}
	
}

divAnimate.prototype.explodeHidden = function()	{
	
	//Return if the el has already been exploded
	if(this.target.style.display == 'block')
	{	
		return this;
	}
	
	//Set a marker so we know the element was originally hidden
	this.hidden = true;
	
	//Position the hidden el over the trigger
	this.target.style.left = this.trigger.pos[0] + "px";
	this.target.style.top = this.trigger.pos[1] + "px";
	
	//Style the el as absolute
	this.target.style.position = 'absolute';
	
	//Fetch the final co-ordinates
	this.finalPos();
	
	//Calculate the movement factors
	this.movement();
	
	//Show hidden target now so we can access its offset properties
	this.target.style.display = 'block';
	
	//Calculate the resize factors
	this.resizing();	
	
	//Initialise a cycle counter
	this.cycle = 0;	
	
	// EXPLODE BABY!
	var self = this;
	
	function callMethod() {
		self.doExplode();
	}
	
	this.intervalId = setInterval(callMethod, 10);
}


divAnimate.prototype.explode = function()	{
	
	//Set a marker so we know the element was originally visibile
	this.hidden = false;
	///************************************************************************************************//
	//							               CREATE THE TARGET								      //
	//Clone the target	
	
	//Save the original target as a different property since other functions act on this.target
	this.origTarget = this.target;
	
	this.target = this.target.cloneNode(true);
			
	this.target.style.zIndex = 11;
	
	//							             END CREATE THE TARGET								      //
	//************************************************************************************************//
	
	
	//************************************************************************************************//
	//								      SETUP THE TARGET FOR MOVEMENT		                          //
	
	//Set the left and top style here to allow movement
	this.target.style.left = this.target.pos[0] + "px";
	this.target.style.top = this.target.pos[1] + "px";
	
	//Adjust for any extra space
	this.eSpace();
	
	
	this.target.style.position = 'absolute';
	
	//Calculate movement factors
	this.movement();
	
	
	//Hide the target
	this.origTarget.style.visibility = 'hidden';
	
	//append the clone
	document.body.appendChild(this.target);	
	
	//Calculate the resize factors
	this.resizing();
	
	//							       END SETUP THE TARGET FOR MOVEMENT					          //
	//************************************************************************************************//
	
	//************************************************************************************************//
	//											IMPLODE SETUP									      //
	//CONVERT THE TRIGGER TO IMPLODE
	
	//Save the original trigger id
	this.origTrigId = this.trigger.id;
		
	//Rename the original trigger id to prevent confusion between the clone and the original
	this.origTrigTempId = Math.random() * (100 - 1) + 1;
	this.trigger.id = this.origTrigTempId; 
		
	//Find and save the clone trigger
	this.target.trigger = document.getElementById(this.origTrigId);
	
	//Save a reference in the clone or target trigger to this object to collect later
	this.target.trigger.obj = this;
	
	//Set the onclick function to implode		
	this.target.trigger.onclick = this.implode;
			
	//										    END IMPLODE SETUP   								  //
	//************************************************************************************************//
	
	
	//Initialise a cycle counter
	this.cycle = 0;	
	
	// EXPLODE BABY!
	var self = this;
	
	function callMethod() {
		self.doExplode();
	}
	
	this.intervalId = setInterval(callMethod, 10);
	
	//Convert the trigger
	
	
	this.trigger = trigger;
	this.implodeTrigger();
		
}


divAnimate.prototype.implode = function()	{
	
	if(this.obj)
	{
		var self = this.obj;
	}
	else
	{
		var self = this;
	}
	/*N.B this now refers to the trigger 
		but since we saved the obj object earlier as trigger.obj we can still access it with this.obj
	*/
	
	//Reset the counter
	self.cycle = 0; // becomes this.cycle since its defined outside the callmethod 
	
	
	//IMPLODE Baby
	
		function callMethod() {
		self.doImplode();
		}
	
	self.intervalId = setInterval(callMethod, 10); //becomes this.intervalId
	
}

divAnimate.prototype.doImplode = function()	{
	
	//*********** ANIMATE DIVS MOVEMENT ********//
	this.shrink();
	
	//************** DECREASE OPACITY ***********/
	
	//this.decOpac();	
	
	//Increment counter
	this.cycle++;
	
	
	if(this.cycle == this.cycles)
	{
		clearInterval(this.intervalId);
		
		//Reset the changes we made to the DOM
		if(this.hidden == false)
		{
			//Remove the clone
			document.body.removeChild(this.target);
		
			//Show the original
			this.origTarget.style.visibility = 'visible';
		
			//Rename the  trigger id in the DOM not the object
			document.getElementById(this.origTrigTempId).id = this.origTrigId;
		}	
		else
		{
			this.target.style.display = 'none';
		}
		
		this.endCallBack();
	}
	
} //End doImplode


//divAnimate.prototype.blowOut = function()	{
//	
//	//clone tha target
//	this.target = this.obj.target.cloneNode(true);
//	
//	//***** STYLE SETUP *****//
//	this.target.style.position = 'absolute';
//	this.target.style.left = this.obj.target.pos[0] + "px";
//	this.target.style.top = this.obj.target.pos[1] + "px";
//	this.target.style.opacity = 1;
//	this.target.style.filter = "alpha(opacity="+ 100 +")";
//	
//	//Save IE filter value seperately as we cant parse out its value directly;
//	this.filterValue = 100;
//	
//	//Hide the orig target if specified
//	if(this.obj.hide == true)
//	{
//		this.obj.target.style.visibility = 'hidden';
//	}
//		
//	//append the clone
//	document.body.appendChild(this.target);
//		
//	//Initialise a cycle counter
//	this.cycle = 0;	
//	
//	//precentage of movement per cycle default 25%
//	this.percentage = 10;
//		
//	//Number of cycles based on this.percentage default is 4
//	this.cycles = 100/this.percentage;
//	
//	//Movement direction
//	this.moveHor = "left";	
//	this.moveVer = "up";
//	
//	//Calculate the px per cycle movements
//	this.pxPerCycleWidth = (this.target.offsetWidth/2)/this.cycles;
//	
//	this.pxPerCycleHeight = (this.target.offsetHeight/2)/this.cycles;
//	
//	this.pxPerCycleX = this.pxPerCycleWidth/2;
//	
//	this.pxPerCycleY = this.pxPerCycleHeight/2;
//	
//	
//	//BLOWOUT or BLOWIN Baby
//	if(this.obj.blowIn == true)
//	{
//		var self = this; 
//			function callMethod() {
//			self.doBlowIn();
//			}
//		
//	}
//	else
//	{
//		
//		var self = this; 
//			function callMethod() {
//			self.doBlowOut();
//			}
//	}
//	
//	this.intervalId = setInterval(callMethod, 30); //becomes this.intervalId	
//
//}
//divAnimate.prototype.doBlowIn = function()	{
//	
//	this.shrink();
//	
//	this.decOpac();
//	
//	//Still very slow in I.E
//	this.filterValue = this.filterValue - this.percentage;
//    this.target.style.filter = "alpha(opacity=" + this.filterValue +")";
//	
//	//Increment counter
//	this.cycle++;
//	
//	
//	if(this.cycle == this.cycles)
//	{	
//		//Remove the orig target if specified
//		if(this.obj.remove == true)
//		{
//			this.obj.target.parentNode.removeChild(this.obj.target);	
//		}
//		
//		//Remove the clone
//		document.body.removeChild(this.target);
//		
//		clearInterval(this.intervalId);
//	}
//}
//
//divAnimate.prototype.doBlowOut = function()	{
//	
//	this.eXpand();
//	
//	this.decOpac();
//	
//	//Still very slow in I.E
//	this.filterValue = this.filterValue - this.percentage;
//    this.target.style.filter = "alpha(opacity=" + this.filterValue +")";
//	
//	//Increment counter
//	this.cycle++;
//	
//	
//	if(this.cycle == this.cycles)
//	{	
//		//Remove the orig target if specified
//		if(this.obj.remove == true)
//		{
//			//timeoutID = window.setTimeout(
//			this.obj.target.parentNode.removeChild(this.obj.target);
//			//, 1000);
//			 //window.clearTimeout(timeoutID);	
//		}
//		clearInterval(this.intervalId);
//		
//		//Remove the clone
//		document.body.removeChild(this.target);
//				
//	}
//}
//		
//
//divAnimate.prototype.implodeTo = function ()	{
//	
//	this.target = this.obj.target;
//	
//	this.pxPerCycleWidth = this.target.offsetWidth/this.cycles;
//	
//	this.pxPerCycleHeight = this.target.offsetHeight/this.cycles;
//	
//	this.pxPerCycleX;
//	
//	
//}

//******************************************************************************************************************//
//											    END  DIV ANIMATE OBJECT                                             //
//******************************************************************************************************************//

////None Object explode hide simply closes and hides the target
//function explodedHide(targetObj, blackout)	{
//	
//	targetObj.innerHTML = null;
//	targetObj.style.width = "0px";
//	targetObj.style.height = "0px";
//	targetObj.style.visibility = 'hidden';
//	
//	if(blackout != false)
//	{
//		removeBlackOut(blackout);
//	}	
//	
//}

//function blowOut(targetId, hide, remove, blowIn)	{
//
//	var TEMP_obj = new Object();
//	
//	TEMP_obj.target = document.getElementById(targetId);
//		
//	TEMP_obj.hide = hide;
//	
//	TEMP_obj.remove = remove;
//	
//	TEMP_obj.blowIn = blowIn;
//	
//	//Initiate a new AnimateObject
//	var blowOut = new divAnimate(TEMP_obj);
//	
//	//Call the blow method
//	blowOut.blowOut();
//	
//	//Destroy the temp object
//	TEMP_obj = null;
//}

/*
FUNCTION CALL for implode to location
	
	implodes to location

*/

//function iMplode(targetId, implodeToId, removeTarget)	{
//	
//	var TEMP_obj = new Object();
//	
//	TEMP_obj.target = document.getElementById(targetId);
//		
//	TEMP_obj.implode_to = document.getElementById(implodeToId);
//	
//	TEMP_obj.removeTarget = removeTarget;
//	
//	var iMplode = new divAnimate(TEMP_obj);
//	
//	iMplode.implodeTo();
//	
//	TEMP_obj = null;
//}


/*
FUNCTION CALL for exploding a div
	
	explodes hidden div
	
	explodes visible div
	
	implodes
	
N.B the target divs width must be specified even if it is 0
*/
