// SpryDOMEffects.js - version 0.6 - Spry Pre-Release 1.7//// Copyright (c) 2007. 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.(function() { // BeginSpryComponent	if (typeof Spry == "undefined" || !Spry.Utils || !Spry.$$){	alert("SpryDOMEffects.js requires SpryDOMUtils.js");	return;}if (!Spry.Effect) Spry.Effect = {};Spry.Effect.Animator = function(opts){	Spry.Effect.Animator.Notifier.call(this);	this.animatorID = Spry.Effect.Animator.nextID++;	this.dropFrames = true;	this.fps = 60; // frames per-second	this.duration = 500; // msecs	this.timer = 0;	this.startTime = 0; // Used only when dropFrames is true.	this.currentFrame = 0;	this.easeFunc = Spry.Effect.Animator.defaultEaseFunc;	this.stopped = false;	Spry.Effect.Animator.copyProps(this, opts);	this.interval = 1000 / this.fps;	this.numFrames = (this.duration / 1000) * this.fps;	if (this.onComplete)	{		var self = this;		this.addObserver({ onAnimationComplete: function(){ self.onComplete(); } });	}};Spry.Effect.Animator.nextID = 1;Spry.Effect.Animator.copyProps = function(dst, src){	if (src)	{		for (prop in src)			dst[prop] = src[prop];	}	return dst;};Spry.Effect.Animator.getElement = function(element){	if (arguments.length > 1)	{		for (var i = 0, elements = [], length = arguments.length; i < length; i++)			elements.push(Spry.Effect.Animator.getElement(arguments[i]));		return elements;	}	if (typeof element == 'string')		element = document.getElementById(element);	return element;};Spry.Effect.Animator.defaultEaseFunc = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };Spry.Effect.Animator.Notifier = function(){	this.observers = [];	this.suppressNotifications = 0;};Spry.Effect.Animator.Notifier.prototype.addObserver = function(observer){	if (!observer)		return;	// Make sure the observer isn't already on the list.	var len = this.observers.length;	for (var i = 0; i < len; i++)	{		if (this.observers[i] == observer)			return;	}	this.observers[len] = observer;};Spry.Effect.Animator.Notifier.prototype.removeObserver = function(observer){	if (!observer)		return;	for (var i = 0; i < this.observers.length; i++)	{		if (this.observers[i] == observer)		{			this.observers.splice(i, 1);			break;		}	}};Spry.Effect.Animator.Notifier.prototype.notifyObservers = function(methodName, data){	if (!methodName)		return;	if (!this.suppressNotifications)	{		var len = this.observers.length;		for (var i = 0; i < len; i++)		{			var obs = this.observers[i];			if (obs)			{				if (typeof obs == "function")					obs(methodName, this, data);				else if (obs[methodName])					obs[methodName](this, data);			}		}	}};Spry.Effect.Animator.Notifier.prototype.enableNotifications = function(){	if (--this.suppressNotifications < 0)	{		this.suppressNotifications = 0;		Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");	}};Spry.Effect.Animator.Notifier.prototype.disableNotifications = function(){	++this.suppressNotifications;};Spry.Effect.Animator.prototype = new Spry.Effect.Animator.Notifier;Spry.Effect.Animator.prototype.constructor = Spry.Effect.Animator;Spry.Effect.Animator.prototype.start = function(){	this.stopped = false;	this.currentFrame = 0;	this.startTime = (new Date()).getTime();	this.notifyObservers("onAnimationStart");	var self = this;	this.timer = setTimeout(function(){ self.onStepAnimation(); }, this.interval);};Spry.Effect.Animator.prototype.stop = function(){	if (this.timer)		clearTimeout(this.timer);	this.timer = 0;	this.stopped = true;	this.notifyObservers("onAnimationStopped");};Spry.Effect.Animator.prototype.onStepAnimation = function(){	var obj = {};	if (this.dropFrames)	{		obj.duration = this.duration;		obj.elapsed = ((new Date).getTime()) - this.startTime;		if (obj.elapsed > obj.duration)			obj.elapsed = obj.duration;	}	else	{		obj.duration = this.numFrames;		obj.elapsed = ++this.currentFrame;	}	obj.easingConst = this.easeFunc(obj.elapsed, 0, 1, obj.duration)	this.notifyObservers("onPreDraw", obj);	this.draw(obj.elapsed, obj.duration, obj.easingConst);	this.notifyObservers("onPostDraw", obj);	if (!this.stopped)	{		if (obj.elapsed < obj.duration)		{			var self = this;			this.timer = setTimeout(function(){ self.onStepAnimation(); }, this.interval);		}		else		{			this.stop();			this.notifyObservers("onAnimationComplete");		}	}};Spry.Effect.Animator.prototype.draw = function(elapsed, duration, easingConst){	// The default draw method does nothing. It is assumed that	// derived classes will provide their own implementation of this	// method.	debug.log("elapsed: " + elapsed + " -- duration: " + duration + " -- easingConst: " + easingConst);};///////////////////////////////////////////////////////////////////////////////Spry.Effect.CSSAnimator = function(elements, styleStr, opts){	this.animationSets = [];	Spry.Effect.Animator.call(this, opts);	this.add(elements, styleStr);};Spry.Effect.CSSAnimator.prototype = new Spry.Effect.Animator();Spry.Effect.CSSAnimator.prototype.constructor = Spry.Effect.CSSAnimator;Spry.Effect.CSSAnimator.prototype.add = function(elements, styleStr){	// The first argument for the CSSAnimator can be	// the id of an element, an element node, or an array of	// elements and/or ids.	elements = Spry.$$(elements);	if (elements.length < 1)		return;	var animSet = { elements: elements, cssProps: []};	this.animationSets.push(animSet);	// Convert the styleStr into an object.	var toObj = Spry.Utils.styleStringToObject(styleStr);	for (var p in toObj)	{		var obj = new Object;		var v = toObj[p];		obj.value = new Number(v.replace(/[^-\d\.]+/g, ""));		obj.units = v.replace(/[-\d+\.]/g, "");		toObj[p] = obj;	}	for (var i = 0; i < elements.length; i++)	{		var obj = animSet.cssProps[i] = new Object;		for (var p in toObj)		{			var pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs[p];			if (!pFuncs)				pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs["default"];			obj[p] = new Object;			obj[p].from = new Number(pFuncs.get(elements[i], p).replace(/[^-\d\.]+/g, ""));			obj[p].to = toObj[p].value;			obj[p].distance = obj[p].to - obj[p].from;			obj[p].units = toObj[p].units;		}	}};Spry.Effect.CSSAnimator.prototype.start = function(){	for (var s = 0; s < this.animationSets.length; s++)	{		var animSet = this.animationSets[s];		var elements = animSet.elements;		var cssProps = animSet.cssProps;		for (var i = 0; i < elements.length; i++)		{			var ele = elements[i];				var eleProps = ele.spryCSSAnimatorProps;			if (!eleProps)				eleProps = ele.spryCSSAnimatorProps = new Object;				var obj = cssProps[i];			for (var p in obj)				eleProps[p] = this.animatorID;		}	}	return Spry.Effect.Animator.prototype.start.call(this);};Spry.Effect.CSSAnimator.prototype.stop = function(){	for (var s = 0; s < this.animationSets.length; s++)	{		var animSet = this.animationSets[s];		var elements = animSet.elements;		var cssProps = animSet.cssProps;		for (var i = 0; i < elements.length; i++)		{			var ele = elements[i];			var obj = cssProps[i];				var eleProps = ele.spryCSSAnimatorProps;			for (var p in obj)			{				if (eleProps[p] == this.animatorID)					delete eleProps[p];			}		}	}	return Spry.Effect.Animator.prototype.stop.call(this);};Spry.Effect.CSSAnimator.prototype.draw = function(elapsed, duration, easingConst){	for (var s = 0; s < this.animationSets.length; s++)	{		var animSet = this.animationSets[s];		var elements = animSet.elements;		var cssProps = animSet.cssProps;		for (var i = 0; i < elements.length; i++)		{			var ele = elements[i];			var eleProps = ele.spryCSSAnimatorProps;			var obj = cssProps[i];			for (var p in obj)			{				if (eleProps[p] == this.animatorID)				{					var pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs[p];					if (!pFuncs)						pFuncs = Spry.Effect.CSSAnimator.stylePropFuncs["default"];						if (elapsed > duration)						pFuncs.set(ele, p, obj[p].to + obj[p].units);					else						pFuncs.set(ele, p, obj[p].from + (obj[p].distance * easingConst) + obj[p].units);				}			}		}	}};Spry.Effect.CSSAnimator.stylePropFuncs = {};Spry.Effect.CSSAnimator.stylePropFuncs["default"] = {	get: function(ele, prop)	{		return ele.style[prop];	},	set: function(ele, prop, val)	{		ele.style[prop] = val;	}};Spry.Effect.CSSAnimator.stylePropFuncs["opacity"] = {	get: function(ele, prop)	{		var val = 1;				if (ele.style.opacity)			val = ele.style.opacity;		else if (ele.style.filter)		{			var strVal = ele.style.filter.replace(/.*alpha\(opacity=(\d+)\).*/, "$1");			if (strVal)				val = parseInt(strVal) / 100;		}		return val + "";	},	set: function(ele, prop, val)	{		ele.style.opacity = "" + val;		ele.style.filter = "alpha(opacity=" + (val * 100) + ")";	}};///////////////////////////////////////////////////////////////////////////////Spry.$$.Results.defaultEaseFunc = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };Spry.$$.Results.animatePropertyTo = function(propName, to, options){	var opts = { interval: 10, duration: 1000, onComplete: null, transition: Spry.$$.Results.defaultEaseFunc };	Spry.Effect.Animator.copyProps(opts, options);	var objs = [];	for (var i = 0; i < this.length; i++)	{		var obj = objs[i] = new Object;		obj.ele = this[i];		obj.from = obj.ele[propName];		obj.distance = to - obj.from;	}	var startTime = (new Date).getTime();	var animateFunc = function()	{		var elapsedTime = ((new Date).getTime()) - startTime;		if (elapsedTime > opts.duration)		{			for (var i = 0; i < objs.length; i++)				objs[i].ele[propName] = to;			if (opts.onComplete)				opts.onComplete();		}		else		{			for (var i = 0; i < objs.length; i++)			{				var obj = objs[i];				obj.ele[propName] = opts.transition(elapsedTime, obj.from, obj.distance, opts.duration);			}			setTimeout(animateFunc, opts.interval);		}	};	setTimeout(animateFunc, opts.interval);	return this;};Spry.$$.Results.animateStyleTo = function(styleStr, options){	var a = new Spry.Effect.CSSAnimator(this, styleStr, options);	a.start();	return this;};})(); // EndSpryComponent
