/*

 * jQuery.ImageSwitch

 * Version: 1.0.2

 * http://www.hieu.co.uk/ImageSwitch/

 *

 * Copyright (c) 2009 Hieu Pham - http://www.hieu.co.uk

 * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)

 * http://www.opensource.org/licenses/cddl1.php

 *

 * Date: 13/03/2009

 * Revision: 50

 */

 //This function to preload the image before using it in the function

 var Debug = function(mess, line){

	if(!$("#Debug"))

	{

		$("body").append("<div id='Debug'></div>");

	}

	if(line){

		$("#Debug").html($("#Debug").html()+"<br/>"+mess);

	}

	else{

		$("#Debug").html($("#Debug").html()+mess);

	}

};

(function($){

	$.fn.ImageSwitch = function(Arguements, FuntionHandle) {

		var defaults = {

			Type: "FadeIn", // Type of effect to run the function

			NewImage: "", //The new image will be loaded in

			EffectOriginal: true,

			Speed: 1000, //Speed of the effect

			StartLeft: 50, //The position the effect start compare to the original position could be (-)

			StartTop: 0,

			StartOpacity: 0, //Which start opacity it would be

			EndLeft: -50, //The position the effect end compare to the original position could be (-)

			EndTop: 0,

			EndOpacity: 0, //Which start opacity it would be

			Direction: "RightLeft", //Which Way the image will be sroll

			Door1: "", //The image for the door 1

			Door2: "" //The image for the door 2

		};

		

		var Args = $.extend(defaults, Arguements);

		var Obj = this; // Just a way to reference to this obj in case we need to pass in another event handle

		//To specific which obj ID the effect will associate to

		var EffectID = 0;

		

		var EffectImageId;//The id of effect image layer : #GrpEffectImg + EffectID

		var EffectDivId1;//The id of effect div layer : #GrpEffectDiv2 + EffectID

		var EffectDivId2;//The id of effect div layer : #GrpEffectDiv2 + EffectID

		

        var EndFunction = function(){

			Obj.data("imageswitch", -1);

		};		

		if($.isFunction(FuntionHandle)){

		    EndFunction = function(){		

				FuntionHandle();	

				Obj.data("imageswitch", -1);

			};

		}

		//-----------------------------------------------------------------------------------------------------------

		//The original image will be fade out when the new image will fade in

		var FadeImage = function(){

			//Generate the effect map, move the effect map overlay the original map

			Obj.parent().append("<img class='GrpEffectImg' id='"+EffectImageId.replace("#","")+"'/>");

			$(EffectImageId).attr("src", Obj.attr("src"));

			$(EffectImageId).css("position", "absolute");

			$(EffectImageId).css("top", Obj.position().top);

			$(EffectImageId).css("left", Obj.position().left);

			$(EffectImageId).css("opacity", 1);

			

			//Change image of the original map

			Obj.attr("src", Args.NewImage);

			

			//Need something special when user want to keep no effect for the orignal

			if(Args.EffectOriginal)

			{

				//Set the start opacity, as the effect will fade out we set in start at 1, vice versa for the original

				Obj.css("opacity", Args.StartOpacity);		

				

				//Fade in the original image

				Obj.animate({"opacity":1}, Args.Speed);			

			}

			

			//Start effect animation

			$(EffectImageId).animate({"opacity":0}, Args.Speed, function(){

					//Remove the effect image when finish the effect

					$(EffectImageId).remove();

					EndFunction();

			});			

		};

		//-----------------------------------------------------------------------------------------------------------

		//The new image will fly from the startPosition with the StartOpacity

		

		var Fly = function(FlyIn){

			//Generate the effect map, move the effect map overlay the original map

			$("body").append("<img class='GrpEffectImg' id='"+EffectImageId.replace("#","")+"'/>");

			$(EffectImageId).css("position", "absolute");

			if(FlyIn){

				//As the new image will fly in, so we set the effect image src = new image

				$(EffectImageId).attr("src", Args.NewImage);			

				$(EffectImageId).css("top", Obj.offset().top + Args.StartTop);

				$(EffectImageId).css("left", Obj.offset().left + Args.StartLeft);

				$(EffectImageId).css("opacity", Args.StartOpacity);

				EndTop = Obj.offset().top;

				EndLeft = Obj.offset().left;

				//Change the opacity base on the input				

				EndOpacity = 1; 			

			}else{

				//As the old image will fly out, so we set the effect image src = new image

				//The effect image will be on top of the old image and hide the old image

				//So we could set the old image with the new src

				$(EffectImageId).attr("src", Obj.attr("src"));						

				Obj.attr("src", Args.NewImage);

				$(EffectImageId).css("top", Obj.offset().top);

				$(EffectImageId).css("left", Obj.offset().left);

				$(EffectImageId).css("opacity", 1);

				EndTop = Obj.offset().top + Args.EndTop;

				EndLeft = Obj.offset().left + Args.EndLeft;

				//Change the opacity base on the input				

				EndOpacity = Args.EndOpacity; 				

			}

			//Let the effect start fly in

			$(EffectImageId).animate({"opacity":EndOpacity, "top":EndTop, 

										"left": EndLeft}, Args.Speed,

				function(){

					Obj.attr("src", Args.NewImage);

					$(EffectImageId).remove();

					EndFunction();

			});

		};

		//-----------------------------------------------------------------------------------------------------------

		//The new image will scoll in and kick the old image out.

		//With the setting ScollIn = false, The original image will scroll out and reveal the new image

		var Scroll = function(ScrollIn){

			//Save the original status so we could set it in the end

			var backup = Obj.clone(true);		

			//Create a viewport for it

			Obj.wrap("<div id='GrpViewport-"+ EffectID+"'></div>");

			$("#GrpViewport-" + EffectID).css("overflow","hidden");

			$("#GrpViewport-" + EffectID).width(Obj.width());

			$("#GrpViewport-" + EffectID).height(Obj.height());								

			//Generate the effect map, move the effect map overlay the original map				

			$("#GrpViewport-" + EffectID).append("<img class='GrpEffectImg' id='"+EffectImageId.replace("#","")+"'/>");

			$(EffectImageId).css("position", "absolute");

			//Find where the Effect Image start

			var StartTop = 0;

			var StartLeft = 0;				

			switch(Args.Direction){

				case "RightLeft":	StartLeft = -Obj.width();	break;

				case "LeftRight":	StartLeft = Obj.width();	break;

				case "TopDown":		StartTop = -Obj.height();	break;

				case "DownTop":		StartTop = Obj.height();	break;

			}

			//In scroll in using the Start position, else, Set it to 0 so it could scroll out

			//Also need o set the destination of the animate different

			if(ScrollIn){

				$(EffectImageId).attr("src", Args.NewImage);

				$(EffectImageId).css("top", StartTop);

				$(EffectImageId).css("left", StartLeft);

				$(EffectImageId).css("opacity", Args.StartOpacity);

				EndTop = 0;

				EndLeft = 0;

				//Don't change the opacity if it scroll in

				EndOpacity = 1; 

			}else{

				$(EffectImageId).attr("src", Obj.attr("src"));

				$(EffectImageId).css("left", 0);

				$(EffectImageId).css("top", 0);

				Obj.attr("src", Args.NewImage);

				EndTop = StartTop;

				EndLeft = StartLeft;

				//Change the opacity base on the input				

				EndOpacity = Args.EndOpacity; 

			}

			//We need to treat absolute position different					

			//In some case there're text arround the image, it could be a bit mess up

			if(Obj.css("position")!="absolute")

			{

				$("#GrpViewport-" + EffectID).css("position","relative");					

				Obj.css("position","absolute");

			}

			else

			{			

				$("#GrpViewport-" + EffectID).css("position","absolute");

				$("#GrpViewport-" + EffectID).css("left",Obj.css("left"));

				$("#GrpViewport-" + EffectID).css("top",Obj.css("top"));		

				Obj.css("top",0);

				Obj.css("left",0);

			}

			//if effect the original image, then move it as well

			if(Args.EffectOriginal && ScrollIn)

			{			

				//Move the original image along

				Obj.animate({"top": - StartTop,

							"left": - StartLeft}, Args.Speed);									

			}			

			//Start the effect

			$(EffectImageId).animate({"opacity":EndOpacity,"top":EndTop,"left":EndLeft}, Args.Speed, 

					function(){

						//Finish the effect, and replace the viewport with this area

						backup.attr("src",Args.NewImage);

						//Also remove the Attr for imageswitch

						backup.removeAttr("imageswitch");

						$("#GrpViewport-" + EffectID).replaceWith(backup);

						EndFunction();

				});	

		};

		//-----------------------------------------------------------------------------------------------------------

		//A door come out create an effect door close.then open the new image

		var SingleDoor = function(){

			//Save the original status so we could set it in the end

			var backup = Obj.clone(true);

			//Create a viewport for it

			Obj.wrap("<div id='GrpViewport'></div>");

			$("#GrpViewport").css("overflow","hidden");

			$("#GrpViewport").width(Obj.width());

			$("#GrpViewport").height(Obj.height());								

			//Generate the effect map, move the effect map overlay the original map				

			$("#GrpViewport").append("<div class='GrpEffectDiv' id='"+EffectDivId1.replace("#","")+"'/>");

			$(EffectDivId1).attr("src", Args.NewImage);

			$(EffectDivId1).css("position", "absolute");

			$(EffectDivId1).css("background-color", "#FFF");

            if(Args.Door1.length>0){

			    $(EffectDivId1).css("background", Args.Door1);

			}

			$(EffectDivId1).width(Obj.width());

			$(EffectDivId1).height(Obj.height());								

			//Find where the Effect Image start

			var StartTop = 0;

			var StartLeft = 0;				

			switch(Args.Direction){

				case "RightLeft":	StartLeft = -Obj.width();	break;

				case "LeftRight":	StartLeft = Obj.width();	break;

				case "TopDown":		StartTop = -Obj.height();	break;

				case "DownTop":		StartTop = Obj.height();	break;

			}				

			$(EffectDivId1).css("top", StartTop);

			$(EffectDivId1).css("left", StartLeft);	

			

			//We need to treat absolute position different	

			if(Obj.css("position")!="absolute")

			{

				$("#GrpViewport").css("position","relative");					

				Obj.css("position","absolute");			

			}

			else

			{

				$("#GrpViewport").css("position","absolute");

				$("#GrpViewport").css("left",Obj.css("left"));

				$("#GrpViewport").css("top",Obj.css("top"));		

				Obj.css("top",0);

				Obj.css("left",0);

			}

			//Start Close the Door

			$(EffectDivId1).animate({"top":0,"left":0}, Args.Speed, function(){

				//Finish the first effect change the image and open the door

				Obj.attr("src", Args.NewImage);

				//Start open the door

				$(EffectDivId1).animate({"top":StartTop,"left":StartLeft}, Args.Speed, function(){

					//Reset style

					backup.attr("src",Args.NewImage);

					//Also remove the Attr for imageswitch

					backup.removeAttr("imageswitch");					

					$("#GrpViewport").replaceWith(backup);

					EndFunction();

				});

			});	

		};

		//-----------------------------------------------------------------------------------------------------------

		//Same with single door but with this effect, there will be 2 door

		var DoubleDoor = function(){

			//Save the original status so we could set it in the end

			var orgPosition = Obj.css("position");

			var orgLeft = Obj.css("left");

			var orgTop = Obj.css("top");

			//Create a viewport for it

			Obj.wrap("<div id='GrpViewport'></div>");

			$("#GrpViewport").css("overflow","hidden");

			$("#GrpViewport").width(Obj.width());

			$("#GrpViewport").height(Obj.height());								

			//Generate the effect map, move the effect map overlay the original map				

			$("#GrpViewport").append("<div class='GrpEffectDiv' id='"+EffectDivId1.replace("#","")+"'/>");

			$(EffectDivId1).css("position", "absolute");

			$(EffectDivId1).css("background-color", "#FFF");

			if(Args.Door1.length>0){

                $(EffectDivId1).css("background", Args.Door1);			

			}

			$(EffectDivId1).width(Obj.width());

			$(EffectDivId1).height(Obj.height());								

			//We need the second door

			$("#GrpViewport").append("<div class='GrpEffectDiv1' id='"+EffectDivId2.replace("#","")+"'/>");

			$(EffectDivId2).css("position", "absolute");

			$(EffectDivId2).css("background-color", "#FFF");

			if(Args.Door2.length>0){

                $(EffectDivId2).css("background", Args.Door2);				

			}

			$(EffectDivId2).width(Obj.width());

			$(EffectDivId2).height(Obj.height());								

			

			//Find where the Effect Image start

			var StartTop = 0;

			var StartLeft = 0;				

			switch(Args.Direction){

				case "RightLeft":	StartLeft = -Obj.width();	break;

				case "LeftRight":	StartLeft = Obj.width();	break;

				case "TopDown":		StartTop = -Obj.height();	break;

				case "DownTop":		StartTop = Obj.height();	break;

			}				

			$(EffectDivId1).css("top", StartTop);

			$(EffectDivId1).css("left", StartLeft);	

			$(EffectDivId2).css("top", -StartTop);

			$(EffectDivId2).css("left", -StartLeft);	

			

			//set the background for the door effect so it look different

			if(!Args.EffectOriginal){

				$(EffectDivId1).css("background","#FFF url("+Args.NewImage+") no-repeat "+ -StartLeft/2 +"px "+ -StartTop/2+"px");

				$(EffectDivId2).css("background","#FFF url("+Args.NewImage+") no-repeat "+ StartLeft/2+"px "+ StartTop/2 +"px");

			}			

			

			//We need to treat absolute position different					

			if(Obj.css("position")!="absolute")

			{

				$("#GrpViewport").css("position","relative");					

				Obj.css("position","absolute");			

			}

			else

			{

				$("#GrpViewport").css("position","absolute");

				$("#GrpViewport").css("left",orgLeft);

				$("#GrpViewport").css("top",orgTop);

				Obj.css("position","absolute");			

				Obj.css("top",0);

				Obj.css("left",0);

			}

			//Start Close the Door

			$(EffectDivId1).animate({"top":StartTop/2,"left":StartLeft/2}, Args.Speed, function(){

				//Finish the first effect change the image and open the door

				Obj.attr("src", Args.NewImage);

				//If EffectOriginal isn't on mean two door stick into the new image, then stop here. Else carry on

				if(!Args.EffectOriginal){

					Obj.css("position", orgPosition);

					Obj.css("top", orgTop);

					Obj.css("left", orgLeft);				

					$("#GrpViewport").replaceWith(Obj);

				}else{

					//Start open the door

					$(EffectDivId1).animate({"top":StartTop,"left":StartLeft}, Args.Speed, function(){

						//Reset style

						Obj.css("position", orgPosition);

						Obj.css("top", orgTop);

						Obj.css("left", orgLeft);

						$("#GrpViewport").replaceWith(Obj);

					});

				}

			});	

			$(EffectDivId2).animate({"top":-StartTop/2,"left":-StartLeft/2}, Args.Speed, function(){

				//Finish the first effect change the image and open the door

				Obj.attr("src", Args.NewImage);

				//If EffectOriginal isn't on mean two door stick into the new image, then stop here. Else carry on

				if(!Args.EffectOriginal){

					EndFunction();

				}else{

					//Start open the door

					$(EffectDivId2).animate({"top":-StartTop,"left":-StartLeft}, Args.Speed, function(){

						//Run the end effect

						EndFunction();

					});

				}

			});					

		};

		//-----------------------------------------------------------------------------------------------------------

		//The new image will flip from the back of the old one to the top

		//If FlipIn is false, then the old image will flip to the back reveal the new one

		var Flip = function(FlipIn){

		    var backup = Obj.clone(true);	

			if(Obj.css("z-index") == 'auto')	{

				Obj.css("z-index", 100);

			}

			//if (position different then absolute and relative then it should be relative)

			if(Obj.css("position") != "absolute"){

				Obj.css("position", "relative");

			}

			//Generate the effect map, move the effect map overlay the original map

			$("body").append("<img class='GrpEffectImg'  id='"+EffectImageId.replace("#","")+"'/>");

			$(EffectImageId).css("position", "absolute");

			$(EffectImageId).css("top", Obj.offset().top);

			$(EffectImageId).css("left", Obj.offset().left);

			

			if(FlipIn){

				$(EffectImageId).css("opacity", Args.StartOpacity);

				//So this layer will be under the original image

				$(EffectImageId).css("z-index", Obj.css("z-index")-1);

				$(EffectImageId).attr("src", Args.NewImage);

			}else{

				$(EffectImageId).css("opacity", 1);

				//This layer will be on top the original image

				$(EffectImageId).css("z-index", Obj.css("z-index")+1);			

				//Turn in to the fake old image

				$(EffectImageId).attr("src", Obj.attr("src"));

				Obj.attr("src", Args.NewImage);

				

			}

			

			//Find where the effect layer stop

			if(Math.abs(Args.EndTop)<Obj.height() && Math.abs(Args.EndLeft)<Obj.width()){

				EndTop = Obj.offset().top;

				EndLeft = Obj.offset().left + Obj.width();

			}else{

				EndTop = Obj.offset().top + Args.EndTop;

				EndLeft = Obj.offset().left + Args.EndLeft;				

			}

			EndOpacity = 1; 

			

			//Let the effect start, 

			$(EffectImageId).animate({"opacity":EndOpacity, "top":EndTop, 

										"left": EndLeft}, Args.Speed,

				function(){

					//Now the effect image is out, move it back again

					if(FlipIn) {

						$(EffectImageId).css("z-index", 101);

					}else{

						EndOpacity = Args.EndOpacity;

						$(EffectImageId).css("z-index", 2);						

					}

					$(EffectImageId).animate({"opacity":EndOpacity, "top":Obj.offset().top, 

												"left": Obj.offset().left}, Args.Speed,

						function(){

							//Restore the image to the original

							backup.attr("src", Args.NewImage);

							//Also remove the Attr for imageswitch

							backup.removeAttr("imageswitch");															

							Obj.replaceWith(backup);

							$(EffectImageId).remove();

							EndFunction();						

						});

			});

		};

		

		return this.each(function(){

			Obj = $(this);		

			if(!Obj.ImageAnimating())

			{

				EffectID = $.data(Obj);

				

				//Mark the effect is running				

				Obj.data("imageswitch", EffectID);

				EffectImageId = "#GrpEffectImg-" + EffectID;//The id of effect image layer : #GrpEffectImg- + EffectID

				EffectDivId1 = "#GrpEffectDiv1-" + EffectID;//The id of effect div layer : #GrpEffectDiv1- + EffectID

				EffectDivId2 = "#GrpEffectDiv2-" + EffectID;//The id of effect div layer : #GrpEffectDiv2- + EffectID

				

				var TempImg = new Image();

				TempImg.src = Args.NewImage;

				$.ImagePreload(Args.NewImage,function(){

					switch(Args.Type){

						case "FadeIn":		FadeImage();	break;

						case "FlyIn": 		Fly(true);		break;

						case "FlyOut":		Fly(false);		break;

						case "FlipIn": 		Flip(true);		break;

						case "FlipOut":		Flip(false);	break;				

						case "ScrollIn":	Scroll(true);	break;

						case "ScrollOut":	Scroll(false);	break;

						case "SingleDoor":	SingleDoor();	break;

						case "DoubleDoor":	DoubleDoor();	break;

					}

				});

			}

		});	

	};	

})(jQuery);



//Check if a IS effect is running

(function($){

	$.fn.ImageAnimating = function(){

		if(this.data("imageswitch")>0){

			return true;

		}else{

			return false;

		}

	};

})(jQuery);

//Stop a specific the IS effect if it's running

(function($){

	$.fn.ImageStop = function(clearQueue, gotoEnd, EndFunction){

		return this.each(function(){

			if($(this).ImageAnimating()){

				var EffectID = $.data(this,"imageswitch");

				$("#GrpEffectImg-"+EffectID).stop(clearQueue, gotoEnd);

				$("#GrpEffectDiv-"+EffectID).stop(clearQueue, gotoEnd);

				$("#GrpEffectDiv1-"+EffectID).stop(clearQueue, gotoEnd);

				$(this).stop(clearQueue, gotoEnd);

				$("#GrpEffectImg-"+EffectID).remove();

				$("#GrpEffectDiv-"+EffectID).remove();

				$("#GrpEffectDiv1-"+EffectID).remove();

				if($.isFunction(EndFunction)){

					EndFunction();

				}

			}

		});

	};

})(jQuery);

//Stop all the IS effect running

(function($){

	$.ImageStopAll = function(clearQueue, gotoEnd, EndFunction){

		$(".GrpEffectImg").stop(clearQueue, gotoEnd);

		$(".GrpEffectDiv").stop(clearQueue, gotoEnd);

		$(".GrpEffectDiv1").stop(clearQueue, gotoEnd);

		$(this).stop(clearQueue, gotoEnd);

		$(".GrpEffectImg").remove();

		$(".GrpEffectDiv").remove();

		$(".GrpEffectDiv1").remove();

		$.data(this, "imageswitch", -1);

		if($.isFunction(EndFunction)){

			EndFunction();

		}

	};

})(jQuery);

//Preload a specific image

(function($){

	$.ImagePreload = function(FileName, EndFunction){

		var TempImage = new Image();

		TempImage.src = FileName;

		if($.isFunction(EndFunction)){

			$(TempImage).load(EndFunction());

		}

	};

})(jQuery);
