/**
 * Slideshow with image preload bar and crossfade.
 * 
 * Developed by Simon Speich for www.lfi.ch
 * copyright (c) 2005, Eidg. Forschungsanstalt WSL, Birmensdorf
 * You can use/alter this freely as long as this entire 
 * copyright notice is included.
 *  
 * v1.2, 02.04.2007 Added callback function. Executed when done preloading all images.
 * Fixed Slide counter and looping.
 * 
 * v1.1, 05.03.2006
 * Added play, stop, pause, next, previous buttons.
 * Code competely rewritten.
 */

// array arrSlides created by php
// var arrSlides = [[file name, file size, image width, image height]]
var d = document;

function ProgressBar() {
	// creates progress bar object
	this.ParEl = null;			// Html Element, only available after document is fully loaded
	this.DivBar = null;			// dito
	this.TotalFileSize = 0;	// total of all file sizes in kb, provided by php
	this.CurImgCount = 0;		// current number of loaded images
	// calculate total file size for progress bar
	for (var i = 0; i < arrSlides.length; i++) {
		this.TotalFileSize += arrSlides[i].FileSize;
	}	
	this.ImgPreloaded = false;
}

ProgressBar.prototype.SetDoneFnc = function(Obj, Fnc, Args) {	
	// callback function to be executed when finished loading
	this.DoneFnc = function() {
		if (!Fnc) { return false; }
		if (!Args) { Fnc.call(Obj); }
		else if (typeof Args == 'object' && Args.constructor == Array) {
			Fnc.apply(Obj, Args);
		}
		else { Fnc.call(Obj, Args); }
	}	
}

ProgressBar.prototype.Create = function(AppendToEl) {
	// draws the preload bar appended to the element provided
	this.ParEl = d.getElementById(AppendToEl);
	this.ParEl.T = window.parseInt(this.ParEl.style.top);
	this.ParEl.L = window.parseInt(this.ParEl.style.left);
	this.ParEl.W = window.parseInt(this.ParEl.style.width);
	this.ParEl.H = window.parseInt(this.ParEl.style.height);
	var El = this.ParEl.appendChild(d.createElement('div'));	// container
	SetupCss(El, 100, 150, 300, 50);	// left, top, width height
	El.setAttribute("id", 'PreloadBarCont');
	El.appendChild(d.createTextNode('lade Bilder'));

	El = d.getElementById('PreloadBarCont').appendChild(d.createElement('div'));
	SetupCss(El, 0, 23, 32, 20);
	El.setAttribute('id', 'DisplPercent');

	this.BarCont = d.getElementById('PreloadBarCont').appendChild(d.createElement('div'));
	SetupCss(this.BarCont, 40, 20, 200, 20)
	this.BarCont.W = 200;
	this.BarCont.style.backgroundColor = 'white';
	this.BarCont.style.border = '1px solid black';
	this.Bar = this.BarCont.appendChild(d.createElement('div'));
	this.Bar.setAttribute("id", 'Bar');
	this.Bar.style.width = '0px';
	this.Bar.W = 0;
	this.BarIncr = this.BarCont.W / this.TotalFileSize;
	this.Bar.style.height = '20px';
	this.Bar.style.backgroundColor = '#FFCC66';

	El = d.getElementById('PreloadBarCont').appendChild(d.createElement('div'));
	SetupCss(El, 250, 23, 80, 20);
	El.appendChild(d.createTextNode(this.TotalFileSize + ' kb'));
}

ProgressBar.prototype.PaintProgress = function(Incr) {
	this.Bar.W += Math.ceil(this.BarIncr * Incr);
	if (this.CurImgCount == arrSlides.length-1) { // last image
		this.Bar.W = this.BarCont.W;
		this.ParEl.removeChild(d.getElementById('PreloadBarCont'));	// remove preload img bar
		if (this.DoneFnc) { this.DoneFnc(); }	// exec callback function
		this.ImgPreloaded = true;
	}
	else { 
		var Num = Math.ceil(this.Bar.W / this.BarCont.W * 100);
		var El = d.getElementById('DisplPercent');
		while (El.firstChild) { El.removeChild(El.firstChild); }; // = El.innerHTML = "";
		El.appendChild(d.createTextNode(Num + '%'));
		d.getElementById('Bar').style.width = this.Bar.W + "px";
	}
	this.CurImgCount++;
}

ProgressBar.prototype.PreloadImages = function(Folder) {
	// preloads the images
	// safari bug
	// .complete image property always returns "undefined" with document.createElement(img'), with new image() (js image object) it works ok
	// onload function on js image object, 'this' refers to the window object instead of the image object
	// if you use onload with document.createElement('img') 'this' work
	// see http://bugzilla.opendarwin.org/show_bug.cgi?id=3869 for more info
	var Bar = this;
	var NumImages = arrSlides.length;
	for (var i = 0; i < NumImages; i++) {
		arrSlides[i].src = Folder + arrSlides[i].Name;
		if (arrSlides[i].complete) {
			// use images from cache
			Bar.PaintProgress(arrSlides[i].FileSize);
		}
		else {
			arrSlides[i].onload = function() { Bar.PaintProgress(this.FileSize); }
		}
	}
}

function SlideShow(AppendToEl, Duration, Fade, Repeat) {
	var Self = this;
	var TimerId = null;
	this.FadeIncr = 4;				// opacity increment
	this.Fade = Fade;					// use fading (true/false)
	this.Duration = Duration;	// time spent between two images
	this.NumImg = arrSlides.length;	// arrSlides is a global variable
	this.CurImgId = 0;				// id of currently displayed image
	this.Repeat = Repeat;			// restart slideshow at beginning if true
	var Paused = false;				// pause slide show if true
	var Counter = 0;
	this.ParEl = d.getElementById(AppendToEl);	// canvas
	this.ParEl.T = window.parseInt(this.ParEl.style.top);
	this.ParEl.L = window.parseInt(this.ParEl.style.left);
	this.ParEl.W = window.parseInt(this.ParEl.style.width);
	this.ParEl.H = window.parseInt(this.ParEl.style.height);
	this.SetDuration(Duration);
	this.Img1 = d.getElementById('ImgAnim1');
	this.Img2 = d.getElementById('ImgAnim2');
	this.Img1.style.zIndex = 11;
	this.Img2.style.zIndex = 10;
	this.SetSlideCounter('0');
	
	// player user interface
	this.ButtPlay = new Object();
	this.ButtPlay.On = false;
	this.ButtPlay.Ref = d.getElementById('ImgPlPlay');
	this.ButtPlay.Img = new Array();
	this.ButtPlay.Img[0] = new Image();
	this.ButtPlay.Img[0].src = "/layout/images/slideshow-player_01.gif";
	this.ButtPlay.Img[1] = new Image();
	this.ButtPlay.Img[1].src = "/layout/images/slideshow-player-over_01.gif";
	this.ButtStop = new Object();
	this.ButtStop.On = true;
	this.ButtStop.Ref = d.getElementById('ImgPlStop');
	this.ButtStop.Img = new Array();
	this.ButtStop.Img[0] = new Image();
	this.ButtStop.Img[0].src = "/layout/images/slideshow-player_03.gif";
	this.ButtStop.Img[1] = new Image();
	this.ButtStop.Img[1].src = "/layout/images/slideshow-player-over_03.gif";
	this.ButtPause = new Object();
	this.ButtPause.On = false;
	this.ButtPause.Ref = d.getElementById('ImgPlPause');
	this.ButtPause.Img = new Array();
	this.ButtPause.Img[0] = new Image();
	this.ButtPause.Img[0].src = "/layout/images/slideshow-player_02.gif";
	this.ButtPause.Img[1] = new Image();
	this.ButtPause.Img[1].src = "/layout/images/slideshow-player-over_02.gif";

	// make play an inner function (closure) to make the setTimout work
	// otherwise 'this' would refer to the window object -> use var Self = this;
	this.Play = function() {
		if (!Paused) {
			if (Counter == 0) { // init play
				this.Img1.src = arrSlides[0].src;
				var Top = this.ParEl.T + this.ParEl.H/2 - arrSlides[this.CurImgId].H/2;
				var Left = this.ParEl.L + this.ParEl.W/2 - arrSlides[this.CurImgId].W/2;
				SetupCss(this.Img1, Left, Top, '', '');
				SetupCss(this.Img2, Left, Top, '', '');
				this.SetSlideCounter(1);
			}
			if (!this.ButtPlay.On) {
				this.ButtPlay.On = true; 
				this.ButtPlay.Ref.src = this.ButtPlay.Img[1].src;
				this.ButtStop.On = false;
				this.ButtStop.Ref.src = this.ButtStop.Img[0].src;
			}
			if (this.Fade) {
				// beginning of crossfade
				if (Counter % this.Duration == 0) {
					// current img
					var Img = d.getElementById('ImgAnim' + (this.CurImgId % 2 + 1));
					SetOpacity(Img, 0);
					arrSlides[this.CurImgId].Opacity = 0;
					// prevous img
					if (this.CurImgId > 0) {
						Img = d.getElementById('ImgAnim' + ((this.CurImgId + 1) % 2 + 1));
						SetOpacity(Img, 100);
						arrSlides[this.CurImgId - 1].Opacity = 100;
					}
				}
				if (Counter % this.Duration < 100/this.FadeIncr) { this.XFade(); }
				// swap image
				else if (Counter % this.Duration == Math.ceil(100/this.FadeIncr)) {
					this.CurImgId++;
					if (this.CurImgId < this.NumImg) { 
						var Img = d.getElementById('ImgAnim' + (this.CurImgId % 2 + 1));
						this.ShowImg(Img);
					}
				}
			}
			// no crossfading
			else if (!this.Fade && Counter % this.Duration == 0) {
				if (this.CurImgId < this.NumImg) {
					arrSlides[this.CurImgId].Opacity = 100;
					SetOpacity(this.Img1, 100);
					this.ShowImg(this.Img1);
					this.SetSlideCounter();
				}
				this.CurImgId++;
			}
	
			if (this.CurImgId == this.NumImg) {
				if (this.Repeat) { this.CurImgId = 0; }	// restart at beginning (repeat)
				else { this.Stop(); return; }
			}
			Counter++;
			if (this.CurImgId < this.NumImg) { this.TimerId = window.setTimeout(function() { Self.Play(); }, 40); }

		}	// end !Paused
	}
	
	this.Pause = function() {
		if (!Paused) {
			// Pause
			window.clearTimeout(this.TimerId);
			this.ButtPause.On = true; 
			this.ButtPause.Ref.src = this.ButtPause.Img[1].src;
			this.ButtPlay.On = false;
			this.ButtPlay.Ref.src = this.ButtPlay.Img[0].src;
	 	}
		else { 
			// resume play
			this.TimerId = window.setTimeout(function() { Self.Play(); }, 1);
			this.ButtPause.On = false; 
			this.ButtPause.Ref.src = this.ButtPause.Img[0].src;
		}
		Paused = Paused ? false : true;
	}
	
	this.Reset = function() {
		window.clearTimeout(this.TimerId);
		this.CurImgId = 0;
		Counter = 0;
		if (this.Fade) {
			SetOpacity(this.Img1, 0);
			SetOpacity(this.Img2, 0);
			for (var i = 0; i < arrSlides.length; i++) {
				arrSlides[i].Opacity = 0;
			}
		}
		this.SetSlideCounter('0');
	}
}

SlideShow.prototype.Start = function() {
	this.Stop();
	this.Play();
}

SlideShow.prototype.Stop = function() {
	this.Reset();
	this.ButtPlay.On = false; 
	this.ButtPlay.Ref.src = this.ButtPlay.Img[0].src;
	this.ButtStop.On = true;
	this.ButtStop.Ref.src = this.ButtStop.Img[1].src;
}

SlideShow.prototype.Next = function(Direction) {
	var Id = this.CurImgId + Direction;		// temp store id before reset
	this.Stop();
	this.CurImgId = Id;
	if (this.CurImgId >= this.NumImg) { this.CurImgId = 0; }
	if (this.CurImgId < 0) { this.CurImgId = this.NumImg-1; }
	SetOpacity(this.Img1, 100);
	this.ShowImg(this.Img1);
	this.SetSlideCounter();
}

SlideShow.prototype.ShowImg = function(Img) {
	// center image in SlideShow container
	var Top = this.ParEl.T + this.ParEl.H/2 - arrSlides[this.CurImgId].H/2;
	var Left = this.ParEl.L + this.ParEl.W/2 - arrSlides[this.CurImgId].W/2;
	SetupCss(Img, Left, Top, '', '');
	Img.src = arrSlides[this.CurImgId].src;	// show image

}

SlideShow.prototype.XFade = function() {
	// fade in current img
	var Img = d.getElementById('ImgAnim' + (this.CurImgId % 2 + 1));
	arrSlides[this.CurImgId].Opacity += this.FadeIncr;
	SetOpacity(Img, arrSlides[this.CurImgId].Opacity);
	this.SetSlideCounter();
	// fade out last img (if any)
	if (this.CurImgId > 0) {
		Img = d.getElementById('ImgAnim' + ((this.CurImgId + 1) % 2 + 1));
		arrSlides[this.CurImgId - 1].Opacity -= this.FadeIncr;
		SetOpacity(Img, arrSlides[this.CurImgId - 1].Opacity);
	}
}

SlideShow.prototype.SetDuration = function(Duration) {
	this.Duration = Duration > 100/this.FadeIncr ? Duration : (100/this.FadeIncr + 1);
}

SlideShow.prototype.SetSlideCounter = function() {
	var Counter = 1;
	if (arguments[0]) { Counter = arguments[0]; }
	else Counter = this.CurImgId + 1;
	while (d.getElementById('DivPlayerCounter').firstChild) {
    d.getElementById('DivPlayerCounter').removeChild(d.getElementById('DivPlayerCounter').firstChild);
	};
	d.getElementById('DivPlayerCounter').appendChild(d.createTextNode(Counter + '/' + this.NumImg));
}

function SetOpacity(Obj, Opacity) {
	Opacity = window.parseInt(Opacity);
	Opacity /= 100;
	Obj.style.opacity = (Opacity == 1) ? 0.9999999 : Opacity;			// css3, moz bug
	Obj.style.filter = 'alpha(Opacity:' + Opacity*100 + ')'; 			// IE win
	Obj.style.KHTMLOpacity = Opacity;															// old Saf, Konqueror
	Obj.style.MozOpacity = (Opacity == 1) ? 0.9999999 : Opacity;	// older Moz, moz bug
}

function SetupCss(El, X, Y, W, H) {
	El.style.position = 'absolute';
	if (/[0-9]/.test(X)) { El.style.left = X + 'px'; }
	if (/[0-9]/.test(Y)) { El.style.top = Y + 'px'; }
	if (/[0-9]/.test(W)) { El.style.width = W + 'px'; }
	if (/[0-9]/.test(H)) { El.style.height = H + 'px'; }
}
