/*
        Usage:
        <img src="Bild0.jpg" onload="slideShow (['Bild0.jpg', 'Bild1.jpg', 'Bild2.jpg'], 3000, 1500, 1)" />
*/
        function slideShow (
          image,
          fileNames,
          slideDuration,
          transDuration,
          counter,
          transitionStep,
          onStartNextImage,
          onEndNextImage
        ) {

          /* debugging */
          var startTime = new Date ();
          function debug (s, i) {
            return false;
            var now = new Date ();
            var diff = Math.round ((now.getTime () - startTime.getTime ())) / 1000;

//            window.status = diff + ': ' + s;
            if (i)
              document.getElementById ('debug').innerHTML += diff + ': ' + s + '<br />';
          }

          /* dont call again */
          image.onload = '';

          /* we need more than 1 image to slide */
          if (fileNames.length < 2) {
            return true;
          }

          debug ('slideshow  ' + fileNames);
          
          /* save parameters */
          slideDuration       = typeof slideDuration      == 'undefined' ? 3000  : slideDuration;
          transDuration       = typeof transDuration      == 'undefined' ? 1000  : transDuration;
          counter             = typeof counter            == 'undefined' ?    0  : counter;

          transitionStep      = typeof transitionStep     == 'undefined' ? false : transitionStep;
          onStartNextImage    = typeof onStartNextImage   != 'function'  ? function () {} : onStartNextImage;
          onEndNextImage      = typeof onEndNextImage     != 'function'  ? function () {} : onEndNextImage;

          /* inits */
          var preloadedImages  = new Array ();
          var framesPerSec     = 30;
          var frameDuration    = Math.round (1000 / framesPerSec);
          var totalFrames      = Math.round (transDuration / frameDuration);
          var loops            = 0;
          var frameCounter     = 0;
          var frameInterval    = false;
          var count            = fileNames.length;
          var next             = (counter + 1) % count;
          var transitionStart  = 0;
          
          /* bring function to local scope */
//          alert (onStartNextImage);
//          alert ('var onStartNextImage = ' + ('' + onStartNextImage).replace (/function \w+\s*\(\)/, 'function ()'));
          eval ('var onStartNextImage = ' + ('' + onStartNextImage).replace (/function \w+\s*\(\)/, 'function ()'));
          


          /* preload image */
          var preload = function (src, i) {
            if (typeof preloadedImages [i] != 'undefined' && preloadedImages [i].isLoaded) {
              return true;
            }
            debug ('preload  ' + i + ': ' + src);
//            var i = preloadedImages.length;
            preloadedImages [i] = new Image ();
            preloadedImages [i].isLoaded = false;
            preloadedImages [i].onload = function () {
              debug ('preloaded ' + i + ': ' + src);
              this.isLoaded = true;
              this.onload = '';
            }
            preloadedImages [i].src = src;
          }
          
          /* preload next image */
//          preload (fileNames [counter], counter);
          preload (fileNames [next], next);
          
          /* delay next image */
          window.setTimeout (
            function () {
              nextImage ();
            },
            slideDuration - transDuration
          );
//          debug ('first delay next image ' + (slideDuration - transDuration));

          /* next image */
          var nextImage = function () {

            debug ('next image ' + counter);
            /* delay until next image is loaded */
            if (!preloadedImages [next].isLoaded) {
              window.setTimeout (
                function () {
                  nextImage ()
                },
                transDuration
              );
              debug ('wait for image loading ' + counter + ': ' + fileNames [next]);
              return true;
            }

            /* show old image in parent nodes background */
            debug ('set bg image ' + counter + ': ' + fileNames [counter]);
            image.parentNode.style.backgroundImage = 'url(' + fileNames [counter] + ')';
            debug ('set fg opacity ' + next + ': ' + fileNames [next]);
            setOpacity (0.0);
            debug ('set fg image ' + next + ': ' + fileNames [next]);
            image.src = fileNames [next];

            /* next image loaded - start fade */
            counter = next;
            next    = (counter + 1) % count;

            debug ('start transition ' + counter + ': ' + fileNames [counter]);
            frameCounter = 0;
            transitionStart = new Date ().getTime ();
            onStartNextImage ();
            transition ();
          }
          
          /* fade transition */
          var fadeTransition = function (f) {
            setOpacity (1 * f);
          }
          var moveTransition = function (f) {
            if (f == 0) {
              image.style.position  = 'absolute';
              image.style.top       = 0;
              setOpacity (1.0);
            }
            var fd =
              f < 0.5 ?
                1 - Math.pow (f, 5) / 0.0625
              :
                Math.pow (1 - f, 5) / 0.0625;
            image.style.left  = (image.width * fd) + 'px';
            image.parentNode.style.backgroundPosition = (image.width * fd) + 'px 0';
          }

          var elasticEaseInOut = function (c,a,p){
          	if (!p) p = c * (.25 * 1.5);
          	if (!a || a < Math.abs(c)) {
          		a = c;
          		var s = p / 2;
          	} else {
          		var s = p / (2 * Math.PI) * Math.asin (c / a);
          	}

          	return function(t) {
          		if (t == 0) return 0;
          		if ((t /= c/2) == 2) return c;
          		if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t-=1)) * Math.sin( (t * c - s) * (2 * Math.PI) / p));
          		return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * c - s) * (2 * Math.PI) / p ) * .5 + c ;
          	};
          }

          var myfun = elasticEaseInOut (1);
          var elasticTransition = function (f) {
            fd = 1 - myfun (f);
//            window.status = fd;
            image.style.left  = (image.width * (fd)) + 'px';
            if (f == 0) {
              image.style.position  = 'absolute';
              image.style.top       = 0;
              setOpacity (1.0);
            }
            image.parentNode.style.backgroundPosition = (image.width * (1 - fd)) + 'px 0';
            debug (fd);
          }

          if (!transitionStep) {
//            transitionStep = moveTransition;
            transitionStep = fadeTransition;
//            transitionStep = elasticTransition;
          }

          var transition = function () {
            /* calculate time difference */
            var timeDiff = (new Date ().getTime () - transitionStart);

            /* do a frame step */
            var f = Math.min (1, timeDiff / transDuration);
            transitionStep (f);

            /* next frame */
            frameCounter++;
            if (f < 1) {
              window.setTimeout (
                function () {
                  transition ();
                },
                Math.min (frameDuration, transDuration - timeDiff)
              );
              return;
            }

            /* clear interval */
            debug ('stop transition ' + counter + ': ' + fileNames [counter]);

            /* end of transition - call user function */
            onEndNextImage ();
            
            /* user supplied function at end of transition */
            if (typeof onEndTransition == 'function') {
              onEndTransition ();
            }

            /* preload next image */
            preload (fileNames [next], next);

            /* finished - delay next image */
            window.setTimeout (
              function () {
                nextImage ();
              },
              slideDuration - transDuration
            );
//            debug ('delay image ' + (slideDuration - transDuration));
          }

          /* set opacity fo browsers */
          var setOpacity = function (value) {
//            debug (obj.src + ' opacity ' + value);
            var obj = image;
            obj.style.opacity       = value;
            obj.style.MozOpacity    = value;
            obj.style.KhtmlOpacity  = value;
            if (document.all) {
              obj.style.filter        = 'alpha(opacity=' + Math.round (value*100) + ')';
//            obj.zoom = 1;
            }
          }
        }

