/*
Name:       ImageFlow
Version:    1.2.1 (August 10 2009)
Author:     Finn Rudolph
Support:    http://finnrudolph.de/ImageFlow
Credits:    This script is based on Michael L. Perrys Cover flow in Javascript [1].
            The reflections are generated server-sided by a slightly hacked version 
            of Richard Daveys easyreflections [2] written in PHP. The mouse wheel 
            support is an implementation of Adomas Paltanavicius JavaScript mouse 
            wheel code [3]. It also uses the domReadyEvent from Tanny O'Haley [4].
*/

function ImageFlow ()
{
	this.defaults =
	{
		aspectRatio:        2.5,
		buttons:            true,
		captions:           false,
		imageCursor:        'default',
		ImageFlowID:        'imageflow',
		imageFocusM:        1.0,
		imageFocusMax:      3,
		imageScaling:       true, 
		imagesHeight:       0.70,
		imagesM:            1.0,
		onClick:            function() {window.open(this.url, '_blank', 'width=680,height=560,left=200,top=200,scrollbars=yes');},
		opacity:            true,
		opacityArray:       [10,7,4,2],
		percentLandscape:   118,
		percentOther:       100,
		preloadImages:      true,
		reflections:        false,
		reflectionGET:      '',
		reflectionP:        0.25,
		reflectionPNG:      false,
		scrollbarP:         0.82,
		slider:             true,
		sliderCursor:       'e-resize',
		sliderWidth:        14,
		startID:            1,
		startAnimation:     false,
		xStep:              180
	};

	
	var thisObject = this;

	
	this.init = function (options)
	{
		var optionsArray = ['aspectRatio', 'buttons', 'captions', 'imageCursor', 'imagesM', 'ImageFlowID', 'imageFocusM', 'imageFocusMax', 'imagesHeight', 'onClick', 'opacity', 'opacityArray', 'percentLandscape', 'percentOther', 'preloadImages', 'reflections', 'reflectionGET', 'reflectionP', 'reflectionPNG','imageScaling', 'scrollbarP', 'slider', 'sliderCursor', 'sliderWidth', 'startID', 'startAnimation', 'xStep'];
		var max = optionsArray.length;
		for (var i = 0; i < max; i++)
		{
			var name = optionsArray[i];
			this[name] = (options !== undefined && options[name] !== undefined) ? options[name] : thisObject.defaults[name];
		}

		var ImageFlowDiv = document.getElementById(thisObject.ImageFlowID);
		if(ImageFlowDiv)
		{
			ImageFlowDiv.style.visibility = 'visible';
			this.ImageFlowDiv = ImageFlowDiv;

			if(this.createStructure())
			{
				this.imagesDiv = document.getElementById(thisObject.ImageFlowID+'_images');
				this.captionDiv = document.getElementById(thisObject.ImageFlowID+'_caption');
				this.navigationDiv = document.getElementById(thisObject.ImageFlowID+'_navigation');
				this.scrollbarDiv = document.getElementById(thisObject.ImageFlowID+'_scrollbar');
				this.sliderDiv = document.getElementById(thisObject.ImageFlowID+'_slider');
				this.buttonNextDiv = document.getElementById(thisObject.ImageFlowID+'_next');
				this.buttonPreviousDiv = document.getElementById(thisObject.ImageFlowID+'_previous');

				this.indexArray = [];
				this.current = 0;
				this.imageID = 0;
				this.target = 0;
				this.memTarget = 0;
				this.firstRefresh = true;
				this.firstCheck = true;
				this.busy = false;

				if(this.slider === false)
				{
					this.scrollbarDiv.style.display = 'none';
				}
                
				var width = this.ImageFlowDiv.offsetWidth;
				var height = Math.round(width / thisObject.aspectRatio);
				document.getElementById(thisObject.ImageFlowID+'_loading_txt').style.paddingTop = ((height * 0.5) -22) + 'px';
				ImageFlowDiv.style.height = height + 'px';

				this.loadingProgress();
			}
		}
	};
	
	this.createStructure = function()
	{
		var imagesDiv = thisObject.Helper.createDocumentElement('div','images');

		var node = null;
		var max = this.ImageFlowDiv.childNodes.length;
		for(var index = 0; index < max; index++)
		{
			node = this.ImageFlowDiv.childNodes[index];
			if (node && node.nodeType == 1 && node.nodeName == 'IMG')
			{
				if(thisObject.reflections === true)
				{
					var version = '2';
					if(thisObject.reflectionPNG === true)
					{
						version = '3';
					}
					var src = node.getAttribute('src',2);
					src =  'reflect'+version+'.php?img='+src+thisObject.reflectionGET;
					node.setAttribute('src',src);
				}

				var imageNode = node.cloneNode(true);
				imagesDiv.appendChild(imageNode);
			}
		}

		var loadingP = thisObject.Helper.createDocumentElement('p','loading_txt');
		var loadingText = document.createTextNode(' ');
		loadingP.appendChild(loadingText);

		var loadingDiv = thisObject.Helper.createDocumentElement('div','loading');

		var loadingBarDiv = thisObject.Helper.createDocumentElement('div','loading_bar');
		loadingDiv.appendChild(loadingBarDiv);

		var captionDiv = thisObject.Helper.createDocumentElement('div','caption');
		
		var scrollbarDiv = thisObject.Helper.createDocumentElement('div','scrollbar');
		var sliderDiv = thisObject.Helper.createDocumentElement('div','slider');
		scrollbarDiv.appendChild(sliderDiv);		
		if(thisObject.buttons)
		{
			var buttonPreviousDiv = thisObject.Helper.createDocumentElement('div','previous', 'button');
			var buttonNextDiv = thisObject.Helper.createDocumentElement('div','next', 'button');
			scrollbarDiv.appendChild(buttonPreviousDiv);
			scrollbarDiv.appendChild(buttonNextDiv);
		}
		
		var navigationDiv = thisObject.Helper.createDocumentElement('div','navigation');
		navigationDiv.appendChild(captionDiv);
		navigationDiv.appendChild(scrollbarDiv);
	
		var success = false;
		if (thisObject.ImageFlowDiv.appendChild(imagesDiv) &&
			thisObject.ImageFlowDiv.appendChild(loadingP) &&
			thisObject.ImageFlowDiv.appendChild(loadingDiv) &&
			thisObject.ImageFlowDiv.appendChild(navigationDiv))
		{
			for(index = 0; index < max; index++)
			{
				node = this.ImageFlowDiv.childNodes[index];
				if (node && node.nodeType == 1 && node.nodeName == 'IMG')
				{
					this.ImageFlowDiv.removeChild(node);
				}
			}
			success = true;
		}
		return success;
	};

	
	this.loadingProgress = function()
	{
		var p = thisObject.loadingStatus();
		if(p < 100 || thisObject.firstCheck === true && thisObject.preloadImages === true)
		{
			if(thisObject.firstCheck === true && p == 100)
			{
				thisObject.firstCheck = false;
				window.setTimeout(thisObject.loadingProgress, 100);
			}
			else
			{
				window.setTimeout(thisObject.loadingProgress, 40);
			}
		}
		else
		{
			document.getElementById(thisObject.ImageFlowID+'_loading_txt').style.display = 'none';
			document.getElementById(thisObject.ImageFlowID+'_loading').style.display = 'none';

			window.setTimeout(thisObject.Helper.addResizeEvent, 1000);

			thisObject.MouseWheel.init();
			thisObject.MouseDrag.init();
			thisObject.Touch.init();
			thisObject.Key.init();

			thisObject.refresh(true);

			document.getElementById(thisObject.ImageFlowID+'_scrollbar').style.visibility = 'visible';

			var startID = thisObject.startID-1;
			if (startID < 0 )
			{
				startID = 0;
			}
			if (startID > thisObject.max)
			{
				startID = thisObject.max -1;
			}
			thisObject.glideTo(startID);

			if(thisObject.startAnimation === true)
			{
				thisObject.moveTo(5000);
			}
		}
	};


	this.loadingStatus = function()
	{
		var max = thisObject.imagesDiv.childNodes.length;
		var i = 0, completed = 0;
		var image = null;
		for(var index = 0; index < max; index++)
		{
			image = thisObject.imagesDiv.childNodes[index];
			if (image && image.nodeType == 1 && image.nodeName == 'IMG')
			{
				if (image.complete === true)
				{
					completed++;
				}
				i++;
			}
		}
		var finished = Math.round((completed/i)*100);
		var loadingBar = document.getElementById(thisObject.ImageFlowID+'_loading_bar');
		loadingBar.style.width = finished+'%';

		var loadingP = document.getElementById(thisObject.ImageFlowID+'_loading_txt');
		var loadingTxt = document.createTextNode('chargement '+completed+'/'+i);
		loadingP.replaceChild(loadingTxt,loadingP.firstChild);
		return finished;
	};

	
	this.refresh = function()
	{
		this.imagesDivWidth = thisObject.imagesDiv.offsetWidth+thisObject.imagesDiv.offsetLeft;
		this.maxHeight = Math.round(thisObject.imagesDivWidth / thisObject.aspectRatio);
		this.maxFocus = thisObject.imageFocusMax * thisObject.xStep;
		this.size = thisObject.imagesDivWidth * 0.5;
		this.sliderWidth = thisObject.sliderWidth * 0.5;
		this.scrollbarWidth = (thisObject.imagesDivWidth - ( Math.round(thisObject.sliderWidth) * 2)) * thisObject.scrollbarP;
		this.imagesDivHeight = Math.round(thisObject.maxHeight * thisObject.imagesHeight);
		
		thisObject.ImageFlowDiv.style.height = thisObject.maxHeight + 'px';

		thisObject.imagesDiv.style.height =  thisObject.imagesDivHeight + 'px'; 
		
		thisObject.navigationDiv.style.height =  (thisObject.maxHeight - thisObject.imagesDivHeight) + 'px'; 

		thisObject.captionDiv.style.width = thisObject.imagesDivWidth + 'px';
		thisObject.captionDiv.style.paddingTop = Math.round(thisObject.imagesDivWidth * 0.02) + 'px';

		thisObject.scrollbarDiv.style.width = thisObject.scrollbarWidth + 'px';
		thisObject.scrollbarDiv.style.marginTop = Math.round(thisObject.imagesDivWidth * 0.02) + 'px';
		thisObject.scrollbarDiv.style.marginLeft = Math.round(thisObject.sliderWidth + ((thisObject.imagesDivWidth - thisObject.scrollbarWidth)/2)) + 'px';

		thisObject.sliderDiv.style.cursor = thisObject.sliderCursor;
		thisObject.sliderDiv.onmousedown = function () { thisObject.MouseDrag.start(this); return false;};
		
		if(thisObject.buttons)
		{
			thisObject.buttonPreviousDiv.onclick = function () { thisObject.MouseWheel.handle(1); };
			thisObject.buttonNextDiv.onclick = function () { thisObject.MouseWheel.handle(-1); };
		}

		var multi = (thisObject.reflections === true) ? thisObject.reflectionP + 1 : 1;

		var max = thisObject.imagesDiv.childNodes.length;
		var i = 0;
		var image = null;
		for (var index = 0; index < max; index++)
		{
			image = thisObject.imagesDiv.childNodes[index];
			if(image !== null && image.nodeType == 1 && image.nodeName == 'IMG')
			{
				this.indexArray[i] = index;

				image.url = image.getAttribute('longdesc');
				image.xPosition = (-i * thisObject.xStep);
				image.i = i;

				if(thisObject.firstRefresh)
				{
					if(image.getAttribute('width') !== null && image.getAttribute('height') !== null)
					{
						image.w = image.getAttribute('width');
						image.h = image.getAttribute('height') * multi;
					}
					else{
						image.w = image.width;
						image.h = image.height;
					}
				}

				if((image.w) > (image.h / (thisObject.reflectionP + 1)))
				{
					image.pc = thisObject.percentLandscape;
					image.pcMem = thisObject.percentLandscape;
				}
				else
				{
					image.pc = thisObject.percentOther;
					image.pcMem = thisObject.percentOther;
				}
				
				if(thisObject.imageScaling === false)
				{		
					image.style.position = 'relative';
					image.style.display = 'inline';
				}

				image.style.cursor = thisObject.imageCursor;
				i++;
			}
		}
		this.max = thisObject.indexArray.length;
		
		if(thisObject.imageScaling === false)
		{
			image = thisObject.imagesDiv.childNodes[thisObject.indexArray[0]];
			
			this.totalImagesWidth = image.w * thisObject.max;
			image.style.paddingLeft = (thisObject.imagesDivWidth/2) + (image.w/2) + 'px';
			
			thisObject.imagesDiv.style.height =  image.h + 'px';
			thisObject.navigationDiv.style.height =  (thisObject.maxHeight - image.h) + 'px'; 
		}

		if(thisObject.firstRefresh)
		{
			thisObject.firstRefresh = false;
		}

		thisObject.glideTo(thisObject.imageID);
		thisObject.moveTo(thisObject.current);
	};


	this.moveTo = function(x)
	{
		this.current = x;
		this.zIndex = thisObject.max;

		for (var index = 0; index < thisObject.max; index++)
		{
			var image = thisObject.imagesDiv.childNodes[thisObject.indexArray[index]];
			var currentImage = index * -thisObject.xStep;

			if(thisObject.imageScaling)
			{
				if ((currentImage + thisObject.maxFocus) < thisObject.memTarget || (currentImage - thisObject.maxFocus) > thisObject.memTarget)
				{
					image.style.visibility = 'hidden';
					image.style.display = 'none';
				}
				else
				{
					var z = (Math.sqrt(10000 + x * x) + 100) * thisObject.imagesM;
					var xs = x / z * thisObject.size + thisObject.size;

					image.style.display = 'block';

					var newImageH = (image.h / image.w * image.pc) / z * thisObject.size;
					var newImageW = 0;
					switch (newImageH > thisObject.maxHeight)
					{
						case false:
							newImageW = image.pc / z * thisObject.size;
							break;

						default:
							newImageH = thisObject.maxHeight;
							newImageW = image.w * newImageH / image.h;
							break;
					}

					var newImageTop = (thisObject.imagesDivHeight - newImageH) + ((newImageH / (thisObject.reflectionP + 1)) * thisObject.reflectionP);

					image.style.left = xs - (image.pc / 2) / z * thisObject.size + 'px';
					if(newImageW && newImageH)
					{
						image.style.height = newImageH + 'px';
						image.style.width = newImageW + 'px';
						image.style.top = newImageTop + 'px';
					}
					image.style.visibility = 'visible';

					switch ( x < 0 )
					{
						case true:
							this.zIndex++;
							break;

						default:
							this.zIndex = thisObject.zIndex - 1;
							break;
					}

					switch ( image.i == thisObject.imageID )
					{
						case false:
							image.onclick = function() { thisObject.glideTo(this.i);};
							break;

						default:
							this.zIndex = thisObject.zIndex + 1;
							if(image.url !== '')
							{
								image.onclick = thisObject.onClick;
							}
							break;
					}
					image.style.zIndex = thisObject.zIndex;
				}
			}

			else
			{
				if ((currentImage + thisObject.maxFocus) < thisObject.memTarget || (currentImage - thisObject.maxFocus) > thisObject.memTarget)
				{
					image.style.visibility = 'hidden';
				}
				else
				{
					image.style.visibility = 'visible';

					switch ( image.i == thisObject.imageID )
					{
						case false:
							image.onclick = function() { thisObject.glideTo(this.i);};
							break;

						default:
							if(image.url !== '')
							{
								image.onclick = thisObject.onClick;
							}
							break;
					}
				}	
				thisObject.imagesDiv.style.marginLeft = (x - thisObject.totalImagesWidth) + 'px';
			}

			x += thisObject.xStep;
		}
	};

	
	this.glideTo = function(imageID)
	{
		var x = -imageID * thisObject.xStep;
		this.target = x;
		this.memTarget = x;
		this.imageID = imageID;

		var caption = thisObject.imagesDiv.childNodes[imageID].getAttribute('alt');
		if (caption === '' || thisObject.captions === false)
		{
			caption = '&nbsp;';
		}
		thisObject.captionDiv.innerHTML = caption;

		if (thisObject.MouseDrag.busy === false)
		{
			this.newSliderX = (imageID * thisObject.scrollbarWidth) / (thisObject.max-1) - thisObject.MouseDrag.newX;
			thisObject.sliderDiv.style.marginLeft = (thisObject.newSliderX - thisObject.sliderWidth) + 'px';
		}

		if(thisObject.opacity === true || thisObject.imageFocusM !== thisObject.defaults.imageFocusM)
		{
			thisObject.Helper.setOpacity(thisObject.imagesDiv.childNodes[imageID], thisObject.opacityArray[0]);
			thisObject.imagesDiv.childNodes[imageID].pc = thisObject.imagesDiv.childNodes[imageID].pc * thisObject.imageFocusM;

			var opacityValue = 0;
			var rightID = 0;
			var leftID = 0;
			var last = thisObject.opacityArray.length;

			for (var i = 1; i < (thisObject.imageFocusMax+1); i++)
			{
				if((i+1) > last)
				{
					opacityValue = thisObject.opacityArray[last-1];
				}
				else
				{
					opacityValue = thisObject.opacityArray[i];
				}

				rightID = imageID + i;
				leftID = imageID - i;

				if (rightID < thisObject.max)
				{
					thisObject.Helper.setOpacity(thisObject.imagesDiv.childNodes[rightID], opacityValue);
					thisObject.imagesDiv.childNodes[rightID].pc = thisObject.imagesDiv.childNodes[rightID].pcMem;
				}
				if (leftID >= 0)
				{
					thisObject.Helper.setOpacity(thisObject.imagesDiv.childNodes[leftID], opacityValue);
					thisObject.imagesDiv.childNodes[leftID].pc = thisObject.imagesDiv.childNodes[leftID].pcMem;
				}
			}
		}

		if (thisObject.busy === false)
		{
			window.setTimeout(thisObject.animate, 50);
			thisObject.busy = true;
		}
	};


	/* Animates image gliding */
	this.animate = function()
	{
		switch (thisObject.target < thisObject.current-1 || thisObject.target > thisObject.current+1)
		{
			case true:
				thisObject.moveTo(thisObject.current + (thisObject.target-thisObject.current)/3);
				window.setTimeout(thisObject.animate, 50);
				thisObject.busy = true;
				break;

			default:
				thisObject.busy = false;
				break;
		}
	};
	
	
	/* Mouse Wheel support */
	this.MouseWheel =
	{
		init: function()
		{
			/* Init mouse wheel listener */
			if(window.addEventListener)
			{
				thisObject.ImageFlowDiv.addEventListener('DOMMouseScroll', thisObject.MouseWheel.get, false);
			}
			thisObject.Helper.addEvent(thisObject.ImageFlowDiv,'mousewheel',thisObject.MouseWheel.get);
		},

		get: function(event)
		{
			var delta = 0;
			if (!event)
			{
				event = window.event;
			}
			if (event.wheelDelta)
			{
				delta = event.wheelDelta / 120;
			}
			else if (event.detail)
			{
				delta = -event.detail / 3;
			}
			if (delta)
			{
				thisObject.MouseWheel.handle(delta);
			}
			thisObject.Helper.suppressBrowserDefault(event);
		},

		handle: function(delta)
		{
			var change = false;
			var newImageID = 0;
			if(delta > 0)
			{
				if(thisObject.imageID >= 1)
				{
					newImageID = thisObject.imageID -1;
					change = true;
				}
			}
			else
			{
				if(thisObject.imageID < (thisObject.max-1))
				{
					newImageID = thisObject.imageID +1;
					change = true;
				}
			}

			if (change === true)
			{
				thisObject.glideTo(newImageID);
			}
		}
	};
	
	
	this.MouseDrag =
	{
		object: null,
		objectX: 0,
		mouseX: 0,
		newX: 0,
		busy: false,

		init: function()
		{
			thisObject.Helper.addEvent(thisObject.ImageFlowDiv,'mousemove',thisObject.MouseDrag.drag);
			thisObject.Helper.addEvent(thisObject.ImageFlowDiv,'mouseup',thisObject.MouseDrag.stop);
			thisObject.Helper.addEvent(document,'mouseup',thisObject.MouseDrag.stop);

			/* Avoid text and image selection while dragging  */
			thisObject.ImageFlowDiv.onselectstart = function ()
			{
				var selection = true;
				if (thisObject.MouseDrag.busy === true)
				{
					selection = false;
				}
				return selection;
			};
		},

		start: function(o)
		{
			thisObject.MouseDrag.object = o;
			thisObject.MouseDrag.objectX = thisObject.MouseDrag.mouseX - o.offsetLeft + thisObject.newSliderX;

		},

		stop: function()
		{
			thisObject.MouseDrag.object = null;
			thisObject.MouseDrag.busy = false;
		},

		drag: function(e)
		{
			var posx = 0;
			if (!e)
			{
				e = window.event;
			}
			if (e.pageX)
			{
				posx = e.pageX;
			}
			else if (e.clientX)
			{
				posx = e.clientX + document.body.scrollLeft	+ document.documentElement.scrollLeft;
			}
			thisObject.MouseDrag.mouseX = posx;

			if(thisObject.MouseDrag.object !== null)
			{
				var newX = (thisObject.MouseDrag.mouseX - thisObject.MouseDrag.objectX) + thisObject.sliderWidth;

				/* Make sure, that the slider is moved in proper relation to previous movements by the glideTo function */
				if(newX < ( - thisObject.newSliderX))
				{
					newX = - thisObject.newSliderX;
				}
				if(newX > (thisObject.scrollbarWidth - thisObject.newSliderX))
				{
					newX = thisObject.scrollbarWidth - thisObject.newSliderX;
				}

				/* Set new slider position */
				var step = (newX + thisObject.newSliderX) / (thisObject.scrollbarWidth / (thisObject.max-1));
				var imageID = Math.round(step);
				thisObject.MouseDrag.newX = newX;
				thisObject.MouseDrag.object.style.left = newX + 'px';
				if(thisObject.imageID !== imageID)
				{
					thisObject.glideTo(imageID);
				}
				thisObject.MouseDrag.busy = true;
			}
		}
	};
	
	
	/* Safari touch events on the iPhone and iPod Touch */
	this.Touch =
	{
		x: 0,		
		startX: 0,
		stopX: 0,
		busy: false,
		first: true,

		/* Init touch event listener */
		init: function()
		{
			thisObject.Helper.addEvent(thisObject.navigationDiv,'touchstart',thisObject.Touch.start);
			thisObject.Helper.addEvent(document,'touchmove',thisObject.Touch.handle);
			thisObject.Helper.addEvent(document,'touchend',thisObject.Touch.stop);	
		},
		
		isOnNavigationDiv: function(e)
		{	
			var state = false;
			if(e.touches)
			{
				var target = e.touches[0].target;
				if(target === thisObject.navigationDiv || target === thisObject.sliderDiv || target === thisObject.scrollbarDiv)
				{
					state = true;
				}
			}
			return state;
		},
		
		getX: function(e)
		{
			var x = 0;
			if(e.touches)
			{
				x = e.touches[0].pageX;
			}
			return x;		
		},
	
		start: function(e)
		{
			thisObject.Touch.startX = thisObject.Touch.getX(e);
			thisObject.Touch.busy = true;
			thisObject.Helper.suppressBrowserDefault(e);			
		},
		
		isBusy: function()
		{
			var busy = false;
			if(thisObject.Touch.busy === true)
			{
				busy = true;
			}
			return busy;
		},

		/* Handle touch event position within the navigation div */
		handle: function(e)
		{
			if(thisObject.Touch.isBusy && thisObject.Touch.isOnNavigationDiv(e))
			{
				if(thisObject.Touch.first)
				{
					thisObject.Touch.stopX = ((thisObject.max-1)-thisObject.imageID) * (thisObject.imagesDivWidth / (thisObject.max-1));
					thisObject.Touch.first = false;
				}
				var newX = -(thisObject.Touch.getX(e) - thisObject.Touch.startX - thisObject.Touch.stopX);

				/* Map x-axis touch coordinates in range of the ImageFlow width */
				if(newX < 0)
				{
					newX = 0;
				}
				if(newX > thisObject.imagesDivWidth)
				{
					newX = thisObject.imagesDivWidth;
				}

				thisObject.Touch.x = newX;
				
				var imageID = Math.round(newX / (thisObject.imagesDivWidth / (thisObject.max-1)));
				imageID = (thisObject.max-1)-imageID;
				if(thisObject.imageID !== imageID)
				{
					thisObject.glideTo(imageID);
				}
				thisObject.Helper.suppressBrowserDefault(e);
			}
		},

		stop: function()
		{
			thisObject.Touch.stopX = thisObject.Touch.x;
			//thisObject.Touch.stopX = -(thisObject.Touch.x - thisObject.imagesDivWidth);
			
			thisObject.Touch.busy = false;
		}
	};
	

	/* Key support */
	this.Key =
	{
		/* Init key event listener */
		init: function()
		{
			document.onkeydown = function(event){ thisObject.Key.handle(event); };
		},

		/* Handle the arrow keys */
		handle: function(event)
		{
			var charCode  = thisObject.Key.get(event);
			switch (charCode)
			{
				/* Right arrow key */
				case 39:
					thisObject.MouseWheel.handle(-1);
					break;

				/* Left arrow key */
				case 37:
					thisObject.MouseWheel.handle(1);
					break;
			}
		},

		/* Get the current keycode */
		get: function(event)
		{
			event = event || window.event;
			return event.keyCode;
		}
	};
	
	
	/* Helper functions */
	this.Helper =
	{
		/* Add events */
		addEvent: function(obj, type, fn)
		{
			if(obj.addEventListener)
			{
				obj.addEventListener(type, fn, false);
			}
			else if(obj.attachEvent)
			{
				obj["e"+type+fn] = fn;
				obj[type+fn] = function() { obj["e"+type+fn]( window.event ); };
				obj.attachEvent( "on"+type, obj[type+fn] );
			}
		},
		
		/* Set image opacity */
		setOpacity: function(object, value)
		{
			if(thisObject.opacity === true)
			{
				object.style.opacity = value/10;
				object.style.filter = 'alpha(opacity=' + value*10 + ')';
			}
		},
		
		/* Creates HTML elements */
		createDocumentElement: function(type, id, optionalClass)
		{
			var element = document.createElement(type);
			element.setAttribute('id',thisObject.ImageFlowID+'_'+id);
			if(optionalClass !== undefined)
			{
				id += ' '+optionalClass;
			}
			element.setAttribute('class',id);
			element.setAttribute('className',id);
			return element;
		},
		
		/* Suppress default browser behaviour to avoid image/text selection while dragging */
		suppressBrowserDefault: function(e)
		{
			if(e.preventDefault)
			{
				e.preventDefault();
			}
			else
			{
				e.returnValue = false;
			}
			return false;
		},
		
		/* Adds functions to the window.onresize event - can not be done by addEvent */
		addResizeEvent: function()
		{
			var otherFunctions = window.onresize;
			if(typeof window.onresize != 'function')
			{
				window.onresize = function()
				{
					thisObject.refresh();
				};
			}
			else
			{
				window.onresize = function(){
					if (otherFunctions)
					{
						otherFunctions();
					}
					thisObject.refresh();
				};
			}
		}
	};
}

/* DOMContentLoaded event handler - by Tanny O'Haley [4] */
var domReadyEvent =
{
	name: "domReadyEvent",
	/* Array of DOMContentLoaded event handlers.*/
	events: {},
	domReadyID: 1,
	bDone: false,
	DOMContentLoadedCustom: null,

	/* Function that adds DOMContentLoaded listeners to the array.*/
	add: function(handler)
	{
		/* Assign each event handler a unique ID. If the handler has an ID, it has already been added to the events object or been run.*/
		if (!handler.$$domReadyID)
		{
			handler.$$domReadyID = this.domReadyID++;

			/* If the DOMContentLoaded event has happened, run the function. */
			if(this.bDone)
			{
				handler();
			}

			/* store the event handler in the hash table */
			this.events[handler.$$domReadyID] = handler;
		}
	},

	remove: function(handler)
	{
		/* Delete the event handler from the hash table */
		if (handler.$$domReadyID)
		{
			delete this.events[handler.$$domReadyID];
		}
	},

	/* Function to process the DOMContentLoaded events array. */
	run: function()
	{
		/* quit if this function has already been called */
		if (this.bDone)
		{
			return;
		}

		/* Flag this function so we don't do the same thing twice */
		this.bDone = true;

		/* iterates through array of registered functions */
		for (var i in this.events)
		{
			this.events[i]();
		}
	},

	schedule: function()
	{
		/* Quit if the init function has already been called*/
		if (this.bDone)
		{
			return;
		}

		/* First, check for Safari or KHTML.*/
		if(/KHTML|WebKit/i.test(navigator.userAgent))
		{
			if(/loaded|complete/.test(document.readyState))
			{
				this.run();
			}
			else
			{
				/* Not ready yet, wait a little more.*/
				setTimeout(this.name + ".schedule()", 100);
			}
		}
		else if(document.getElementById("__ie_onload"))
		{
			/* Second, check for IE.*/
			return true;
		}

		/* Check for custom developer provided function.*/
		if(typeof this.DOMContentLoadedCustom === "function")
		{
			if(typeof document.getElementsByTagName !== 'undefined' && (document.getElementsByTagName('body')[0] !== null || document.body !== null))
			{
				/* Call custom function. */
				if(this.DOMContentLoadedCustom())
				{
					this.run();
				}
				else
				{
					/* Not ready yet, wait a little more. */
					setTimeout(this.name + ".schedule()", 250);
				}
			}
		}
		return true;
	},

	init: function()
	{
		/* If addEventListener supports the DOMContentLoaded event.*/
		if(document.addEventListener)
		{
			document.addEventListener("DOMContentLoaded", function() { domReadyEvent.run(); }, false);
		}

		/* Schedule to run the init function.*/
		setTimeout("domReadyEvent.schedule()", 100);

		function run()
		{
			domReadyEvent.run();
		}

		/* Just in case window.onload happens first, add it to onload using an available method.*/
		if(typeof addEvent !== "undefined")
		{
			addEvent(window, "load", run);
		}
		else if(document.addEventListener)
		{
			document.addEventListener("load", run, false);
		}
		else if(typeof window.onload === "function")
		{
			var oldonload = window.onload;
			window.onload = function()
			{
				domReadyEvent.run();
				oldonload();
			};
		}
		else
		{
			window.onload = run;
		}

		/* for Internet Explorer */
		/*@cc_on
			@if (@_win32 || @_win64)
			document.write("<script id=__ie_onload defer src=\"//:\"><\/script>");
			var script = document.getElementById("__ie_onload");
			script.onreadystatechange = function()
			{
				if (this.readyState == "complete")
				{
					domReadyEvent.run(); // call the onload handler
				}
			};
			@end
		@*/
	}
};

var domReady = function(handler) { domReadyEvent.add(handler); };
domReadyEvent.init();


/* Create ImageFlow instances when the DOM structure has been loaded */
domReady(function()
{
	var instanceOne = new ImageFlow();
	instanceOne.init({ ImageFlowID:'imagesfjeu' });
});