3
* Version 4.1 30/03/2007
5
* Copyright (c) 2007 Millstream Web Software http://www.millstream.com.au
7
* Permission is hereby granted, free of charge, to any person
8
* obtaining a copy of this software and associated documentation
9
* files (the "Software"), to deal in the Software without
10
* restriction, including without limitation the rights to use, copy,
11
* modify, merge, publish, distribute, sublicense, and/or sell copies
12
* of the Software, and to permit persons to whom the Software is
13
* furnished to do so, subject to the following conditions:
15
* The above copyright notice and this permission notice shall be
16
* included in all copies or substantial portions of the Software.
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
* This version of Crossfade is modified from the original as available
31
* from Millstream Web Software.
33
* There is an additional "loop" option, defined in Crossfade.defaults
34
* and applied inside Crossfade.prototype.cycle().
36
* There is an additional (optional) "dir" parameter for the Cycle
37
* function of a transition, sent from Crossfade.prototype.cycle() via
38
* me.options.transition.cycle.
40
* Added a new transition option (Crossfade.Transition.Cover), which
41
* slides the previous slide off stage and the new one on stage
42
* horizontally. By using absolute positions, it makes some dangerous
43
* assumptions about the layout of the page. However, it should be
44
* adaptable to other needs.
49
var Crossfade = Class.create();
51
Crossfade.prototype = {
53
initialize : function(elm, options) {
54
var me = this, next, prev;
56
var n, elements = this.elm.getElementsByClassName("load");
58
for (n=0; n!=elements.length; ++n) {
59
this.filenames.push(elements[n].href);
62
this.prevSlide = null;
64
for(t in Crossfade.Transition) {
65
var trans = Crossfade.Transition[t];
66
if(trans.className && this.elm.hasClassName(trans.className)) {
67
t_opt = {transition:trans};
71
this.options = Object.extend(Object.clone(Crossfade.defaults),Object.extend(options || {},t_opt));
72
this.options.interval = Math.max(2,this.options.interval);
73
this.elm.makePositioned();
74
this.slides = this.elm.immediateDescendants();
75
if(this.options.random || this.elm.hasClassName(this.options.randomClassName)){
76
this.slides.sort(function(a,b){
81
next = $(this.elm.id + '-next');
82
prev = $(this.elm.id + '-previous');
83
if(next) { Event.observe(next, 'click', this.next.bind(this)); }
84
if(prev) { Event.observe(prev, 'click', this.previous.bind(this)); }
87
this.loadSlide(this.slides[0],function() {
88
me.options.transition.prepare(me);
90
this.loadSlide(this.slides[1]);
92
if(this.options.autoStart) { setTimeout(this.start.bind(this),this.rndm((this.options.interval-1)*1000,(this.options.interval+1)*1000)); }
97
return this.timer = new PeriodicalExecuter(this.cycle.bind(this), this.options.interval);
100
this.options.transition.cancel(this);
104
this.options.transition.cancel(this);
107
previous : function() {
108
this.options.transition.cancel(this);
111
cycle : function(dir) {
112
if(!this.ready) { return; }
114
dir = (dir === -1) ? dir : 1;
115
var me = this, prevSlide, nextSlide, opt, fade;
116
prevSlide = this.slides[this.counter];
117
this.counter = this.loopCount(this.counter + dir);
118
if(this.counter == 0){
121
document.getElementById("current-slide").value = this.filenames[this.counter];
122
nextSlide = this.slides[this.counter];
123
if(this.options.loop == false && this.counter >= this.slides.length-1) {
126
this.loadSlide(nextSlide, me.options.transition.cycle(prevSlide, nextSlide, me, dir));
128
this.loadSlide(this.slides[this.loopCount(this.counter+1)]);
131
loadSlide : function(slide, onload){
132
var loaders = [], me = this, img, pnode, onloadFunction;
133
onload = typeof onload === 'function' ? onload : function(){};
134
onloadFunction = function() {
139
loaders = Selector.findChildElements(slide,[this.options.imageLoadSelector]);
140
if(loaders.length && loaders[0].href !== ''){
141
img = document.createElement('img');
142
img.className = 'loadimage';
143
img.onload = onloadFunction;
144
img.src = loaders[0].href;
145
loaders[0].parentNode.replaceChild(img,loaders[0]);
148
loaders = Selector.findChildElements(slide, [this.options.ajaxLoadSelector]);
149
if(loaders.length && loaders[0].href !== ''){
150
new Ajax.Updater(slide, loaders[0].href, {method:'get',onComplete:onloadFunction});
156
loopCount : function(c){
157
if(c >= this.slides.length){
160
c = this.slides.length - 1
164
rndm : function(min, max){
165
return Math.floor(Math.random() * (max - min + 1) + min);
167
timer : null,effect : null,ready : false
169
Crossfade.Transition = {};
170
Crossfade.Transition.Switch = {
171
className : 'transition-switch',
172
cycle : function(prev, next, show) {
173
show.slides.without(next).each(function(s){
178
cancel : function(show){},
179
prepare : function(show){
180
show.slides.each(function(s,i){
181
$(s).setStyle({display:(i === 0 ? 'block' : 'none')});
185
Crossfade.Transition.Crossfade = {
186
className : 'transition-crossfade',
187
cycle : function(prev, next, show) {
188
var opt = show.options;
189
show.effect = new Effect.Parallel([new Effect.Fade(prev ,{sync:true}),
190
new Effect.Appear(next,{sync:true})],
191
{duration: opt.duration, queue : 'Crossfade', afterFinish:function(){
192
show.slides.without(next).each(function(s){
193
$(s).setStyle({opacity:0,display:'none'});
198
cancel : function(show){
199
if(show.effect) { show.effect.cancel(); }
201
prepare : function(show){
202
show.slides.each(function(s,i){
203
$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible',display:(i === 0 ? 'block' : 'none')});
207
Crossfade.Transition.FadeOutFadeIn = {
208
className : 'transition-fadeoutfadein',
209
cycle : function(prev, next, show) {
210
var opt = show.options;
211
show.effect = new Effect.Fade(prev ,{
212
duration: opt.duration/2,
213
afterFinish: function(){
214
show.effect = new Effect.Appear(next,{duration: opt.duration/2});
215
show.slides.without(next).each(function(s){
216
$(s).setStyle({opacity:0});
221
cancel : function(show){
222
if(show.effect) { show.effect.cancel(); }
224
prepare : function(show){
225
show.slides.each(function(s,i){
226
$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible',display:(i === 0 ? 'block' : 'none')});
231
Crossfade.Transition.Cover = {
232
className : 'transition-cover',
233
cycle : function(prev, next, show, dir) {
234
var opt = show.options;
236
var next_x = '700px';
239
/* set up slides for flipping backwards */
240
next_x = prev.getWidth() + 'px';
242
/* set up slides for flipping forwards */
243
next_x = -prev.getWidth() + 'px';
245
next.setStyle({left:next_x});
247
prev_new_x = dir * -prev.getWidth();
250
show.effect = new Effect.Parallel([
251
new Effect.Move(prev, {x:prev_new_x, y:0, mode:'absolute', sync:true}),
252
new Effect.Appear(next, {sync:true}),
253
new Effect.Move(next, {x:next_new_x, y:0, mode:'absolute', sync:true})],
254
{ duration: opt.duration,
256
afterFinish:function(){
257
show.slides.without(next).each(function(s){
258
$(s).setStyle({opacity:0,display:'none'});
263
cancel : function(show){
264
if(show.effect) { show.effect.cancel(); }
266
prepare : function(show){
267
show.slides.each(function(s,i){
268
$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible',display:(i === 0 ? 'block' : 'none')});
273
Effect.DoNothing = Class.create();
274
Object.extend(Object.extend(Effect.DoNothing.prototype, Effect.Base.prototype), {
275
initialize: function() {
276
this.start({duration: 0});
278
update: Prototype.emptyFunction
280
Crossfade.Transition.FadeOutResizeFadeIn = {
281
className : 'transition-fadeoutresizefadein',
282
cycle : function(prev, next, show) {
283
var opt = show.options;
284
show.effect = new Effect.Fade(prev ,{
285
duration: (opt.duration-1)/2,
286
afterFinish: function(){
287
show.slides.without(next).each(function(s){
288
$(s).setStyle({opacity:0});
290
var slideDims = [next.getWidth(),next.getHeight()];
291
var loadimg = Selector.findChildElements(next,['img.loadimage']);
292
if(loadimg.length && loadimg[0].offsetWidth && loadimg[0].offsetHeight){
293
slideDims[0] += slideDims[0] < loadimg[0].offsetWidth ? loadimg[0].offsetWidth : 0;
294
slideDims[1] += slideDims[1] < loadimg[0].offsetHeight ? loadimg[0].offsetHeight : 0;
296
var showDims = [show.elm.getWidth(),show.elm.getHeight()];
297
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];
298
show.effect = new Effect.Parallel([
299
(scale[0] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[0],{sync:true,scaleY:false,scaleContent:false})),
300
(scale[1] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[1],{sync:true,scaleX:false,scaleContent:false}))
304
queue : 'FadeOutResizeFadeIn',
305
afterFinish: function(){
306
show.effect = new Effect.Appear(next,{duration: (opt.duration-1)/2});
313
cancel : function(show){
314
if(show.effect) { show.effect.cancel(); }
316
prepare : function(show){
317
var slideDims = [$(show.slides[0]).getWidth(),$(show.slides[0]).getHeight()];
318
show.elm.setStyle({width:slideDims[0]+'px', height:slideDims[1]+'px'});
319
show.slides.each(function(s,i){
320
$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible',display:(i === 0 ? 'block' : 'none')});
324
Crossfade.defaults = {
329
randomClassName : 'random',
330
selectors : ['.crossfade'],
331
imageLoadSelector : 'a.loadimage',
332
ajaxLoadSelector : 'a.load',
335
transition : Crossfade.Transition.Crossfade
337
Crossfade.setup = function(options) {
338
Object.extend(Crossfade.defaults,options);
340
Crossfade.load = function() {
341
if(Crossfade.defaults.autoLoad) {
342
Crossfade.defaults.selectors.each(function(s){
343
$$(s).each(function(c){
344
return new Crossfade(c);
350
if(window.FastInit) {
351
FastInit.addOnLoad(Crossfade.load);
353
Event.observe(window, 'load', Crossfade.load);