/*  ContentFlow, version 1.0.2 
 *  (c) 2007 - 2010 Sebastian Kutsch
 *  <http://www.jacksasylum.eu/ContentFlow/>
 *
 *  ContentFlow is distributed under the terms of the MIT license.
 *  (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
 *
 *--------------------------------------------------------------------------*/
/* 
 * ============================================================
 * Global configutaion and initilization object
 * ============================================================
 */
var ContentFlowGlobal = {
	Flows: new Array,
	AddOns: {},
	scriptName: 'contentflow.js',
	scriptElement:  null,
	Browser: new (function () {
		this.Opera = window.opera ? true : false;
		this.IE = document.all && !this.Opera ? true : false;
		this.IE6 = this.IE && typeof(window.XMLHttpRequest) == "undefined" ? true : false;
		this.IE8 = this.IE && typeof(document.querySelectorAll) != "undefined" ? true : false;
		this.IE7 = this.IE && ! this.IE6 && !this.IE8 ? true : false;
		this.WebKit = /WebKit/i.test(navigator.userAgent) ? true : false,
		this.iPhone = /iPhone|iPod/i.test(navigator.userAgent)? true : false;
		this.Chrome = /Chrome/i.test(navigator.userAgent) ? true : false;
		this.Safari = /Safari/i.test(navigator.userAgent) && !this.Chrome ? true : false;
		this.Konqueror = navigator.vendor == "KDE" ? true : false;
		this.Konqueror4 = this.Konqueror && /native code/.test(document.getElementsByClassName) ? true : false;
		this.Gecko = !this.WebKit && navigator.product == "Gecko" ? true : false;
		this.Gecko19 = this.Gecko && Array.reduce ? true : false;
	})(),

	getAddOnConf: function(name) {
		if(this.AddOns[name])
			return this.AddOns[name].conf;
		else
			return {};
	},

	setAddOnConf: function (name, conf) {
		this.AddOns[name].setConfig(conf);
	},

	getScriptElement:function (scriptName) {
		var regex = new RegExp(scriptName);
		var scripts = document.getElementsByTagName('script');
		for (var i=0; i<scripts.length; i++) {
			if (scripts[i].src && regex.test(scripts[i].src))
				return scripts[i];
		}
		return '';
	},

	getScriptPath: function (scriptElement, scriptName) {
		var regex = new RegExp(scriptName+".*");
		return scriptElement.src.replace(regex, '');
	},

	addScript: function  (path) {
		if (this.Browser.IE || this.Browser.WebKit || this.Browser.Konqueror) {
			document.write('<script type="text/javascript" src="'+path+'"><\/script>');
		}
		else {
			var script = document.createElement('script');
			script.src = path;
			script.setAttribute('type', 'text/javascript');
			document.getElementsByTagName('head')[0].appendChild(script);
		}
	},

	addScripts: function  (basePath, filenames) {
		for (var i=0; i<filename.length; i++)
			this.addScript(basepath+filenames[i]);
	},

	addStylesheet: function (path) {
		if (this.Browser.Gecko19) {
			var link = document.createElement('link');
			link.setAttribute('rel', 'stylesheet');
			link.setAttribute('href', path);
			link.setAttribute('type', 'text/css');
			link.setAttribute('media', 'screen');
			document.getElementsByTagName('head')[0].appendChild(link);
		}
		else {
			document.write('<link rel="stylesheet" href="'+path+'" type="text/css" media="screen" />');
		}

	},

	addStylesheets: function  (basePath, filenames) {
		for (var i=0; i<filename.length; i++)
			this.addStylesheet(basepath+filenames[i]);
	},

	initPath: function () {
		/* get / set basic values */
		this.scriptElement = this.getScriptElement(this.scriptName);
		if (!this.scriptElement) {
			this.scriptName = 'contentflow_src.js';
			this.scriptElement = this.getScriptElement(this.scriptName);
		}

		this.BaseDir = this.getScriptPath(this.scriptElement, this.scriptName) ;
		if (!this.AddOnBaseDir) this.AddOnBaseDir = this.BaseDir;
		if (!this.CSSBaseDir) this.CSSBaseDir = this.BaseDir;
	},

	init: function () {
		/* add default stylesheets */
		this.addStylesheet(this.CSSBaseDir+'contentflow.css');
		this.addStylesheet(this.CSSBaseDir+'mycontentflow.css');    // FF2: without adding a css-file FF2 hangs on a reload.
		//      I don't have the slidest idea why
		//      Could be timing problem
		this.loadAddOns = new Array();
		/* add AddOns scripts */
		if (this.scriptElement.getAttribute('load')) {
			var AddOns = this.loadAddOns = this.scriptElement.getAttribute('load').replace(/\ +/g,' ').split(' ');
			for (var i=0; i<AddOns.length; i++) {
				if (AddOns[i] == '') continue;
				//if (AddOns[i] == 'myStyle') {
				//this.addStylesheet(this.BaseDir+'mycontentflow.css');
				//continue;
				//}
				this.addScript(this.AddOnBaseDir+'ContentFlowAddOn_'+AddOns[i]+'.js');
			}
		}

		/* ========== ContentFlow auto initialization on document load ==========
         * thanks to Dean Edwards
         * http://dean.edwards.name/weblog/2005/02/order-of-events/
         */
		var CFG = this;

		/* for Mozilla, Opera 9, Safari */
		if (document.addEventListener) {
			/* for Safari */
			if (this.Browser.WebKit) {
				var _timer = setInterval(function() {
					if (/loaded|complete/.test(document.readyState)) {
						clearInterval(_timer);
						CFG.onloadInit(); // call the onload handler
					}
				}, 10);
			}
			else {
				document.addEventListener("DOMContentLoaded", CFG.onloadInit, false);
			}
		}
		else if (this.Browser.IE) {
			document.write("<script id=__ie_cf_onload defer src=javascript:void(0)><\/script>");
			var script = document.getElementById("__ie_cf_onload");
			script.onreadystatechange = function() {
				if (this.readyState == "complete") {
					CFG.onloadInit(); // call the onload handler
				}
			};
		}

		/* for all other browsers */
		window.addEvent('load', CFG.onloadInit, false);

	/* ================================================================== */

	},

	onloadInit: function () {
		// quit if this function has already been called
		if (arguments.callee.done) return;
		for (var i=0; i< ContentFlowGlobal.loadAddOns.length; i++) {
			var a = ContentFlowGlobal.loadAddOns[i];
			if (!ContentFlowGlobal.AddOns[a]) {
				var CFG = ContentFlowGlobal;
				window.setTimeout( CFG.onloadInit, 10);
				return;
			}
		}
		// flag this function so we don't do the same thing twice
		arguments.callee.done = true;
        
		/* fix for mootools */
		if (window.Element && Element.implement && document.all && !window.opera) {
			for (var prop in window.CFElement.prototype) {
				if(!window.Element.prototype[prop]) {
					var implement = {};
					implement[prop] = window.CFElement.prototype[prop];
					Element.implement(implement);
				}
			}
		}

		/* init all manualy created flows */
		for (var i=0; i< ContentFlowGlobal.Flows.length; i++) {
			ContentFlowGlobal.Flows[i].init();
		}

		/* init the rest */
		var divs = document.getElementsByTagName('div');
			DIVS: for (var i = 0; i < divs.length; i++) {
				if (divs[i].className.match(/\bContentFlow\b/)) {
					for (var j=0; j<ContentFlowGlobal.Flows.length; j++) {
						if (divs[i] == ContentFlowGlobal.Flows[j].Container) continue DIVS;
					}
					var CF = new ContentFlow(divs[i],{}, false);
					CF.init();
				}
			}
	}

};

ContentFlowGlobal.initPath();


/*
 * ============================================================
 * ContentFlowAddOn
 * ============================================================
 */
var ContentFlowAddOn = function (name, methods, register) {
	if (typeof register == "undefined" || register != false)
		ContentFlowGlobal.AddOns[name] = this;
        
	this.name = name;
	if (!methods) methods = {};
	this.methods = methods;
	this.conf = {};
	if (this.methods.conf) {
		this.setConfig(this.methods.conf);
		delete this.methods.conf;
	}


	this.scriptpath = ContentFlowGlobal.AddOnBaseDir;
	if (methods.init) {
		var init = methods.init.bind(this);
		init(this);
	}
};

ContentFlowAddOn.prototype = {
	Browser: ContentFlowGlobal.Browser,

	addScript: ContentFlowGlobal.addScript,
	addScripts: ContentFlowGlobal.addScripts,

	addStylesheet: function (path) {
		if (!path)
			path = this.scriptpath+'ContentFlowAddOn_'+this.name+'.css';
		ContentFlowGlobal.addStylesheet(path);
	},
	addStylesheets: ContentFlowGlobal.addStylesheets,

	setConfig: function (conf) {
		for (var c in conf) {
			this.conf[c] = conf[c];
		}
	},

	_init: function (flow) {
		if (this.methods.ContentFlowConf) {
			flow.setConfig(this.methods.ContentFlowConf);
		}
	}


};



/* 
 * ============================================================
 * ContentFlowGUIElement
 * ============================================================
 */

var ContentFlowGUIElement = function (CFobj, element) {
	element.setDimensions = function () {
		this.dimensions = this.getDimensions();
		this.center = {
			x: this.dimensions.width/2,
			y:this.dimensions.height/2
		};
		this.position = this.findPos();
	};
	element.addObserver = function (eventName, method) {
		var m = this.eventMethod = method.bind(CFobj);
		this.observedEvent = eventName;
		this.addEvent(eventName, m, false);
	};
    
	element.makeDraggable = function (onDrag, beforeDrag, afterDrag) {

		this.stopDrag = function(event) {
			if (!event) var event = window.event;
			if (this.Browser.iPhone)  {
				window.removeEvent('touchemove', onDrag, false);
				if (!this.ontochmove) {
					var t = event.target;
					if (t.firstChild) t = t.firstChild;
					var e = document.createEvent('MouseEvents');
					e.initEvent('click', true, true);
					t.dispatchEvent(e);
				}
			}
			else {
				window.removeEvent('mousemove', onDrag, false);
			}
			afterDrag(event);
		}.bind(this);

		this.initDrag = function (event) {
			if (!event) var event = window.event;
			var e = event;
			if (event.touches) e = event.touches[0];

			this.mouseX = e.clientX;
			this.mouseY = e.clientY;

			beforeDrag(event);

		}.bind(this);

		this.startDrag = function (event) {
			if (!event) var event = window.event;

			var stopDrag = this.stopDrag;

			if (this.Browser.iPhone)  {
				var s = this;
				s.ontouchmove = false
				window.addEvent('touchmove', function (e) {
					s.ontouchmove = true;
					onDrag(e);
				}, false);
				event.preventDefault();
				window.addEvent('touchend', stopDrag, false);
			}
			else {
				window.addEvent('mousemove', onDrag, false);
				window.addEvent('mouseup', stopDrag, false);
			}
			if(event.preventDefault) {
				event.preventDefault()
			}

		}.bind(this);

		var startDrag = this.startDrag;
		if (this.Browser.iPhone)  {
			this.addEventListener('touchstart', startDrag, false);
		}
		else {
			this.addEvent('mousedown', startDrag, false);
		}
        
	};

	element.Browser = ContentFlowGlobal.Browser;
	$CF(element).setDimensions();
	return element;
};


/* 
 * ============================================================
 * ContentFlowItem
 * ============================================================
 */
var ContentFlowItem  = function (CFobj, element, index) {
	this.CFobj = CFobj;
	this._activeElement = CFobj.conf.activeElement;
	this.pre = null;
	this.next = null;
	/*
     * ==================== item click events ====================
     * handles the click event on an active and none active item
     */

	this.clickItem = function (event) {
		if(!event) var event = window.event;
		var el = event.target ? event.target : event.srcElement;
		var index = el.itemIndex ? el.itemIndex : el.parentNode.itemIndex;
		var item = this.items[index];
		if (this._activeItem == item) {
			this.conf.onclickActiveItem(item);
		}
		else {
			if (this.conf.onclickInactiveItem(item) != false ) this.moveToIndex(index);
		}
	}.bind(CFobj),

	this.setIndex = function (index) {
		this.index = index;
		this.element.itemIndex = index;
	};
	this.getIndex = function () {
		return this.index;
	};


	/* generate deault HTML structure if item is an image */
	if ($CF(element).nodeName == "IMG") {
		var el = document.createElement('div');
		el.className = "item";

		var cont = element.parentNode.replaceChild( el, element);
		cont.className = "content";
		el.appendChild(cont);

		if (element.title) {
			var cap = document.createElement('div');
			cap.className = "caption";
			cap.innerHTML = element.title;
			el.appendChild(cap);
		}
		element = el;
	}

	/* create item object */
	this.element = $CF(element);
	this.item = element;
	if (typeof index != "undefined") this.setIndex(index);
	this.content = this.element.getChildrenByClassName('content')[0];
	this.caption = this.element.getChildrenByClassName('caption')[0];
	this.label = this.element.getChildrenByClassName('label')[0];

	/* if content is image set properties */
	if (this.content.nodeName == "IMG") {
		CFobj._imagesToLoad++;

		var foobar = function () {
			CFobj._imagesToLoad--;
			this.image = this.content;
			this.setImageFormat(this.image);
			if ( CFobj.conf.reflectionHeight > 0) {
				this.addReflection();
			}
			this.initClick();
			CFobj._addItemCueProcess(true);
		}.bind(this);

//		if (this.content.complete && this.content.width > 0)
//			window.setTimeout(foobar, 100);
//		else
			if (!this.content.onload) { //this.Browser.IE && 
			var self = this;
			var t = window.setInterval( function () {
				if (self.content.complete && self.content.width > 0) {
					window.clearInterval(t);
					foobar();
				}
			}, 10);
		}
		else
			this.content.onload = window.setTimeout(foobar, 100);
	}
	else {
		this.initClick();
		CFobj._addItemCueProcess(true);
	}

};

ContentFlowItem.prototype = {
    
	Browser: ContentFlowGlobal.Browser,

	makeActive: function () {
		this.element.addClassName('active');
		this.CFobj.conf.onMakeActive(this);
	},
    
	makeInactive: function () {
		this.element.removeClassName('active');
		this.CFobj.conf.onMakeInactive(this);
	},

	initClick: function () {
		var cItem = this.clickItem;
		this[this._activeElement].addEvent('click', cItem, false);
	},
    
	setImageFormat: function (img) {
		if (this.Browser.IE6 || this.Browser.IE7) img.style.width = "auto";
		img.origProportion =  img.width / img.height;
		img.setAttribute('origProportion', img.width / img.height);
		if (this.Browser.IE6 || this.Browser.IE7) img.style.width = "";
		//img.origWidth = img.width;
		//img.origHeight = img.height;
		if (img.origProportion <= 1)
			img.addClassName('portray');
		else
			img.addClassName('landscape');
	},

	/*
     * add reflection to item
     */
		addReflection: function(){}
//	addReflection: function() {
//		var CFobj = this.CFobj;
//		var reflection;
//		var image = this.content;
//
//
//		if (this.Browser.IE) {
//			var filterString = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)';
//			if (CFobj._reflectionColorRGB) {
//				// transparent gradient
//				if (CFobj.conf.reflectionColor == "transparent") {
//					var RefImg = reflection = this.reflection = document.createElement('img');
//					reflection.src = image.src;
//				}
//				// color gradient
//				else {
//					reflection = this.reflection = document.createElement('div');
//					var RefImg = document.createElement('img');
//					RefImg.src = image.src;
//					reflection.width = RefImg.width;
//					reflection.height = RefImg.height;
//					RefImg.style.width = '100%';
//					RefImg.style.height = '100%';
//					var color = CFobj._reflectionColorRGB;
//					reflection.style.backgroundColor = '#'+color.hR+color.hG+color.hB;
//					reflection.appendChild(RefImg);
//				}
//				filterString += ' progid:DXImageTransform.Microsoft.Alpha(opacity=0, finishOpacity=50, style=1, finishX=0, startY='+CFobj.conf.reflectionHeight*100+' finishY=0)';
//			} else {
//				var RefImg = reflection = this.reflection = document.createElement('img');
//				reflection.src = image.src;
//			}
//			// crop image (streches and crops (clip on default dimensions), original proportions will be restored through CSS)
//			filterString += ' progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22='+1/CFobj.conf.reflectionHeight+')';
//
//			if (ContentFlowGlobal.Browser.IE6) {
//				if (image.src.match(/\.png$/) ) {
//					image.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )";
//					image.filterString = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )";
//					filterString += " progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )";
//					image.origSrc = image.src;
//					image.src='img/blank.gif';
//					RefImg.src="img/blank.gif";
//				}
//			}
//
//			reflection.filterString = filterString;
//			RefImg.style.filter = filterString;
//
//		} else {
//			if (CFobj._reflectionWithinImage)
//				var canvas = this.canvas = $CF(document.createElement('canvas'));
//			else
//				var canvas = reflection = this.reflection = document.createElement('canvas');
//
//			if (canvas.getContext) {
//				if (CFobj._reflectionWithinImage) {
//					for (var i=0; i <image.attributes.length; i++) {
//						canvas.setAttributeNode(image.attributes[i].cloneNode(true));
//					}
//				}
//
//				var context = canvas.getContext("2d");
//
//				/* calc image size */
//				var max = CFobj.maxHeight;
//				var size = CFobj._scaleImageSize(this, {
//					width: max,
//					height: max
//				}, max)
//				var width = size.width;
//				var height = size.height;
//
//				// overwrite default height and width
//				if (CFobj._reflectionWithinImage) {
//					canvas.width = width;
//					canvas.height = height;
//					this.setImageFormat(canvas);
//					canvas.height = height * (1 + CFobj.conf.reflectionHeight + CFobj.conf.reflectionGap);
//
//				}
//				else {
//					canvas.width = width;
//					canvas.height = height * CFobj.conf.reflectionHeight;
//				}
//
//				context.save(); /* save default context */
//
//				/* draw image into canvas */
//				if (CFobj._reflectionWithinImage) {
//					context.drawImage(image, 0, 0, width, height);
//				}
//
//				/* mirror image by transformation of context and image drawing */
//				if (CFobj._reflectionWithinImage) {
//					var contextHeight = height * ( 1 + CFobj.conf.reflectionGap/2) * 2;
//				}
//				else {
//					var contextHeight = image.height;
//				}
//				// -1 for FF 1.5
//				contextHeight -= 1;
//
//				context.translate(0, contextHeight);
//				context.scale(1, -1);
//				/* draw reflection image into canvas */
//				context.drawImage(image, 0, 0, width, height);
//
//				/* restore default context for simpler further canvas manupulation */
//				context.restore();
//
//				if (CFobj._reflectionColorRGB) {
//					var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
//
//					var alpha = [0, 0.5, 1];
//					if (CFobj._reflectionColor == "transparent") {
//						context.globalCompositeOperation = "destination-in";
//						alpha = [1, 0.5, 0];
//					}
//
//					var red = CFobj._reflectionColorRGB.iR;
//					var green = CFobj._reflectionColorRGB.iG;
//					var blue = CFobj._reflectionColorRGB.iB;
//					if (CFobj._reflectionWithinImage) {
//						gradient.addColorStop(0, 'rgba('+red+','+green+','+blue+','+alpha[0]+')');
//						gradient.addColorStop(height/canvas.height, 'rgba('+red+','+green+','+blue+','+alpha[0]+')');
//						gradient.addColorStop(height/canvas.height, 'rgba('+red+','+green+','+blue+','+alpha[1]+')');
//					}
//					else {
//						gradient.addColorStop(0, 'rgba('+red+','+green+','+blue+','+alpha[1]+')');
//					}
//					gradient.addColorStop(1, 'rgba('+red+','+green+','+blue+','+alpha[2]+')');
//
//					context.fillStyle = gradient;
//					context.fillRect(0, 0, canvas.width, canvas.height);
//
//				}
//
//				if (CFobj._reflectionWithinImage) {
//					image.parentNode.replaceChild(canvas, image);
//					this.content = canvas;
//					this.origContent = canvas;
//					delete this.image;// = true;
//
//				}
//
//			} else {
//				CFobj._reflectionWithinImage = false;
//				delete this.reflection;
//			}
//
//		}
//		if (reflection) {
//			reflection.className = "reflection";
//			this.element.appendChild(reflection);
//
//			/* be shure that caption is last child */
//			if (this.caption) this.element.appendChild(this.caption);
//		}
//
//	}


};

/*
 * ============================================================
 * ContentFlow
 * ============================================================
 */
var ContentFlow = function (container, config) {

	if (container) {
		ContentFlowGlobal.Flows.push(this);
		this.Container = container;
		this._userConf = config?config:{};
		this.conf = {};
		this._loadedAddOns = new Array();
	} else {
		throw ('ContentFlow ERROR: No flow container node or id given');
	}

};

ContentFlow.prototype = {
	_imagesToLoad: 0,
	_activeItem: 0,
	_currentPosition: 0,
	_targetPosition: 0,
	_stepLock: false,
	_millisecondsPerStep: 40,
	_reflectionWithinImage: true,
	Browser: ContentFlowGlobal.Browser,
    
	_defaultConf: {
		/* pre conf */
		useAddOns: 'none', // all, none, [AddOn1, ... , AddOnN]

		biggestItemPos: 0,
		loadingTimeout: 30000, //milliseconds
		activeElement: 'content', // item or content

		maxItemHeight: 0,
		scaleFactor: 1,
		scaleFactorLandscape: 1.33,
		scaleFactorPortrait: 1.0,
		fixItemSize: false,
		relativeItemPosition: "center center", // align top/above, bottom/below, left, right, center of position coordinate

		circularFlow: true,
		verticalFlow: false,
		visibleItems: 2,
		endOpacity: 1,
		startItem:  "center",
		scrollInFrom: "pre",

		flowSpeedFactor: 1.0,
		flowDragFriction: 1.0,
		scrollWheelSpeed: 1.0,
		keys: {
			13: function () {
				this.conf.onclickActiveItem(this._activeItem)
			},
			37: function () {
				this.moveTo('pre')
			},
			38: function () {
				this.moveTo('visibleNext')
			},
			39: function () {
				this.moveTo('next')
			},
			40: function () {
				this.moveTo('visiblePre')
			}
		},

		reflectionColor: "transparent", // none, transparent or hex RGB CSS style #RRGGBB
		reflectionHeight: 0.5,          // float (relative to original image height)
		reflectionGap: 0.0,

		/* ==================== actions ==================== */

		onInit: function () {},

		onclickInactiveItem: function (item) {},

		onclickActiveItem: function (item) {
			var url, target;

			if (url = item.content.getAttribute('rel')) {
				target = item.content.getAttribute('target');
			}

//			if (url = item.content.getAttribute('href')) {
//				target = item.content.getAttribute('target');
//			}
//			else if (url = item.element.getAttribute('href')) {
//				target = item.element.getAttribute('target');
//			}
//			else if (url = item.content.getAttribute('src')) {
//				target = item.content.getAttribute('target');
//			}

			if (url) {
				if (target)
					window.open(url, target).focus();
				else
					window.location.href = url;
			}else{
				var content = item.content;
				if (content.getAttribute('src')) {

					if (content.getAttribute('class')) {
						var ic = content.getAttribute('class').split(' ');
					}else{
						var ic = content.className.split(' ');
					}
					if (item.content.getAttribute('href')) {
						item.element.href = item.content.getAttribute('href');
					}
					else if (! item.element.getAttribute('href')) {
						item.element.href = content.getAttribute('src');
					}
					if (item.caption)
						item.element.setAttribute ('title', item.caption.innerHTML);
					$(item.element).fancybox({
						'showCloseButton': false,
						'padding': (ic[1] == 'landscape')?190:235,
						'titleShow':false,
						'autoScale':false,
						'margin': 50,
						'frameType': ic[1],
						'hideOnContentClick': true
						,
						'overlayOpacity': 1,
						'overlayColor' : '#000'
					}).click();
				}
			}
		},

		onMakeInactive: function (item) {},

		onMakeActive: function (item) {
			carousel.scroll(item.index-2);
		},

		onReachTarget: function(item) {},

		onMoveTo: function(item) {},

		//onDrawItem: function(item, relativePosition, relativePositionNormed, side, size) {},
		onDrawItem: function(item) {},
        
		onclickPreButton: function (event) {
			this.moveToIndex('pre');
			return Event.stop(event);
		},
        
		onclickNextButton: function (event) {
			this.moveToIndex('next');
			return Event.stop(event);
		},

		/* ==================== calculations ==================== */

		calcStepWidth: function(diff) {
			var vI = this.conf.visibleItems;
			var items = this.items.length;
			items = items == 0 ? 1 : items;
			if (Math.abs(diff) > vI) {
				if (diff > 0) {
					var stepwidth = diff - vI;
				} else {
					var stepwidth = diff + vI;
				}
			} else if (vI >= this.items.length) {
				var stepwidth = diff / items;
			} else {
				var stepwidth = diff * ( vI / items);
			//var stepwidth = diff/absDiff * Math.max(diff * diff,Math.min(absDiff,0.3)) * ( vI / this.items.length);
			//var stepwidth = this.flowSpeedFactor * diff / this.visibleItems;
			//var stepwidth = this.flowSpeedFactor * diff * ( this.visibleItems / this.items.length)
			//var stepwidth = this.flowSpeedFactor * diff / this._millisecondsPerStep * 2; // const. speed
			}
			return stepwidth;
		},
        
		calcSize: function (item) {
			var rP = item.relativePosition;
			//var rPN = relativePositionNormed;
			//var vI = this.conf.visibleItems;

			var h = 1/(Math.abs(rP)+1);
			var w = h;
			return {
				width: w,
				height: h
			};
		},

		calcCoordinates: function (item) {
			var rP = item.relativePosition;
			//var rPN = item.relativePositionNormed;
			var vI = this.conf.visibleItems;

			var f = 1 - 1/Math.exp( Math.abs(rP)*0.75);
			var x =  item.side * vI/(vI+1)* f;
			var y = 1;

			return {
				x: x,
				y: y
			};
		},

		/*
        calcRelativeItemPosition: function (item) {
            var x = 0;
            var y = -1;
            return {x: x, y: y};
        },
        */

		calcZIndex: function (item) {
			return -Math.abs(item.relativePositionNormed);
		},

		calcFontSize: function (item) {
			return item.size.height;
		},
   
		calcOpacity: function (item) {
			return Math.max(1 - ((1 - this.conf.endOpacity ) * Math.sqrt(Math.abs(item.relativePositionNormed))), this.conf.endOpacity);
		}
	},

	/* ---------- end of defaultConf ---------- */

    
	/*
     * ==================== index helper methods ====================
     */

	/*
     * checks if index is within the index range of the this.items array
     * returns a value that is within this range
     */
	_checkIndex: function (index) {
		index = Math.max(index, 0);
		index = Math.min(index, this.itemsLastIndex);
		return index;
	},

	/*
     * sets the object property itemsLastIndex
     */
	_setLastIndex: function () {
		this.itemsLastIndex = this.items.length - 1;
	},

	/*
*/
	_getItemByIndex: function (index) {
		return this.items[this._checkIndex(index)];
	},

	_getItemByPosition: function (position) {
		return this._getItemByIndex(this._getIndexByPosition(position));
	},

	/* returns the position of an item-index relative to current position */
	_getPositionByIndex: function(index) {
		if (!this.conf.circularFlow) return this._checkIndex(index);
		var cI = this._getIndexByPosition(this._currentPosition);
		var dI = index - cI;
		if (Math.abs(dI) > dI+this.items.length)
			dI += this.items.length;
		else if (Math.abs(dI) > (Math.abs(dI-this.items.length)))
			dI -= this.items.length;

		return this._currentPosition + dI;

	},

	/* returns the index an item at position p would have */
	_getIndexByPosition: function (position) {
		if (position < 0) var mod = 0;
		else var mod = 1;

		var I = (Math.round(position) + mod) % this.items.length;
		if (I>0) I -= mod;
		else if(I<0) I += this.items.length - mod;
		else if(position<0) I = 0;
		else I = this.items.length - 1;

		return I;
	},

	_getIndexByKeyWord: function (keyword, relativeTo, check) {
		if (relativeTo)
			var index = relativeTo;
		else if (this._activeItem)
			var index = this._activeItem.index;
		else
			var index = 0;

		if (isNaN(keyword)) {
			switch (keyword) {
				case "first":
				case "start":
					index = 0;
					break;
				case "last":
				case "end":
					index = this.itemsLastIndex;
					break;
				case "middle":
				case "center":
					index = Math.round(this.itemsLastIndex/2);
					break;
				case "right":
				case "next":
					index += 1;
					break;
				case "left":
				case "pre":
				case "previous":
					index -= 1;
					break;
				case 'visible':
				case 'visiblePre':
				case 'visibleLeft':
					index -= this.conf.visibleItems;
					break;
				case 'visibleNext':
				case 'visibleRight':
					index += this.conf.visibleItems;
					break;
				default:
					index = index;
			}
		}
		else {
			index = keyword;
		}
		if (check != false)
			index = this._checkIndex(index);
        
		return index;
	},


	_setCaptionLabel: function (index) {
		if(this.Position && !this.Slider.locked)
			this.Position.setLabel(index);
		this._setGlobalCaption();
	},


	/*
     * ==================== public methods ==================== 
     */
	getAddOnConf: function(name) {
		return ContentFlowGlobal.getAddOnConf(name);
	},

	setAddOnConf: function(name, conf) {
		ContentFlowGlobal.setAddOnConf(name, conf);
	},


	/*
     * calls _init() if ContentFlow has not been initialized before
     * needed if ContentFlow is not automatically initialized on window.load
     */
	init: function () {
		if(this.isInit) return;
		this._init();
	},

	/*
     * parses configuration object and initializes configuration values
     */
	setConfig: function(config) {
		if (!config) return;
		var dC = this._defaultConf;
		for (var option in config) {
			if (dC[option] == "undefined" ) continue;
			switch (option) {
				case "scrollInFrom":
				case "startItem":
					if (typeof(config[option]) == "number"  || typeof(config[option]) == "string") {
						//this["_"+option] = config[option];
						this.conf[option] = config[option];
					}
					break;
				default:
					if (typeof(dC[option] == config[option])) {
						//this["_"+option] = config[option];
						if (typeof config[option] == "function") {
							this.conf[option] = config[option].bind(this);
						}
						else {
							this.conf[option] = config[option];
						}
					}
			}
		}
		switch (this.conf.reflectionColor) {
			case this.conf.reflectionColor.search(/#[0-9a-fA-F]{6}/)>= 0?this.conf.reflectionColor:
				this.conf.reflectionColor+"x":
				this._reflectionColorRGB = {
					hR: this.conf.reflectionColor.slice(1,3),
					hG: this.conf.reflectionColor.slice(3,5),
					hB: this.conf.reflectionColor.slice(5,7),
					iR: parseInt(this.conf.reflectionColor.slice(1,3), 16),
					iG: parseInt(this.conf.reflectionColor.slice(3,5), 16),
					iB: parseInt(this.conf.reflectionColor.slice(5,7), 16)
				};
				break;
			case "none":
			case "transparent":
			default:
				this._reflectionColor = "transparent";
				this._reflectionColorRGB = {
					hR: 0,
					hG: 0,
					hB:0,
					iR: 0,
					iG: 0,
					iB:0
				};
				break;
		}
		if (this.items) {
			if (this.conf.visibleItems <  0)
				this.conf.visibleItems = Math.round(Math.sqrt(this.items.length));
			this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1);
		}

		if (this.conf.relativeItemPosition) {
			var calcRP = {
				x: {
					left: function(size) {
						return -1
					},
					center: function(size) {
						return 0
					},
					right: function(size) {
						return 1
					}
				},
				y: {
					top: function(size) {
						return -1
					},
					center: function(size) {
						return 0
					},
					bottom: function(size) {
						return 1
					}
				}
			};

			var iP = this.conf.relativeItemPosition;
			iP = iP.replace(/above/,"top").replace(/below/,"bottom");
			var x, y = null;
			x = iP.match(/left|right/);
			y = iP.match(/top|bottom/);
			c = iP.match(/center/);
			if (!x) {
				if (c) x = "center";
				else x = "center";
			}
			if (!y) {
				if (c) y = "center";
				else y = "top";
			}
			var calcX = calcRP.x[x];
			var calcY = calcRP.y[y];
			this.conf.calcRelativeItemPosition = function (item) {
				var x = calcX(item.size);
				var y = calcY(item.size);
				return {
					x: x,
					y: y
				};
			};
			this.conf.relativeItemPosition = null;
		}

		if (this._reflectionType && this._reflectionType != "clientside") {
			this.conf.reflectionHeight = 0;
		}

	},

	getItem: function (index) {
		return this.items[this._checkIndex(Math.round(index))];
	},

	/*
     * returns the index number of the active item
     */
	getActiveItem: function() {
		return this._activeItem;
	},

	/*
     * returns the number of items the flow contains
     */
	getNumberOfItems: function () {
		return this.items.length;
	},

	/*
     * reinitializes sizes.
     * called on window.resize
     */
	resize: function () {
		this._initSizes();
		this._initStep();
	},

	/*
     * scrolls flow to item i
     */
	moveToPosition: function (p, holdPos) {
		if (!this.conf.circularFlow) p = this._checkIndex(p);
		this._targetPosition = p;
		this.conf.onMoveTo(this._getItemByPosition(p));
		this._initStep(false, holdPos);
	},
	moveToIndex: function (index) {
		this._targetPosition = Math.round(this._getPositionByIndex(this._getIndexByKeyWord(index, this._activeItem.index, !this.conf.circularFlow)));
		this.conf.onMoveTo(this._getItemByPosition(this._targetPosition));
		this._initStep();
	},
	moveToItem: function (item) {
		var i;
		if (item.itemIndex) i = item.itemIndex;
		else i = item.index;
		this.moveToIndex(i);
	},
	moveTo: function (i) {
		if (typeof i == "object") this.moveToItem(i);
		else if (isNaN(i) || (i == Math.floor(i) && i < this.items.length) ) this.moveToIndex(i);
		else this.moveToPosition(i);
	},

	/*
     * initializes item and adds it at index position
     */
	_addItemCue: [],
	_addItemCueProcess: function (deleteFirst) {
		var c = this._addItemCue;
		if (deleteFirst == true)
			c.shift();
		if (c.length > 0 && ! c[0].p) {
			c[0].p = true;
			var self = this;
			var t = c.length > 5 ? 1 : 40;
			window.setTimeout(function () {
				self._addItem(c[0].el, c[0].i)
			}, t) ;
		}
	},
	addItem: function(el, index) {
		this._addItemCue.push({
			el: el,
			i: index,
			p: false
		});
		if (this._addItemCue.length == 1)
			this._addItemCueProcess();
	},

	_addItem: function(el, index) {
		if (typeof index == "string") {
			switch (index) {
				case "first":
				case "start":
					index = 0;
					break;
				case "last":
				case "end":
					index = isNaN(this.itemsLastIndex) ? 0 : this.itemsLastIndex;
					index += 1;
					break;
				default:
					index = this._getIndexByKeyWord(index);
			}
		}

		index = Math.max(index, 0);
		index = Math.min(index, this.itemsLastIndex + 1);
		index = isNaN(index) ? 0 : index;
        
		this.Flow.appendChild(el);

		/* init item after insertion. that way it's part of the document and all styles are applied */
		var item = new ContentFlowItem(this, el, index);
		if (this.items.length == 0 ) {
			this.resize();
			if (this.conf.circularFlow) {
				item.pre = item;
				item.next = item;
			}
		}
		else {
			if (index == this.itemsLastIndex + 1) {
				item.pre = this.items[this.itemsLastIndex];
				item.next = item.pre.next;
			}
			else {
				item.next = this.items[index];
				item.pre = item.next.pre;
			}
			if (item.pre) item.pre.next = item;
			if (item.next) item.next.pre = item;
		}
		this.items.splice(index,0, item);

		/* adjust item indices */
		for (var i = index; i < this.items.length; i++) {
			this.items[i].setIndex(i);
		}
		this._setLastIndex();

		if (this.conf.origVisibleItems < 0) {
			this.conf.visibleItems = Math.round(Math.sqrt(this.items.length));
		}
		this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1);

		/* adjust targetItem, currentPos so that current view does not change*/
		if (Math.round(this._getPositionByIndex(index)) <= Math.round(this._targetPosition)) {
			this._targetPosition++;
			if (!this.conf.circularFlow)
				this._targetPosition = Math.min(this._targetPosition, this.itemsLastIndex);
		}
		if (this._getPositionByIndex(index) <= this._currentPosition) {
			this._currentPosition++;
			if (!this.conf.circularFlow)
				this._currentPosition = Math.min(this._currentPosition, this.itemsLastIndex);
		}
        
		// avoid display errors (wrong sizing)
		var CF = this;
		window.setTimeout(function () {
			if(CF.items.length == 1 ) {
				CF._currentPosition = -0.01;
				CF._targetPosition = 0;
				CF.resize();
			}
			else {
				CF._initStep();
			}
		}, 100);

		return index;
        
	},
        
	/*
     * removes item at index position, cleans it up and returns it
     */
	rmItem: function(index) {
		if  (index == "undefined") index = this._activeItem.index;
		index = this._getIndexByKeyWord(index);
		if (!this.items[index]) return null;

		var item = this.items[index];

		if (item.pre) item.pre.next = item.next;
		if (item.next) item.next.pre = item.pre;
		this.items.splice(index,1);

		/* adjust item indices */
		for (var i = index ; i < this.items.length; i++) {
			this.items[i].setIndex(i);
		}
		this._setLastIndex();
        
		/* adjust targetItem, currentPos and activeItem so that current view does not change*/
		if (Math.round(this._getPositionByIndex(index)) < Math.round(this._targetPosition)) {
			this._targetPosition--;
			if (!this.conf.circularFlow)
				this._targetPosition = this._checkIndex(this._targetPosition);
		}
		if (this._getPositionByIndex(index) < this._currentPosition) {
			this._currentPosition--;
			if (!this.conf.circularFlow)
				this._currentPosition = this._checkIndex(this._currentPosition);
		}
		this._activeItem = this._getItemByPosition(this._currentPosition);

		/* remove item from DOM tree, take the next step and return removed item  */
		var removedItem = item.element.parentNode.removeChild(item.element);
		// avoid display errors (wrong sizing)
		var CF = this;
		window.setTimeout(function () {
			CF._initStep()
		}, 10);
		return removedItem;

	},


	/*
     * ==================== initialization ====================
     */
    

	/* -------------------- main init -------------------- */
	_init: function () {

		if (typeof(this.Container) == 'string') { // no node
			var container = document.getElementById(this.Container);
			if (container) {
				this.Container = container;
			} else {
				throw ('ContentFlow ERROR: No element with id \''+this.Container+'\' found!');
				return;
			}
		}
        
		/* ----------  reserve CSS namespace */

		$CF(this.Container).addClassName('ContentFlow');

		/* ---------- detect GUI elements */
		var flow = $CF(this.Container).getChildrenByClassName('flow')[0];
		if (!flow) {
			throw ('ContentFlow ERROR: No element with class\'flow\' found!');
			return;
		}
		this.Flow = new ContentFlowGUIElement(this, flow);

		var scrollbar = this.Container.getChildrenByClassName('scrollbar')[0];
		if (scrollbar) {
			this.Scrollbar = new ContentFlowGUIElement(this, scrollbar);
			var slider = this.Scrollbar.getChildrenByClassName('slider')[0];
			if (slider) {
				this.Slider = new ContentFlowGUIElement(this, slider);
				var position = this.Slider.getChildrenByClassName('position')[0];
				if (position) {
					this.Position = new ContentFlowGUIElement(this, position);
				}
			}

		}

		/* ----------  init configuration */
		this.setConfig(this._defaultConf);
		this._initAddOns(); /* init AddOns */
		this.setConfig(this._userConf);
        
		this._initSizes(); // ......


		/* ---------- init item lists ---------- */
		var items = this.Flow.getChildrenByClassName('item');

		this.items = new Array();
		for (var i=0; i<items.length; i++) {
			var item = this.items[i] = new ContentFlowItem(this, items[i], i);
			if (i > 0) {
				item.pre = this.items[i-1];
				item.pre.next = item;
			}
		}
		this._setLastIndex();
		if (this.conf.circularFlow && this.items.length > 0) {
			var s = this.items[0];
			s.pre = this.items[this.items.length-1];
			s.pre.next = s;
		}

		/* ----------  init GUI */
		this._initGUI();

		/* ---------- init start parameters ---------- */
		if (this._activeElement != "content")
			this._activeElement = "element";

		this.conf.origVisibleItems = this.conf.visibleItems;
		if (this.conf.visibleItems < 0) {
			this.conf.visibleItems = Math.round(Math.sqrt(this.items.length));
		}
		this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1);

		this._targetPosition = this._getIndexByKeyWord(this.conf.startItem, 0);

		var index = this._getIndexByKeyWord(this.conf.scrollInFrom, this._targetPosition);
		switch (this.conf.scrollInFrom) {
			case "next":
			case "right":
				index -= 0.5;
				break;
			case "pre":
			case "previous":
			case "left":
				index += 0.5;
				break;
		}
		this._currentPosition = index;
        

		/* ---------- wait till all images are loaded or
         * grace time is up to show all and take the first step  
        */
		var now = new Date();
		var cf = this;
		var timer = window.setInterval (
			function() {
				if ( cf._imagesToLoad == 0 || new Date() - now > cf._loadingTimeout ) {
					clearInterval(timer);

					cf._activeItem = cf.getItem(cf._currentPosition);
					if (cf._activeItem) {
						cf._activeItem.makeActive();
						cf._setCaptionLabel(cf._activeItem.index);
					}
                    
					cf.Flow.style.visibility = "visible"; // show flow after images are loaded
					if (cf.loadIndicator) cf.loadIndicator.style.display = "none";
					if (cf.Scrollbar) cf.Scrollbar.style.visibility = "visible";

					cf.resize();
					for (var i=0; i < cf._loadedAddOns.length; i++) {
						var a = ContentFlowGlobal.AddOns[cf._loadedAddOns[i]];
						if (a.methods.afterContentFlowInit)
							a.methods.afterContentFlowInit(cf);
					}
					cf.conf.onInit();
				}
			}, 10
			);
        
		this.isInit = true;

	},
    
	/* ---------- init AddOns ---------- */
	_initAddOns: function () {

		// get an array of names of all AddOns that should be used
		var loadAddOns = [];
		if (this._userConf.useAddOns) {
			if (typeof this._userConf.useAddOns == "string") {
				loadAddOns = this._userConf.useAddOns.split(" ");
			}
			else if (typeof this._userConf.useAddOns == "array") {
				loadAddOns = this._userConf.useAddOns;
			}
		}
		else if (this.Container.getAttribute("useAddOns")) {
			loadAddOns = this.Container.getAttribute("useAddOns").split(" ");
		}
		else {
			loadAddOns = this.conf.useAddOns.split(' ');
		}


		// check the names for keywords
		for (var i=0; i<loadAddOns.length; i++) {
			if (loadAddOns[i] == "none") {
				loadAddOns = new Array();
				break;
			}
			else if (loadAddOns[i] == "all") {
				loadAddOns = new Array();
				for (var AddOn in ContentFlowGlobal.AddOns)
					loadAddOns.push(AddOn);
				break;
			}
		}

		// init all AddOns that should be used and exist
		for (var i=0; i<loadAddOns.length; i++) {
			var AddOn = ContentFlowGlobal.AddOns[loadAddOns[i]];
			if (AddOn) {
				this._loadedAddOns.push(loadAddOns[i]);
				AddOn._init(this);
				this.Container.addClassName('ContentFlowAddOn_'+AddOn.name);
				if (AddOn.methods.onloadInit)
					AddOn.methods.onloadInit(this);
			}
		}

	},


	_initGUI: function () {
        
		// resize
		//if (!this.Browser.iPhone) {
		var resize = this.resize.bind(this);
		window.addEvent('resize', resize, false);
		//}
		//else {
		//var g = this;
		//window.addEvent('resize', function () {
		//g._initSizes();
		//g._initStep();
		//} , false);
		//}
        
		// pre and next buttons
		var divs = this.Container.getElementsByTagName('div');
		for (var i = 0; i < divs.length; i++) {
			if ($CF(divs[i]).hasClassName('preButton')) {
				var pre = divs[i];
				var mt = this.conf.onclickPreButton;
				pre.addEvent('click', mt, false);
			}
			else if (divs[i].hasClassName('nextButton')) {
				var next = divs[i];
				var mt = this.conf.onclickNextButton;
				next.addEvent('click', mt, false);
			}
		}

		// Container object
		// mousewheel
		if (this.conf.scrollWheelSpeed != 0) {
			var wheel = this._wheel.bind(this);
			if(window.addEventListener) this.Container.addEventListener('DOMMouseScroll', wheel, false);
			this.Container.onmousewheel = wheel;
		}

		// key strokes
		var key = this._keyStroke.bind(this);
		if (this.conf.keys && !this.Browser.iPhone) {
			if (document.addEventListener) {
				if (!this.Browser.Opera) {
					var mouseoverCheck = document.createElement('div');
					mouseoverCheck.addClassName('mouseoverCheckElement');
					this.Container.appendChild(mouseoverCheck);

					if (this.Browser.WebKit) {
						document.body.addEvent('keydown',  function (event) {
							if (mouseoverCheck.offsetLeft > 0) key(event) ;
						});
					} else {
						window.addEvent('keydown',  function (event) {
							if (mouseoverCheck.offsetLeft > 0) key(event) ;
						});
					}
				}
				else {
					this.Container.addEvent('keydown', key);
				}
			}
			else {
				this.Container.onkeydown = key;
			}
		}


		// Flow object
		if (this.conf.flowDragFriction > 0) {
			var onDrag = function (event) {
				var e = event;
				if (event.touches) e = event.touches[0];
				var mouseX = e.clientX;
				var mouseY = e.clientY;
                
				if (this.conf.verticalFlow) {
					var dist = mouseY - this.Flow.mouseY; // px / or px per sec because _dragFlow wil be called in shorter intervalls if draged fast
					var dim = this.Flow.dimensions.height;
				}
				else {
					var dist = mouseX - this.Flow.mouseX; // px / or px per sec because _dragFlow wil be called in shorter intervalls if draged fast
					var dim = this.Flow.dimensions.width;
				}
				var itemDist = (dist / dim )* (2*this.conf.visibleItems +1); // items
				var target = this._currentPosition - itemDist * 2*this.conf.visibleItems / this.conf.flowDragFriction ;

				this.Flow.mouseX = mouseX;
				this.Flow.mouseY = mouseY;

				this.moveToPosition(target, true);
			}.bind(this);

			var beforeDrag = function () {};

			var afterDrag = function (event) {
				var t = Math.round(this._targetPosition);
				if (Math.abs( t - this._currentPosition) > 0.001 )
					this.moveToPosition(t);
			}.bind(this);


			this.Flow.makeDraggable(onDrag, beforeDrag, afterDrag);
		}

		// Scrollbar Object
		if (this.Scrollbar) {
			var click = function(event) {
				if (!event) var event = window.event;

				if (!this.Scrollbar.clickLocked) {
					var mouseX = event.clientX;
					var positionOnScrollbar = mouseX - this.Scrollbar.position.left;
					var targetIndex = Math.round(positionOnScrollbar/this.Scrollbar.dimensions.width * this.itemsLastIndex);
					this.moveToIndex(targetIndex);
				}
				else
					this.Scrollbar.clickLocked = false;
			}.bind(this);
			this.Scrollbar.addObserver('click', click);
		}

		// Slider Object
		if (this.Slider) {

			if (this.Browser.IE6) {
				var virtualSlider = document.createElement('div');
				virtualSlider.className = 'virtualSlider';
				this.Slider.appendChild(virtualSlider);
			}

			// position slider on scrollbar
			this.Slider.setPosition = function (relPos) {
				relPos = relPos - Math.floor(relPos) + this._getIndexByPosition(Math.floor(relPos));
				if (Math.round(relPos) < 0)
					relPos = this.itemsLastIndex;
				else if (relPos <= 0)
					relPos = 0;
				else if (Math.round(relPos) > this.itemsLastIndex)
					relPos = 0;
				else if (relPos >= this.itemsLastIndex)
					relPos = this.itemsLastIndex;


				if (this.items.length > 1) {
					var sPos = (relPos / this.itemsLastIndex)* this.Scrollbar.dimensions.width;
				} else {
					var sPos = 0.5 * this.Scrollbar.dimensions.width;
				}
				this.Slider.style.left = sPos - this.Slider.center.x+ "px";
				this.Slider.style.top = this.Scrollbar.center.y - this.Slider.center.y +"px";

			}.bind(this);

			// make slider draggable
			var beforeDrag = function (event) {
				this.Scrollbar.clickLocked = true;
			}.bind(this);

			var onDrag = function (event) {
				var e = event;
				if (event.touches) e = event.touches[0];
				var selectedIndex = this._checkIndex((e.clientX - this.Scrollbar.position.left) / this.Scrollbar.dimensions.width * this.itemsLastIndex);
				this._targetPosition = this._getPositionByIndex(selectedIndex);
				this.Slider.setPosition(selectedIndex);
				if (this.Position) this.Position.setLabel(selectedIndex);
				this._initStep(true, true);
			}.bind(this);

			var afterDrag = function (event) {
				this._targetPosition = Math.round(this._targetPosition);
				this.conf.onMoveTo(this._getItemByPosition(this._targetPosition));
				this._initStep(true);
			}.bind(this);

			this.Slider.makeDraggable(onDrag, beforeDrag, afterDrag);
		}

                
		// Position object
		if (this.Position) {
			this.Position.setLabel = function (index) {
				index = this._checkIndex(Math.round(index));
				if (this.items && this.items[index].label)
					this.Position.innerHTML = this.items[index].label.innerHTML;
				else
					this.Position.innerHTML = index + 1;
			}.bind(this);
		}


		this.globalCaption = this.Container.getChildrenByClassName('globalCaption')[0];
		this.loadIndicator = this.Container.getChildrenByClassName('loadIndicator')[0];
	},

	/* ---------- init element sizes ---------- */
	_initSizes: function (x) {
		//if (this.Browser.Konqueror4 && x != true) {
		//var t = this;
		//window.setTimeout( function () { t._initSizes(true) }, 0);
		//return;
		//}

		// sets this.maxHeight
		this._initMaxHeight();

		var scrollbarHeight = this._initScrollbarSize();

		// reduce maxHeit if container has a fixed height
		if (!this.conf.verticalFlow && this.Container.style.height && this.Container.style.height != "auto")
			this.maxHeight -= scrollbarHeight;

		if (!this._activeItem) return;

		var mFS = this._findBiggestItem();

		var pF = this.Flow.findPos();

		/* set height / width of flow */
		if (this.conf.verticalFlow) {
			this.Flow.style.width = mFS.width.width+"px";
			this.Flow.style.height =3* mFS.width.width * (1 + this.conf.reflectionHeight + this.conf.reflectionGap) + "px";
		} else {
			this.Flow.style.height = mFS.height.height +(mFS.height.top - pF.top)+"px";
		}

		/* remove gap */
		var s = this.conf.verticalFlow ? mFS.width.width : mFS.height.height;
		var cH = s /(1 + this.conf.reflectionHeight + this.conf.reflectionGap);
		this.Flow.style.marginBottom = - (s - cH)+ "px";

		this.Flow.dimensions = this.Flow.getDimensions();

		if (!this.Browser.IE6) {
			if (this.conf.verticalFlow && this.Container.clientWidth < this.Flow.dimensions.width) {
			//this.Container.style.width = this.Flow.dimensions.width+"px";
			}
			else if (this.Container.clientHeight < this.Flow.dimensions.height) {
				this.Container.style.height = this.Flow.dimensions.height+"px";
			}
		}

		if (this.conf.verticalFlow) {
			this.Flow.center = {
				x: this.Flow.dimensions.height/2,
				y:mFS.width.width/2
			};
		} else {
			this.Flow.center = {
				x: this.Flow.dimensions.width/2,
				y:mFS.height.height/2
			};
		}

	},

	/* -------------------------------------------------------------------------------- */

	_initScrollbarSize: function () {
		var SB;
		var SL;
		var PO;
		if (SB = this.Scrollbar) {
			SB.setDimensions();
			var scrollbarHeight = SB.dimensions.height;

			if (SL = this.Slider) {
				SL.setDimensions();
				scrollbarHeight += SL.dimensions.height;

				if (PO = this.Position) {
                    
					var oldLabel = PO.innerHTML;
					var maxH = maxW = 0;
					PO.style.width = "auto";

					if (this.items) {
						for (var i=0; i < this.items.length; i++) {
							var item = this.items[i];
							if (item.label) {
								PO.innerHTML = item.label.innerHTML;
							}
							else {
								PO.innerHTML = item.index;
							}
							var h = PO.clientHeight;
							var w = PO.clientWidth;
							if ( h >  maxH) maxH = h;
							if ( w >  maxW) maxW = w;
						}
					}
					else {
						PO.innerHTML = "&nbsp;";
						maxH = PO.clientHeight;
						maxW = PO.clientWidth;
					}

					PO.innerHTML = oldLabel;

					PO.setDimensions();

					PO.style.width = maxW +"px";
					PO.style.left = (SL.dimensions.width - maxW)/2 + "px";

					var extraSpace = PO.position.top - SL.position.top;
					if (extraSpace > 0) {
						extraSpace += -SB.dimensions.height + maxH;
						SB.style.marginBottom = extraSpace + "px";
					}
					else {
						extraSpace *= -1;
						SB.style.marginTop = extraSpace + "px";
					}
					scrollbarHeight += extraSpace;
				}
			}
		}
		else {
			scrollbarHeight = 0;
		}

		return scrollbarHeight;

	},

	/* -------------------------------------------------------------------------------- */

	_initMaxHeight: function () {

		if (this.conf.verticalFlow) {
			var proportion = screen.width/screen.height;
			var Csd = this.Container.style.width;
			var Cdim = this.Container.clientWidth;
			var Fsd = this.Flow.style.width;
			var Fdim = this.Flow.clientWidth;
			var Fdim_o = this.Flow.clientHeight;
		} else {
			var proportion = screen.height/screen.width;
			var Csd = this.Container.style.height;
			var Cdim = this.Container.clientHeight;
			var Fsd = this.Flow.style.height;
			var Fdim = this.Flow.clientHeight;
			var Fdim_o = this.Flow.clientWidth;
		}

		// set height of container and flow
		if (this.ContainerOldDim)
			Csd = this.ContainerOldDim;
		if (this.FlowOldDim)
			Fsd = this.FlowOldDim;

		this.ContainerOldDim = "auto";
		this.FlowOldDim = "auto";
        

		/* calc maxHeight */
		if (this.conf.maxItemHeight <= 0) {

			this.maxHeight = Fdim_o / 3 * proportion/1 * this.conf.scaleFactor;  // divided by 3 because of left/center/right, yes it's a magic number

			if (this.conf.verticalFlow && (this.maxHeight == 0 || this.maxHeight > Fdim)) {
				this.maxHeight = Fdim;
			}

			if (Csd && Csd != "auto") {
				var gap = this.conf.verticalFlow  ? 0 : this.conf.reflectionGap;
				var rH = this.conf.verticalFlow  ? 0 : this.conf.reflectionHeight;
				this.maxHeight = Cdim/ (this.conf.scaleFactor* (1 + rH + gap));
				this.ContainerOldDim = Csd;
			}
			else if (Fsd && Fsd != "auto") {
				var gap = this.conf.verticalFlow  ? 0 : this.conf.reflectionGap;
				this.maxHeight = Fdim / (this.conf.scaleFactor* (1 + this.conf.reflectionHeight + gap));
				this.FlowOldDim = Fsd;
			}
		}
		else {
			this.maxHeight = this.conf.maxItemHeight;
		}
	},

	/* -------------------------------------------------------------------------------- */

	_findBiggestItem: function () {

		var currentItem = this._activeItem;

		var itemP = currentItem.pre;
		var itemN = currentItem.next;
		var mFS = maxFlowSize = {
			width: {
				width: 0,
				left: 0,
				height:0,
				top: 0,
				item: null,
				rI: 0
			},
			height: {
				width: 0,
				left: 0,
				height:0,
				top: 0,
				item: null,
				rI: 0
			}
		}


		var checkMax = function (item, rI) {
			var el = item.element;
			el.style.display = "block";
			var p = el.findPos();
			var h =  el.clientHeight;
			var w = el.clientWidth;
			if (h + p.top >= mFS.height.height + mFS.height.top) {
				mFS.height.height = h;
				mFS.height.top = p.top;
				mFS.height.item = item;
				mFS.height.rI = rI;
			}
			if (w + p.left >= mFS.width.width + mFS.width.left) {
				mFS.width.width = w;
				mFS.width.left = p.left;
				mFS.width.item = item;
				mFS.width.rI = rI;
			}
			el.style.display = "none";
		}

		var ocp = this._currentPosition;
		this._currentPosition = this.conf.visibleItems+1;

		// find the position with highest y-value
		for (var i=-this.conf.visibleItems; i <= this.conf.visibleItems; i++) {
			currentItem.element.style.display = "none";
			this._positionItem(currentItem, i);
			checkMax(currentItem, i);
		}

		// find the biggest item
		var index = mFS.height.rI;
		for (var i=0; i < this.items.length; i++) {
			var item = this.items[i];
			item.element.style.display = "none";
			this._positionItem(item, index);
			checkMax(item, index);
		}

		this._currentPosition = ocp;

		return mFS
	},



	/*
     * ==================== Key strok ====================
     */

	/*
     * handles keystroke events
     */
	_keyStroke: function(event) {
		if(!event) var event = window.event;

		if (event.which) {
			var keyCode = event.which;
		} else if (event.keyCode) {
			var keyCode = event.keyCode;
		}

		if (this.conf.keys[keyCode]) {
			this.conf.keys[keyCode].bind(this)();
			return Event.stop(event);
		}
		else {
			return true;
		}
	},
    
	/*
     * ==================== mouse wheel ====================
     * Event handler for mouse wheel event
     * http://adomas.org/javascript-mouse-wheel/
     */

	_wheel: function (event) {
		if (!event) var event = window.event; // MS
        
		var delta = 0;
		if (event.wheelDelta) {
			delta = event.wheelDelta/120;
		} else if (event.detail) {
			delta = -event.detail/3;
		}

		if (delta) {
			var target = this._targetPosition ;
			if (delta < 0 ) {
				target += (1 * this.conf.scrollWheelSpeed);
			} else {
				target -= (1 * this.conf.scrollWheelSpeed);
			}
			this.moveToPosition(Math.round(target));
		}

		return Event.stop(event);
	},


	/*
     * ==================== set global Caption ====================
     */
	_setGlobalCaption: function () {
		if (this.globalCaption) {
			this.globalCaption.innerHTML = '';
			if(this._activeItem && this._activeItem.caption)
				this.globalCaption.appendChild(this._activeItem.caption.cloneNode(true));
		}
	},

	/*
     * ==================== move items ====================
     */

	/*
     * intend to make a step 
     */
	_initStep: function (holdSlider, holdPos) {
		if (this.Slider) {
			if(holdSlider) {
				this.Slider.locked = true;
			} else {
				this.Slider.locked = false;
			}
		}
		this._holdPos = holdPos == true ? true : false;
		if (!this._stepLock) {
			this._stepLock = true;
			this._step();
		}
	},

	/*
     * make a step
     */
	_step: function () {

		var diff = this._targetPosition - this._currentPosition;
		var absDiff = Math.abs(diff);
		if ( absDiff > 0.001) { // till activeItem is nearly at position 0

			this._currentPosition += this.conf.flowSpeedFactor * this.conf.calcStepWidth(diff, absDiff, this.items.length, this.conf.visibleItems);

			var AI = this.items[(this._getIndexByPosition(this._currentPosition))];

			if (AI && AI != this._activeItem) {
				if (this._activeItem) this._activeItem.makeInactive();
				this._activeItem = AI;
				this._activeItem.makeActive();
				this._setCaptionLabel(this._activeItem.index);
				if (Math.abs(this._targetPosition - this._currentPosition) <= 0.5 ) this.conf.onReachTarget(this._activeItem);
			}
            
			this._positionItems();

			var st = this._step.bind(this);
			window.setTimeout(st,this._millisecondsPerStep);

		} else if (!this._holdPos) {
			if (this.Slider) this.Slider.locked = false;
			this._currentPosition = Math.round(this._currentPosition);
			if(this.Position && !this.Slider.locked && this._activeItem) {
				this._setCaptionLabel(this._activeItem.index);
			}
			this._positionItems();
			this._stepLock = false;
		} else {
			this._stepLock = false;
		}

		if (this.Slider && !this.Slider.locked) {
			this.Slider.setPosition(this._currentPosition);
		}
	},
    


	/* ------------------------------------------------------------------------------------------------------ */
    
	/*
     * position items
     */
	_positionItems: function () {

		if (this._lastStart) {
			var item = this._lastStart;
			while (item) {
				item.element.style.display="none";
				item = item.next;
				if (item == this._lastStart) break;
				if (item && item.pre == this._lastEnd) break;
			}
		}
		else {
			this._lastStart = this._activeItem;
		}

		if (!this._activeItem) return;
		var currentItem = this._activeItem;
		var itemP = currentItem.pre;
		var itemN = currentItem.next;

		this._positionItem(currentItem, 0);
		for (var i=1; i <= this.conf.visibleItems && 2*i < this.items.length ; i++) {
			if (itemP) {
				this._positionItem(itemP, -i);
				this._lastStart = itemP;
				itemP = itemP.pre;
			}
			if (itemN) {
				this._positionItem(itemN, i);
				this._lastEnd = itemN;
				itemN = itemN.next;
			}
		}

	},

	_positionItem: function (item, relativeIndex) {

		var conf = this.conf;
		var vF = conf.verticalFlow;

		var els = item.element.style;
		//els.display =" none";
		//if (els.display != "none") return;

		/* Index and position relative to activeItem */
		var p = item.position = this._currentPosition + relativeIndex;
		var relativePosition = item.relativePosition = Math.round(p) - this._currentPosition;
		var relativePositionNormed = item.relativePositionNormed = conf.visibleItems > 0 ? relativePosition/conf.visibleItems : 0;
		var side = relativePosition < 0 ? -1 : 1;
		side *= relativePosition == 0 ? 0 : 1;
		item.side = side;

		var size = conf.calcSize(item);
		size.height = Math.max(size.height, 0);
		size.width = Math.max(size.width, 0);
		if (item.content.origProportion) size = this._scaleImageSize(item, size);
		item.size = size;

		var coords = item.coordinates = conf.calcCoordinates (item);
		var relItemPos = item.relativeItemPosition = conf.calcRelativeItemPosition(item);
		var zIndex = item.zIndex = conf.calcZIndex (item);
		var fontSize = item.fontSize = conf.calcFontSize (item);
		var opacity = item.opacity = conf.calcOpacity(item);

		size.height *= this.maxHeight*1.5;
		size.width *= this.maxHeight*1.5;

		/* set position */
		var sA = vF ? size.height : size.width;
		var sB = vF ? size.width : size.height;
		var pX = this.Flow.center.x * ( 1 + coords.x )  + (relItemPos.x - 1)  * sA/2;
		var pY = this.maxHeight/2 * ( 1 + coords.y ) + (relItemPos.y - 1 )* sB/2;
		els.left = (vF ? pY : pX)+"px";
		els.top = (vF ? pX : pY)+"px";
        
		this._setItemSize(item, size);

		/* set opacity */
		if (conf.endOpacity != 1) {
			this._setItemOpacity(item);
		}

		/* set font size */
		if (!this.Browser.IE) els.fontSize = (fontSize * 100) +"%";

		/* set z-index */
		els.zIndex = 32768 + Math.round(zIndex * this.items.length); // just for FF

		conf.onDrawItem(item);

		els.visibility = "visible";
		els.display = "block";
	},

	_scaleImageSize: function (item, size, max) {
		var sFL = this.conf.scaleFactorLandscape;
		var sFP = this.conf.scaleFactorPortrait;
		var vF = this.conf.verticalFlow;
		var prop = item.content.origProportion;
		var width = size.width;
		var height = size.height;
		var c = item.content;

		if (vF) {
			if (prop <= 1) {
				if (sFL != "max" && sFL != 1) {
					height *= sFL;
					width = Math.min(height * prop, max ? max : 1 );
				}
				height = width / prop;
			}
			else if (prop > 1) {
				if (sFP == "max") {
					height = max ? max : 1;
				}
				else if (sFP != 1) {
					width *= sFP;
					height = Math.min(width/prop, max ? max : 1)
				}
				else {
					height = width / prop;
				}
				width = height * prop;
			}
		}
		else {
			if (prop > 1) {
				if (sFL != "max" && sFL != 1) {
					width *= sFL;
					height = Math.min(width / prop, max ? max : 1);
				}
				width = height * prop;
			}
			else if (prop <= 1) {
				if (sFP == "max") {
					width = max ? max : 1;
				}
				else if (sFP != 1) {
					height *= sFP;
					width = Math.min(height*prop, max ? max : 1);
				}
				else {
					width = height * prop;
				}
				height = width / prop;
			}
		}

		height = isNaN(height) ? 0 : height;
		width = isNaN(width) ? 0 : width;

		if (!max && this.conf.fixItemSize) {

			var propS = size.width / size.height;

			var max = Math.max(size.width, size.height);
			var s = this._scaleImageSize(item, {
				width: max,
				height: max
			}, max);

			if (propS < 1) {
				height = s.height/size.height;
				width = height * prop / propS;
			}
			else {
				width = s.width/size.width;
				height = width / prop * propS;
			}

			var h = height * 100;
			var w = width * 100;
			var mL= (1 - width)/2 * 100;
			var mT= ( 1 - height ) / propS * 100 * (vF ? 0.5 : 1 );
			c.style.height = h+"%";
			if (item.reflection) item.reflection.style.height = h*this.conf.reflectionHeight+"%";
			c.style.width = w+"%";
			if (item.reflection) item.reflection.style.width = w+"%";
			c.style.marginLeft = mL+"%";
			if (item.reflection) item.reflection.style.marginLeft = mL+"%";
			c.style.marginTop = mT+"%";

			item.element.style.overflow = "hidden";

			return size;
		}
		else {
			return {
				width: width,
				height: height
			};
		}

	},

	_setItemSize: (function () {
		if (ContentFlowGlobal.Browser.IE) {
			var _setItemSize = function (item, size) {
				if (!this.conf.fixItemSize) {
					item.content.style.height = size.height+"px";
				}
				else if (ContentFlowGlobal.Browser.IE6) {
					var h = parseInt(item.content.style.height)/100;
					item.content.style.height = size.height*h+"px";
					var mT = parseInt(item.content.style.marginTop)/100;
					item.content.style.marginTop = size.height*mT+"px";
				}
				if (item.reflection) {
					var h = parseInt(item.content.style.height);
					item.reflection.style.height = h*this.conf.reflectionHeight+"px";
					item.reflection.style.marginTop = h * this.conf.reflectionGap + "px";
				}
				item.element.style.width = size.width +"px";
				item.element.style.height = size.height*(1+this.conf.reflectionHeight+this.conf.reflectionGap)+"px";
			}
		}
		else {
			var _setItemSize = function (item, size) {
				if (item.reflection) {
					item.element.style.height = size.height*(1+this.conf.reflectionHeight + this.conf.reflectionGap) +"px";
					item.reflection.style.marginTop = size.height * this.conf.reflectionGap + "px";
				}
				else if (this._reflectionWithinImage) {
					item.element.style.height = size.height*(1+this.conf.reflectionHeight + this.conf.reflectionGap) +"px";
				}
				else {
					item.element.style.height = size.height +"px";
				}
				item.element.style.width = size.width +"px";
			}
		}
		return _setItemSize;

	})(),

	_setItemOpacity: (function () {
		if (ContentFlowGlobal.Browser.IE6) {
			var _setItemOpacity = function (item) {
				if (item.content.origSrc && item.content.origSrc.match(/\.png$/) ) {
					var s = item.content.src;
					item.content.src = item.content.origSrc;
					item.content.style.filter = item.content.filterString+" progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")";
					item.content.src = s;
				}
				else {
					item.content.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")";
				}
				if (item.reflection) item.reflection.style.filter = item.reflection.filterString+"progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")";
			}
		}
		else if (ContentFlowGlobal.Browser.IE) {
			var _setItemOpacity = function (item) {
				item.element.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")";
			}
		}
		else {
			var _setItemOpacity = function (item) {
				item.element.style.opacity = item.opacity;
			}
		}
		return  _setItemOpacity;
	})()


};


/* ==================== extendig javascript/DOM objects ==================== */

/*
 *  adds bind method to Function class
 *  http://www.digital-web.com/articles/scope_in_javascript/
 */

if (!Function.bind) {
	Function.prototype.bind = function(obj) {
		var method = this;
		return function () {
			return method.apply(obj, arguments);
		};
	};
}


/*
 * extending Math object
 */
if (!Math.erf2) {
	// error function (http://en.wikipedia.org/wiki/Error_function), implemented as erf(x)^2
	Math.erf2 = function (x) {
		var a = - (8*(Math.PI -3)/(3*Math.PI*(Math.PI -4)));
		var x2 = x*x;
		var f = 1 - Math.pow(Math.E, -x2 * (4/Math.PI + a*x2)/(1+a*x2));
		return f;
	};
}

if (!Math._2PI05) {
	Math._2PI05 = Math.sqrt(2*Math.PI);
}

if (!Math.normDist) {
	// normal distribution
	Math.normDist = function (x, sig, mu) {
		if (!sig) var sig = 1;
		if (!mu) var mu = 0;
		if (!x) var x = - mu;
		return 1/(sig * Math._2PI05) * Math.pow(Math.E, - (x-mu)*(x-mu)/(2*sig*sig) );
	};
}

if (!Math.normedNormDist) {
	Math.normedNormDist = function (x, sig, mu) {
		return this.normDist(x, sig, mu)/this.normDist(mu, sig, mu);
	};
}

if (!Math.exp) {
	Math.exp = function(x) {
		return Math.pow(Math.E, x);
	};
}

if (!Math.ln) {
	Math.ln = Math.log;
}

if (!Math.log2) {
	Math.log2 = function (x) {
		return Math.log(x)/Math.LN2;
	};
}

if (!Math.log10) {
	Math.log10 = function (x) {
		return Math.log(x)/Math.LN10;
	};
}

if (!Math.logerithm) {
	Math.logerithm = function (x, b) {
		if (!b || b == Math.E)
			return Math.log(x);
		else if (b == 2)
			return Math.log2(x);
		else if (b == 10)
			return Math.log10(x);
		else
			return Math.log(x)/Math.log(b);
	};
}


/*
 * extending Event object
 */
if (!Event) var Event = {};

if (!Event.stop) {
	Event.stop = function (event) {
		event.cancelBubble = true;
		if (event.preventDefault) event.preventDefault();
		if (event.stopPropagation) event.stopPropagation();
		return false;
	};
}

/*
 * extending Element object
 */
if (document.all && !window.opera) {
	window.$CF = function (el) {
		if (typeof el == "string") {
			return window.$CF(document.getElementById(el));
		}
		else {
			if (CFElement.prototype.extend && el && !el.extend) CFElement.prototype.extend(el);
		}
		return el;
	};
} else {
	window.$CF = function (el) {
		return el;
	};
}

if (!window.HTMLElement) {
	CFElement = {};
	CFElement.prototype = {};
	CFElement.prototype.extend = function (el) {
		for (var method in this) {
			if (!el[method]) el[method] = this[method];
		}
	};
}
else {
	CFElement = window.HTMLElement;
}


/*
 * Thanks to Peter-Paul Koch
 * http://www.quirksmode.org/js/findpos.html
 */
if (!CFElement.findPos) {
	CFElement.prototype.findPos = function() {
		var obj = this;
		var curleft = curtop = 0;
		try {
			if (obj.offsetParent) {
				curleft = obj.offsetLeft;
				curtop = obj.offsetTop;
				while (obj = obj.offsetParent) {
					curleft += obj.offsetLeft;
					curtop += obj.offsetTop;
				}
			}
		}
		catch (ex) {}
		return {
			left:curleft,
			top:curtop
		};
	};
}

if (!CFElement.getDimensions) {
	CFElement.prototype.getDimensions = function() {
		return {
			width: this.clientWidth,
			height: this.clientHeight
		};
	};
}

/*
 * checks if an element has the class className
 */
if (!CFElement.hasClassName) {
	CFElement.prototype.hasClassName = function(className) {
		return (new RegExp('\\b'+className+'\\b').test(this.className));
	};
}

/*
 * adds the class className to the element
 */ 
if (!CFElement.addClassName) {
	CFElement.prototype.addClassName = function(className) {
		if(!this.hasClassName(className)) {
			this.className += (this.className ? ' ':'') + className ;
		}
	};
}

/*
 * removes the class className from the element el
 */ 
if (!CFElement.removeClassName) {
	CFElement.prototype.removeClassName = function(className) {
		this.className = this.className.replace(new RegExp('\\b'+className+'\\b'), '').replace(/\s\s/g,' ');
	};
}

/*
 * removes or adds the class className from/to the element el
 * depending if the element has the class className or not.
 */
if (!CFElement.toggleClassName) {
	CFElement.prototype.toggleClassName = function(className) {
		if(this.hasClassName(className)) {
			this.removeClassName(className);
		} else {
			this.addClassName(className);
		}
	};
}

/*
 * returns all children of element el, which have the class className
 */
if (!CFElement.getChildrenByClassName) {
	CFElement.prototype.getChildrenByClassName = function(className) {
		var children = new Array();
		for (var i=0; i < this.childNodes.length; i++) {
			var c = this.childNodes[i];
			if (c.nodeType == 1 && $CF(c).hasClassName(className)) {
				children.push(c);
			}
		}
		return children;
	};
}

/*
 * Browser independent event handling method.
 * adds the eventListener  eventName to element el and attaches the function method to it.
 */
if (!CFElement.addEvent) {
	CFElement.prototype.addEvent = function(eventName, method, capture) {
		if (this.addEventListener)
			this.addEventListener(eventName, method, capture);
		else
			this.attachEvent('on'+eventName, method);
	};
}
   
/*
 * Browser independent event handling method.
 * removes the eventListener  eventName with the attached function method from element el.
 */
if (!CFElement.removeEvent) {
	CFElement.prototype.removeEvent = function(eventName, method, capture) {
		if (this.removeEventListener)
			this.removeEventListener(eventName, method, capture);
		else
			this.detachEvent('on'+eventName, method);
	};
}

/*
 * Browser independent event handling method.
 * adds the eventListener  eventName to element el and attaches the function method to it.
 */
if (!window.addEvent) {
	window.addEvent = function(eventName, method, capture) {
		if (this.addEventListener) {
			this.addEventListener(eventName, method, capture);
		} else {
			if (eventName != 'load' && eventName != 'resize')
				document.attachEvent('on'+eventName, method);
			else
				this.attachEvent('on'+eventName, method);
		}
	};
}
   
/*
 * Browser independent event handling method.
 * removes the eventListener  eventName with the attached function method from element el.
 */
if (!window.removeEvent) {
	window.removeEvent = function(eventName, method, capture) {
		if (this.removeEventListener) {
			this.removeEventListener(eventName, method, capture);
		} else {
			if (eventName != 'load' && eventName != 'resize')
				document.detachEvent('on'+eventName, method);
			else
				this.detachEvent('on'+eventName, method);
		}
	};
}

/* ==================== start it all up ==================== */
ContentFlowGlobal.init();


