/**
 * @author Matze
 */


var config = new Hash();


$(document).observe("dom:loaded", function() {
	
	// wenn wir mit nem normalen Browser hier sind, initialisiere
	// die dynamischen Funktionalitaeten der Seite
	if (!isIE6OrLess()) {
		
		// Füge dem body Klasse hinzu, damit im CSS zwischen JS und
		// Non-JS unterschieden werden kann
		$(document.body).addClassName('dynd');
		
		// initialisiere globales Overlay
		window.overlay = new Overlay($('overlay'));
		
		// Initialisiere die JS-Pulldowns
		$$('.jspd').each(function(elm){
			new Pulldown(elm);
		});
		
		// Initialisiere den News-Pager
		if ($('feedcontent')) {
			new Feedpager($('feedcontent'), { showCount: 2 });
		}
		
		// Initialisiere die Initiativen-Links
		if (config.get("init-links")) {
			$(config.get("init-links")).each(function(elm) {
				new InitLink(elm);
			});
		}

		// Initialisiere den Chronik-Slider
		if ($('timelineslider')) {
			chronik = new ChronikSlider({});
		}
		
		// Initialisiere die Slideshows
		$$('.slideshow').each(function(elm){
			new Pager(elm, { showCount: 1 });
		});

		// Initialisiere die Auf-Zu-Schieber
		$$('.openhandler').each(function(elm){
			new Expandable(elm);
		});
		
		// initialisiere den Über-Uns-Link (Video)
		if ($('ueberuns')) {
			$('ueberuns').observe('click', function(event) {
				event.stop();
				
				if ($('ueberunscontent')) {
					$('ueberunscontent').setStyle("left:"+ ($(document.body).getWidth()/2 - $('ueberunscontent').getWidth()/2) +"px");
					overlay.show($('ueberunscontent'));
				}
			});
		}
		
		// initialisiere das Layer am Footer bei Klick auf Fingerstern
		if ($('layertrigger') && $('sternlayer')) {
			$('layertrigger').observe('click', function(event) {
				event.stop();
				if (overlay.show($('sternlayer'))) {
				}
			});
			
			$('footerlogo').observe('mouseover', function(event) {
				if (!overlay.isOpen()) {
					Effect.Queues.get('footer').each(function(effect){
						effect.cancel();
					});
					
					new Effect.Parallel([new Effect.Morph($('layertrigger').down("img"), {
						style: "width:142px;",
						sync: true
					}), new Effect.Morph($('footerlogo'), {
						style: "top:-20px;",
						sync: true
					})], {
						duration: 0.5,
						delay: 0.1,
						queue: {
							scope: 'footer'
						}
					});
				}
			});
			
			$('footerlogo').observe('mouseout', function(event) {
				Effect.Queues.get('footer').each(function(effect) { effect.cancel(); });
				
				new Effect.Parallel([
						new Effect.Morph($('layertrigger').down("img"), {
							style: "width:75px;",
							sync: true
						}),
						new Effect.Morph($('footerlogo'), {
							style: "top:0px;",
							sync: true
						})
					], {
						duration:0.5,
						delay:0.1,
						queue: {
							scope:'footer'
						}
					}
				);
			});
		}
		
		// Versieh alle inputs, deren Inhalt ungueltig ist, mit dem entsprechenden ARIA-Attribut
		$$('label').each(function(label) {
			if (label.hasClassName('error')) {
				$(label.readAttribute("for")).writeAttribute('aria-invalid', 'true');
			}
		});
		
	}
	// wenn es der IE6 ist, mach nur das noetigste
	else {
		
		// nur das erste Bild jeder Slideshow anzeigen
		$$('.slideshow').each(function(elm){
			elm.down("li").setStyle("display:block;");
		});
		
		// das Overlay so groß wie die Seite machen
		if ($('overlay')) {
			if ($('overlay').visible()) {
				$('overlay').setStyle({
					height: (Math.max($(document.viewport).getHeight(), $(document.body).getHeight()) - parseInt($('overlay').getStyle("top")))+"px"
				});				
			}
		}		
	}	
});


var Overlay = Class.create({
	initialize: function(elm) {
		this.element = $(elm).hide();
		this.open = false;
		this.content = null;
		this.lastContent = null;
		
		this.element.observe('click', function(event) {
			event.stop();
			this.hide();
		}.bind(this));
	},
	show: function(content) {
		this.content = content;
		if (!this.open && this.content) {
			
			this.element.setStyle({
				height: (Math.max($(document.viewport).getHeight(), $(document.body).getHeight()) - $('topbar').getHeight())+"px"
			});
			
		
			this.element.appear({
				duration: 0.4,
				to:0.8,
				afterFinish: function() {
					this.open = true;
					document.fire("overlay:opened");
					
					if (this.content) {
						this.content.appear({duration:0.4});
					}
					
				}.bind(this)
			});
			
			this.lastContent = this.content;
			return true;
		}
		else if(this.content && this.content != this.lastContent) {
			this.lastContent.fade({duration:0.4});
			this.content.appear({duration:0.4});
			this.lastContent = this.content;
			return true;
		}
		else {
			return false;
		}
	},
	hide: function() {
		if (isIE6OrLess()) {
			return true;
		}
		
		if (this.open) {
			if (this.content) {
				this.content.fade({duration:0.4});
			}
			
			this.element.fade({
				duration: 0.4,
				afterFinish: function() {
					this.open = false;
					document.fire("overlay:closed");
				}.bind(this)
			});
			return true;
		}
		else {
			return false;
		}		
	},
	isOpen: function() {
		return this.open;
	}
});



var InitLink = Class.create({
	// als elm erwartet wird ein objekt mit den folgenden eigenschaften:
	/*
	{
		id: 'init-biene',
		url: "snippets/get.php?key=biene",
		activeImg: "img/content/logo-biene-active.png",
		inactiveImg: "img/content/logo-biene-inactive.png"
	}
	*/
	initialize: function(elm, root) {
		
		lg("start initializing InitLink");
		
		// setze defaultwerte
		root = root || $(document.body);			// höchste Initalisierungsebene (im Normalfall <body>)
		this.content = null;						// cache-variable für ajax-inhalt
		this.elements = root.select("."+elm.id);	// elements beinhaltet alle relevanten Links

		// wenn elements leer ist, brich die ganze Initialiserung ab
		if (!this.elements[0]) {
			lg("no link in DOM, aborted initializing InitLink");
			return;
		} 

		this.url = elm.url;
		this.activeImg = elm.activeImg;
		this.inactiveImg = elm.inactiveImg;
		
		// hol dir das derzeitige Bild, das den Link in der oberen Box repräsentiert
		this.domimg = $$("."+elm.id).find(function(link){
			if (link.down("img") && link.down("img").hasClassName('stickylink'))
				return link.down("img");
		});
		if (this.domimg) {
			this.domimg = this.domimg.down("img");
			this.defaultImg = this.domimg.src;
		}
		
		// in welchem Container befinden wir uns? muss später animiert werden
		this.expandable = this.elements[0].up(".elementcontainer").down(".subelement").identify();
		
		// setze EventListener auf alle meine Links
		this.elements.each(function(link){
			link.observe("click", this.click.bindAsEventListener(this));
		}.bind(this));
		
		// listen auf diese Events
		document.observe("initlinks:activate", this.setActive.bind(this));
		document.observe("initlinks:deactivate", this.setInactive.bind(this));
		document.observe("initlinks:reset", this.setDefault.bind(this));
		
		this.boundLoadAjax = this.loadAjax.bind(this);
		lg("finished initializing InitLink");
	},
	click: function(event) {
		event.stop();
		
		
		// aktiviere dieses Linkbild (if) bzw. setze alle Linkbilder zurück (else) 
		if (this.domimg) {
			// deaktiviere alle Links
			document.fire("initlinks:deactivate");
			lg("active set");
			this.domimg.src = this.activeImg;
		} else {
			document.fire("initlinks:reset");
		}
		
		// sollte der container offen sein, blende den
		// Inhalt aus und lade danach den neuen Inhalt
		if ($(this.expandable).hasClassName("active")) {
			new Effect.Morph($("init-contentcontainer"), {
				duration: 0.4,
				style: "opacity:0",
				afterFinish: this.boundLoadAjax,
				queue: {
					scope: $("init-contentcontainer").identify(),
					limit: 1
				}
			});
		}
		// sonst lade einfach direkt den neuen Inhalt
		else {
			this.loadAjax();
		}
	},
	loadAjax: function() {
		lg("loadAjax()");
		
		// nimm den content aus dem cache, wenn er schon vorhanden sein sollte
		if (this.content) {
			lg("Content taken from cache.");
			$('init-contentcontainer').update(this.content);
			this.initializeDynamicContent();
			this.reopenContainer();
		}
		// lade den content per ajax, da er noch nicht im cache war
		else {
			lg("Content not in cache.");
			new Ajax.Request(this.url, {
				onSuccess: function(transport) {
					lg("Ajax success.");
					this.content = transport.responseText;
					$('init-contentcontainer').update(this.content);
					this.initializeDynamicContent();
					this.reopenContainer();
				}.bind(this)
			});
		}
	},
	initializeDynamicContent: function() {
		// initialisiere die Links in dem neuen Inhalt
		// (wenn keine vorhanden sein sollten, kümmert sich die Klasse automatisch darum)
		if (config.get("init-links")) {
			$(config.get("init-links")).each(function(elm) {
				new InitLink(elm, $('init-contentcontainer'));
			});
		}
					
		// Initialisiere die Slideshows (falls welche drin sein sollten)
		$('init-contentcontainer').select('.slideshow').each(function(elm){
			new Pager(elm, { showCount: 1 });
		});
		
		document.fire("expandable-"+this.expandable+":resize");
	},
	reopenContainer: function() {
		lg("reopenContainer()");

		// wenn der container offen ist, lass den inhalt einfaden
		if ($(this.expandable).hasClassName("active")) {
			this.containerFadeIn();
		}
		// ist der container geschlossen gewesen, sende das signal, ihn zu öffnen
		else {
			document.fire("expandable-"+this.expandable+":open");
			lg("fired: expandable-"+this.expandable+":open");
		}
	},
	containerFadeIn: function() {
		// definiere gebundene Funktion
		this.boundFunc = function() {
			new Effect.Morph($("init-contentcontainer"), {
				duration: 0.4,
				style: "opacity:1",
				queue: {
					scope: $("init-contentcontainer").identify(),
					limit: 1
				}
			});
			document.stopObserving("expandable-"+this.expandable+":finishedResizing", this.boundFunc);
		}.bind(this);
		
		// observe ob der container fertig ist mit resizen, ruf dann die gebundene funktion auf (s.o.)
		document.observe("expandable-"+this.expandable+":finishedResizing", this.boundFunc);
		// gib dem container den befehl, zu resizen
		document.fire("expandable-"+this.expandable+":resize");

	},
	// die folgenden drei Funktionen setzen den Aktiv-Zustand des Link-Bildes (sofern vorhanden)
	setInactive: function() {
		lg("setInactive");
		if (this.domimg){
			this.domimg.src = this.inactiveImg;
		} 
	},
	setActive: function() {
		lg("setActive");
		if (this.domimg){
			this.domimg.src = this.activeImg;
		}
	},
	setDefault: function() {
		lg("setDefault");
		if (this.domimg){
			this.domimg.src = this.defaultImg;
		}
	}
});

var Pulldown = Class.create({
	initialize: function(elm) {
		lg("start initializing Pulldown");
		this.element = elm;
		this.trigger = this.element.down(".pdhandler");
		this.content = this.element.down('.pdflesh');
		this.closeBtn = this.element.down(".pdclose") || null;
		this.opened = false;
		
		this.setLinkTabIndex(-1);

		var bordertop = 0;
		var borderbottom = 0;
		// Mindestbreite auf die Breite des Trigger setzen
		if (this.content.getWidth() < this.trigger.getWidth()) {
			this.content.setStyle({
				width: (this.trigger.getWidth() - parseInt(this.trigger.getStyle("borderLeftWidth")) - parseInt(this.trigger.getStyle("borderRightWidth")) ) + "px"
			});
		}

		this.boundBodyClicked = this.bodyClicked.bindAsEventListener(this);

		this.trigger.observe("click", this.click.bindAsEventListener(this));

		// wenn ein CloseButton angegeben wurde (optional), dann mit Schließmechanik versehen.
		if (this.closeBtn) {
			this.closeBtn.observe("click", this.hide.bindAsEventListener(this));
		}
		
		// wenn schon mit Klasse "active" versehen, dann soll das Pulldown initial geöffnet sein
		if (this.element.hasClassName("active")) {
			this.show();
		}
		lg("end initializing Pulldown");
	},
	setLinkTabIndex: function(tabindex){
		var links = this.content.select('a');
		links.each(function(link){
			link.writeAttribute('tabindex', tabindex);
		});
	},
	click: function(event) {
		if (this.opened) {
			this.hide();
		} else {
			this.show();
		}
	},
	show: function() {
		if (!this.opened) {
			this.content.setStyle({position:"relative",left:"0px"});
			this.content.writeAttribute('aria-hidden', 'false');
			this.setLinkTabIndex(0);
			this.opened = true;
			this.element.addClassName("active");

			// this checks if tooltip would be outside of the document and moves it to the left until it fits in
			var dims = this.content.getDimensions();
			var vport = document.viewport.getDimensions();
			
			while (parseInt(this.content.viewportOffset().left)+dims.width+2 > vport.width) {
				this.content.setStyle({
					left: (parseInt(this.content.getStyle("left"))-2)+"px"
				});
			}

			var that = this;
			var temp = function() {
				document.observe("mousedown", that.boundBodyClicked);
			}.delay(0.2);
			
			
		}
	},
	hide: function() {
		if (this.opened) {
			this.content.setStyle({position:"absolute",left:"-10000px"});
			this.content.writeAttribute('aria-hidden', 'true');
			this.setLinkTabIndex(-1);
			this.opened = false;
			this.element.removeClassName("active");

			document.stopObserving("click", this.boundBodyClicked);
		}
	},
	bodyClicked: function(event) {
		var sOffset = document.viewport.getScrollOffsets();
		var pos = {
			x: event.pointer().x + sOffset[0],
			y: event.pointer().y + sOffset[1]
		};
		if (!isInElement(pos, this.content)) {
			this.hide();
			document.stopObserving("mousedown", this.boundBodyClicked)
		}
	}
});

var Pager =  Class.create({
	initialize: function(elm, params) {
		lg("start initializing Pager");
		
		params = params || {};
		this.element = elm;
		this.entries = this.element.select("li");
		this.next = this.element.down('.next');
		this.prev = this.element.down('.prev');
		this.activePage = 1;
		this.showCount = params.showCount || 2;
		this.pageCount = this.entries.eachSlice(this.showCount).length;
		this.pagenum = this.element.down('.pagenum');
		
		this.createPaging();
		
		// initialen Inhalt anzeigen
		this.showPage(this.activePage);
		
		this.next.observe("click", this.showNext.bindAsEventListener(this));
		this.prev.observe("click", this.showPrev.bindAsEventListener(this));
		
		lg("end initializing Pager");
	},
	createPaging: function() {
		lg("createPaging");
		// wenn mehr als eine Seite vorhanden ist, müssen die Statuspunkte generiert und
		// mit der Klickmechanik versehen werden
		if (this.pageCount > 1) {
			var dot;
			for (i = 0; i < this.pageCount; i++) {
				this.pagenum.insert(dot = new Element("div", {
					className: "dot"
				}));
				dot.observe("click", this.showPage.bind(this, i + 1));
			}
			var width = ((this.pageCount) * this.pagenum.down('.dot').getWidth()) || this.pageCount * 9;
			this.pagenum.setStyle({
				width: width + "px"
			});
		}		
	},
	showNext: function(event) {
		event.stop();
		lg("showNext");
		
		if (this.activePage < this.pageCount) {
			this.showPage(this.activePage+1);
		} else {
			this.showPage(1);
		}
		
	},
	showPrev: function(event) {
		event.stop();
		lg("showPrev");
		
		if (this.activePage > 1) {
			this.showPage(this.activePage-1);
		} else {
			this.showPage(this.pageCount);
		}
	},
	showPage: function(page) {
		lg("showPage("+page+")");
		this.activePage = page;		
		
		// verstecke nicht benötigte und zeige geforderte Seiten
		this.entries.eachSlice(this.showCount).each(function(group, index) {
			if (page != index+1 ) {
				group.invoke("hide");
			} else {
				group.invoke("show");
			}
		});
		
		// CSS noch anpassen an neuen internen Status
		if (this.pagenum.down('.active'))
			this.pagenum.down('.active').removeClassName("active");
		this.pagenum.select('div')[page-1].addClassName("active");
	}
});

// erbt das meiste von Pager, nur initialize() und showPage() muessen ueberschrieben werden
var Feedpager =  Class.create(Pager, {
	initialize: function($super, elm, params) {
		//$super(elm, params);
		lg("start initializing Feedpager");
		
		params = params || {};
		this.element = elm;
		this.entries = this.element.select("li");
		this.next = this.element.down('.next');
		this.prev = this.element.down('.prev');
		this.activePage = 1;

		this.next.observe("click", this.showNext.bindAsEventListener(this));
		this.prev.observe("click", this.showPrev.bindAsEventListener(this));
		
		// groups speichert die anzahl der jeweiligen posts pro seite,
		// also z.B. [1, 2, 1, 1, 2]
		this.groups = [];
		var classPrefix = "news-1of";
		var elmcount;
		for (var i = 0; i < this.entries.length;) {
			
			// hol dir die Klassennamen des Listenelements und die Position
			// unserer Spezialklasse, die wir in classPrefix zwischengespeichert haben
			var classes = this.entries[i].classNames().toString();
			var pos = this.entries[i].classNames().toString().indexOf(classPrefix);
			
			// wenn wir einen validen Klassennamen haben, zieh dir die Anzahl
			// der Elemente in der Gruppe aus dem Namen
			if (pos > -1) {
				elmcount = classes.substr(pos + classPrefix.length, 1);
				elmcount = parseInt(elmcount);
			}
			// ist der Klassenname versehentlicherweise nicht korrekt,
			// setze den elmcount-Wert auf ganz hoch, was zu einem eleganten
			// Abbruch fuehrt
			else {
				elmcount = this.entries.length+1;
			}
			
			// falls versehentlich dem letzten element der newsliste die falsche
			// klasse (z.B. 1of2) mitgegeben wurde, obwohl es alleine ist			
			if (i+elmcount >= this.entries.length ) {
				elmcount = this.entries.length - i;
			}
			
			// fuege die anzahl der posts auf dieser seite den groups hinzu
			this.groups.push(elmcount);
			this.entries[i].addClassName("nodivider");
			// erhoehe die schleifenvariable um den wert der posts, um erst bei den
			// elementen der naechsten seite weiterzumachen und keine doppelt zu zaehlen
			i += elmcount;
			
		}
		
		this.pageCount = this.groups.length;
		this.pagenum = this.element.down('.pagenum');
		
		this.createPaging();

		// initialen Inhalt anzeigen
		this.showPage(this.activePage);

		
		lg("end initializing Feedpager");
		
	},
	showPage: function(page) {
		lg("showPage("+page+")");
		this.activePage = page;
		
		// CSS der Paging-Punkte anpassen an neuen internen Status
		if (this.pagenum.down('.active'))
			this.pagenum.down('.active').removeClassName("active");
		this.pagenum.select('div')[this.activePage-1].addClassName("active");
		
		// verstecke nicht benötigte und zeige geforderte Seiten
		var current = 0;
		for (var i = 0; i < this.groups.length; i++) {
			if (i == this.activePage-1) {
				for (var j = 0; j < this.groups[i]; j++) {
					if (this.entries.length >= current + j) {
						this.entries[current + j].show();
//						lg("show Feedentry:" + (current + j));
					}
				}
			} else {
				for (var j = 0; j < this.groups[i]; j++) {
					if (this.entries.length >= current + j) {
						this.entries[current + j].hide();
//						lg("hide Feedentry:" + (current + j));
					}
				}
			}
			current += this.groups[i];
		}
		
		lg("end showPage");
	}
});


var Expandable = Class.create({
	initialize: function(elm, params) {
		lg("start initialize Expandable");
		this.handler = elm;
		this.element = this.handler.up(".subelement");
		this.content = this.element.down(".shadowcontent");
		this.active = false;
		this.height = this.content.getHeight();
		this.element.identify();  // versieht das Element mit einer ID, falls noch keine vorhanden ist
		
		if (this.element.up('.elementcontainer') && this.element.up('.elementcontainer').down('.secondaryopenhandler')) {
			this.secondaryHandler = this.element.up('.elementcontainer').down('.secondaryopenhandler');
		}
		
		// content initial verstecken, falls nicht eingeblendet
		if (this.content.readAttribute('aria-hidden')=='false') {
			// eingeblendet
			this.content.setStyle({
				overflow:"hidden"
			});
			this.element.addClassName("active")
			this.active = true;
		} else {
			// ausgeblendet
			this.content.setStyle({
				height:"0px",
				overflow:"hidden",
				display:"none"
			});
			this.element.removeClassName("active")
		}
		
		// öffnen-funktionalität
		this.handler.observe("click", this.click.bindAsEventListener(this));
		if (this.secondaryHandler) {
			this.secondaryHandler.observe("click", this.clickSecondary.bindAsEventListener(this));
		}
		
		// listener definieren
		document.observe("expandable-"+this.element.identify()+":toggle", this.click.bindAsEventListener(this));
		document.observe("expandable-"+this.element.identify()+":open", this.open.bind(this));
		document.observe("expandable-"+this.element.identify()+":close", this.close.bind(this));
		document.observe("expandable-all:close", this.close.bind(this));
		document.observe("expandable-"+this.element.identify()+":resize", this.resize.bind(this));
		
		lg("finished initializing Expandable");		
	},	
	updateTitles: function(){
		var from 	= this.active ? 'ausblenden' : 'anzeigen';
		var to 		= this.active ? 'anzeigen' : 'ausblenden';		
		
		this.handler.writeAttribute('title', this.handler.readAttribute('title').split(from).join(to));
		this.handler.update(this.handler.innerHTML.split(from).join(to));
		if (this.secondaryHandler) {
			this.secondaryHandler.writeAttribute('title', this.secondaryHandler.readAttribute('title').split(from).join(to));
		}		
	},
	click: function(event) {
		lg("click");
		event.stop();
		
		// halte alle effekte an
		Effect.Queues.get(this.element.identify()).each(function(effect) { effect.cancel(); });
		
		if (this.active) {
			this.updateTitles();
			this.close();
		}
		else {
			this.updateTitles();
			this.open();
		}
	},
	clickSecondary: function(event) {
		lg("clickSecondary");
		event.stop();
		
		// halte alle effekte an
		Effect.Queues.get(this.element.identify()).each(function(effect) { effect.cancel(); });
		
		if (!this.active) {
			this.updateTitles();
			this.open();
		}
	},	
	open: function() {
		if (!this.active) {
			lg("start opening");
			
			document.fire("expandable-all:close");
			
			// vorbereiten der neuen höhe
			this.content.setStyle({
				display:"block",
				height:"auto"
			});
			// hol die neue hoehe
			this.height = this.content.getHeight();
			
			this.content.setStyle({
				height:"0px"
			});

			// versteck den hilfs-oeeffner
			if (this.secondaryHandler) {
				this.secondaryHandler.hide();
			}
			
			// morphe zu neuer Höhe
			this.element.addClassName("active");
			this.element.up(".elementcontainer").addClassName("active");
			this.active = true;
			new Effect.Morph(this.content, {
				duration: 1,
				style: "height:" + this.height + "px; padding-bottom:4px;",
				afterFinish: this.endOpen.bind(this),
				queue: {
					scope: this.element.identify(),
					limit: 1
				}
			});
		}	
	},
	close: function() {
		if (this.active) {
			lg("start closing");
			this.element.removeClassName("active");
			this.element.up(".elementcontainer").removeClassName("active");
			this.active = false;
			new Effect.Morph(this.content, {
				duration: 1,
				style: "height:0px; padding-bottom:0px;",
				afterFinish: this.endClose.bind(this),
				queue: {
					scope: this.element.identify(),
					limit: 1
				}
			});
		}
	},
	// funktion, die von höhe 1 zu höhe 2 resized
	resize: function() {
		// cache alte höhe
		var tempHeight = this.content.getHeight();
		// hole neue höhe
		this.content.setStyle({
			height:"auto"
		});
		var newHeight = this.content.getHeight();
		// setze wieder auf alte höhe
		this.content.setStyle({
			height:tempHeight+"px"
		});
		
		// morphe zu neuer höhe und feure den dazugehörigen event ab
		new Effect.Morph(this.content, {
			duration: 0.4,
			style: "height:"+newHeight+"px;",
			afterFinish: function() {
				document.fire("expandable-"+this.element.identify()+":finishedResizing");
			}.bind(this),
			queue: {
				scope: this.element.identify(),
				limit: 1
			}
		});
	},
	endOpen: function() {
		lg("end opening");
		document.fire("expandable-"+this.element.identify()+":finishedOpening");
		this.content.writeAttribute('aria-hidden', 'false');
	},
	endClose: function() {
		lg("end closing");
		// zeig den hilfs-oeeffner
		if (this.secondaryHandler) {
			this.secondaryHandler.show();
		}
		this.content.setStyle({
			display:"none"
		});
		document.fire("expandable-"+this.element.identify()+":finishedClosing");
		this.content.writeAttribute('aria-hidden', 'true');
	}
});



/*
 * Suchfunktionalitaeten
 */

function setSearchLocation(params) {
	if ($('searchcontainer') && $('searchid') && $('searchlocation') && params && params.caption && params.value) {
		$('searchid').update(params.caption);
		$('searchlocation').writeAttribute({value: params.value});
//		$('searchcontainer').removeClassName('active');
		$$('#searchcontainer #scope a').invoke('removeClassName', 'active');
		$(params.element).addClassName('active');
		toggleSearchContainer();
		return true;
	} else {
		return false;
	}
}

boundSearchFunction = function(event){
    if (!isInElement(Event.pointer(event), $('searchcontainer'))) {
        toggleSearchContainer();
    }
}

function toggleSearchContainer () {
	if ($('searchcontainer').hasClassName('active')) {
		document.stopObserving("click", boundSearchFunction);
	} else {
		document.observe("click", boundSearchFunction);
	}
	$('searchcontainer').toggleClassName('active');
}



var ChronikSlider = Class.create({
	initialize: function(params){
		this.build();
		this.observePaging();
	},
	build: function() {
		// falls es schon einen slider gibt, eventListener und slider selbst loeschen
		if (this.slider && this.slider.options && this.slider.options.onChange) {
			this.slider.options.onChange = null;
			this.slider = null;
		}
		
		// hol dir die anzahl der jahre
		this.valueElms = $('timelineslider').up().down(".timeline").childElements();

		// berechne den pixel-abstand zwischen den jahren und positioniere die jahre
		var width = Math.floor(($('timelineslider').getWidth() - this.valueElms[0].getWidth()) / (this.valueElms.length-1));
		this.widthVals = [];
		this.valueElms.each(function(li, index) {
			li.setStyle({
				left:Math.floor(index*width - li.getWidth()/2) + "px"
			});
			this.widthVals.push(Math.floor(index*width - li.getWidth()/2));
		}.bind(this));

		// wenn es noch kein aktuelles jahr gibt, hol es dir aus der timeline-beschriftung
		if (!this.currentYear)
			this.currentYear = parseInt(this.valueElms[0].up().down(".active").down().innerHTML);
		
		// wenn es noch kein naechstes jahr gibt, hol es dir aus der timeline-beschriftung.
		// wenn dort keins mehr ist (weil wir im letzten jahr des aktuellen timeframe sind),
		// dann hol es dir aus der URL des von PHP generierten "Next"-Link
		if (!this.nextYear) {
			if (this.valueElms[0].up().down(".active").nextSiblings().length) {
				this.nextYear = parseInt(this.valueElms[0].up().down(".active").nextSiblings()[0].down().innerHTML);
			} else {
				this.nextYear = $('timelinepaging').down('.next').href.toQueryParams()['year'] || 0;
			}
		}
		
		// wenn es noch kein vorheriges jahr gibt, hol es dir aus der timeline-beschriftung.
		// wenn dort keins mehr ist (weil wir im ersten jahr des aktuellen timeframe sind),
		// dann hol es dir aus der URL des von PHP generierten "Prev"-Link
		if (!this.prevYear) {
			if (this.valueElms[0].up().down(".active").previousSiblings().length) {
				this.prevYear = parseInt(this.valueElms[0].up().down(".active").previousSiblings()[0].down().innerHTML);
			} else {
				this.prevYear = $('timelinepaging').down('.prev').href.toQueryParams()['year'] || 0;
			}
		}

		// wenn es noch keinen aktuellen timeframe gibt, hol ihn dir aus der zeitabschnitt-liste
		// anhand der klasse des aktiven timeframes
		if (typeof(this.timeframe) == "undefined") {
			this.timeframe = $('timeframeselector').down('a.active').up('li').previousSiblings().length;
		}
		
		// erstelle den slider
		this.slider = new Control.Slider('timelinehandler', 'timelineslider', {
			minimum: 0,
			maximum: $('timelineslider').getWidth(),
			range: $R(0, this.widthVals[this.widthVals.length-1] + parseInt($('timelinehandler').getStyle("margin-left"))),
			onChange: this.onChange.bindAsEventListener(this),
			values: this.widthVals,
			sliderValue: this.getPositionFromYear(this.currentYear)
		});
		
	},
	observePaging: function() {
		// belege den next-link mit einem eventListener
		if ($('timelinepaging').down('.next')) {
			$('timelinepaging').down('.next').observe("click", this.goToNextYear.bindAsEventListener(this));
		}
		
		// belege den prev-link mit einem eventListener
		if ($('timelinepaging').down('.prev')) {
			$('timelinepaging').down('.prev').observe("click", this.goToPrevYear.bindAsEventListener(this));
		}
		
		// belege die timeframe-links mit einem eventListener
		$('timeframeselector').select('a').each(function(link, index){
			link.observe("click", this.goToTimeframe.bindAsEventListener(this, index));
		}.bind(this));
		
		this.managePagingVisibility();
	},
	// managePagingVisibility sorgt dafuer, dass immer nur die next/previous-Links
	// zu sehen sind, die auch Sinn machen und kuemmert sich um die korrekte
	// auszeichnung des aktiven timeframes
	managePagingVisibility: function() {
		if (this.nextYear) {
			$('timelinepaging').down('.next').show();
			$('timelinepaging').down('.next').update("Weiter zu " + this.nextYear);
		} else {
			$('timelinepaging').down('.next').hide();
		}
		
		if (this.prevYear) {
			$('timelinepaging').down('.prev').show();
			$('timelinepaging').down('.prev').update("Zur&uuml;ck zu " + this.prevYear);
		} else {
			$('timelinepaging').down('.prev').hide();
		}
		
		$('timeframeselector').down("a.active").removeClassName("active");
		$('timeframeselector').select("li")[this.timeframe].down("a").addClassName("active");
	},
	onChange: function(value) {
		// wenn jemand am slider rumzieht, hol dir das neue jahr
		if (this.valueElms[this.getIndexFromPosition(value)].down()) {
			var year = this.valueElms[this.getIndexFromPosition(value)].down().innerHTML;
			this.goToYear(year);
		}
	},
	goToYear: function(year) {
		// AJAX-request, wenn das jahr gewechselt wird (ueber slider oder prev/next-links)
		new Ajax.Request('?', {
			parameters: {
				year: year,
				lastYear: this.currentYear,
				ajax: true
			},
			onSuccess: this.ajaxSuccess.bindAsEventListener(this)
		});
	},
	goToTimeframe: function(event, timeframe) {
		// AJAX-request, wenn der timeframe gewechselt wird
		// (ueber klicks auf die timeframe-links)
		event.stop();
		this.timeframe = timeframe;
		
		new Ajax.Request('?', {
			parameters: {
				timeframe: this.timeframe,
				lastYear: this.currentYear,
				ajax: true
			},
			onSuccess: this.ajaxSuccess.bindAsEventListener(this)
		});
	},
	goToNextYear: function(event) {
		event.stop();
		this.goToYear(this.nextYear);
	},
	goToPrevYear: function(event) {
		event.stop();
		this.goToYear(this.prevYear);
	},
	getIndexFromPosition: function(pixels) {
		var vindex; 
		this.widthVals.each(function(val, index) {
			if (val == pixels) {
				vindex = index;
			}
		});	
		return vindex;
	},
	getIndexFromYear: function(year) {
		var vindex;
		this.valueElms.each(function(elm, index) {
			if (elm.down().innerHTML == year) {
				vindex = index;
			}
		});		
		return vindex;
	},
	getPositionFromYear: function(year) {
		var vposition;
		this.widthVals.each(function(position, index) {
			if (this.valueElms[index].down().innerHTML == year) {
				vposition = position;
			}
		}.bind(this));
		return vposition;
	},
	ajaxSuccess: function(request) {
		// wird ausgefuehrt, wenn das mit dem AJAX-request geklappt hat
		
		// setze die neue umgebung
		this.timeframe = request.responseJSON.timeframe;
		this.currentYear = request.responseJSON.currentYear;
		this.nextYear = request.responseJSON.nextYear;
		this.prevYear = request.responseJSON.prevYear;
		
		if (request.responseJSON.type == "simple") {
			// wenn es ein simpler request war (kein timeframe-wechsel)
			$('yeardetails').update(request.responseJSON.response);
			
			this.valueElms[this.getIndexFromYear(this.currentYear)].up().down(".active").removeClassName("active");
			this.valueElms[this.getIndexFromYear(this.currentYear)].addClassName("active");
			$('timelinehandler').setStyle({ left: this.getPositionFromYear(this.currentYear) + "px" });
			
		} else if (request.responseJSON.type == "complex") {
			// wenn es ein komplexer request war (neues jahr hat anderen timeframe als vorheriges)
			$('timelinecontainer').update(request.responseJSON.timelinecontent);
			this.build();
		}
		
		// aktualisiere noch die anzeige der prev/next/timeframe-links
		this.managePagingVisibility();
	}
});



/**
 * Prueft, ob point innerhalb der Grenzen von elm liegt. Gibt true oder false zurueck.
 * @param {x:integer, y:integer} point
 * @param {Object} elm
 * @return boolean true, wenn point innerhalb von elm liegt, sonst false
 */
function isInElement(point, elm) {
	var x = point.x;
	var y = point.y;
	var elm = elm;

	 var dOffset = document.viewport.getScrollOffsets();

	if ((x > elm.viewportOffset()[0]+elm.cumulativeScrollOffset()[0]+dOffset[0]+elm.getWidth() || x < elm.viewportOffset()[0]+elm.cumulativeScrollOffset()[0]+dOffset[0])
	|| (y > elm.viewportOffset()[1]+elm.cumulativeScrollOffset()[1]+dOffset[1]+elm.getHeight() || y < elm.viewportOffset()[1]+elm.cumulativeScrollOffset()[1]+dOffset[1])) {
		return false;
	} else {
		return true;
	}
}


/**
 * Prueft, ob der verwendete Browser Internet Explorer 6 oder aelter ist.
 * @return boolean true, wenn User Agent IE6 oder aelter ist, sonst false
 */
function isIE6OrLess(){
	var agt=navigator.userAgent.toLowerCase();
	var is_major = parseInt(navigator.appVersion);
	var is_minor = parseFloat(navigator.appVersion);
	var is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
	return (is_ie && (is_major == 4) && (agt.search(/msie [56]\./)!=-1) );
}


/**
 * Stellt Debug-Messages für Firefox, IE8, Opera, Safari, Chrome (Konsole) und IE<8 (alert) zur Verfügung.
 * @param string text
 * @return void
 */
function lg(text) {
	if (false) {
		if (typeof(opera) != "undefined" && opera != null) {
			opera.postError(text);
			return;
		}
		else 
			if (typeof(console) != "undefined" && console != null) {
				console.log(text);
				return;
			}
//			else {
//				alert(text);
//			}
	}
}
