slideshow met div's dmv scriptaculous

Update: I've recently written a JQuery version of this slideshow. It operates in roughly the same way and is a lot simpler. You can find it on github.

Geïnspireerd door een post bij code snippets heb ik met een kopje koffie zitten klungelen met javascript. Ik wilde graag een OOP versie en daarmee dus de mogelijkheid om meerdere slideshows gemakkelijk op een pagina te kunnen plaatsen. En, in tegenstelling tot de inspiratie bron wilde ik dat de foto's inelkaar over zouden gaan. Het resultaat:

Maar hoe werkt het?

Net als de post van Peter is mijn code afhankelijk van prototype.js en effect.js van script.aculo.us. In plaats van Element.Fade en Element.Appear af te wisselen heb ik alle afbeeldingen opgestapeld (dmv z-index), laat ik de bovenste verdwijnen (met Element.Fade) en stop ik afbeeldingen die verdwenen zijn onder op.

De HTML is simpel, een div met wat "slide" div's erin:

<div id="slideshow">
  <div class="slide">
    <img src="kokmeeuwen.jpg"/>
  </div>
  <div class="slide">
    <img src="binti.jpg"/>
  </div>
  <div class="slide">
    <img src="stoptrein.jpg"/>
  </div>
</div>

Met CSS worden de "slides" overelkaar heen geplaatst:

#slideshow {
  position: relative;
  width: 240px;
  height: 180px;
}
#slideshow div {
  position: absolute;
  top: 0;
  left: 0;
}

Door middel van JavaScript krijgen de "slides" allemaal een andere z-index:

function Slideshow(slideshow, timeout) {
  this.slides = [];
  var nl = $(slideshow).getElementsByTagName('div');
  for (var i = 0; i < nl.length; i++) {
    if (Element.hasClassName(nl[i], 'slide')) {
      this.slides.push(nl[i]);
    }
  }
  for (var i = 0; i < this.slides.length; i++) {
    this.slides[i].style.zIndex = this.slides.length - i;
  }

Dan wordt de next functie getimed:

  this.timeout = timeout;
  this.current = 0;

  Element.show(slideshow);
  setTimeout((function(){this.next();}).bind(this), this.timeout + 850);
}

Deze next functie schuift alle de z-index door:

Slideshow.prototype = {
  next: function() {
    for (var i = 0; i < this.slides.length; i++) {
      var slide = this.slides[(this.current + i) % this.slides.length];
      slide.style.zIndex = this.slides.length - i;
    }

Laat dan de bovenste afbeelding zachtjes verdwijnen:

Effect.Fade(this.slides[this.current], {

Gooit hem daarna onderop:

  afterFinish: function(effect) {
    effect.element.style.zIndex = 0;
    Element.show(effect.element);
    Element.setOpacity(effect.element, 1);
  }
});

En zorgt dat de volgde "slide" getimed staan:

    this.current = (this.current + 1) % this.slides.length;
    setTimeout((function(){this.next();}).bind(this), this.timeout + 850);
  }
}

En zo wordt nu een dia-presentatie geregistreerd:

new Slideshow('slideshow', 3000);

Voor mij werkt dit onder Internet Explorer, Firefox, Safari, Omniweb en Opera (hoewel deze niet fade). Probeer het zelf, download de volgden javascripts en hang ze in een stukkie HTML zoals boven beschreven:

Remco van 't Veer — 2006-01-23 Mon 01:03