/* * 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); if(this.timer) 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 : 3, 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); }