// Slideshow class
// 
// Copyright 2008 René Lønstrup @ RLdesign.dk
// 
// May not be used commercially without permission from the author.
//
// Version: 1.1.0.1
//
//
// CHANGELOG:
//
// 16/12/2008
//     1.1.0.1
//           Fixed a small bug meaning you had to manually set position: relative on the container div
// 15/12/2008
//     1.1.0.0
//           Drastically changed the functionality of the class, making it possible to control it externally
// 14/08/2008
//     1.0.0.0
//           First public release
//

// USAGE:
//
// var oSlideshowVars = new Object();
// oSlideshowVars.ContainerID = "rl_slideshow";
// oSlideshowVars.FadeTime = 2000; // milliseconds
// oSlideshowVars.WaitTime = 10; // seconds
//
// var slideshow = new RLdesign.Web.UI.Slideshow(oSlideshowVars);
// slideshow.Start();


if (!RLdesign) {
	var RLdesign = function() { };
}
if (!RLdesign.Web) {
	RLdesign.Web = function() { };
}
if (!RLdesign.Web.UI) {
	RLdesign.Web.UI = function() { };
}
RLdesign.Web.UI.Slideshow = function(varArray) {
	this._ready = false;
	this.oVars = null;
	this.oElements = null;
	this._currentdisplay = "block";
	this._current = 0;
	this._next = 0;
	this._max = 0;
	this._waittime = 10;
	this._fadetime = 2000;
	this._waittimeout = null;

	this.Init = function(Variables) {
		var oThis = this;

		if (!RLdesign.Utils.IsObject(Variables) && typeof (Variables) != "string") {
			alert("Exiting slideshow - no container ID.");
			return;
		}

		this._current = 0;

		this.oVars = Variables;

		var container = RLdesign.Utils.DefineObject(this.oVars.ContainerID);
		if (container == null) return;
		if (RLdesign.Utils.GetCssValue(container, "position") != "absolute") {
			container.style.position = "relative";
		}
		if (container.childNodes != null && container.childNodes.length != 0) {
			var els = container.childNodes;
			this.oElements = new Array();
			var q = 0;
			var satActive = false;
			for (var i = 0; i < els.length; i++) {
				if (els[i].tagName != null && els[i].tagName.toLowerCase() == "div") {
					this.oElements[q] = els[i];
					this.oElements[q].style.position = "absolute";
					this.oElements[q].style.top = "0px";
					this.oElements[q].style.left = "0px";
					this.oElements[q].style.zIndex = "1";
					this.oElements[q].style.display = "none";
					RLdesign.Utils.SetOpacity(this.oElements[q], 0);
					if (this.oElements[q].className.indexOf("active") > -1) {
						RLdesign.Utils.SetOpacity(this.oElements[q], 100);
						RLdesign.Utils.SetDisplay(this.oElements[q], this._currentdisplay);
						this.oElements[q].style.zIndex = "10";
						satActive = true;
						this._current = q;
					}
					q++;
				}
			}
			if (!satActive) {
				RLdesign.Utils.SetOpacity(this.oElements[0], 100);
				this.oElements[0].style.display = this._currentdisplay;
				this.oElements[0].style.zIndex = "10";
			}
		}
		else if (this.oVars.Elements != null && this.oVars.Elements.length > 0) {
			// fetch images
			this.oElements = this.oVars.Elements;
		}
		else {
			return;
		}


		this._max = this.oElements.length;
		this._waittime = this.oVars.WaitTime;
		this._fadetime = this.oVars.FadeTime;

		if (this._current < this._max - 1) {
			this._next = this._current + 1;
		}
		else {
			this._next = 0;
		}

		//this._initopacity();
		//this._setnext();

		this.Start();
	}


	this.Stop = function() {
		this._ready = false;
		this._stoptimeouts();
	}

	this.Start = function() {
		if (!RLdesign.Utils.IsObject(this.oVars)) {
			alert("Exiting slideshow - no container ID.");
			return;
		}
		else {
			this._ready = true;
		}

		//		for (var i = 0; i < this._max; i++) {
		//			if (this.oElements[i])
		//				this.oElements[i].style.display = "none";
		//		}
		//		this.oElements[this._current].style.display = this._currentdisplay;

		this._wait();
	}



	this._wait = function() {
		var oThis = this;
		if (!oThis._ready) return;
		oThis._waittimeout = window.setTimeout(function() { oThis._nextimage(oThis); }, oThis._waittime * 1000);
	}


	this._nextimage = function(oThis) {
		if (!oThis._ready) return;
		RLdesign.Utils.SetOpacity(oThis.oElements[oThis._next], 100);
		RLdesign.Utils.SetDisplay(oThis.oElements[oThis._next], oThis._currentdisplay);
		//RLdesign.Web.UI.Fader.Fade(oThis.oElements[oThis._next], 100, oThis._fadetime, 20, oThis._currentdisplay, null);
		RLdesign.Web.UI.Fader.Fade(oThis.oElements[oThis._current], 0, oThis._fadetime, 20, "none", function() { oThis._setnext(oThis); });

	}

	// moves the cursor to the next image
	this._setnext = function(oThis) {
		if (!oThis) oThis = this;
		if (!oThis._ready) return;

		oThis.oElements[oThis._current].style.zIndex = 1;
		oThis.oElements[oThis._next].style.zIndex = 10;

		oThis._current = oThis._next;
		if (oThis._next < oThis._max - 1) {
			oThis._next++;
		}
		else {
			oThis._next = 0;
		}

		for (var i = 0; i < oThis._max; i++) {
			if (oThis.oElements[i])
				oThis.oElements[i].style.display = "none";
		}
		RLdesign.Utils.SetDisplay(oThis.oElements[oThis._current], oThis._currentdisplay);

		oThis._wait();
	}

	this._stoptimeouts = function() {
		window.clearTimeout(this._waittimeout);
	}

	// sets the opacity of the images
	this._initopacity = function() {
		if (!this._ready) return;
		for (var i = 0; i < this._max; i++) {
			if (this.oElements[i])
				RLdesign.Utils.SetOpacity(this.oElements[i], 0);
		}
		RLdesign.Utils.SetOpacity(this.oElements[this._current], 100);
	}


	this.Init(varArray);
}


if (!RLdesign) {
	var RLdesign = function() { };
}

if (!RLdesign.Utils) {
	RLdesign.Utils = function() {
		return {
			// returns a crossbrowser event object
			DefineEvent: function(e) {
				return e || window.event;
			},

			// returns the target for the event in question, typically a click-event
			// ie. in the case of a click-event, the target is the element being clicked on
			DefineEventTarget: function(e) {
				var ev = RLdesign.Utils.DefineEvent(e);
				var element = ev.srcElement || ev.target;
				if (element.nodeType == 3) element = element.parentNode; // defeat Safari bug
				return element;
			},

			// tries to return an object from an arbitrary argument that can be a string or an object
			// if successfully finding an object, either from a search for the object-id or the object itself, 
			// returns the object. If unsuccessful, returns null
			DefineObject: function(el, d) {
				var doc = (d) ? d : document;
				var elem = null;
				// if el is an object
				if (typeof (el) == "object") {
					try {
						elem = el;
					}
					catch (ex) {
						elem = null;
					}
				}
				// if el is the id of an html-object
				else if (doc.getElementById(el)) {
					try {
						elem = doc.getElementById(el);
					}
					catch (ex) {
						elem = null;
					}
				}
				// if el is a string representation of an document.getElementById - or similar statement
				else if (typeof (el) == "string" && (el.indexOf("(") != -1 || el.indexOf("[") != -1)) {
					try {
						eval("elem = " + el);
					}
					catch (ex) {
						elem = null;
					}
				}
				// last resort
				else if (typeof (el) == "string") {
					try {
						eval("elem = " + el);
					}
					catch (ex) {
						elem = null;
					}
				}
				return elem;
			},

			// returns a crossbrowser return code designed to prevent further events i mozilla browser, if need be
			DefineReturnCode: function(e, r) {
				var ev = RLdesign.Utils.DefineEvent(e);
				if (r == false) {
					if (ev.stopPropagation) ev.stopPropagation();
					else if (ev.cancelBubble) ev.cancelBubble = true;
					if (ev.preventDefault) ev.preventDefault();
					else if (ev.returnValue) ev.returnValue = false;
				}
				else {
					if (typeof (ev.returnValue) == "string") ev.returnValue = r;
				}
				return r;
			},

			// clears the specified global timeout variable (specified as a string), if exists
			ClearTimeout: function(sTimeout) {
				var bTimeoutExist = !!window[sTimeout];
				if (bTimeoutExist) window.clearTimeout(window[sTimeout]);
			},

			// evaluates whether the given argument object is an array, returning a boolean
			IsArray: function(a) {
				return (a && a.length && typeof (a) != "string" && !a.tagName && !a.alert && typeof (a[0]) != "undefined");
			},

			// evaluates whether the given argument object is an object, returning a boolean
			IsObject: function(o) {
				return (o && o.length == undefined && typeof (o) == "object" && !o.alert);
			},

			SetDisplay: function(obj, sParam) {
				obj = RLdesign.Utils.DefineObject(obj);
				obj.style.display = (sParam) ? sParam : "";
			},

			GetCssValue: function(obj, sCss) {
				var elem = RLdesign.Utils.DefineObject(obj);
				if (elem == null) return;
				var cStyle = null;
				if (elem.currentStyle) {
					cStyle = elem.currentStyle;
				}
				else if (document.defaultView && document.defaultView.getComputedStyle) {
					cStyle = document.defaultView.getComputedStyle(elem, "");
				}
				var sValue;
				if (cStyle) {
					sValue = cStyle[sCss];
				}
				else {
					sValue = elem.style[sCss];
				}
				return sValue;
			},

			GetOpacity: function(obj) {
				var opacity = (parseInt(obj.style.width) == obj.offsetWidth) ? 100 : 0;
				if (obj.style.opacity) { opacity = Math.round(obj.style.opacity * 100); }
				else if (obj.style.MozOpacity) { opacity = Math.round(obj.style.MozOpacity * 100); }
				else if (obj.style.KHTMLOpacity) { opacity = Math.round(obj.style.KHTMLOpacity * 100); }
				else if (obj.style.filter) {
					var filter = obj.style.filter;
					//				var pattern = /opacity\b[^=]*=(.*?)\)/;
					var pattern = /\(opacity:(.*?)\)/;
					oRegex = filter.match(pattern);
					if (typeof (oRegex) == "object") {
						var match = oRegex[1];
						opacity = (match != null) ? parseInt(match) : opacity;
					}
				}
				return opacity;
			},

			// sets opacity in a cross-browser sort-of way (doesn't work in pre-9 operas)
			SetOpacity: function(obj, iOpacity, bRelative, iDirection) {
				iDirection = (iDirection && iDirection < 0) ? -1 : 1;
				oElem = RLdesign.Utils.DefineObject(obj);
				if (oElem == null) return;
				if (bRelative) {
					iOpacity = iOpacity * iDirection;
					/*  NOT WORKING! - Figure out opacity when first time (should possibly be 100% but seen as "" (empty string)  */
					//						if (oElem.filter) oElem.filter.item("DXImageTransform.Microsoft.Alpha").opacity += iOpacity;
					//						oElem.style.KHTMLOpacity += (iOpacity / 100); // Safari<1.2, Konqueror
					//						oElem.style.MozOpacity += (iOpacity / 100); // Older Mozilla and Firefox
					//						oElem.style.opacity += (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
					oElem.style.opacity = oElem.style.opacity * 1 + (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
				}
				else {
					iOpacity = (iOpacity == 100) ? 99.999 : iOpacity;
					oElem.style.filter = "alpha(opacity:" + iOpacity + ")"; // IE/Win
					oElem.style.KHTMLOpacity = iOpacity / 100; // Safari<1.2, Konqueror
					oElem.style.MozOpacity = iOpacity / 100; // Older Mozilla and Firefox
					oElem.style.opacity = iOpacity / 100; // Safari 1.2, newer Firefox and Mozilla, CSS3
				}
			}

		}
	} ();
}



RLdesign.Web.UI.Fader = function() {
	return {
		Fade: function(obj, iEndOpacity, iTotalDuration, iResolution, sDisplayProp, fnWhenDone) {
			if (sDisplayProp == null) sDisplayProp = "block";
			if (iResolution == null || isNaN(iResolution) || iResolution < 1) iResolution = 6;
			var bSetNoneDisplay = false;
			switch (sDisplayProp.toString().toLowerCase()) {
				case "inline":
					sDisplayProp = "inline";
					break;
				case "inline-block":
					sDisplayProp = "inline-block";
					break;
				case "none":
					bSetNoneDisplay = true;
				case "block":
				default:
					sDisplayProp = "block";
					break;
			}

			obj = RLdesign.Utils.DefineObject(obj);
			if (obj == null) return false;

			fnWhenDone = (typeof (fnWhenDone) == "function") ? fnWhenDone : null;

			if (obj.tRLdesignFader) {
				clearTimeout(obj.tRLdesignFader);
			}
			var iCurrentOpacity = parseInt(RLdesign.Utils.GetOpacity(obj));
			if (iCurrentOpacity != iEndOpacity) {
				RLdesign.Utils.SetOpacity(obj, iCurrentOpacity);
				RLdesign.Utils.SetDisplay(obj, sDisplayProp);
				var iTotalSteps = (iTotalDuration / iResolution) / 2;
				var iTimeout = iTotalDuration / iTotalSteps;
				var iStep = (iEndOpacity - iCurrentOpacity) / iTotalSteps;
				obj.tRLdesignFader = window.setTimeout(function() { RLdesign.Web.UI.Fader._DoFade(obj, iCurrentOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				RLdesign.Utils.SetDisplay(obj, sDisplayProp);
				if (typeof (fnWhenDone) == "function") fnWhenDone(obj);
			}
		},

		_DoFade: function(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone) {
			iOpacity += iStep;
			if (iOpacity < 0) iOpacity = 0;
			else if (iOpacity > 100) iOpacity = 100;
			else if (iStep > 0 && iOpacity > iEndOpacity) iOpacity = iEndOpacity;
			else if (iStep < 0 && iOpacity < iEndOpacity) iOpacity = iEndOpacity;
			RLdesign.Utils.SetOpacity(obj, iOpacity);
			if (bSetNoneDisplay && iOpacity == 0 && iOpacity == iEndOpacity) {
				RLdesign.Utils.SetDisplay(obj, "none");
			}
			if (((iStep > 0 && iOpacity < iEndOpacity) || (iStep < 0 && iOpacity > iEndOpacity)) && (iOpacity > 0 && iOpacity < 100)) {
				obj.tRLdesignFader = window.setTimeout(function() { RLdesign.Web.UI.Fader._DoFade(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				if (typeof (fnWhenDone) == "function") fnWhenDone(obj);
			}
		}
	}
} ();
