/*
Name:       ImageFlow
Version:    1.0.2 (November 10 2008)
Author:     Finn Rudolph
Support:    http://finnrudolph.de/ImageFlow

Licence:    ImageFlow is licensed under a Creative Commons 
            Attribution-Noncommercial 3.0 Unported License 
            (http://creativecommons.org/licenses/by-nc/3.0/).

            You are free:
                + to Share ó to copy, distribute and transmit the work
                + to Remix ó to adapt the work

            Under the following conditions:
                + Attribution. You must attribute the work in the manner specified by the author or licensor 
                  (but not in any way that suggests that they endorse you or your use of the work). 
                + Noncommercial. You may not use this work for commercial purposes. 

            + For any reuse or distribution, you must make clear to others the license terms of this work.
            + Any of the above conditions can be waived if you get permission from the copyright holder.
            + Nothing in this license impairs or restricts the author's moral rights.

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].

            [1] http://www.adventuresinsoftware.com/blog/?p=104#comment-1981
            [2] http://reflection.corephp.co.uk/v2.php
            [3] http://adomas.org/javascript-mouse-wheel/
            [4] http://tanny.ica.com/ICA/TKO/tkoblog.nsf/dx/domcontentloaded-for-browsers-part-v
*/


/* ImageFlow constructor */

var imf = {

/* Configuration variables */
conf_reflection_p : 0.5,         		// Sets the height of the reflection in % of the source image
conf_focus : 1,                  		// Sets the numbers of images on each side of the focussed one
max_conf_focus : 0,
conf_slider_width : 14,          		// Sets the px width of the slider div
conf_images_cursor : 'pointer',  		// Sets the cursor type for all images default is 'default'
conf_slider_cursor : 'pointer', 		// Sets the slider cursor type: try "e-resize" default is 'default'




/* Id names used in the HTML */
conf_imageflow : 'imageflow',    		// Default is 'imageflow'
conf_loading : 'loading',       		// Default is 'loading'
conf_images : 'images',          		// Default is 'images'
conf_captions : 'captions',      		// Default is 'captions'
conf_scrollbar : 'scrollbar',    		// Default is 'scrollbar'
conf_slider : 'slider',          		// Default is 'slider'


/* Define global variables */

caption_id : 0,
new_caption_id : 0,
current : 0,
target : 0,
mem_target : 0,
timer : 0,
array_images : [],
new_slider_pos : 0,
dragging : false,
dragobject : null,
dragx : 0,
posx : 0,
new_posx : 0,
xstep : 150,
img_div : null,
imageflow_div : null,
scrollbar_div : null,
slider_div : null,
caption_div : null,
hide_slider : false,
hide_caption : false,
images_width : 0,
images_top : 0,
images_left : 0,
size : 0,
scrollbar_width : 0,
max_height : 0,
max : 0,


step : function()
{
	switch (imf.target < imf.current-1 || imf.target > imf.current+1)
	{
		case true:
			imf.moveTo(imf.current + (imf.target-imf.current)/3);
			window.setTimeout(imf.step, 50);
			imf.timer = 1;
			break;

		default:
			imf.timer = 0;
			break;
	}
},

glideTo : function(x, new_caption_id)
{
	/* Animate gliding to new x position */
	imf.target = x;
	imf.mem_target = x;
	if (imf.timer == 0)
	{
		window.setTimeout(imf.step, 50);
		imf.timer = 1;
	}

	/* Display new caption */
	imf.caption_id = new_caption_id;
	var image = imf.img_div.childNodes.item(imf.array_images[imf.caption_id]);
	image = imf.getImage( image );
	var caption;

	if (imf.hide_caption)
	{
		caption = '';
	}
	else
	{
		caption = image.getAttribute('alt');
	}
	if (caption == '') caption = '&nbsp;';
	imf.caption_div.innerHTML = caption;

	/* Set scrollbar slider to new position */
	if (imf.dragging == false)
	{
		imf.new_slider_pos = (imf.scrollbar_width * (-(x*100/((imf.max-1)*imf.xstep))) / 100) - imf.new_posx;
		imf.slider_div.style.marginLeft = (imf.new_slider_pos - imf.conf_slider_width) + 'px';
	}
},

moveTo : function(x)
{
	imf.current = x;
	var zIndex = imf.max;

	/* Main loop */
	for (var index = 0; index < imf.max; index++)
	{
		var image = imf.img_div.childNodes.item(imf.array_images[index]);
		image = imf.getImage( image );

		var current_image = index * -imf.xstep;

		/* Don't display images that are not imf.conf_focussed */
		if ((current_image+imf.max_conf_focus) < imf.mem_target || (current_image-imf.max_conf_focus) > imf.mem_target)
		{
			image.style.visibility = 'hidden';
			image.style.display = 'none';
		}
		else
		{
			var z = Math.sqrt(10000 + x * x) + 100;
			var xs = x / z * imf.size + imf.size;

			/* Still hide images until they are processed, but set display style to block */
			image.style.display = 'block';

			/* Process new image height and image width */
			var new_img_h = (image.h / image.w * image.pc) / z * imf.size;
			var new_img_w = 0;
			switch ( new_img_h > imf.max_height )
			{
				case false:
					new_img_w = image.pc / z * imf.size;
					break;

				default:
					new_img_h = imf.max_height;
					new_img_w = image.w * new_img_h / image.h;
					break;
			}
			var new_img_top = (imf.images_width * 0.34 - new_img_h) + imf.images_top + ((new_img_h / (imf.conf_reflection_p + 1)) * imf.conf_reflection_p);

			/* Set new image properties */
			image.style.left = xs - (image.pc / 2) / z * imf.size + imf.images_left + 'px';
			if(new_img_w && new_img_h)
			{
				image.style.height = new_img_h + 'px';
				image.style.width = new_img_w + 'px';
				image.style.top = new_img_top + 'px';
			}
			image.style.visibility = 'visible';

			/* Set image layer through zIndex */
			switch ( x < 0 )
			{
				case true:
					zIndex++;
					break;

				default:
					zIndex = zIndex - 1;
					break;
			}

			/* Change zIndex and onclick function of the focussed image */
			switch ( image.i == imf.caption_id )
			{
				case false:
					//image.onclick = function() { imf.glideTo(this.x_pos, this.i); } kdl
					break;

				default:
					zIndex = zIndex + 1;
					//image.onclick = function() { document.location = this.url; }
					// Highslide hack
					//image.onclick = function() { return hs.expand(this, { src: this.getAttribute('longdesc') }); } kdl
					break;
			}
			image.style.zIndex = zIndex;
		}
		x += imf.xstep;
	}
},

getImage : function( image )
{
	if (image.nodeName == 'IMG' || image.childNodes.length == 0)
	{
		return image;
	}

	for (var i = 0; i < image.childNodes.length; i++)
	{
		if (image.childNodes[i].nodeName == 'IMG')
		{
			return image.childNodes[i];
		}
	}
	return image;
},

/* Main function */
refresh : function(onload)
{
	/* Cache document objects in global variables */
	imf.imageflow_div = document.getElementById(imf.conf_imageflow);
	imf.img_div = document.getElementById(imf.conf_images);
	imf.scrollbar_div = document.getElementById(imf.conf_scrollbar);
	imf.slider_div = document.getElementById(imf.conf_slider);
	imf.caption_div = document.getElementById(imf.conf_captions);

	/* Cache global variables, that only change on refresh */
	imf.images_width = imf.img_div.offsetWidth;
	imf.images_top = imf.img_div.offsetTop;
	imf.images_left = imf.img_div.offsetLeft;
	imf.max_conf_focus = imf.conf_focus * imf.xstep;
	imf.size = imf.images_width * 0.5;
	imf.scrollbar_width = imf.images_width * 0.6;
	imf.conf_slider_width = imf.conf_slider_width * 0.5;
	imf.max_height = imf.images_width * 0.51;

	/* Change imageflow div properties */
	imf.imageflow_div.style.height = imf.max_height + 'px';

	/* Change images div properties */
	imf.img_div.style.height = imf.images_width * 0.338 + 'px';

	/* Change captions div properties */
	imf.caption_div.style.width = imf.images_width + 'px';
	imf.caption_div.style.marginTop = imf.images_width * 0.03 + 'px';

	/* Change scrollbar div properties */
	imf.scrollbar_div.style.marginTop = imf.images_width * 0.02 + 'px';
	imf.scrollbar_div.style.marginLeft = imf.images_width * 0.2 + 'px';
	imf.scrollbar_div.style.width = imf.scrollbar_width + 'px';

	/* Set slider attributes */
	imf.slider_div.onmousedown = function () { imf.dragstart(this); };
	imf.slider_div.style.cursor = imf.conf_slider_cursor;

	/* Cache EVERYTHING! */
	imf.max = imf.img_div.childNodes.length;
	var i = 0;
	for (var index = 0; index < imf.max; index++)
	{
		var image = imf.img_div.childNodes.item(index);
		if (image.nodeType == 1)
		{
			imf.array_images[i] = index;
			image = imf.getImage( image );

			/* Set image onclick by adding i and x_pos as attributes! */
			//image.onclick = function() { imf.glideTo(this.x_pos, this.i); } kdl
			image.x_pos = (-i * imf.xstep);
			image.i = i;

			/* Add width and height as attributes ONLY once onload */
			if(onload == true)
			{
				image.w = image.width;
				image.h = image.height;
			}

			/* Check source image format. Get image height minus reflection height! */
			switch ((image.w + 1) > (image.h / (imf.conf_reflection_p + 1)))
			{
				/* Landscape format */
				case true:
					image.pc = 118;
					break;

				/* Portrait and square format */
				default:
					image.pc = 100;
					break;
			}
            /* Disabled doubleclick for a better highslide */
			/* Set ondblclick event */
			//image.url = image.getAttribute('longdesc');
			//image.ondblclick = function() { document.location = this.url; }
			//Highslide
			//image.ondblclick = function() { return hs.expand(this, { src: this.getAttribute('longdesc') }); }

			/* Set image cursor type */
			//image.style.cursor = imf.conf_images_cursor; kdl

			i++;
		}
	}
	imf.max = imf.array_images.length;

	/* Display images in current order */
	imf.moveTo(imf.current);
	imf.glideTo(imf.current, imf.caption_id);
},

/* Show/hide element functions */
show : function(id)
{
	var element = document.getElementById(id);
	element.style.visibility = 'visible';
},

hide : function(id)
{
	var element = document.getElementById(id);
	element.style.visibility = 'hidden';
	element.style.display = 'none';
},

/* Hide loading bar, show content and initialize mouse event listening after loading */
initOnLoad : function()
{
	if(document.getElementById(imf.conf_imageflow))
	{
		imf.hide(imf.conf_loading);
		imf.refresh(true);
		imf.show(imf.conf_images);
		if (imf.hide_slider === false)
		{
			imf.show(imf.conf_scrollbar);
		}
		imf.initMouseWheel();
		imf.initMouseDrag();
		imf.moveTo(5000);
	}
},

/* Refresh ImageFlow on window resize */
resize : function()
{
	if(document.getElementById(imf.conf_imageflow)) imf.refresh();
},

unload : function()
{
	if(navigator.userAgent.search(/msie/i)!= -1)
	{
		// nothing !!
	}
	else
	{
  		document = null;
	}
},

/* Handle the wheel angle change (delta) of the mouse wheel */
handle : function(delta)
{
	var change = false;
	switch (delta > 0)
	{
		case true:
			if(imf.caption_id >= 1)
			{
				imf.target = imf.target + imf.xstep;
				imf.new_caption_id = imf.caption_id - 1;
				change = true;
			}
			break;

		default:
			if(imf.caption_id < (imf.max-1))
			{
				imf.target = imf.target - imf.xstep;
				imf.new_caption_id = imf.caption_id + 1;
				change = true;
			}
			break;
	}

	/* Glide to next (mouse wheel down) / previous (mouse wheel up) image */
	if (change == true)
	{
		imf.glideTo(imf.target, imf.new_caption_id);
	}
},

/* Event handler for mouse wheel event */
wheel : 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) imf.handle(delta);
	if (event.preventDefault) event.preventDefault();
	event.returnValue = false;
},

addEventListener : function (el, event, func) {
	try {
		el.addEventListener(event, func, false);
	} catch (e) {
		try {
			el.detachEvent('on'+ event, func);
			el.attachEvent('on'+ event, func);
		} catch (e) {
			el['on'+ event] = func;
		}
	}
},

/* Initialize mouse wheel event listener */
initMouseWheel : function()
{
	if(window.addEventListener) imf.imageflow_div.addEventListener('DOMMouseScroll', imf.wheel, false);
	imf.imageflow_div.onmousewheel = imf.wheel;
},

/* This function is called to drag an object (= slider div) */
dragstart : function(element)
{
	imf.dragobject = element;
	imf.dragx = imf.posx - imf.dragobject.offsetLeft + imf.new_slider_pos;
},

/* This function is called to stop dragging an object */
dragstop : function()
{
	imf.dragobject = null;
	imf.dragging = false;
},

/* This function is called on mouse movement and moves an object (= slider div) on user action */
drag : function(e)
{
	imf.posx = document.all ? window.event.clientX : e.pageX;
	if(imf.dragobject != null)
	{
		imf.dragging = true;
		imf.new_posx = (imf.posx - imf.dragx) + imf.conf_slider_width;

		/* Make sure, that the slider is moved in proper relation to previous movements by the glideTo function */
		if(imf.new_posx < ( - imf.new_slider_pos)) imf.new_posx = - imf.new_slider_pos;
		if(imf.new_posx > (imf.scrollbar_width - imf.new_slider_pos)) imf.new_posx = imf.scrollbar_width - imf.new_slider_pos;

		var slider_pos = (imf.new_posx + imf.new_slider_pos);
		var step_width = slider_pos / ((imf.scrollbar_width) / (imf.max-1));
		var image_number = Math.round(step_width);
		var new_target = (image_number) * -imf.xstep;
		var new_caption_id = image_number;

		imf.dragobject.style.left = imf.new_posx + 'px';
		imf.glideTo(new_target, new_caption_id);
	}
},

/* Initialize mouse event listener */
initMouseDrag : function()
{
	document.onmousemove = imf.drag;
	document.onmouseup = imf.dragstop;

	/* Avoid text and image selection while dragging  */
	document.onselectstart = function ()
	{
		if (imf.dragging == true)
		{
			return false;
		}
		else
		{
			return true;
		}
	};
},

getKeyCode : function(event)
{
	event = event || window.event;
	return event.keyCode;
},

keyHandler : function(event)
{
	var charCode  = imf.getKeyCode(event);
	switch (charCode)
	{
		/* Right arrow key */
		case 39:
			imf.handle(-1);
			break;

		/* Left arrow key */
		case 37:
			imf.handle(1);
			break;
	}
}

};

imf.addEventListener(document, 'keydown', imf.keyHandler);
imf.addEventListener(window, 'load', imf.initOnLoad);
imf.addEventListener(window, 'unload', imf.unload);
imf.addEventListener(window, 'resize', imf.resize);

