// effects.js - version 0.2 - Spry Pre-Release 1.6.1

//

// Copyright (c) 2006. Adobe Systems Incorporated.

// All rights reserved.

// Redistribution and use in source and binary forms, with or without

// modification, are permitted provided that the following conditions are met:

//

//   * Redistributions of source code must retain the above copyright notice,

//     this list of conditions and the following disclaimer.

//   * Redistributions in binary form must reproduce the above copyright notice,

//     this list of conditions and the following disclaimer in the documentation

//     and/or other materials provided with the distribution.

//   * Neither the name of Adobe Systems Incorporated nor the names of its

//     contributors may be used to endorse or promote products derived from this

//     software without specific prior written permission.

//

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

// POSSIBILITY OF SUCH DAMAGE.



///////////////////////////////////////////////////////////////////////////////////////

// 

//  This file is used in an advanced demo to examplify the Spry Effects functionalities 

//  and interoperability between them. To read more details about different Spry Effects

// 	and their detailed options please see our detailed samples:

//

// 	http://labs.adobe.com/technologies/spry/samples/#effects

//

// 	We had to write the following custom objects and functions to achieve our demo goal:

//  

//  Spry.Effect.FadeBlind 

//			- A custom cluster effect which group together a Fade and a Blind Effect

//

//  Spry.Effect.FadeSlide 

// 			- A custom cluster effect which group together a Fade and a Blind Effect

//

// 	Observer 

//      - A custom observer attached to every effect that will run in page. This observer 

// 			was designed to run any effect a second time in the opposite direction and 

// 			revert at the end any CSS changes that where changed by the effect on the target

// 			element

//

// 	runEffect()

// 			- A custom function that will prepare and run a given effect on a target element

//

//  ExampleHelpText()

// 			- A custom function designed to change the content text of an element.

//  

///////////////////////////////////////////////////////////////////////////////////////





////////////////////////////////////////////////////

//

// 	Global Variables

//

////////////////////////////////////////////////////



// list of effects already run to be reused

var effects = {};

// latest effect ran

var prevEffect = false;

// CSS initial properties for the elements on which we apply the effects

var initialElements = [];

// list of style properties to be monitored

var saveStyle = ['position', 'width', 'height', 'opacity', 'filter', 'top', 'left', 'backgroundColor', 'visibility', 'display'];



////////////////////////////////////////////////////

//

// 	Cluster Effects

//

////////////////////////////////////////////////////



/* 

 * FadeBlind 

 * 		Custom Cluster effect that fade in/out and blind in/out simultanous an element

 * 		by running in parallel the Fade() and Blind() predefined clusters

 */



Spry.Effect.FadeBlind = function(element, options)

{

	Spry.Effect.Cluster.call(this, options);

	

	this.name = 'FadeBlind';

	var duration = 1000;

	var doToggle = false;

	var from = 100;

	var to = 0;



	if (options)

	{

		if (options.duration) duration = options.duration;

		if (options.toggle) doToggle = options.toggle;

		if (options.from) from = options.from;

		if (options.to) to = options.to;

	}



	var options = {duration: duration, from: from, to: to, toggle: doToggle};

	var blind = new Spry.Effect.Blind(element, options); 

	this.addParallelEffect(blind);



	var options = {duration: duration, from: from, to: to, toggle: doToggle};

	var fade = new Spry.Effect.Fade(element, options); 

	this.addParallelEffect(fade);

};



Spry.Effect.FadeBlind.prototype = new Spry.Effect.Cluster();

Spry.Effect.FadeBlind.prototype.constructor = Spry.Effect.FadeBlind; 



/* 

 * FadeSlide 

 * 		Custom Cluster effect that fade in/out and slide simultaneous an element

 * 		by running in parallel the Fade() and Slide() predefined clusters

 */



Spry.Effect.FadeSlide = function(element, options)

{

	Spry.Effect.Cluster.call(this, options);

	

	this.name = 'FadeSlide';

	var duration = 1000;

	var doToggle = false;

	var from = 100;

	var to = 0;



	if (options)

	{

		if (options.duration) duration = options.duration;

		if (options.toggle) doToggle = options.toggle;

		if (options.from) from = options.from;

		if (options.to) to = options.to;

	}



	var options = {duration: duration, from: from, to: to, toggle: doToggle};

	var slide = new Spry.Effect.Slide(element, options);

	this.addParallelEffect(slide);



	var options = {duration: duration, from: from, to: to, toggle: doToggle};

	var fade = new Spry.Effect.Fade(element, options);

	this.addParallelEffect(fade);

};



Spry.Effect.FadeSlide.prototype = new Spry.Effect.Cluster();

Spry.Effect.FadeSlide.prototype.constructor = Spry.Effect.FadeSlide;



///////////////////////////////////////////////////////////////

//

// Generic Observer

//

// 		The observer will save the initial element state, 

// 		restore the effect and the element to their original 

// 		states when the effect finished or canceled.

//

///////////////////////////////////////////////////////////////



var Observer = {};



/*

 * 	Observer.onPreEffect(obj)

 * 		Before running an effect forward the initial CSS values are saved.

 *    We will use later these when the animation will finish or is canceled 

 * 		to restore the animated element to be ready for the next effect.

 *    This function is automatically called by the effect.

 *  Parameters:

 * 		obj - the running effect that calls this function

 */

Observer.onPreEffect = function(obj){

	if (obj.direction && obj.direction == Spry.forwards){

		saveElement(obj.element);

		if (obj.name == 'Slide' || obj.name == 'FadeSlide'){

			saveElement(document.getElementById('content_box'));

		}

	}

};



/*

 * 	Observer.onCancel(obj)

 * 		When an effect is canceled this function will restore the element CSS.

 * 		Also we toggle the effect so the next time will run to go forward again.

 *    This function is automatically called by the effect.

 *  Parameters:

 * 		obj - the running effect that calls this function

 */

Observer.onCancel = function(obj){

	if (obj.direction == Spry.forwards){

		obj.doToggle();

	}

	

	restoreElement(obj.element);



	if (obj.name == 'Slide' || obj.name == 'FadeSlide'){

		var el = document.getElementById('content_box')

		restoreElement(el);

	}

};



/*

 * 	Observer.onPostEffect(obj)

 * 		When a forward effect finish the effect is restarted to toggle the effect. 

 * 		We will use a small timeout to make sure the effect properly finish the 

 * 		animation in forward direction.

 * 		After the second run will restore the element CSS

 *    This function is automatically called by the effect.

 *  Parameters:

 * 		obj - the running effect that calls this function

 */

Observer.onPostEffect = function(obj){

	if (obj.direction == Spry.forwards)

		setTimeout(function(){obj.start()}, 150);

	else

		restoreElement(obj.element);

};



/////////////////////////////////////////////////

//

// Utilities functions

//

/////////////////////////////////////////////////



/* 

 * ExampleHelpText

 * 		change the content text of the text_pane div with the new one received

 * Parameters:

 * 		helpText - the new text to be displayed into the text_pane element

 * 

 */

function ExampleHelpText(helpText)

{

	document.getElementById("text_pane").innerHTML='<p>'+helpText+'</p>';

};



/* 

 * ReloadDocument()

 * 		reload the current page from the server

 * 

 */

function ReloadDocument()

{

	window.location.reload(true);

};



/* 

 * saveElement(el)

 * 		Save into the global array of 'initialElements' some CSS properties 

 * 		of the given element that where altered by the animation running.

 * Parameters:

 *		el - the DOM element for which to save the CSS properties

 */

var saveElement = function(el){

	if (!initialElements[el.id])

	{

		initialElements[el.id] = {};

		for (var i = 0; i < saveStyle.length; i++)

		{

			initialElements[el.id][saveStyle[i]] = Spry.Effect.getStyleProp(el, saveStyle[i]);

		}

	}

};



/* 

 * restoreElement(el)

 * 		Restore from the global array 'initialElements' some CSS properties 

 * 		of the given element to prepare it for the next effect to run.

 * Parameters:

 *		el - the DOM element for which to restore the CSS properties

 */

var restoreElement = function(el){

	for (var i = 0; i < saveStyle.length; i++)

		el.style[saveStyle[i]] = initialElements[el.id][saveStyle[i]];

};



/*

 * runEffect()

 *    This is the dispatcher that will instantiate, if not already done, 

 * 		the given 'effect' with a list of 'options' to run on a given target 'element'.

 *

 *  	The observer defined above will also be attached to the effect to 

 * 		initially save the unaltered 'element' properties, automatically restart 

 *    the animation in backward direction and restore the saved properties at the end.

 *

 * 		The 'effect' is than started and the text from the text_pane is changed

 * 		with the 'helpText'

 *

 * 		The "new Spry.Effect[effect]" is a generic way of initializing a given 'effect'.

 * 		The Spry samples are describing for each effect what is the specific code

 * 		to be included in page and the complete list of supported options. An online version

 * 		of the Spry Effects samples could be accessed here:

 *

 *    http://labs.adobe.com/technologies/spry/samples/#effects

 *

 * 		The function will return false to prevent the href of <a> tag to be followed by the browser.

 *

 * Parameters:

 * 		effect - the name of the effect to run

 * 		element - the element id from page to run this effect on

 * 		options - the options necessary for the effect to run

 * 		helptext - the new status page to be displayed

 */

var runEffect = function(effect, element, options, helptext){

	if (prevEffect && effects[prevEffect].isRunning){

		effects[prevEffect].cancel();

		setTimeout(function(){runEffect(effect, element, options, helptext)}, 150);

		return false;

	}



	if (!effects[effect]){

		effects[effect] = new Spry.Effect[effect](element, options);

		if (effect != 'Highlight' && effect != 'Shake' && effect != 'Pulsate')

			effects[effect].addObserver(Observer);

	}



	effects[effect].start();



	if (helptext)

		ExampleHelpText(helptext);



	prevEffect = effect;

	return false;

};

