/*

* Crossfade

* Version 4.1 30/03/2007

* 

* Copyright (c) 2007 Millstream Web Software http://www.millstream.com.au

* 

* Permission is hereby granted, free of charge, to any person

* obtaining a copy of this software and associated documentation

* files (the "Software"), to deal in the Software without

* restriction, including without limitation the rights to use, copy,

* modify, merge, publish, distribute, sublicense, and/or sell copies

* of the Software, and to permit persons to whom the Software is

* furnished to do so, subject to the following conditions:

* 

* The above copyright notice and this permission notice shall be

* included in all copies or substantial portions of the Software.

* 

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS

* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN

* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN

* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

* SOFTWARE.

* * 

*/



var Crossfade = Class.create();



Crossfade.prototype = {

	loaded : false,

	initialize : function(elm, options) {

		var me = this, next, prev;

		this.elm = $(elm);

		this.counter = 0;

		this.prevSlide = null;

		var t_opt = {};

		for(t in Crossfade.Transition) {

			var trans = Crossfade.Transition[t];

			if(trans.className && this.elm.hasClassName(trans.className)) {

				t_opt = {transition:trans};

				break;

			}

		}

		this.options = Object.extend(Object.clone(Crossfade.defaults),Object.extend(options || {},t_opt));

		this.options.interval = Math.max(2,this.options.interval);

		this.elm.makePositioned();

		this.slides = this.elm.immediateDescendants();

		if(this.options.random || this.elm.hasClassName(this.options.randomClassName)){

			this.slides.sort(function(a,b){

				return me.rndm(-1,1);

			});

		}

		if(this.elm.id) {

			next = $(this.elm.id + '-next');

			prev = $(this.elm.id + '-previous');

			if(next) { Event.observe(next, 'click', this.next.bind(this)); }

			if(prev) { Event.observe(prev, 'click', this.previous.bind(this)); }

		}

		

		this.loadSlide(this.slides[0],function() {

			me.options.transition.prepare(me);

		});

		this.loadSlide(this.slides[1]);

		

		if(this.options.autoStart) { setTimeout(this.start.bind(this),this.rndm((this.options.interval-1)*1000,(this.options.interval+1)*1000)); }

	},

	start : function() {

		this.ready = true;

		this.cycle()

		return this.timer = new PeriodicalExecuter(this.cycle.bind(this), this.options.interval); 

	},

	stop : function() {

		this.options.transition.cancel(this);

		this.timer.stop(); 

	},

	next : function(){

		this.options.transition.cancel(this);

		this.cycle();

	},

	previous : function() {

		this.options.transition.cancel(this);

		this.cycle(-1);

	},

	cycle : function(dir) {

		if(!this.ready) { return; }

		this.ready = false;

		dir = (dir === -1) ? dir : 1;

		var me = this, prevSlide, nextSlide, opt, fade;

		prevSlide = this.slides[this.counter];

		this.counter = this.loopCount(this.counter + dir);

		if(this.counter == 0){

			this.loaded = true;

		}

		nextSlide = this.slides[this.counter];

		this.loadSlide(nextSlide, me.options.transition.cycle(prevSlide, nextSlide, me));

		if(!this.loaded) {

			this.loadSlide(this.slides[this.loopCount(this.counter+1)]);

		}

	},

	loadSlide : function(slide, onload){

		var loaders = [], me = this, img, pnode, onloadFunction;

		onload = typeof onload === 'function' ? onload : function(){};

		onloadFunction = function() {

				onload();

				me.ready = true;

			};

		slide = $(slide);

		loaders = Selector.findChildElements(slide,[this.options.imageLoadSelector]);

		if(loaders.length && loaders[0].href !== ''){

			img = document.createElement('img');

			img.className = 'loadimage';

			img.onload = onloadFunction;

			img.src = loaders[0].href;

			loaders[0].parentNode.replaceChild(img,loaders[0]);

		} else {

			loaders = [];

			loaders = Selector.findChildElements(slide, [this.options.ajaxLoadSelector]);

			if(loaders.length && loaders[0].href !== ''){

				new Ajax.Updater(slide, loaders[0].href, {method:'get',onComplete:onloadFunction});

			} else {

				onloadFunction();

			}

		}

	},

	loopCount : function(c){

		if(c >= this.slides.length){

			c = 0;

		} else if (c < 0) {

			c = this.slides.length - 1

		}

		return c;

	},

	rndm : function(min, max){

		return Math.floor(Math.random() * (max - min + 1) + min);

	},

	timer : null,effect : null,ready : false

};

Crossfade.Transition = {};

Crossfade.Transition.Switch = {

	className : 'transition-switch',

	cycle : function(prev, next, show) {

		show.slides.without(next).each(function(s){

			$(s).hide();

		})

		$(next).show();

	},

	cancel : function(show){},

	prepare : function(show){

		show.slides.each(function(s,i){

			$(s).setStyle({display:(i === 0 ? 'block' : 'none')});

		});	

	}

};

Crossfade.Transition.Crossfade = {

	className : 'transition-crossfade',

	cycle : function(prev, next, show) {

		var opt = show.options;

		show.effect = new Effect.Parallel([new Effect.Fade(prev ,{sync:true}),

			new Effect.Appear(next,{sync:true})],

			{duration: opt.duration, queue : 'Crossfade', afterFinish:function(){

				show.slides.without(next).each(function(s){

					$(s).setStyle({opacity:0});

				})

			}}

		);

	},

	cancel : function(show){

		if(show.effect) { show.effect.cancel(); }

	},

	prepare : function(show){

		show.slides.each(function(s,i){

			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});

		});	

	}

};

Crossfade.Transition.FadeOutFadeIn = {

	className : 'transition-fadeoutfadein',

	cycle : function(prev, next, show) {

		var opt = show.options;

		show.effect = new Effect.Fade(prev ,{

			duration: opt.duration/2,

			afterFinish: function(){

				show.effect = new Effect.Appear(next,{duration: opt.duration/2});

				show.slides.without(next).each(function(s){

					$(s).setStyle({opacity:0});

				})

			}

		});

	},

	cancel : function(show){

		if(show.effect) { show.effect.cancel(); }

	},

	prepare : function(show){

		show.slides.each(function(s,i){

			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});

		});	

	}

};



Effect.DoNothing = Class.create();

Object.extend(Object.extend(Effect.DoNothing.prototype, Effect.Base.prototype), {

	initialize: function() {

		this.start({duration: 0});

	},

	update: Prototype.emptyFunction

});

Crossfade.Transition.FadeOutResizeFadeIn = {

	className : 'transition-fadeoutresizefadein',

	cycle : function(prev, next, show) {

		var opt = show.options;

		show.effect = new Effect.Fade(prev ,{

			duration: (opt.duration-1)/2,

			afterFinish: function(){

				show.slides.without(next).each(function(s){

					$(s).setStyle({opacity:0});

				})

				var slideDims = [next.getWidth(),next.getHeight()];

				var loadimg = Selector.findChildElements(next,['img.loadimage']);

				if(loadimg.length && loadimg[0].offsetWidth && loadimg[0].offsetHeight){

					slideDims[0] += slideDims[0] < loadimg[0].offsetWidth ? loadimg[0].offsetWidth : 0;

					slideDims[1] += slideDims[1] < loadimg[0].offsetHeight ? loadimg[0].offsetHeight : 0;

				}

				var showDims = [show.elm.getWidth(),show.elm.getHeight()];

				var scale = [(showDims[0] > 0 && slideDims[0] > 0 ? slideDims[0]/showDims[0] : 1)*100,(showDims[1] > 0 && slideDims[1] > 0 ? slideDims[1]/showDims[1] : 1)*100];

				show.effect = new Effect.Parallel([

						(scale[0] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[0],{sync:true,scaleY:false,scaleContent:false})),

						(scale[1] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[1],{sync:true,scaleX:false,scaleContent:false}))

					],

					{

						duration: 1,

						queue : 'FadeOutResizeFadeIn',

						afterFinish: function(){

							show.effect = new Effect.Appear(next,{duration: (opt.duration-1)/2});

						}

					}

				);

			}

		});

	},

	cancel : function(show){

		if(show.effect) { show.effect.cancel(); }

	},

	prepare : function(show){

		var slideDims = [$(show.slides[0]).getWidth(),$(show.slides[0]).getHeight()];

		show.elm.setStyle({width:slideDims[0]+'px', height:slideDims[1]+'px'});

		show.slides.each(function(s,i){

			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});

		});	

	}

};

Crossfade.defaults = {

	autoLoad : true,

	autoStart : true,

	random : false,

	randomClassName : 'random',

	selectors : ['.crossfade'],

	imageLoadSelector : 'a.loadimage',

	ajaxLoadSelector : 'a.load',

	interval : 5,

	duration : 2,

	transition : Crossfade.Transition.Crossfade

};

Crossfade.setup = function(options) {

	Object.extend(Crossfade.defaults,options);

};

Crossfade.load = function() {

	if(Crossfade.defaults.autoLoad) {

		Crossfade.defaults.selectors.each(function(s){

			$$(s).each(function(c){

				return new Crossfade(c);

			});

		});

	}

};



if(window.FastInit) {

	FastInit.addOnLoad(Crossfade.load);

} else {

	Event.observe(window, 'load', Crossfade.load);

}


