/**
 * Suchbox rein- und rausfahren
 */
function showSearch() {
	new Effect.Parallel (
			[
			new Effect.Appear("suche", {sync:true, duration: 2.1}),
			new Effect.SlideDown("suche", {sync:true,duration: 2.1})
			],
			{
			}

	);
	return false;
}

function hideSearch() {
	new Effect.Parallel (
			[
			new Effect.SlideUp("suche", {sync:true,duration: 2.1}),
			new Effect.Fade("suche", {sync:true, duration: 2.1})
			],
			{
			}

	);
	return false;
}

function showBox(id, parentElement) {
	var boxHolder = $(id);
	var box = boxHolder.down('.box') ? boxHolder.down('.box') : boxHolder;
	if ($(parentElement)) {
		var pos = Position.cumulativeOffset($(parentElement));
		boxHolder.setStyle({
			position:   'absolute',
			display:    'block',
			visibility: 'hidden',
			left:       pos.left + 'px',
			top:        pos.top + 'px'
		});
		var boxHeight = box.getHeight();
		if (boxHeight) {
			boxHolder.setStyle({
				height:     boxHeight + 'px',
				width:      box.getWidth() + 'px',
				top:        (parseInt(boxHolder.getStyle('top')) - boxHeight) + 'px',
				visibility: 'visible',
				display:    'none'
			});
		}
	}

	new Effect.Parallel (
		[
			new Effect.Appear(boxHolder, {sync:true, duration: 2.1}),
			new Effect.SlideDown(boxHolder, {sync:true,duration: 2.1})
		],
		{}
	);
	return false;
}

function hideBox(id) {
	new Effect.Parallel (
		[
			new Effect.SlideUp(id, {sync:true,duration: 2.1}),
			new Effect.Fade(id, {sync:true, duration: 2.1})
		],
		{}
	);
	return false;
}

function switchImg(name, state) {
	document.getElementById(name).removeAttribute("src");
	document.getElementById(name).setAttribute("src","/img/" + name + "_" + state + ".gif");

}

function inputFocus(element, defaultValue) {
	if ($F(element) == defaultValue) $(element).value = '';
}

function inputBlur(element, defaultValue) {
	if ($F(element) == '') {
		$(element).value = defaultValue;
	}
}

function value_clean (name, value) {
	var e = $(name);
	if (value && value == e.value) {
		e.setAttribute("value","");
	}
}

function changeProductNav(idx) {
	var background = $('product_background');
	var aPos = new Array(
		'0x0'  , '149x0',   '298x0',
		'0x128', '149x128', '298x128'
	);
	for (var i = 1; i < aPos.length; i++) {
		var element = $('sortiment_navi_'+i);
		if (element) {
			if (i == idx) {
				element.style.display = 'block';
				var pos = aPos[i];
				var aDim = pos.split('x');
				background.style.display = 'block';
				background.style.left = String(aDim[0])+"px";
				background.style.top = String(aDim[1])+"px";
			} else {
				element.style.display = 'none';
			}
		}
	}
}

function switchBackground(elementId, imageUrl) {
	var e = document.getElementById(elementId);
	if (e) {
		e.style.backgroundImage = 'url("'+imageUrl+'")';
	}
}

function changeWorldwideNavi (imgid, name) {
	var id = parseInt(imgid);
	switchBackground(name, '/img/karte_' + id + '.gif');
	var i = 1;
	var navInactive;
	while (navInactive = document.getElementById(name+'_point_'+i)) {
		var liInactive;
		if (liInactive = document.getElementById(name+'_li_'+i)) {
			liInactive.removeAttribute("class");
		}
		navInactive.removeAttribute("class");
		navInactive.style['color'] = 'E2001A';
		i++;
	}
	var navLi = document.getElementById(name+'_li_'+id);
	var navPt = document.getElementById(name+'_point_'+id);
	if (navLi && navPt) {
		if (imgid > 0) {
			navLi.setAttribute("class", "current");
			navPt.setAttribute("class", "tesa_blue");
			navPt.style['color'] = '6C77AB';
		}
	}
}

function redirectSelect(select) {
	document.location.href = select[select.selectedIndex].value;
}

function change_tab (name) {
	var klasse = "tab_container_" + name + " clearfix";
	document.getElementById('tab_container_list').removeAttribute("class");
	document.getElementById('tab_container_list').setAttribute("class", klasse );
	//alert (klasse);

	for (i=1; i<=4; i++) {
		if (i == name) {
			document.getElementById('content_inner_' + i).style.display ='block';

			document.getElementById('tab_nav_' + i).style.backgroundPosition ='0 -150px';
			document.getElementById('tab_nav_' + i).style.borderBottom ='0';

			document.getElementById('tab_link_' + i).style.borderBottom ='0';
			document.getElementById('tab_link_' + i).style.backgroundPosition ='100% -150px';
			document.getElementById('tab_link_' + i).style.color ='#6D75AA';
			document.getElementById('tab_link_' + i).style.paddingBottom ='3px';

		} else {
			document.getElementById('content_inner_' + i).style.display ='none';

			document.getElementById('tab_nav_' + i).style.backgroundPosition ='left top';
			document.getElementById('tab_nav_' + i).style.borderWith ='1px solid #6D75AA';

			document.getElementById('tab_link_' + i).style.color ='#E2001A';
			document.getElementById('tab_link_' + i).style.backgroundPosition ='right top';
			document.getElementById('tab_link_' + i).style.borderWith ='1px solid #6D75AA';
			document.getElementById('tab_link_' + i).style.paddingBottom ='2px';
		}
	}
}


function writeDropdown(id, hOption, showDropdown) {
	var dropdown = $(id);
	var oldValue = $F(id);
	var aOldNode = dropdown.getElementsByTagName('option');
	var nodes = $A(aOldNode);
	var i = 0;
	nodes.each(function(node) {
		if (i) dropdown.removeChild(node);
		i++;
		}
	);
	hOption.each(function(value) {
		var tag = document.createElement('option');
		tag.value = value[0];
		tag.selected = (tag.value == oldValue);
		var inner = document.createTextNode(value[1]);
		tag.appendChild(inner);
		dropdown.appendChild(tag);
		}
	);
	if (showDropdown && hOption.keys().length) {
		Element.show(dropdown);
	} else if (Element.hasClassName(dropdown, 'hide')) {
		Element.hide(dropdown);
	}
}


function setDropdown(id, value) {
	var dropdown = $(id);
	var aOption = dropdown.getElementsByTagName('option');
	var aNode = $A(aOption);
	aNode.each(function(node) {
		node.selected = (node.value == value);
		}
	);
}


function openLayerVideo(status) {
	if (status == 'open') {
		document.getElementById('video_layer').style.display ='block';
	} else {
		document.getElementById('video_layer').style.display ='none';
	}
}

function openMediaPopup(url, width, height, top, left) {
	if (!top) top  = (screen.height  / 2) - 250;
	if (!left) left = (screen.width / 2) - 230;
	if (!width) width = 500; //459;
	if (!height) height = 540; //494;

	var F2=window.open(url, 'mediapopup', 'resizable=no,menubar=no,scrollbars=no,status=no,directories=no,width=' + width + ',height=' + height + ',top=' + top + ',left='+ left);
	F2.focus();
}

function openMicrositePopup(url, width, height, top, left, scrollbars) {
	if (!top) top  = 100;
	if (!left) left = 0;
	if (!width) width = 738;
	if (!height) height = 600;
	if (!scrollbars) scrollbars = 'yes';

	var F2=window.open(url, 'microsite','resizable=no,menubar=no,scrollbars=' + scrollbars + ',status=no,directories=no,width=' + width + ',height=' + height + ',top=' + top + ',left='+ left);
	F2.focus();
}

sitemapInProgress = false;
function toggleSitemapbox(elementId, myDuration) {
	if ($(elementId) && !sitemapInProgress) {
		sitemapInProgress = true;
		if (myDuration == undefined)
			myDuration = 0.5;
		if ($(elementId).style.display == 'none')  {
			Effect.BlindDown(elementId, {duration: myDuration, afterFinish:function(){sitemapInProgress = false;}});
			document.getElementById(elementId+'_img').src="/img/icon_minus.gif";
			document.getElementById(elementId+'_link').removeAttribute("class");
			document.getElementById(elementId+'_link').setAttribute("class", "tesa_blue" );
		} else {
			Effect.BlindUp(elementId, {duration: myDuration, afterFinish:function(){sitemapInProgress = false;}});
			document.getElementById(elementId + '_img').src="/img/icon_plus.gif";
			document.getElementById(elementId+'_link').removeAttribute("class");
			document.getElementById(elementId+'_link').setAttribute("class", "" );
		}
	}
}

function preload() {
	var preSource = document.getElementsByClassName("hiddenpreload");
	var preImages = new Array;
	for (i = 0; i < preSource.length; i++) {
		preImages[i] = new Image();
		preImages[i].src = preSource[i].firstChild.data;
	}
}

function countCookies(base) {
	var c = 0;
	var aCookie = document.cookie.split(/;/);
	for (var i = 0; i < aCookie.length; i++) {
		if (aCookie[i].trim().substr(0, base.length) == base) c++;
	}
	return c;
}

function setCookie(name, value, expires, path, domain, secure) {
	var today = new Date();
	today.setTime(today.getTime());
	if (expires) {
		expires = expires * 1000 * 60 * 60 * 24;
	}
	var expires_date = new Date(today.getTime() + (expires));
	if (!path) path = "/";

	document.cookie = name + "=" +escape( value ) +
	( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
	( ( path ) ? ";path=" + path : "" ) +
	( ( domain ) ? ";domain=" + domain : "" ) +
	( ( secure ) ? ";secure" : "" );
}

function getCookie(name) {
	var start = document.cookie.indexOf(name + "=");
	var len = start + name.length + 1;
	if ((!start) && (name != document.cookie.substring(0, name.length))) {
		return null;
	}
	if (start == -1) return null;
	var end = document.cookie.indexOf( ";", len );
	if (end == -1) end = document.cookie.length;
	return unescape(document.cookie.substring(len, end));
}

function deleteCookie(name, path, domain) {
	if (!path) path = "/";
	if (getCookie(name)) {
		document.cookie = name + "=" +
		((path) ? ";path=" + path : "") +
		((domain) ? ";domain=" + domain : "" ) +
		";expires=Thu, 01-Jan-1970 00:00:01 GMT";
	}
}

function addToCookie(name, value, index, expires) {
	index = Number(index);
	var content = getCookie(name);
	if (!content) {
		if (index > 0) {
			var arr = new Array(index+1);
			value = arr.join(',').concat(value);
		}
		setCookie(name, value, expires);
		return;
	}
	var list = content.split(',');
	if (list.indexOf(value) < 0) {
		if (index >= 0) {
			if (list[index]) {
				list.splice(index, 0, value);
			} else {
				list[index] = value;
			}
		} else {
			list.push(value);
		}
	}
	setCookie(name, list.join(','), expires);
}

function removeFromCookie(name, value, expires) {
	var content = getCookie(name);
	if (!content) return;
	var list = content.split(',');
	var idx = list.indexOf(value);
	if (idx >= 0) {
		list = list.slice(0, idx).concat(list.slice(idx + 1));
	}
	setCookie(name, list.join(','), expires);
}

function isInCookie(name, value) {
	var content = getCookie(name);
	if (!content) return false;
	var list = content.split(',');
	var idx = list.indexOf(value);
	return (idx >= 0);
}

function switchCookie(name, value, expires) {
	if (getCookie(name)) {
		deleteCookie(name);
	} else {
		setCookie(name, value, expires);
	}
}


function show(id) {
	var e = $(id);
	if (e) {
		e.style.display = 'block';
		e.style.visibility = 'visible';
		return true;
	}
	return false;
}

function hide(id) {
	var e = $(id);
	if (e) {
		e.style.display = 'none';
		e.style.visibility = 'hidden';
		return true;
	}
	return false;
}


function activate(id) {
	var e = $(id);
	if (e) {
		e.disabled = false;
		return true;
	}
	return false;
}

function deactivate(id) {
	var e = $(id);
	if (e) {
		e.disabled = true;
		return true;
	}
	return false;
}

function go(select) {
	var path = $F(select);
	if (path) document.location.href = path;
}

function zoomPackshot() {
	var aPackshot = $$('.packshot');
	aPackshot = $A(aPackshot);
	for (var i = 0; i < aPackshot.length; i++) {
		if (aPackshot[i].style.display != 'none') document.location.href = aPackshot[i].parentNode.href;
	}
}

function togglePackshotShow() {
	if (!window.packshotShow) {
		window.packshotShow = new PeriodicalExecuter(nextPackshot, 10);
	} else {
		window.packshotShow.currentlyExecuting = !window.packshotShow.currentlyExecuting;
		if (window.packshotShow.currentlyExecuting) {
			$('packshotShowStart').show();
			$('packshotShowPause').hide();
		} else {
			$('packshotShowStart').hide();
			$('packshotShowPause').show();
		}
	}
}

function nextPackshot(step) {
	step = step || 1;
	var aPackshot = $$('.packshot');
	aPackshot = $A(aPackshot);
	var fadeIdx   = 0;
	var appearIdx = 0;
	if (aPackshot.length < 2) return;
	for (var i = 0; i < aPackshot.length; i++) {
		if (aPackshot[i].style.display != 'none') fadeIdx = i;
	}

	if (step == 1) {
		appearIdx = (fadeIdx + 1 >= aPackshot.length ? 0 : fadeIdx + 1);
	} else {
		appearIdx = (fadeIdx - 1 < 0 ? aPackshot.length - 1 : fadeIdx - 1);
	}
	if (fadeIdx != appearIdx) {
		aPackshot[fadeIdx].hide();
		aPackshot[appearIdx].show();
	}
}

/*
 * Element per Ajax aktualisieren
 */
function updateContainer(elementId, parameter, url, method, urlParam, indicator) {
	parameter = parameter || '';
	method = method || 'get';

	var newQuery = parameter.toQueryParams();
	newQuery['target'] = encodeURIComponent(elementId);
	if (urlParam) newQuery['url'] = encodeURIComponent(urlParam);
	var queryString;

	if (!url) {
		url = document.location.protocol+'//'+document.location.host+document.location.pathname;
		var oldQuery = document.location.search.toQueryParams();
		var hOldQuery = $H(oldQuery);
		queryString = hOldQuery.merge(newQuery).toQueryString();
	} else {
		hNewQuery = $H(newQuery);
		queryString = hNewQuery.toQueryString();
	}

	var indicatorImg = indicator ? $(indicator) : $(elementId).down('.indicator');
	if (indicatorImg) indicatorImg.show();

	new Ajax.Updater (elementId, url, {
		method: method,
		parameters: queryString,
		evalScripts: true,
		onComplete: function() {
			if (indicatorImg) indicatorImg.hide();
		}
	});

	return false;
}

function submitForm(formId, elementId) {
	var form = $(formId);
	if (form) {
		updateContainer(elementId, form.serialize(), form.action, form.method);
		return false;
	}
	return true;
}

function updateDropdownElement(target, url, parameters, element, selectProdukt) {
	if (element) parameters += "ajax=1&produkt="+element.value+"&update="+target+"&selectProdukt="+selectProdukt;

	new Ajax.Updater (target, url, {
		method: "get",
		parameters: parameters,
		evalScripts: true
	});
}

/*
 * Funktionen der Productfinder Teaser
 */
function updateCpdbDropdowns(formId) {
	var f = $(formId);
	var suffix = formId.substr(4);
	var url  = f.action.replace('result', 'update');
	var pars = f.serialize();
	var a = new Ajax.Request(url,
		{
		method: 'get',
		parameters: pars,
		onComplete: function(response, json) {
				writeDropdown('selectAssortment'+suffix,       $H(json.selectAssortment), json.showHiddenDropdowns);
				writeDropdown('selectApplicationfield'+suffix, $H(json.selectApplicationfield), json.showHiddenDropdowns);
				writeDropdown('selectApplication'+suffix,      $H(json.selectApplication), json.showHiddenDropdowns);
			}
		}
	);

}

function initCpdbDropdowns(formId) {
	var f = $(formId);
	var suffix = formId.substr(4);
	try {
		var data = getCookie('cpdbSettings'+suffix);
		if (data) {
			data = eval('('+data+')');
			setDropdown('selectAssortment'+suffix,       data.assortmentId);
			setDropdown('selectApplicationfield'+suffix, data.applicationfieldId);
			setDropdown('selectApplication'+suffix,      data.applicationId);
			if (data.query) {
				$('search'+suffix).value = data.query.replace(/\+/g, ' ');
			}
			updateCpdbDropdowns(formId);
		}
	} catch (e) {
		return null;
	}
}

function resetForm(formId) {
	var f = $(formId);
	var suffix = formId.substr(4);
	document.cookie = 'cpdbSettings'+suffix+'=;path=/;expires=Thu, 01-Jan-70 00:00:01 GMT';
	f.q.value = '';
	f.assortment.selectedIndex = 0;
	f.applicationfield.selectedIndex = 0;
	f.application.selectedIndex = 0;

	updateCpdbDropdowns(formId);
}

/*
 * Ausklappnavigation
 */
Event.observe(document, 'dom:loaded', function(){
	var openNav,      // Funktion zum Öffnen (Ausklappen) einer Navigation
	    closeNav,     // Funktion zum Schließen der aktuell geöffneten Navigation
	    $currentNav;  // Speichert die aktuell geöffnete Box

	/*
	 * Öffnet die Navigation von element (Link oder LI)
	 * Übergeordnete Navigation (LI) ermitteln und CSS Klasse "open" hinzufügen und "closed" entfernen
	 */
	openNav = function(element) {
		var $nav = element.tagName == 'LI' ? $(element) : $(element).up('li'),  // Navigation ist das Element selbst, oder das übergeordnete Listenelement
		    open = $nav !== $currentNav;  // Element ist bereits geöffnet?

		// Aktuelle Navigation schließen
		closeNav();

		// Neue Navigation öffnen, wenn sie vorher nicht bereits geöffnet war
		// d.h. ein Klick auf die geöffnete Nav schließt sie wieder
		if (open) {
			$nav.addClassName('open');
			$nav.removeClassName('closed');
			$currentNav = $nav;
		}

		return true;
	};

	/*
	 * Schließt die aktuelle Ausklappnavi
	 * Aktuell geöffnete Navigation ermitteln und CSS Klasse "closed" hinzufügen und "open" entfernen
	 */
	closeNav = function() {
		if ($currentNav) {
			$currentNav.removeClassName('open');
			$currentNav.addClassName('closed');
			$currentNav = null;
		}

		return true;
	};

	// Öffnung der Ausklappnavi per Click
	$$('#nav > li > a', '.sub-nav .box3 ul li.has-subnav > a').each(function($a) {
		$a.onclick = function() {
			return !openNav($a);
		};
	});

	// Schließen der Ausklappnavigation
	$$('.main-nav a.close', '.sub-nav a.close').each(function($a) {
		$a.onclick = function(e) {
			return !closeNav();
		};
	});

	// Einige Links in der Subsubnav nicht verfolgen
	$$('.sub-nav li.has-subnav li a[rel=nofollow]').each(function($a) {
		$a.onclick = function() {
			return false;
		};
	});

	// Ausklappnavigation positionieren
	$$('#wrapper').each(function($wrapper) {
		var maxHeight = 320,                      // maximale Höhe der Navigation
		    minMargin = 12,                       // minimaler Abstand zum Rand der Seite
		    liClass = '',                         // CSS Klasse für Listenelemente
		    wrapperWidth = $wrapper.getWidth(),   // Breite des Wrappers, also der gesamten Seite
	        $currentUl,                           // aktuell bearbeitete Liste (UL Node)
	        $oldUl;                               // zuvor aktuelle Liste (UL Node)

		/*
		 * Alle Listenelemente der Subnavigation durchlaufen und in mehrere Listen umsortieren.
		 *
		 * $oldUl enthält das UL Element, zu dem das zuletzt bearbeitete LI Element ursprünglich gespeichert war
		 * $newUl enthält ein neu erzeugtes UL Element, wenn für eine Navigation eine neue Spalte benötigt wird
		 * $currentUl enthält das UL Element, in dem LI Elemente aktuell abgelegt werden
		 */
		$$('.sub-nav .box3 ul li.has-subnav ul li').each(function($li) {
			var $newUl;  // neu erzeugte Liste (UL Node)

			// Ziel-Liste zurücksetzen, wenn das zuvor bearbeitete Listeelement
			// nicht zu der gleichen Liste wie das aktuelle Element gehört.
			if ($oldUl && $oldUl != $li.up('ul')) {
				$currentUl = null;
			}

			// Neue Ziel-Liste erzeugen, wenn keine Ziel-Liste existiert, oder
			// das Hinzufügen des Punktes zur aktuellen Liste die maximale Höhe
			// überschreiten würde
			if (!$currentUl || $currentUl.getHeight() + $li.getHeight() >= maxHeight) {
				liClass = 'first';
				$newUl = document.createElement('ul');
				$oldUl = $li.up('ul');
				Element.insert($currentUl ? $currentUl : $oldUl, { after: $newUl });
				$currentUl = $newUl;
			}

			// CSS Klasse des Listenelementes setzen
			if (liClass) {
				$li.addClassName(liClass);
				liClass = '';
			}

			// Listenelement an Ziel-Liste anhängen und aus der alten Liste entfernen
			if ($currentUl) {
				$($currentUl).insert($li.remove());
			}

			// Original-Liste entfernen, wenn es sich um das letzte Listenelement hantelt
			if ($oldUl && !$oldUl.down('li')) {
				$oldUl.remove();
			}
		});

		/*
		 * Breiten und Positionierung der Ausklappnavigation nach dem
		 * Umbau der Liste setzen.
		 */
		$$('.sub-nav .box3 ul li.has-subnav .holder').each(function($div) {
			var $li         = $div.up('li'),             // Navigationspunkt, zu dem die Liste gehört
			    navPosition = $li.positionedOffset(),    // Position des Navigationspunktes im Wrapper
			    columns     = $li.select('ul').length,   // Anzahl der Spalten der Ausklappnavigation
			    boxWidth,                                // Breite der Ausklappnavigation
			    boxTop,                                  // Top Positionierung der Ausklappnavigation
			    boxLeft,                                 // Linke Positionierung der Ausklappnavigation
			    minLeft,                                 // minimale linke Positionierung
			    maxLeft;                                 // maximale linke Positionierung (abhängig von der Breite der Box)

			// CSS Klasse für Navigation setzen, da z.B. einspaltige Ausklappnavigation relativ breiter ist
			$li.addClassName('columns-' + columns);

			// Breite der Ausklappbox
		    boxWidth    = $div.getWidth(),

		    // Top Position = Top Position der übergeordneten Nav + Höhe der übergeordneten Nav
		    boxTop      = navPosition.top + $li.getHeight(),

		    // Linke Position = Linke Position der Nav - (Hälfte der Breite der Ausklappbox + Hälte der Breite der Nav) => mittig unterhalb der Navigation
		    boxLeft     = navPosition.left + Math.round(-0.5 * boxWidth + $li.getWidth() / 2),

		    // minimale linke Position entspricht dem definierten Mindestabstand, da 0 = ganz links
		    minLeft     = minMargin,

		    // maximale linke Position = Breite der Seite - Breite der Box - Mindestabstand, da Positionierung der Box über linken Rand erfolgt
		    maxLeft     = wrapperWidth - boxWidth - minMargin;

		    // ermittelte Werte setzen
			$div.setStyle({
				left: Math.max(minLeft, Math.min(maxLeft, boxLeft)) + 'px',
				top:  boxTop + 'px'
			});

			// Navigation als geschlossen markieren
			$li.addClassName('closed');
		});
	});
});

/*
 * Clean Air Teaser
 */
function updateCleanAirPrinter(target, url, company) {
	var _a = new Ajax.Updater(target, url, {
		method:      'get',
		parameters:  'company='+company,
		evalScripts: true,
		onComplete:  function() {
			initCustomForms();
		}
	});
	return false;
}

/*
 * Höhe von Listenelemente mit float:left für IE7 korrigieren
 */
function fixFloatingList(list) {
	var maxHeight = 0;
	var aLi = new Array();
	$(list).select('li').each(function(li) {
		if (li.hasClassName('clearfix')) {
			if (maxHeight) {
				aLi.each(function(e) {
					e.setStyle({ 'height': maxHeight + 'px' });
				});
				maxHeight = 0;
				aLi = new Array();
			}
		}
		maxHeight = Math.max(maxHeight, li.getHeight());
		aLi.push(li);
	});
}
Event.observe(window, 'load', function() {
	$(document.body).select('ul.floating').each(function(list) {
		fixFloatingList(list);
	});
});


/*
 * Sortierung und Filterung von Produkt-Tabellen
 */
var TesaProductTable = Class.create({
	initialize: function(wrapper) {
		this.$wrapper          = $(wrapper);

		this.$productTable     = this.$wrapper.down('table.product-table');
		this.sortableColumns   = this.$productTable.select('thead th.sortable');     // Liste der Spalten, nach denen sortiert werden kann
		this.$tableBody        = this.$productTable.down('tbody');                   // Body der Tabelle, der die zu sortierenden Zeilen enthält

		// Alle Spalten durchlaufen und Onclick Handler zur Sortierung aktivieren
		this.sortableColumns.each(function($col) {
			$col.onclick = this.clickOnSortableColumn.bindAsEventListener(this, $col);
		}.bind(this));

		// Filter initialisieren
		this.$filterForm = this.$wrapper.down('form');
		if (this.$filterForm) {
			this.filterUpdateFunction = this.filterTableRows.bind(this);
			this.filterForProperty    = {};

			this.$filterForm.select('td.filter').each(function($filterCell) {
				$filterCell.down('a.toggle').onclick = this.toggleFilter.bindAsEventListener(this, $filterCell);
				switch(true) {
				case $filterCell.hasClassName('checkbox'):
					this.initCheckboxFilter($filterCell);
					break;
				case $filterCell.hasClassName('range-slider'):
					this.initRangeSlider($filterCell);
					break;
				}
			}.bind(this));
		}

		// Filter ausblenden, wenn gewünscht
		this.$filterForm.select('table').each(function($table) {
			if ($table.hasClassName('init-closed')) {
				$table.removeClassName('init-closed');
				$table.addClassName('closed');
			}
		});
	},

	/**
	 * Initialisiert die Filter, bei denen die Auswahl über ordinäre
	 * Checkboxen vorgenommen wird (Standardfall)
	 */
	initCheckboxFilter: function($filterCell) {
		var propertyKey = $filterCell.down('input').getAttribute('name'),
		    checkboxes  = $filterCell.select('input[type="checkbox"]'),
		    updateTable = this.filterUpdateFunction,
		    filter;

		/*
		 * Checkboxen mit click-Handler versehen
		 * Die doppelte Event-Abfrage (auf checkbox:click) ist notwendig,
		 * da die umgestylten Checkboxen kein Click-Event liefern können, und
		 * daher das Event "checkbox:click" feuern
		 */
		checkboxes.each(function($checkbox) {
			Event.observe($checkbox, 'checkbox:click', updateTable);
			Event.observe($checkbox, 'click', updateTable);
		});

		/*
		 * Filter definieren.
		 * Werte aller markierten Checkboxen in diesem Filter in eine Liste lesen
		 * und für die Zeile prüfen, ob der fragliche Wert in dieser Liste
		 * enthalten ist
		 */
		filter = function(propertyKey, checkboxes, row) {
			var values = $H(Form.serializeElements(checkboxes, true)).get(propertyKey);
			if (typeof values === 'string') {
				values = [ values ];
			}
			return values.indexOf(this.propertyValueForRow(row, propertyKey)) >= 0;
		}.bind(this);

		//Funktion mit Eigentschaft und Checkboxen vordefinieren
		this.filterForProperty[propertyKey] = filter.curry(propertyKey, checkboxes);

		$filterCell.down('a.reset').onclick = function() {
			checkboxes.each(function($checkbox) {
				$checkbox.checked = false;

				// Gestylte Checkbox zu Fuß entfernen (dringen ändern!)
				updateCheckbox($checkbox);
			});

			updateTable();
			return false;
		};
	},

	/**
	 * Bereichsauswahlslider initialisieren
	 */
	initRangeSlider: function($filterCell) {
		var inputs         = $filterCell.select('input'),                          // Eingabefelder, die minimalen und maximalen Wert enthalten
		    inputMin       = inputs[0],                                            // Eingabefeld für Minimalwert
	        inputMax       = inputs[1],                                            // Eingabefeld für Maximalwert
	        minValue       = parseInt($F(inputMin), 10),                           // Startwert Minimum
	        maxValue       = parseInt($F(inputMax), 10),                           // Startwert Maximum
	        minDiff        = 30,                                                   // minimaler Abstand zwischden den beiden Handlen
	        propertyKey    = inputMin.getAttribute('name').replace(/\-min$/, ''),  // Schlüssel der Eigenschaft, die gefiltert werden soll
	        handles        = $filterCell.select('.slider-handle'),                 // Handle für Einstellung der Wertespanne
	        $range         = $filterCell.down('.slider-range'),                    // Anzeige der Spanne zwischen den beiden Handles
	        $sliderHolder  = $filterCell.down('.slider-holder'),                   // Element, dass den gesamten Slider enthält
	        holderWidth    = $sliderHolder.getWidth(),                             // Breite des Sliders in Pixel
	        updateTable    = this.filterUpdateFunction,
	        slider,
	        filter,
	        calculateValue;

		// Handle für Slider initialisieren
		slider = new Control.Slider(handles, $sliderHolder, {
			restricted:  true,
			sliderValue: [0, 1],
			onSlide:     function(values) {
				// Während des Verstellens ständig die Anzeige und Eingabefelder aktualisieren
				handles[0].innerHTML = inputs[0].value = calculateValue(values[0]);
				handles[1].innerHTML = inputs[1].value = calculateValue(values[1]);

				// Anzeige zwischden den beiden Handlen aktualisieren
				$range.setStyle({
					left:  Math.round(holderWidth * values[0]) + 'px',
					width: Math.round(holderWidth * values[1] - holderWidth * values[0]) + 'px'
				});
			},
			onChange:    function(values, slider) {
				var diff = Math.round(holderWidth * values[1] - holderWidth * values[0]);

				/*
				 * Wenn der Abstand zwischen den beiden Einstellungen kleiner ist als der Mindestabstand
				 * wird der aktive Handle soweit zurückgesetzt, dass der Mindestabstand wieder herstestellt ist
				 * Zum Abschluss wird dann noch this.onSlide() aufgerufen, damit die Werte der verteckten
				 * Felder aktualisiert werden etc.
				 */
				if (diff < minDiff) {
					if (slider.activeHandleIdx === 0) {
						values[0] = values[1] - minDiff / holderWidth;
						slider.setValue(values[0], 0);
					} else {
						values[1] = values[0] + minDiff / holderWidth;
						slider.setValue(values[1], 1);
					}
					this.onSlide(slider.values);
				}

				// nach dem Loslassen eines Handles die Update Methode der Tabelle aufrufen
				updateTable();
			}
		});

		// Berechnet aus dem Prozentwert des Sliders den tatsächlich angezeigten Wert des Filters
		calculateValue = function(min, max, percentage) {
			return Math.round(min + (max - min) * percentage);
		}.curry(minValue, maxValue);

		// Filter definieren, dazu Wert der Zeile und des Eingabefeldes auslesen und Vergleichen
		filter = function(propertyKey, input, isMinValue, row) {
			var rowValue   = parseFloat(this.propertyValueForRow(row, propertyKey)),
			    inputValue = parseFloat($F(input));

			return isMinValue ? rowValue >= inputValue : rowValue <= inputValue;
		}.bind(this);

		// Filter mit Eigenschaft verknüpfen
		this.filterForProperty[inputMin.getAttribute('name')] = filter.curry(propertyKey, inputMin, true);
		this.filterForProperty[inputMax.getAttribute('name')] = filter.curry(propertyKey, inputMax, false);

		// Reset Button
		$filterCell.down('a.reset').onclick = function() {
			slider.setValue(0, 0);
			slider.setValue(1, 1);
			slider.options.onSlide(slider.values);
			updateTable();
			return false;
		};
	},

	/**
	 * Einstellung einer Checkbox geändert
	 */
	filterTableRows: function() {
		var properties = $H(this.$filterForm.serialize(true)).keys(),
			rows       = this.findRows();

		rows.map(this.showRow);

		properties.each(function(property) {
			var filter = this.filterForProperty[property];
			rows.each(function(row) {
				if (filter && !filter(row)) {
					$(row).hide();
				}
			});
		}.bind(this));

		this.updateRows();

	},

	/**
	 * Blendet eine Filterzeile ein oder aus
	 */
	toggleFilter: function(event, $filterCell) {
		$filterCell.up('table').toggleClassName('closed');
		return false;
	},


	/**
	 * Click auf einen Spaltenkopf
	 */
	clickOnSortableColumn: function(event, $column) {
		var columnIndex   = $column.previousSiblings().length,               // Index der geklickten Spalte
			columnClasses = $column.classNames(),                            // CSS Klassen der geklickten Spalte auslesen
		    defaultOrder  = columnClasses.include('default-desc') ? 'desc' : 'asc',  // Ist eine Standard-Sortierung gesetzt?
		    currentOrder  = columnClasses.include('ordered-desc') ? 'desc' : columnClasses.include('ordered-asc') ? 'asc' : '',  // Ist aktuelle eine Sortierung gesetzt?
		    newOrder      = currentOrder ? currentOrder == 'desc' ? 'asc' : 'desc' : defaultOrder,  // aktuelle Sortierung umdrehen, wenn vorhanden, ansonsten Standardsortierung
		    itemsToSort   = [],  // Liste der Elemente, die sortiert werden sollen
		    sortType;            // Art der Sortierung (nummerisch, alphabetisch, nach Datum)

		// Art der Sortierung ermitteln
		switch (true) {
		case columnClasses.include('sortable-number'):
			sortType = 'number';
			break;
		case columnClasses.include('sortable-date'):
			sortType = 'date';
			break;
		default:
			sortType = 'char';
		}

		// zu sortierende Elemente sammeln
		this.findRows().each(function($row) {
			itemsToSort.push({
				value: this.rowValue($row, columnIndex, sortType),
				row:   $row
			});
		}.bind(this));

		// Sortieren...
		itemsToSort = itemsToSort.sort(this.compareRow.bind(this));

		// Ergebnis umdrehen, wenn absteigend sortiert werden soll
		if (newOrder == 'desc') {
			itemsToSort = itemsToSort.reverse();
		}

		// Ergebnis rückwärts durchlaufen und Spalte jeweils oben anfügen
		// Über den Zähler werden außerdem noch die Spaltennamen "odd" und "even" verteilt
		itemsToSort.reverse().each(function(item) {
			Element.insert(this.$tableBody, { top: item.row });
		}.bind(this));

		this.updateRows();

		// Alle aktuellen Sortieranzeigen löschen und die aktuelle Spalte markieren
		this.sortableColumns.each(function($col) {
			$col.removeClassName('ordered-asc');
			$col.removeClassName('ordered-desc');
		});
		$column.addClassName('ordered-' + newOrder);

		return false;
	},

	/**
	 * Gibt eine Liste aller Tabellenzeilen zurück
	 */
	findRows: function() {
		return this.$productTable.select('tbody tr');
	},

	/**
	 * Aktualisiert die Tabellenzeilen (fügt die Klassen "odd" und "even" ein,
	 * damit die Zeilen wechselnde Hintergrundfarben erhalten
	 */
	updateRows: function() {
		var i = 1;
		this.findRows().each(function($row) {
			if ($row.visible()) {
				$row.removeClassName('odd');
				$row.removeClassName('even');
				$row.addClassName(i % 2 ? 'odd' : 'even');
				i = i + 1;
			}
		});
	},

	/**
	 * Zeile einblenden
	 */
	showRow: function(row) {
		$(row).setStyle({
			display: 'table-row'
		});
	},

	/**
	 * Zeile ausblenden
	 */
	hideRow: function(row) {
		$(row).setStyle({
			display: 'none'
		});
	},

	/**
	 * Vergleichsfunktion für zwei Zeilen
	 */
	compareRow: function($row1, $row2) {
		return $row1.value == $row2.value ? 0 : $row1.value > $row2.value ? 1 : -1;
	},

	/**
	 * Wert der Spalte index für die Zeile row zurückliefern
	 */
	rowValue: function(row, index, type) {
		var value = $(row).select('td')[index].innerHTML.replace(/&nbsp;/i, ' ');

		switch (type) {
		case 'number':
			value = value.replace(/ /, '');
			value = value.replace(/,/, '.');
			value = value.replace(/^.*?([0-9\.]+).*/, "$1", value).trim();
			return value.match(/^[\.0-9]+/)? parseFloat(value) : 0;
		case 'date':
			return new Date(value);
		default:
			return value.toLowerCase();
		}
	},

	/**
	 * Wert der Eigenschaft propertyKey für die Zeile row zurückliefern
	 */
	propertyValueForRow: function(row, propertyKey) {
		return $(row).down('td.property-' + propertyKey).getAttribute('data-value');
	}
});

Event.observe(document, 'dom:loaded', function() {
	$$('.industry-product-filter').each(function($element) {
		new TesaProductTable($element);
	});
});


/*
 * Hintergrund für Lightbox etc
 */
var TesaBackground = Class.create({
	initialize: function() {
		var _self = this;
		this.callbacks  = {};
		this.background = $(document.createElement('div'));
		this.background.setStyle({
			display:         'none',
			backgroundColor: '#000',
			position:        'absolute',
			top:             0,
			left:            0,
			width:           0,
			height:          0,
			zIndex:          1000
		});
		new Insertion.Bottom(document.body, this.background);
		this.background.onclick = this.clickOnBackground.bindAsEventListener(this);
		Event.observe(window, 'scroll', function() { _self.update(); });
		Event.observe(window, 'resize', function() { _self.update(); });
	},

	setAfterShow: function(object, callback) {
		this.callbacks.afterShow = callback.bindAsEventListener(object);
	},

	setBeforeHide: function(object, callback) {
		this.callbacks.beforeHide = callback.bindAsEventListener(object);
	},

	show: function() {
		var _self = this;
		_self.update();
		new Effect.Appear(_self.background, {
			duration:    0.5,
			to:          0.8,
			beforeStart: _self.callbacks.beforeShow || Prototype.emptyFunction,
			afterFinish: _self.callbacks.afterShow || Prototype.emptyFunction
		});
	},

	hide: function() {
		var _self = this;
		var before = _self.callbacks.beforeHide || Prototype.emptyFunction;
		var after  = _self.callbacks.afterHide || Prototype.emptyFunction;
		_self.callbacks = {};
		new Effect.Fade(_self.background, {
			duration:    0.5,
			to:          0.0,
			beforeStart: before,
			afterFinish: after,
			queue:       'end'
		});
	},

	update: function() {
		var bodyOffset = Position.realOffset(document.body);
		var viewport   = document.viewport.getDimensions();
		this.background.setStyle({
			top:    Math.max(bodyOffset[1] - 100, 0) + 'px',
			width:  viewport.width + 'px',
			height: (viewport.height + 200) + 'px'
		});
	},

	clickOnBackground: function() {
		this.hide();
		return false;
	}
});
TesaBackground.singleton = function() {
	if (!TesaBackground.background) {
		TesaBackground.background = new TesaBackground();
	}
	return TesaBackground.background;
};


/*
 * Homepage Key Visual
 */
var HomepageKeyVisual = Class.create({
	initialize: function(element) {
		var _self = this;

		if (!$(element)) return false;

		this.periodicalExecuter = null;
		this.switching          = false;
		this.currentIdx         = 0;
		this.currentPage        = 0;
		this.frequency          = 5;
		this.duration           = 1;
		this.switchDelay        = 0.2;
		this.switchExecuter     = null;
		this.stage              = $(element).down('.kv-stage');
		this.aStageElement      = this.stage.select('.kv-stageElement');
		this.box                = $(element).down('.kv-box');
		this.holder             = $(element).down('.kv-holder');
		this.aThumb             = this.holder.select('ul li');
		this.aPage              = $(element).select('ul.kv-pages li');
		this.thumbWidth         = 0;
		this.thumbMargin        = 0;
		this.thumbsPerPage      = 0;

		var idx = 0;
		this.aThumb.each(function(e) {
			_self.thumbWidth  = _self.thumbWidth || e.getWidth();
			_self.thumbMargin = _self.thumbMargin || parseInt(e.getStyle('marginRight'));
			Event.observe(e, 'mouseover', _self.mouseOverThumb.bindAsEventListener(_self, idx));
			Event.observe(e, 'mouseout',  _self.mouseOutThumb.bindAsEventListener(_self, idx));
			if (Prototype.Browser.MobileSafari) {
				e.onclick = _self.clickOnThumb.bindAsEventListener(_self, idx);
			}
			if (e.hasClassName('active')) {
				_self.currentIdx = idx;
			}
			idx++;
		});

		idx = 0;
		this.aPage.each(function(e) {
			e.onclick = _self.clickOnPage.bindAsEventListener(_self, idx);
			if (e.hasClassName('active')) {
				_self.currentPage = idx;
			}
			idx++;
		});

		this.thumbsPerPage = Math.floor(this.box.getWidth() / this.thumbWidth);

		this.stage.onmouseover = this.stop.bindAsEventListener(this);
		this.stage.onmouseout  = this.start.bindAsEventListener(this);

		this.start();
	},

	switchToIndex: function(idx) {
		var _self = this;
		idx = idx % this.aThumb.length;
		if (!this.switching && idx != this.currentIdx) {
			this.moveToPage(Math.floor(idx / this.thumbsPerPage));

			this.switching = true;
			this.aThumb.each(function(e) {
				e.removeClassName('active');
			});
			new Effect.Fade(this.aStageElement[this.currentIdx], {
				duration: this.duration
			});
			new Effect.Appear(this.aStageElement[idx], {
				duration: this.duration,
				afterFinish: function() {
					_self.currentIdx = idx;
					_self.aThumb[idx].addClassName('active');
					_self.switching = false;
				}
			});
		}
	},

	moveToPage: function(page) {
		var _self = this;


		if (this.currentPage != page) {
			var x = page * this.thumbsPerPage * (this.thumbWidth + this.thumbMargin);

			// Auf der letzten Seite nur so weit scrollen, dass das letzte Thema ganz rechts stehen bleibt
			if (page + 1 == this.aPage.length && this.aThumb.length % this.thumbsPerPage > 0) {
				x -= (this.thumbsPerPage - this.aThumb.length % this.thumbsPerPage) * (this.thumbWidth + this.thumbMargin);
			}

			this.aPage.each(function(e) {
				e.removeClassName('active');
			});
			new Effect.Move(this.holder, {
				x: -1 * x,
				mode: 'absolute',
				duration: this.duration,
				afterFinish: function() {
					_self.currentPage = page;
					_self.aPage[page].addClassName('active');
				}
			});
		}
	},

	start: function() {
		if (!this.periodicalExecuter) {
			var _self = this;
			this.periodicalExecuter = new PeriodicalExecuter(function(pe) {
				_self.switchToIndex(_self.currentIdx + 1);
			}, this.frequency);
		}
	},

	stop: function() {
		if (this.periodicalExecuter) {
			this.periodicalExecuter.stop();
			this.periodicalExecuter = null;
		}
	},

	clickOnThumb: function(evt, idx) {
		if (this.switchExecuter) this.switchExecuter.stop();
		this.stop();
		this.switchToIndex(idx);
		return false;
	},

	mouseOverThumb: function(evt, idx) {
		var _self = this;
		this.stop();
		if (this.switchExecuter) this.switchExecuter.stop();
		this.switchExecuter = new PeriodicalExecuter(function(pe) {
			pe.stop();
			_self.switchToIndex(idx);
		}, this.switchDelay);
		return true;
	},

	mouseOutThumb: function(evt, idx) {
		var _self = this;
		if (this.switchExecuter) this.switchExecuter.stop();
		this.switchExecuter = new PeriodicalExecuter(function(pe) {
			pe.stop();
			_self.start();
		}, this.switchDelay);
		return true;
	},

	clickOnPage: function(evt, idx) {
		this.moveToPage(idx);
		return false;
	}
});
Event.observe(document, 'dom:loaded', function() {
	new HomepageKeyVisual('homepageKeyVisual');
});


/*
 * Aufruf der Mediengalerie per rel="lightbox"
 */
var TesaLightbox = Class.create({
	initialize: function(link) {
		var _self = this;

		this.currentGallery;
		this.galleryLink = link;
		this.background = TesaBackground.singleton();

		this.lightbox = $(document.createElement('div'));
		this.lightbox.setStyle({
			padding:         '20px',
			width:           '940px',
			overflow:        'hidden',
			position:        'absolute',
			top:             0,
			left:            0,
			zIndex:          1010,
			backgroundColor: 'white',
			display:         'none'
		});

		new Insertion.Bottom(document.body, this.lightbox);

		this.background.setAfterShow(this, this.showLightbox);
		this.background.setBeforeHide(this, this.hideLightbox);
		this.background.show();
	},

	showLightbox: function() {
		var _self = this;
		new Ajax.Updater(_self.lightbox, _self.galleryLink.href, {
			method: 'get',
			onComplete: function() {
				_self.lightbox.select('.close').each(function(close) {
					close.onclick = function() {
						_self.background.hide();
						return false;
					};
				});
				_self.currentGallery = new Gallery(_self.lightbox.down('.gallery'), true);
				_self.updatePosition(true);
				new Effect.Appear(_self.lightbox, {
					duration: 0.5,
					afterFinish: function() {
						_self.currentGallery.switchToElement(null);
					}
				});
			}
		});
	},

	hideLightbox: function() {
		var _self = this;
		new Effect.Fade(this.lightbox, {
			duration: 0.5,
			afterFinish: function() {
				if (_self.currentGallery) _self.currentGallery.remove();
				_self.lightbox.remove();
			}
		});
	},

	updatePosition: function(initLightbox) {
		var bodyOffset = Position.realOffset(document.body);
		var viewport   = document.viewport.getDimensions();
		if (this.lightbox && initLightbox) {
			new Effect.Move(this.lightbox, {
				x:        Math.floor((viewport.width - this.lightbox.getWidth()) / 2),
				y:        (bodyOffset[1] + 10),
				mode:     'absolute',
				duration: 0
			});
		}
	},

	clickOnBackground: function(evt) {
		this.hideLightbox();
		return false;
	}
});
Event.observe(document, 'dom:loaded', function() {
	$$('a[rel="lightbox"]').each(function(link) {
		link.onclick = function() {
			new TesaLightbox(link);
			return false;
		};
	});
});


/*
 * Mediengalerie
 */
var Gallery = Class.create({
	initialize: function(element, autoPlay) {
		var _self = this;

		this.gallery          = $(element);
		this.mediaHolder      = this.gallery.down('.media-holder');
		this.galleryScroller  = this.gallery.down('.gallery-box');
		this.galleryThumblist = this.gallery.down('.gallery-holder ul');
		this.aGalleryThumb    = [];
		this.currentIndex     = 0;
		this.pageWidth;

		// Breite der Liste anpassen, Thumbnails mit Click-Events verknüpfen, aktuelle Datei laden
		this.galleryThumblist.select('li.thumb').each(function(li) {
			_self.aGalleryThumb.push(li);
			var href = li.down('a');
			if (href) {
				href.onclick = _self.clickOnThumb.bindAsEventListener(_self, href);
			}
		});

		// Wenn nur ein Medium gefunden wurde, kann die Thumbnail-Leiste auch versteckt werden
		if (this.aGalleryThumb.length <= 1) {
			this.galleryScroller.hide();
		}

		// Aktuelle und maximale Seitenzahl festlegen
		this.currentPage     = 1;
		if (this.gallery.hasClassName('gallery-small')) {
			this.elementsPerPage = 2;
		} else if (this.gallery.hasClassName('gallery-big')) {
			this.elementsPerPage = 5;
		} else {
			this.elementsPerPage = 4;
		}
		this.totalPages = Math.ceil(this.aGalleryThumb.length / this.elementsPerPage);


		// Steuerungsbuttons mit Events verknüpfen
		this.scrollLeft              = this.galleryScroller.down('.btn-left');
		this.scrollRight             = this.galleryScroller.down('.btn-right');
		this.scrollLeft.onclick      = this.clickOnScrollButton.bindAsEventListener(this, this.scrollLeft, -1);
		this.scrollRight.onclick     = this.clickOnScrollButton.bindAsEventListener(this, this.scrollRight, 1);
		this.mediaHolder.onclick     = this.clickOnMediaHolder.bindAsEventListener(this);
		this.mediaHolder.onmousemove = this.mouseMoveMediaHolder.bindAsEventListener(this);
		this.mediaHolder.onmouseout  = this.mouseOutMediaHolder.bindAsEventListener(this);


		this.switchToElement(null);
	},

	scrollThumbnails: function(toPage) {
		var _self = this;
		if (!this.pageWidth) {
			this.pageWidth = this.gallery.down('.gallery-holder').getWidth();
		}
		if (!toPage) {
			toPage = this.totalPages;
		} else if (toPage > this.totalPages) {
			toPage = 1;
		}
		new Effect.Move(this.galleryThumblist, {
			x:     ((toPage - 1) * this.pageWidth * -1),
			mode:  'absolute',
			queue: 'end',
			afterFinish: function() {
				if (toPage == 1) {
					_self.scrollLeft.hide();
				} else {
					_self.scrollLeft.show();
				}
				if (toPage == _self.totalPages) {
					_self.scrollRight.hide();
				} else {
					_self.scrollRight.show();
				}
			}
		});
		this.currentPage = toPage;
	},

	switchToElement: function(element, autoPlay) {
		var _self = this;
		var isVideo = false;
		var isImage = false;
		_self.mediaHolder.removeClassName('video');

		// Wenn kein Element übergeben wurde das erste aktive Element, oder das erste überhaupt verwenden
		if (!element) {
			var i = 0;
			var found = false;
			this.aGalleryThumb.each(function(li) {
				if (!i++ || (li.hasClassName('active') && !found)) {
					found   = li.hasClassName('active');
					element = li;
				}
			});
		}

		// Alle anderen Elemente deaktivieren
		if (element) {
			element.siblings().each(function(li) {
				$(li).removeClassName('active');
			});
			element.addClassName('active');
			isVideo = element.hasClassName('video');
			isImage = element.hasClassName('image');
		}

		// Thumbnail-Seite des aktiven Elements berechnen und Scroller entsprechend verschieben
		this.currentIndex   = element.previousSiblings().length;
		this.scrollThumbnails(Math.floor(this.currentIndex / this.elementsPerPage) + 1);

		// Ladevorgang ankündigen
		this.beforeLoading();

		var link = element.down('a');
		new Ajax.Updater(this.mediaHolder, link.href, {
			method: 'get',
			evalScripts: true,
			parameters: 'autoplay='+(autoPlay ? '1' : '0'),
			onComplete: function(req, json) {
				if (isImage) {
					var img = _self.mediaHolder.down('img');
					img.onload = function() {
						new Effect.Appear(img);
						_self.afterLoading();
					};
					img.src   = img.title;
					img.title = img.alt;
				} else {
					if (isVideo) {
						_self.mediaHolder.addClassName('video');
					}
					_self.afterLoading();
				}
			}
		});
	},

	clickOnScrollButton: function(evt, element, direction) {
		$(element).blur();
		this.scrollThumbnails(this.currentPage + direction);
		return false;
	},

	clickOnThumb: function(evt, thumb) {
		// Bereits geladene Flowplayer von der Seite entfernen
		$f("*").each(function() {
			this.unload();
		});
		$(thumb).blur();
		this.switchToElement(thumb.up('li'));
		return false;
	},

	imageAction: function(evt) {
		var leftY = null;
		var offset = this.mediaHolder.cumulativeOffset();
		if (this.currentIndex > 0 && this.currentIndex < this.aGalleryThumb.length - 1) {
			leftY = parseInt(offset.left) + Math.floor(parseInt(this.mediaHolder.getWidth()) / 2);
		} else if (this.currentIndex > 0) {
			leftY = parseInt(offset.left) + parseInt(this.mediaHolder.getWidth());
		} else if (this.currentIndex < this.aGalleryThumb.length - 1) {
			leftY = 0;
		} else {
			return false;
		}
		return (Event.pointerX(evt) < leftY) ? 'prev' : 'next';
	},

	clickOnMediaHolder: function(evt) {
		switch (this.imageAction(evt)) {
		case 'prev':
			this.switchToElement(this.aGalleryThumb[this.currentIndex - 1]);
			break;
		case 'next':
			this.switchToElement(this.aGalleryThumb[this.currentIndex + 1]);
			break;
		}
		return false;
	},

	mouseMoveMediaHolder: function(evt) {
		if (this.mediaHolder.hasClassName('loading') || this.mediaHolder.hasClassName('video')) return false;
		switch (this.imageAction(evt)) {
		case 'prev':
			this.mediaHolder.down('.prevImage').show();
			this.mediaHolder.down('.nextImage').hide();
			break;
		case 'next':
			this.mediaHolder.down('.prevImage').hide();
			this.mediaHolder.down('.nextImage').show();
			break;
		}
	},

	mouseOutMediaHolder: function(evt) {
		if (this.mediaHolder.hasClassName('loading') || this.mediaHolder.hasClassName('video')) return false;
		this.mediaHolder.down('.prevImage').hide();
		this.mediaHolder.down('.nextImage').hide();
	},

	beforeLoading: function() {
		this.gallery.addClassName('loading');
	},

	afterLoading: function() {
		this.gallery.removeClassName('loading');

		// Event Handler für Pfeilnavigation
		/*
		var image = this.mediaHolder.down('img');
		if (image && !this.mediaHolder.hasClassName('video')) {
			image.onclick = this.clickOnMainImage.bindAsEventListener(this);
			image.onmousemove = this.mouseMoveMainImage.bindAsEventListener(this);
			image.onmouseout  = this.mouseOutMainImage.bindAsEventListener(this);
		}
		*/

		// Bildunterschrift einblenden
		var currentElement = this.aGalleryThumb[this.currentIndex];
		var data = this.gallery.down('.data-box');
		data.innerHTML = $(currentElement).down('.data-box').innerHTML;
		var newHeight  = Math.max(data.down('.about-box').getHeight(), data.down('.option-list').getHeight());
		new Effect.Morph(data, {
			style: 'height:'+ newHeight + 'px',
			duration: 0.5
		});
	},

	remove: function() {
		this.gallery.remove();
	}
});
Event.observe(window, 'load', function() {
	$$('.gallery').each(function(gallery) {
		var g = new Gallery(gallery);
	});
});


var GalleryBox = Class.create({
	initialize: function(element) {
		var _self = this;

		// Hauptelement
		this.$wrapper           = $(element);

		// Liste aller DIVs, die Medien enthalten
		this.mediaHolder        = this.$wrapper.select('.image-holder');

		// Anzahl der Medien in der Galerie-Box
		this.mediaCount         = this.mediaHolder.length;

		// Liste aller Pager-Blöcke (graue Kästen zur Navigation)
		this.pagerBlocks        = this.$wrapper.select('ul.pager li');

		// Liste aller Titel der Medien
		this.mediaTitles        = this.$wrapper.select('span.medium-title');

		// Index des aktuell dargestellten Mediums
		this.currentIndex       = 0;

		// Liste von Medien, die nach dem aktuellen Wechsel noch angezeigt werden müssen
		// Im Moment wird immer nur das zuletzt zur Liste hinzugefügte Medium angezeigt und die Liste dann gelöscht
		this.indexQueue         = [];

		// Durchschalten durch die Medien automatisch starten?
		this.autoPlay           = this.$wrapper.getAttribute('data-autoplay') ? true : false;

		// Geschwindigkeit für das Überblenden von einem Medium zum nächsten
		this.transitionSpeed    = parseInt(this.$wrapper.getAttribute('data-transition-speed', 10)) || 1;

		// Pause zwischen den Überblendungen
		this.rotationSpeed      = parseInt(this.$wrapper.getAttribute('data-rotation-speed', 10)) || 5;

		// Speichert den PeriodicalExecuter, der für die automatische Rotation verantwortlich ist
		this.rotationExecuter   = null;

		// Gibt an, ob gerade von einem Medium zum nächsten umgeschaltet wird
		this.switching          = false;

		// Gibt an, ob gerade ein Video abgespielt wird
		this.videoPlaying       = false;


		// Verarbeitung abbrechen, wenn kein Pager gefunden wird
		if (!this.pagerBlocks.length) {
			return;
		}

		// Alle Medien bis auf das erste ausblenden
		for (var i = 1; i < this.mediaCount; i += 1) {
			this.mediaHolder[i].setStyle({
				display: 'none'
			});
		}

		// Event Listener (click) für Pager setzen
		this.pagerBlocks.each(function($block, idx) {
			$block.onclick = function() {
				_self.stopRotation();
				_self.showMedium(idx);
				return false;
			};
		});

		// Event Listener für Videos
		// - beim Starten des Videos die Rotation unterbrechen
		// - beim Stoppen und Pausieren des Videos den Status auf "wird nicht abgespielt" setzen
		this.$wrapper.select('.video a').each(function($a) {
			flowplayer($a).onStart(function() {
				_self.videoPlaying = true;
				_self.stopRotation();
			});
			flowplayer($a).onStop(function() {
				_self.videoPlaying = false;
			});
			flowplayer($a).onPause(function() {
				_self.videoPlaying = false;
			});
			flowplayer($a).onFinish(function() {
				_self.videoPlaying = false;
			});
		});

		// Rotation starten, wenn autoPlay gesetzt ist
		this.startRotation();

		// Rotation pausieren, wenn Maus über den Teaser läuft
		this.$wrapper.onmouseover = function() {
			_self.stopRotation();
		};

		// Rotation starten, wenn die Maus den Teaser wieder verlässt
		this.$wrapper.onmouseout = function() {
			_self.startRotation();
		};
	},

	// Automatische Rotation der Medien starten
	startRotation: function() {
		var _self = this;

		// automatische Rotation deaktiviert?
		if (!this.autoPlay) return;

		// Regelmäßigen Wechsel starten, wenn nicht bereits geschehen
		if (!this.rotationExecuter) {
			this.rotationExecuter = new PeriodicalExecuter(function() {
				_self.showNextMedium();
			}, this.rotationSpeed + this.transitionSpeed);
		}
	},

	// Automatische Rotation stoppen
	stopRotation: function() {
		if (this.rotationExecuter) {
			this.rotationExecuter.stop();
			this.rotationExecuter = null;
		}
	},

	// Zeigt das letzte Medium aus dem Queue an (wenn ein Pager Block während eines Bildwechsels geklickt wird)
	showQueuedMedium: function() {
		if (this.indexQueue.length) {
			this.stopRotation();
			this.showMedium(this.indexQueue.pop());
			this.indexQueue = [];
		}
	},

	// Zeigt das nächste Medium nach dem aktuellen an (bzw. das erste nach dem letzten)
	showNextMedium: function() {
		if (!this.videoPlaying) {
			this.showMedium((this.currentIndex + 1) % this.mediaCount);
		}
	},

	// Zeigt das Medium mit dem Index index an
	showMedium: function(index) {
		var _self         = this,
		    currentMedium = this.currentMedium();

		// nichts machen, wenn das aktuelle Bild angezeigt werden soll
		if (index == this.currentIndex) {
			return;
		}

		// Index hinten anhängen, wenn gerade ein Wechsel läuft
		if (this.switching) {
			this.indexQueue.push(index);
			return;
		}

		// Video stoppen
		if (currentMedium.hasClassName('video')) {
			flowplayer(currentMedium.down('a')).stop();
		}

		// Transition beginnen
		this.switching = true;

		// Markierung des aktuellen Pager Block entfernen
		this.pagerBlocks[this.currentIndex].removeClassName('active');
		this.mediaTitles[this.currentIndex].hide();

		// Neues Element einblenden, altes ausblenden
		new Effect.Appear(this.medium(index), {
			duration: _self.transitionSpeed
		});
		new Effect.Fade(currentMedium, {
			duration:    _self.transitionSpeed,
			afterFinish: function() {
				// aktuellen Index setzen und Pager markieren
				_self.currentIndex = index;
				_self.pagerBlocks[_self.currentIndex].addClassName('active');
				_self.mediaTitles[_self.currentIndex].show();
				_self.switching = false;
				_self.showQueuedMedium();
			}
		});
	},

	// Gibt das Medium an der Stelle index zurück
	medium: function(index) {
		return this.mediaHolder[index];
	},

	// Gibt das aktuelle Medium zurück
	currentMedium: function() {
		return this.medium(this.currentIndex);
	}
});

Event.observe(document, 'dom:loaded', function() {
	$$('.teaser-gallery').each(function($teaser) {
		var g = new GalleryBox($teaser);
	});
});







var CommerceConnectorPopup = Class.create({
	initialize: function() {
		var _self = this;
		this.href = null;

		_self.background;

		Event.observe(window, 'load', function() {
			$$('.stockist a').each(function(a) {
				a.onclick = _self.clickOnButton.bindAsEventListener(_self, a.href);
			});
		});
	},

	show: function() {
		var _self = this;
		var a = new Ajax.Request(this.href, {
			method: 'get',
			evalScripts: true,
			onSuccess: function(req, json) {
				new Insertion.After(_self.background.background, req.responseText);
				var $e     = $('commerceConnector');
				var dim    = $e.getDimensions();
				var scroll = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.documentElement.scrollTop;
				var offset = -1 * (parseInt(dim.height) - parseInt(scroll));
				$e.setStyle({
					top:    offset+'px',
					zIndex: _self.background.background.getStyle('zIndex') + 1
				});

				new Effect.Move($e, {
					y: dim.height,
					mode:'relative'
				});

				Event.observe(window, 'scroll', function() { _self.updatePosition(); });
				Event.observe(window, 'resize', function() { _self.updatePosition(); });

				_self.parseResponse();
			}
		});
	},

	hide: function() {
		var _self = this;
		if ($('commerceConnector')) {
			new Effect.Move($('commerceConnector'), {
				y:           $('commerceConnector').getHeight() * -1,
				mode:        'relative',
				afterFinish: function() {
					$('commerceConnector').remove();
					if (_self.background) _self.background.hide();
				}
			});
		}
	},

	updatePosition: function() {
		new Effect.Move('commerceConnector', {
			y: typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.documentElement.scrollTop,
			mode:'absolute',
			duration:0.5
		});
	},

	parseResponse: function(code) {
		var _self = this;

		$('commerceConnector').select('.close').each(function(a) {
			a.onclick = _self.clickOnClose.bindAsEventListener(_self);
		});

		$('commerceConnector').select('.ajax').each(function(e) {
			switch (e.nodeName) {
			case 'A':
				e.onclick  = _self.clickOnAjaxLink.bindAsEventListener(_self, e.href);
				break;
			case 'FORM':
				e.onsubmit = _self.submitAjaxForm.bindAsEventListener(_self, e);
			}
		});
	},

	clickOnAjaxLink: function(evt, href) {
		var _self = this;
		var a = new Ajax.Updater('commerceConnector', href, {
			method: 'get',
			evalScripts: true,
			onComplete: function(req, json) {
				_self.parseResponse();
			}
		});
		return false;
	},

	submitAjaxForm: function(evt, form) {
		this.clickOnAjaxLink(evt, form.action + '?' + form.serialize());
		return false;
	},

	clickOnButton: function(evt, href) {
		this.href = href;
		this.background = TesaBackground.singleton();
		this.background.setAfterShow(this, this.show);
		this.background.setBeforeHide(this, this.hide);
		this.background.show();
		return false;
	},

	clickOnClose: function(evt) {
		this.background.hide();
		return false;
	}
});

var TesaTouch = Class.create({
	initialize: function(element, hOption) {
		this.element = $(element);
		this.initVariables();
		this.deltaX    = hOption.deltaX || 1;
		this.deltaY    = hOption.deltaY || 1;
		this.minLength = hOption.minLength || 20;
		this.restrict  = hOption.restrict || null;

		this.onStart  = hOption.onStart || Prototype.emptyFunction;
		this.onEnd    = hOption.onEnd || Prototype.emptyFunction;
		this.onCancel = hOption.onCancel || Prototype.emptyFunction;
		this.onMove   = hOption.onMove || Prototype.emptyFunction;
		this.onStep   = hOption.onStep || Prototype.emptyFunction;

		this.element.ontouchstart   = this.touchStart.bindAsEventListener(this);
		this.element.ontouchend     = this.touchEnd.bindAsEventListener(this);
		this.element.ontouchmove    = this.touchMove.bindAsEventListener(this);
		this.element.ontouchcancel  = this.touchCancel.bindAsEventListener(this);

	},

	initVariables: function(hOption) {
		this.fingerCount = 0;
		this.startX = 0;
		this.startY = 0;
		this.curX = 0;
		this.curY = 0;
		this.stepsX = 0;
		this.stepsY = 0;
	},

	touchStart: function(evt) {
		this.initVariables();
		this.fingerCount = evt.touches.length;
		if (this.fingerCount == 1) {
			this.startX = evt.touches[0].pageX;
			this.startY = evt.touches[0].pageY;
			this.onStart(this.startX, this.startY);
		} else {
			this.touchCancel(evt);
		}
	},

	touchMove:function(evt) {
		if (evt.touches.length == 1) {
			this.curX = evt.touches[0].pageX;
			this.curY = evt.touches[0].pageY;

			var length = Math.round(Math.sqrt(Math.pow(this.curX - this.startX, 2) + Math.pow(this.curY - this.startY, 2)));
			if (length >= this.minLength) {
				var direction = this.direction();
				if (!this.restrict ||
				(this.restrict == 'horizontal' && (direction == 'left' || direction == 'right')) ||
				(this.restrict == 'vertical' && (direction == 'up' || direction == 'down'))) {
					evt.preventDefault();
					var stepsX = Math.floor((this.curX - this.startX) / this.deltaX);
					var stepsY = Math.floor((this.curY - this.startY) / this.deltaY);
					this.onMove(direction, length);
					if (stepsX != this.stepsX || stepsY != this.stepsY) {
						this.onStep(direction, stepsX - this.stepsX, stepsY - this.stepsY);
						this.stepsX = stepsX;
						this.stepsY = stepsY;
					}
				}
			}

		} else {
			this.touchCancel(evt);
		}
	},

	touchEnd:function(evt) {
		this.onEnd(this.curX, this.curY);
	},

	touchCancel:function(evt) {
		this.onCancel(this.curX, this.curY);
	},

	angle: function () {
		var X = this.startX - this.curX;
		var Y = this.curY - this.startY;
		var Z = Math.round(Math.sqrt(Math.pow(X, 2) + Math.pow(Y, 2))); //the distance - rounded - in pixels
		var r = Math.atan2(Y, X); //angle in radians (Cartesian system)
		var angle = Math.round(r * 180 / Math.PI); //angle in degrees
		if (angle < 0) {
			angle = 360 - Math.abs(angle);
		}
		return angle;
	},

	direction: function () {
		var angle = this.angle();
		if ((angle <= 45) && (angle >= 0) ) {
			return 'left';
		} else if ((angle <= 360) && (angle >= 315) ) {
			return 'left';
		} else if ((angle >= 135) && (angle <= 225) ) {
			return 'right';
		} else if ((angle > 45) && (angle < 135) ) {
			return 'down';
		} else {
			return 'up';
		}
	}

});

var TesaAutocompleter = null;
if (Prototype.Browser.IE && "undefined" == typeof document.documentMode || Prototype.Browser.IE && document.documentMode < 8) {
	TesaAutocompleter = Class.create(Ajax.Autocompleter, {
		initialize: function($super, element, update, url, options) {
			$super(element, update, url, options);
			this.clicked_outside = false;
			Event.observe(document, "click", this.onDocumentClick.bindAsEventListener(this));
			this.element.stopObserving("blur");
			this.element.observe("blur", this.onBlurOverride.bindAsEventListener(this));
		},
		onDocumentClick: function(event) {
			if (this.element.id != event.target.id) {
				this.clicked_outside = true;
			}
		},
		onBlurOverride: function(event) {
			var thisObject = this;
			var callback = function() {
				if (thisObject.clicked_outside) {
					thisObject.clicked_outside = false;
					thisObject.onBlur(event);
				} else {
					thisObject.element.focus();
				}
			};
			setTimeout(callback, 200);
		}
	});
} else {
	TesaAutocompleter = Ajax.Autocompleter;
}

var TesaInfographic = Class.create({
	initialize: function(element) {
		var _self = this;

		this.$wrapper = $(element);
		this.spots = this.$wrapper.select('.spot');
		this.boxes = this.$wrapper.select('.messagebox');
		this.$currentBox;

		this.$wrapper.select('.messagebox .close').each(function($close) {
			$close.onclick = _self.clickOnClose.bindAsEventListener(_self, $close);
		});

		this.spots.each(function($spot) {
			$spot.onclick = function() {
				var idx = _self.spots.indexOf($spot);
				_self.openMessageBox(_self.boxes[idx]);
				return false;
			};
		});
	},

	clickOnClose: function(event, $close) {
		this.closeMessageBox();
		return false;
	},

	openMessageBox: function($box) {
		this.closeMessageBox();
		$box.addClassName('open');
		this.$currentBox = $box;

		$box.setStyle({
			top: Math.round((this.$wrapper.getHeight() - $box.getHeight()) / 2) + 'px'
		});
	},

	closeMessageBox: function() {
		if (this.$currentBox) {
			this.$currentBox.removeClassName('open');
			this.$currentBox = null;
		}
	}
});

Event.observe(document, 'dom:loaded', function() {
	$$('#infographic').each(function($infographic) {
		var i = new TesaInfographic($infographic);
	});
});


/* Standardeinstellungen für Video-Player */
var Videoplayer = Class.create({});
Videoplayer.defaults = {
	controls: {
		buttonColor:        '#FFFFFF',
		progressColor:      '#E60000',
		progressGradient:   'none',
		bufferColor:        '#999999',
		sliderColor:        '#999999',
		sliderBorder:       '#999999',
		volumeColor:        '#E60000',
		volumeSliderColor:  '#999999',
		volumeGradient:     'none',
		backgroundColor:    'rgba(0, 0, 0, 0.3)',
		backgroundGradient: 'none'
	},
	canvas: {
		background: '#ff0000'
	}
};
