/**
 * Haengt einen Eventhandler an ein DOM Element und faengt alle Events in dem Element ab
 *  auch wenn sie von Kindknoten kommen. Die Abfrage der gespeichetren Funktionen luft ueber
 *  'Eventtyp' und 'Klassenname'. Es kann also nur eine Funktion pro Eventtyp und Klassennamen gespeichert werden.
 */

Element.implement({
	/**
	 * Statt in den Event an das jeweilige Object per addEvent zu hngen, diese Funktion aufrufen
	 * @param {String} eventTyp
	 * @param {String} className
	 * @param {Function} func
	 */
	registerEvent: function(eventTyp, className, func){
		var savedEvents = this.retrieve('savedEvents') || {};
		if (!savedEvents[eventTyp]) {
			if (eventTyp == 'blur') {
				if (Browser.Engine.trident) {
					this.onfocusout = this.handleEvents.bind(this);
				} else {
					this.addEventListener('blur', function(e){this.handleEvents(e)}.bind(this), true );
				}
			} else {
				this.addEvent(eventTyp, this.handleEvents.bindWithEvent(this));
			}
			savedEvents[eventTyp]={};
		}
		savedEvents[eventTyp][className] = func;
		this.store('savedEvents', savedEvents);
		return this;
	},
	handleEvents: function(event){
		var storedEvents = this.retrieve('savedEvents')[(!event.type.match(/DOMMouseScroll|focusout/)) ? event.type : event.type == 'DOMMouseScroll' ? 'mousewheel' : 'blur'];
		if (storedEvents) {
			var target = $(event.target),
				eventIsFired = false;
			while (!eventIsFired && target) {
				target.className.split(' ').some(function(className){
					if (storedEvents[className]) {
						event.target = target;
						storedEvents[className].run(event);
						eventIsFired = true;
						return true;
					}
				}, this);
				target = target.getParent();
			}
		}
	}
});
/**
 * Wait Funktion fr chains
 * @param {Object} duration wie lange soll gestopt werden
 */
Chain.implement({
	wait: function(duration){
		return this.chain(function(){
			this.callChain.delay($pick(duration, 500), this);
		}.bind(this));
	}
});
try {
	Element.implement({
		chains: function(){
			['tween', 'morph'].each(function(effect){
				this.get(effect).setOptions({
					link:'chain'
				});
			}, this);
			return this;
		},
		pauseFx: function(duration, effect) {
			this.chains().get($pick(effect, 'tween')).wait(duration);
			return this;
		}
	});
} catch(e){}

/**
 * Pseudoselectbox frs sparachmenue.
 * @param {Aray} containers DOM Elemente uf die der Effekt angwedent werden soll
 */
var Selectbox = new Class({
	options:{
		toggleClass: null
	},
	initialize: function(containers) {
		$splat(containers).each(function(container) {
			var toggleBox = container.getElement('.jsSelect');
			container.removeClass('jsFreeSelect')
			.addEvents({
				'mouseenter': this.toggle.bindWithEvent(this, toggleBox),
				'mouseleave': this.toggle.bindWithEvent(this, toggleBox)
			});
			this.initialStoring(toggleBox, toggleBox.getSize().y, 0)
		}, this);
	},
	toggle: function(event, toggleBox){
		event.stop();
		toggleBox = toggleBox || $(event.target).retrieve('toggleBox');
		toggleBox.style.overflow = '';
		var tween = toggleBox.retrieve('tween'),
			state = !toggleBox.retrieve('state');
		if (!tween) {
			tween = new Fx.Tween(toggleBox, {link: 'cancel', transition: Fx.Transitions.Circ.easeOut});
			toggleBox.store('tween', tween);
		}
		if ($(document.body).getStyle('fontSize') != toggleBox.retrieve('initialFontsize') && state) {
			this.handleFontsize(toggleBox);
		} else {
			tween.options.duration = (state ? 600 : 300);
			tween.start('height', state ? toggleBox.retrieve('openHeight') : toggleBox.retrieve('closedHeight')).chain(function(){if(state)toggleBox.style.overflow ='visible'});
		}
		if(this.options.toggleClass){
			var target = $(event.target),
				parent = target.getParent('div.le'); // fuer Abschluss Teaser
			$$(parent ? parent.getElements('a.jsToggleAbschluss') : target)[(state ? 'add' : 'remove') + 'Class'](this.options.toggleClass);
		}

		toggleBox.store('state', state);
	},
	handleFontsize: function(toggleBox){
		toggleBox.setStyle('height', 'auto')
		.store('openHeight', toggleBox.getSize().y)
		.store('closedHeight', 0)
		.store('initialFontsize', $(document.body).getStyle('fontSize'));
	},
	initialStoring: function(toggleBox, openHeight, closedHeight, toggler){
		toggleBox.store('openHeight', openHeight)
		.store('closedHeight', closedHeight)
		.setStyle('height', closedHeight)
		.store('initialFontsize', $(document.body).getStyle('fontSize'));
		$splat(toggler).each(function(toggler){
			toggler.store('toggleBox', toggleBox);
		})
	}
});

/**
 * Toggler fr den Abschlussteaser.
 * @param {Array} containers Array mit Abschlussteasern
 */
var Abschluss = new Class({
	options: {
		toggleClass: 'jsShow'
	},
	Extends: Selectbox,
	initialize: function(){
		$('content').getElements('div.jsAbschlussToggle').each(function(container){
			container.registerEvent('click', 'jsToggleAbschluss', this.toggle.bindWithEvent(this))
			.getElements('.le').each(function(le, cnt){
				var closedHeight = le.getElement('h3').getSize().y + le.getElement('p').getSize().y,
					openHeight = le.getSize().y;
				this.initialStoring(le, openHeight, closedHeight, le.getElements('a'));
			}, this);
		}, this);
	},
	handleFontsize: function(toggleBox){
		toggleBox.setStyle('height', 'auto')
		.store('openHeight', toggleBox.getSize().y)
		.store('closedHeight',toggleBox.getElement('h3').getSize().y + toggleBox.getElement('p').getSize().y)
		.store('initialFontsize', $(document.body).getStyle('fontSize'));
	}
});

var Klappliste = new Class({
	options: {
		toggleClass: 'jsShow'
	},
	Extends: Selectbox,
	initialize: function(){
		var content = $('content'),
		togglers = content.getElements('.jsToggler');
		content.registerEvent('click', 'jsToggler', this.toggle.bindWithEvent(this))
		.getElements('.jsToggle').each(function(toggle, i){
			this.initialStoring(toggle,  toggle.getSize().y, 0, togglers[i]);
		}, this);
	}
})

/**
 * Hilfe bei Klick einblenden und bei Mouseout ber dem Text sofort und beim Button nach 200 ms ausblenden 
 * (wenn die Maus bis dahin nicht in den Hilfetext bewegt wurde).
 * @param {Node} containers DOM Element in dem die Hilfebutton
 */
var Help = new Class({
	initialize: function(){
		$$('.jsHelp').each(function(help){
			var tip = help.getElement('div'),
			link = help.getElement('img');
			tip.addClass('jsHide').addClass('jsShowHelp');
			tip.getElement('div')
			tip.addEvent('mouseenter', this.stopTimer.bindWithEvent(this))
			.addEvent('mouseleave', this.hide.bindWithEvent(this, tip));
			link.addEvent('click', this.toggle.bindWithEvent(this, tip))
			.addEvent('mouseleave', this.startTimer.bindWithEvent(this, tip));
		},this)
	},
	toggle: function(event, tip){
		if (event.type === 'click') {
			event.stop();
		}
		tip.toggleClass('jsHide');
	},
	hide: function(event, tip){
		tip.addClass('jsHide');
	},
	startTimer: function(event, tip){
		this.timer = this.hide.delay(200, this, [event, tip]);
	},
	stopTimer: function(){
		$clear(this.timer);
	}
});
var Help02 = new Class({
	initialize: function(){
		$$('.jsHelp').each(function(help){
									
			var tip = help.getElement('div'),
			link = help.getElement('img');
			tip.addClass('jsHide');
			var size = tip.getSize();
			var topPos=size.y-25;
			var theHeight=size.y-50;
			tip.setStyle('top', -topPos+'px');
			
			if (Browser.Engine.trident) {
				this.iframe = new Element('iframe', { 
					'styles': { left: '0', position: 'absolute', top: '0', zIndex: 999, height:theHeight}
				}).injectInside(tip);
				this.iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=1)';
			}
			tip.addEvent('mouseenter', this.stopTimer.bindWithEvent(this))
			.addEvent('mouseleave', this.hide.bindWithEvent(this, tip));
			link.addEvent('click', this.toggle.bindWithEvent(this, tip))
			.addEvent('mouseleave', this.startTimer.bindWithEvent(this, tip));
		},this)
	},
	toggle: function(event, tip){
		if (event.type === 'click') {
			event.stop();
		}
		tip.toggleClass('jsHide');
		
	},
	hide: function(event, tip){
		tip.addClass('jsHide');
	},
	startTimer: function(event, tip){
		this.timer = this.hide.delay(200, this, [event, tip]);
	},
	stopTimer: function(){
		$clear(this.timer);
	}
});
var LinkList = new Class({
	initialize: function(containers){
		$splat(containers).each(function(container){
            var firstLi = container.getElements('li')[0];
            firstLi.className = 'aktiv';
            container.store('activeLink', firstLi)
			.getElements('li').each(function(li){
				li.addEvents({
					'mouseenter': this.blend.bindWithEvent(container, [li, li.getElement('div.subteaser')])
				});
			}, this)
		}, this);
	},
	/**
	 * Blendet den Inhalt bei mouseenter ein und den des zuletzt angezeigten aus
	 * @param {Event} event
	 * @param {Node} li			Link der das mouseEnter ausgelst hat
	 * @param {Node} blendBox	der zum Link gehrente Content der eingeblendet werden soll
	 */
	blend: function(event, li, blendBox){
		var oldLi = this.retrieve('activeLink');
		if (li != oldLi) {
			var tween = blendBox.retrieve('tween');
				oldLi = this.retrieve('activeLink');
				tweenOut = oldLi.getElement('div.subteaser').retrieve('tween');
				stoerer = li.retrieve('stoerer');
			li.className = 'aktiv';
			this.store('activeLink', li);
			oldLi.removeClass('aktiv');
			//Tween initial erstellen
			if (!tween) {
				tween = new Fx.Tween(blendBox, {link: 'cancel', duration: 200});
				blendBox.store('tween', tween);
			}
			//Alten Content ausblenden
			if (tweenOut) {
				var oldStoerer = oldLi.retrieve('stoerer');
				if (oldStoerer) {
					oldStoerer.setStyle('display', 'none');
				}
				tweenOut.start('opacity', 0.5, 0);
			}
			//Aktuellen Content einblenden
			if (stoerer) {
				tween.start('opacity', 0.5, 1).wait(200).chain(function(){
					stoerer.setStyle('display', '')
				});
			} else {
				tween.start('opacity', 0.5, 1);
			}
		}
	}
})

/**
 * Die aktuelle Seite in der contentNav von Popups highlighten
 */
var PopMenuHighLight = new Class({
	initialize: function(){
        var body = $$('body.maxi')[0];
		if ($defined(body)) {
			var string = document.location.href;
			$$('#contentNav a').some(function(a){
				if (string.match(a.get('href'))) {
					a.addClass('active');
					return true;
				}
			})
		}
	}
});

/**
 * Erstellt Lightboxe aus er Kombination von Elementen mit der Klasse 'lightboxContent' bzw. 'lightboxLink'
 *
 */
var Lightbox = new Class({
	initialize: function(){
		var contents = $$('.lightboxContent');
		$$('.lightboxLink').each(function(link, cnt){
			var content = contents[cnt];
			link.store('content', content.removeClass('jsHide').clone())
			.store('height', content.getSize().y)
			.store('width', content.getSize().x)
			.addEvent('click', this.trigger.bindWithEvent(this));
			content.dispose();
		}, this);
	},
	/**
	 * Lightbox an/ausschalten
	 * @param {Event} event
	 */
	trigger: function(event){
		event.preventDefault();
		if (!this.cover) {
			this.create();
		}
		if (this.status) {
			this.fade.start('opacity', 0);
			this.lightbox.addClass('jsHide').set({'styles': {'height': 0}});
		} else {
			var target = $(event.target).hasClass('lightboxLink') ? event.target : event.target.getParent('a.lightboxLink'),
				width= target.retrieve('width'),
				height= target.retrieve('height'),
				bodySize = this.body.getSize();
			this.lightbox.removeClass('jsHide').set({'styles':{
				'top': Math.max(0, this.body.getScroll().y + bodySize.y / 2 - height / 2),
				'left':  Math.max(0, bodySize.x / 2 - width/2 +8)
				}
			});
			target.retrieve('content').replaces(this.lightbox.getElement('div'));
			this.fade.start('opacity', 0.5);
			this.slideHeight.start({
				'height': height
			}).chain(function(){
				var scroll = this.body.getScrollSize();
				this.cover.set({
					'styles': {
						'width': scroll.x,
						'height': scroll.y
					}
				});
			}.bind(this));
		}
		this.status = !this.status;
	},
	/**
	 * Lightbox erstellen
	 */
	create: function(){
		this.body = $$('body')[0];
		var size = this.body.getSize(),
			link = new Element('a', {
				'class': 'close',
				'html': 'Schliessen'
			});
		this.cover = new Element('div', {
			'id': 'cover',
			'class': 'cover noScroll',
			'styles': {
				'width': size.x,
				'height': size.y
			}
		}).inject(this.body);

		//window.addEvent('scroll', this.scrollToCenter.bindWithEvent(this));
		this.status = false;
		this.fade = new Fx.Tween(this.cover, {transition: Fx.Transitions.Pow.easeOut});
		this.lightbox = new Element('div', {
			'id':'lightbox',
			'styles': {
				'height': 0
			}
		});

		link.inject(this.lightbox);
		this.lightboxContent = new Element('div', {
			'class': 'content'
		}).inject(this.lightbox);

		link.clone().addClass('bottom').inject(this.lightbox);

		this.lightbox.registerEvent('click', 'close', this.trigger.bindWithEvent(this))
		.inject(this.body);
		this.slideWidth= new Fx.Tween(this.lightbox);
		this.slideHeight= new Fx.Morph(this.lightbox);
	},
	/**
	 * Scroll die Lightbox in die Mitte des Screens wenn der Bildschrim gescrollt wird
	 */
	scrollToCenter: function(){
		if(!this.lightbox.hasClass('jsHide')){
			if (!this.scrollToCenterFX) {
				this.scrollToCenterFX = new Fx.Tween(this.lightbox, {link: 'cancel', transition: Fx.Transitions.Bounce.easeOut});
			}
			this.scrollToCenterFX.start('top', Math.max(0, this.body.getScroll().y + this.body.getSize().y / 2 - this.lightbox.getSize().y / 2));
		}
	}
})

var Popup = new Class({
	initialize: function(container) {
		container.registerEvent('click', 'jsPopup', this.openPopup);
	},
	openPopup: function(event){
		event.preventDefault();
		var link = $(event.target),
			height = link.hasClass('jsMini') ? 450 : 770;
			width = link.hasClass('jsMini') ? 514 : link.hasClass('jsMidi') ? 666 : 844;
		window.open(link.href, link.target, 'height=' + height + ', width=' + width + ', left=100, top=100, dependent, scrollbars=yes, resizable=yes');
	}
})

var Close = new Class({
	initialize: function(element) {
        if ($defined(element)) {
            element.addEvent('click', function() {
                window.close();
                return false;
            });
        }
	}
})

/***
 * ndern der Schriftgroee in 3 Schritten (ber alternative CSS Dateien) und speichern in einem Cookie.
 */
var Fontsize = new Class({
	initialize: function(element) {
        if($defined(element)) {
            this.styles = $$('link[rel^=alternate]').set('disabled', true);
	        this.setCss(Cookie.read('aragFontsize'));
		    element.registerEvent('click', 'jsFontsize', this.setFontsize.bindWithEvent(this))
		    .registerEvent('keydown', 'jsFontsize', this.setFontsize.bindWithEvent(this))
		    .removeClass('hide');
        }
	},
	setFontsize: function(event) {
		event.stop();
		if (event.key == 'enter' || event.type == 'click') {
			var size = event.target.className.replace('jsFontsize', '').trim();
			this.setCss(size);
			Cookie.write('aragFontsize', size, {duration: 30});
		}
	},
	setCss: function(size) {
		this.styles.each(function(style){
			style.disabled = style.title == size ? false : true;
		});
	}
})

/**
 * Drucken und Bookmarken Funktionen im Seitenfu
 */
var Footer = new Class({
	initialize: function(){
		if ($('close02')) {
			$('close02').addEvent('click', function() {
				window.close();
				return false;
			})
		}
		$('contentFooter').getElements('a').each(function(thePics){
			thePics.addEvent('click', function() {
				if (this.id=='print') {
					window.print();
					return false;
				}else if(this.id=='close') {
					window.close();
					return false;
				}else if(this.id=='recomment') {
					var seite = self.location,
						ws_start = 'Hallo, \n\nich habe folgende interessante Seite entdeckt:\n\n',
						titel = document.title,
						link = 'mailto:?subject='+ titel + '&body=' +  escape(ws_start) + ' ' + titel + ' ' +  escape('\n' + seite);
					this.href = link;
					return true;
				} else if(this.id=='notice') {
					var mac = Browser.Platform.mac,
						apfeltaste = ((mac) ? 'Apfel' : 'Strg'),
						lz_tastatur = 'Bitte ' + apfeltaste + '-D druecken, um ein Lesezeichen fuer diese Seite anzulegen.',
						lz_drag = 'Bitte ziehen Sie diesen Link auf Ihre Lesezeichenleiste.',
						seite = location.href,
						seite = seite.replace(/;jsessionid=[A-F0-9]+/g, '');
					if (Browser.Engine.trident && !mac) {
						window.external.AddFavorite(seite, document.title);
						return false;
					}
					else if (Browser.Engine.presto || Browser.Engine.gecko) {
						this.href = seite;
						this.title = document.title;
						alert(lz_drag);
					} else {
						this.href = seite;
						alert(lz_tastatur);
					}
					return false;
				}
			});
		})
	}
})


var Schnellzugriff = new Class({
	initialize: function(){
        if (!$chk($('schnellzugriff'))) return;
		$('schnellzugriff').getElements('select').each(function(select){
			select.addEvent('change', this.openLink);
		}, this);
	},
	openLink: function(e){
		var select = e.target,
			value = select.options[select.selectedIndex].value.split(';');
		if(value.length<=1){
			window.location.href = value[0];
		}else{
			window.open(value[0], 'fenster', value[1])
		}
	}
})

var Pager = new Class({
    initialize: function(sourceTable, targetTable) {
        if (!$chk(sourceTable)) return;

        $('pager-entries').className = 'hide';
        $('pager-table').className = '';

        this.pageSize;

        this.targetTable = targetTable;
        this.sourceTable = sourceTable.getElements('tr');
        this.numberOfElements = this.sourceTable.length;

        this.displayTexts = $$('.pager-text');
        this.pagerPages = $$('.pager-pages');
        this.pagerPages.addEvent('click', function(e) {
            e.stop();
            if (e.target.tagName=="A") {
                var startIdx = ($(e.target).get('class').toInt() - 1) * this.pageSize.toInt();
                this.trigger(startIdx, this.pageSize);
            }
        }.bindWithEvent(this));

        var select = $('entrySelect');

        select.addEvent('change', function(entry) {
            this.trigger(0, entry.get('value'));
            return false;
            }.bind(this, select));
        select.fireEvent('change');
    },
    moveRows: function(startIndex, pageSize) {
        /* negative pageSize values: show all */
        pageSize = pageSize < 0 ? this.sourceTable.length : pageSize;

        this.targetTable.empty();
        var mystr = "";
        for (var i=startIndex; i < Math.min(this.sourceTable.length, startIndex.toInt()+pageSize.toInt()); i++) {
            mystr += "<tr>" + this.sourceTable[i].innerHTML + "</tr>";
        }
        if (Browser.Engine.trident) {
            this.ieTableInnerHTML(this.targetTable, mystr);
        } else {
            this.targetTable.innerHTML = mystr;
        }
    },
    display: function(startIdx, val) {
        var text = "";
        if (val<0) {
            text = "Alle " + this.numberOfElements + " Einträge";
        } else {
            text = "Einträge " + (startIdx.toInt()+1) + "\u2013" + (startIdx.toInt()+val.toInt()) + " von " + this.numberOfElements;
        }
        this.displayTexts.each(function(h6) {
            h6.set('text', text)
            }, this
        );
    },
    ieTableInnerHTML: function (target, rowHTML) {
            /* Vars */
            target = $(target);

            /* Remove all existing rows */
            while (target.rows.length > 0) {
                target.deleteRow(0);
            }

            /* Create temporary table */
            var tempDiv = document.createElement("div");
            document.body.appendChild(tempDiv);
            tempDiv.innerHTML = '<table id="tempTable" style="display: none">' + rowHTML + '</table>';
            var tt = $("tempTable");

            /* Copy temporary table's rows to target */
            for (var i = 0; i < tt.rows.length; i++) {
                target.appendChild(tt.rows[i].cloneNode(true));
            }

            /* Remove temporary table */
            tt.dispose();
    },
    trigger: function(startIdx, pageSize) {
        var s = startIdx.toInt();
        var p = pageSize.toInt();
        this.moveRows(s, p);
        this.display(s, p);
        this.refreshPager(s, p);
    },
    refreshPager: function(startIndex, pageSize) {
        this.pageSize = pageSize;
        var pages = (this.numberOfElements < pageSize || pageSize < 0 )? 1 : Math.ceil(this.numberOfElements/pageSize);
        var activepage = Math.ceil((startIndex.toInt() + pageSize.toInt())/pageSize.toInt());

        var pagerStart;
        var pagerEnd;
        if (pages>6) {
            pagerStart = Math.min(pages-6, Math.max(1, activepage-2));
            pagerEnd = Math.min(pagerStart+6, pages);
        } else {
            pagerStart = 1
            pagerEnd = pages;
        }

        /* create temporary element */
        var temp = [];
        var temp2 = [];
        for (var i = pagerStart; i <= pagerEnd; i++) {
            var li = new Element('li');
            if (activepage!=i) {
                var t = ( pages>6 && ( i == pagerStart || i == pagerEnd)) ? '...' : i;
                var a = new Element('a', {href: '#', 'class': i + 'page' , text: t});
                a.inject(li)
            } else {
                li.set('text', i);
            }
            if (i!=pagerEnd) {
                new Element('span', {text: ' |'}).inject(li);
            }
            temp[temp.length] = li;
            temp2[temp2.length] = li.clone();
        }
        this.pagerPages[0].empty();
        this.pagerPages[0].adopt(temp);
        this.pagerPages[1].empty();
        this.pagerPages[1].adopt(temp2);
        this.refreshArrows(activepage, pages, startIndex, pageSize);
    },
    refreshArrows: function(activePage, pages, startIndex, pageSize) {
        var back =  $$('.pager-back');
        var forward =  $$('.pager-forward');

        if (activePage==1) {
            back.setStyles({display: 'none'});
        } else {
            back.setStyles({display: ''});
            back.removeEvents('click');
            back.addEvent('click', function() {
                    this.trigger(startIndex-pageSize, pageSize);
                    return false;
                    }.bind(this));
        }

        if (activePage==pages) {
            forward.setStyles({display: 'none'});
        } else {
            forward.setStyles({display: ''});
            forward.removeEvents('click');
            forward.addEvent('click', function() {
                    this.trigger(startIndex+pageSize, pageSize);
                    return false;
                    }.bind(this));
        }

        if (pages==1) {
            back.setStyles({display: 'none'});
            forward.setStyles({display: 'none'});
        }
    }
});
var Testimonial = new Class({
	initialize: function(){
		$$('.kunden').each(function(){

			theLink=$$('.kunden').getChildren('a.txtToggler');
			theText=$$('.kunden').getChildren('div.theText');
		}, this)
	},
	toggleText: function(e){
		/*var select = e.target;

		var value = select.options[select.selectedIndex].value.split(';');
		if(value.length<=1){
			window.location.href = value[0];

		}else{
			window.open(value[0], 'fenster', value[1])
		}*/
	}

});

/**
 * Gallerie Widget
 * @param {String} containerId
 * @param {Object} options folgende Optionen können übergebenen werden:
 *                 stepSize: Pixel um die die Bilder je  Schritt verschoben werden (z.B. Bildbreite +Margin)
 *                 galleryLength: Anzahl der Sichtbaren Bilder
 *                 duration: Verschiebezeit in Millsekunden
 */
var Gallery = new Class({
	Implements: Options,
	options: {
		stepSize: 206,
		galleryLength: 3,
		duration: 700
	},
	initialize: function(container, options){
		this.setOptions(options);
		this.next = container.getElement('.left').addEvent('click', this.move.bindWithEvent(this, -1));
		this.prev = container.getElement('.right').addEvent('click', this.move.bindWithEvent(this, 1));
		this.slide = container.getElement('div.boxContainer').setStyle('left', 0); //IE braucht Wert fuer den ersten Durchgang
		var teasers = this.slide.getChildren();
		this.maxSteps = teasers.length;
		this.step = 0;
		this.fx = new Fx.Tween(this.slide, {
			duration: this.options.duration,
			link: 'cancel'
		});
		for (var i = 0; i < this.options.galleryLength; i++) {
			this.slide.appendChild(teasers[i].clone());
		}
		this.move(null, 0);
	},
	/**
	 * Bewegt die Gallerie um sub Schritte
	 * @param {Event} event
	 * @param {Number} sub
	 */
	move: function(event, sub){
		this.step += sub;
		if (this.step > this.maxSteps) {
			this.step = 1;
			this.slide.setStyle('left', (-(this.step - 1)) * this.options.stepSize + 'px');
		};
		if (this.step < 0) {
			this.step = this.maxSteps - 1;
			this.slide.setStyle('left', (-(this.step + 1)) * this.options.stepSize + 'px');
		};
		this.fx.start('left', -this.step * this.options.stepSize);
	}
});

var CutText = new Class({
	initialize: function(){
		$$('.theText').each(function(p){
			var fulltext= p.get('html');
			p.store('fulltext', fulltext)
			.store('fulltextsize', p.getSize().y)
			.store('state', true);

			var cuttext = p.get('text').substr(0,240),
				cuttext = cuttext.substr(0, cuttext.lastIndexOf(' '))+'...';

			p.store('cuttext', cuttext)
			.set('text', cuttext).
			setStyle('height', p.getSize().y)
			.store('cuttextsize', p.getSize().y)
			.set('tween')
			.getNext().addEvent('click', this.toggleText.pass([p, p.getNext()]));

		}, this)
	},
	toggleText: function(p, button){
		var state = p.retrieve('state');
		if(state){
			p.set('html', p.retrieve('fulltext'))
			.get('tween', {property: 'height'}).start(p.retrieve('fulltextsize'));
		}else{
			p.get('tween', {property: 'height'}).start(p.retrieve( 'cuttextsize')).
			chain(function(){p.set('text', p.retrieve('cuttext'))});
		}
		button.set('text', state ? 'Den ganzen Text anzeigen' : 'Den Text minimieren');
		p.store('state', !state);
	}
})

   /**
            Funktion zur Darstellung von Email-Adressen
        **/
function demaskEml(){
	var eml = document.getElementsByTagName("EML")
	var myEml = new Array();
	for (i=0;i<eml.length;i++){
		myEml[i] = eml[i]
	}
	for (i=0;i<myEml.length;i++){
		var curEml = myEml[i]
		var para = (curEml.getAttribute("para")).split(";")
		var first = para[0]
		var second = para[1]
		var third = para[2]
		var lable = curEml.getAttribute("lable")
		var curCon = document.createElement("span")
		curCon.setAttribute("class","mskeml")
		curCon.setAttribute("class","mskeml")
		if (lable == null){
			curCon.appendChild(document.createTextNode(first))
			curCon.appendChild(document.createTextNode("@"))
			curCon.appendChild(document.createTextNode(second))
			curCon.appendChild(document.createTextNode("."))
			curCon.appendChild(document.createTextNode(third))
		} else {
			curCon.appendChild(document.createTextNode(lable))
		}
		if (curEml.getAttribute("link") == "true"){
			var lnk = document.createElement("A")
			lnk.setAttribute("href","javascript:doMail('"+first+"','"+second+"','"+third+"')")
            lnk.setAttribute("class","link")
			lnk.appendChild(curCon)
			curEml.parentNode.replaceChild(lnk,curEml)
		} else {
			curEml.parentNode.replaceChild(curCon,curEml)
		}
	}
}
function doMail(first,second,third){
	string="mailto:"+first+"@"+second+"."+third
	location.href = string
}

/* deprecated */
var initClicktracker = function(secureID) {
    var c = new ClickTracker($$('body'), secureID);
}

var ClickTracker = new Class({
    initialize: function(container, secureID) {
        this.secureID = secureID;
        container.registerEvent('click', 'ctrack', this.click.bindWithEvent(this));
    },
    click: function(event){
        var classes = event.target.className;
        var regex = /ct-([^ ]*)/;
        if (classes.test(regex)) {
            var decoded = decodeURI(RegExp.$1);
            clickTracker(decodeded, this.secureID);
        }
    }
})

var toSleep = true;
function stopTimer() {
    toSleep = false;
}
function clickTracker(LinkName, secureID) {
    var redirectUrl = "http://www.etracker.de/skin/de.def/img/1px.gif";
    etrackerSink = new Image(1, 1);
    toSleep = true;
    try {
        var useSSL = et_ssl;
    } catch(e) {
        var useSSL = 0
    };
    if (useSSL == 1) {
        redirectUrl = "https://www.etracker.de/skin/de.def/img/1px.gif";
        etrackerSink.src = "https://www.etracker.de/lnkcnt.php?et=" + secureID + "&url=" + redirectUrl + "&lnkname=" + LinkName;
        etrackerSink.onload = stopTimer;
    } else {
        etrackerSink.src = "http://www.etracker.de/lnkcnt.php?et=" + secureID + "&url=" + redirectUrl + "&lnkname=" + LinkName;
        etrackerSink.onload = stopTimer;
    }
    if (toSleep == true) {
        maxDelay(500);
    }
    return true;
}
function maxDelay(gap) {
    var then, now;
    then = new
    Date().getTime();
    now = then;
    while (toSleep == true && (now - then) < gap) {
        now = new Date().
        getTime();
    }
}


var Calendar = new Class({	
	
	options: {
		blocked: [], // blocked dates 
		classes: [], // ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite']
		days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnertag', 'Freitag', 'Samstag'], // days of the week starting at sunday
		direction: 0, // -1 past, 0 past + future, 1 future
		draggable: false,
		months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
		navigation: 2, // 0 = no nav; 1 = single nav for month; 2 = dual nav for month and year
		offset: 0, // first day of the week: 0 = sunday, 1 = monday, etc..
		onHideStart: Class.empty,
		onHideComplete: Class.empty,
		onShowStart: Class.empty,
		onShowComplete: Class.empty,
		pad: 1, // padding between multiple calendars
		tweak: {x: 0, y: 0} // tweak calendar positioning
	},

	// initialize: calendar constructor
	// @param obj (obj) a js object containing the form elements and format strings { id: 'format', id: 'format' etc }
	// @param props (obj) optional properties

	initialize: function(obj, options) {
		// basic error checking
		
		if (!obj) { return false; }
		this.setOptions(options);
		
		// create our classes array
		var keys = ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite'];

		var values = keys.map(function(key, i) {
			if (this.options.classes[i]) {
				if (this.options.classes[i].length) { key = this.options.classes[i]; }
			}
			return key;
		}, this);

		this.classes = values.associate(keys);

		// create cal element with css styles required for proper cal functioning
		this.calendar = new Element('div', { 
			'styles': { left: '-1000px', opacity: 0, position: 'absolute', top: '-1000px', zIndex: 1000}
		}).addClass(this.classes.calendar).injectInside(document.body);
		// iex 6 needs a transparent iframe underneath the calendar in order to not allow select elements to render through
		if (Browser.Engine.trident && Browser.Engine.version < 5) {
			this.iframe = new Element('iframe', { 
				'styles': { left: '-1000px', position: 'absolute', top: '-1000px', zIndex: 999}
			}).injectInside(document.body);
			
			this.iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=1)';
		}

		// initialize fade method
		this.fx = new Fx.Tween(this.calendar, {
			onStart: function() { 
				if (this.calendar.getStyle('opacity') == 0) { // show
					if (Browser.Engine.trident && Browser.Engine.version < 5) { this.iframe.setStyles({'display':'block','height':this.calendar.getStyle('height')}); }
					this.calendar.setStyle('display', 'block');
					this.fireEvent('onShowStart', this.element);
				}
				else { // hide
					this.fireEvent('onHideStart', this.element);
				}
			}.bind(this),
			onComplete: function() { 
				if (this.calendar.getStyle('opacity') == 0) { // hidden
					this.calendar.setStyle('display', 'none');
					if (Browser.Engine.trident && Browser.Engine.version < 5) { this.iframe.setStyle('display', 'none'); }
					this.fireEvent('onHideComplete', this.element);
				}
				else { // shown
					this.fireEvent('onShowComplete', this.element);
				}
			}.bind(this)
		});

		// initialize drag method
		if (window.Drag && this.options.draggable) {
			this.drag = new Drag.Move(this.calendar, { 
				onDrag: function() {
					if (Browser.Engine.trident && Browser.Engine.version < 5) { this.iframe.setStyles({ left: this.calendar.style.left, top: this.calendar.style.top }); } 
				}.bind(this) 
			}); 
		}
		
		// create calendars array
		this.calendars = [];

		var id = 0;
		var d = new Date(); // today

		d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset

		for (var i in obj) {
			var cal = { 
				button: new Element('button', { 'type': 'button' }),
				el: $(i),
				els: [],
				id: id++,
				month: d.getMonth(),
				visible: false,
				year: d.getFullYear()
			};
			// fix for bad element (naughty, naughty element!)
			if (!this.element(i, obj[i], cal)) { continue; }
			
			cal.el.addClass(this.classes.calendar);
			// create cal button
			cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el.getNext());
			// read in default value
			cal.val = this.read(cal);

			$extend(cal, this.bounds(cal)); // abs bounds of calendar

			$extend(cal, this.values(cal)); // valid days, months, years

			this.rebuild(cal);
			this.calendars.push(cal); // add to cals array		
		}	
	},


	// blocked: returns an array of blocked days for the month / year
	// @param cal (obj)
	// @returns blocked days (array)

	blocked: function(cal) {
		var blocked = [];
		var offset = new Date(cal.year, cal.month, 1).getDay(); // day of the week (offset)
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
		
		this.options.blocked.each(function(date){
			var values = date.split(' ');
			
			// preparation
			for (var i = 0; i <= 3; i++){ 
				if (!values[i]){ values[i] = (i == 3) ? '' : '*'; } // make sure blocked date contains values for at least d, m and y
				values[i] = values[i].contains(',') ? values[i].split(',') : new Array(values[i]); // split multiple values
				var count = values[i].length - 1;
				for (var j = count; j >= 0; j--){
					if (values[i][j].contains('-')){ // a range
						var val = values[i][j].split('-');
						for (var k = val[0]; k <= val[1]; k++){
							if (!values[i].contains(k)){ values[i].push(k + ''); }
						}
						values[i].splice(j, 1);
					}
				}
			}

			// execution
			if (values[2].contains(cal.year + '') || values[2].contains('*')){
				if (values[1].contains(cal.month + 1 + '') || values[1].contains('*')){
					values[0].each(function(val){ // if blocked value indicates this month / year
						if (val > 0){ blocked.push(val.toInt()); } // add date to blocked array
					});

					if (values[3]){ // optional value for day of week
						for (var i = 0; i < last; i++){
								var day = (i + offset) % 7;
	
								if (values[3].contains(day + '')){ 
									blocked.push(i + 1); // add every date that corresponds to the blocked day of the week to the blocked array
								}
						}
					}
				}
			}
		}, this);

		return blocked;
	},


	// bounds: returns the start / end bounds of the calendar
	// @param cal (obj)
	// @returns obj	

	bounds: function(cal) {
		// 1. first we assume the calendar has no bounds (or a thousand years in either direction)
		
		// by default the calendar will accept a millennium in either direction
		var start = new Date(1000, 0, 1); // jan 1, 1000
		var end = new Date(2999, 11, 31); // dec 31, 2999

		// 2. but if the cal is one directional we adjust accordingly
		var date = new Date().getDate() + this.options.direction.toInt();

		if (this.options.direction > 0) {
			start = new Date();
			start.setDate(date + this.options.pad * cal.id);
		}
		
		if (this.options.direction < 0) {
			end = new Date();
			end.setDate(date - this.options.pad * (this.calendars.length - cal.id - 1));
		}

		// 3. then we can further filter the limits by using the pre-existing values in the selects
		cal.els.each(function(el) {	
			if (el.get('tag') == 'select') {		
				if (el.format.test('(y|Y)')) { // search for a year select
					var years = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
					}, this);
	
					years.sort(this.sort);
			
					if (years[0] > start.getFullYear()) { 
						d = new Date(years[0], start.getMonth() + 1, 0); // last day of new month
					
						if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
	
						start.setYear(years[0]); 
					}
					
					if (years.getLast() < end.getFullYear()) { 
						d = new Date(years.getLast(), end.getMonth() + 1, 0); // last day of new month
					
						if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
	
						end.setYear(years.getLast());
					}		
				}
	
				if (el.format.test('(F|m|M|n)')) { // search for a month select
					var months_start = [];
					var months_end = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if ($type(values[0]) != 'number' || values[0] == years[0]) { // if it's a year / month combo for curr year, or simply a month select
							if (!months_start.contains(values[1])) { months_start.push(values[1]); } // add to months array
						}
	
						if ($type(values[0]) != 'number' || values[0] == years.getLast()) { // if it's a year / month combo for curr year, or simply a month select
							if (!months_end.contains(values[1])) { months_end.push(values[1]); } // add to months array
						}
					}, this);
	
					months_start.sort(this.sort);
					months_end.sort(this.sort);
					
					if (months_start[0] > start.getMonth()) { 
						d = new Date(start.getFullYear(), months_start[0] + 1, 0); // last day of new month
					
						if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
	
						start.setMonth(months_start[0]); 
					}
					
					if (months_end.getLast() < end.getMonth()) { 
						d = new Date(start.getFullYear(), months_end.getLast() + 1, 0); // last day of new month
					
						if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
	
						end.setMonth(months_end.getLast());
					}		
				}
			}
		}, this);
		
		return { 'start': start, 'end': end };
	},


	// caption: returns the caption element with header and navigation
	// @param cal (obj)
	// @returns caption (element)

	caption: function(cal) {
		// start by assuming navigation is allowed
		var navigation = {
			prev: { 'month': true, 'year': true },
			next: { 'month': true, 'year': true }
		};
		
		// if we're in an out of bounds year
		if (cal.year == cal.start.getFullYear()) { 
			navigation.prev.year = false; 
			if (cal.month == cal.start.getMonth() && this.options.navigation == 1) { 
				navigation.prev.month = false;
			}		
		}		
		if (cal.year == cal.end.getFullYear()) { 
			navigation.next.year = false; 
			if (cal.month == cal.end.getMonth() && this.options.navigation == 1) { 
				navigation.next.month = false;
			}
		}

		// special case of improved navigation but months array with only 1 month we can disable all month navigation
		if ($type(cal.months) == 'array') {
			if (cal.months.length == 1 && this.options.navigation == 2) {
				navigation.prev.month = navigation.next.month = false;
			}
		}
		var caption = new Element('caption');
		var prev = new Element('a').addClass(this.classes.prev).appendText('\x3c'); // <		
		var next = new Element('a').addClass(this.classes.next).appendText('\x3e'); // >
		if (this.options.navigation == 2) {
			var actMonth=(this.options.months[cal.month]),
				monthSelectId = 'month_' + this.calendars[0].el.id,
				monthSelect = new Element('select',{
					id:monthSelectId
				}),
				yearSelectId = 'year_' + this.calendars[0].el.id,
				yearSelect = new Element('select',{
					id:yearSelectId
				});
			this.options.months.each(function(item, cnt){
				var monthOptions = new Element('option',{
					text: item,
					value: cnt + 1
				})
				.inject(monthSelect);
				if(item === actMonth){
					monthOptions.setProperty('selected', 'selected');
				}
			});

			for (i=1908; i<=2020; i++){
				var yearOptions = new Element('option',{text:i}).inject(yearSelect);
				if(i === cal.year){
					yearOptions.setProperty('selected', 'selected');
				}
			}
			
			yearSelect.injectInside(caption);
			monthSelect.injectInside(caption);
			cal.monthSelectId = monthSelectId;
			cal.yearSelectId = yearSelectId;
				
		}
		/*if (this.options.navigation == 2) {
			var month = new Element('span').addClass(this.classes.month).injectInside(caption);
			
			if (navigation.prev.month) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(month); }
			
			month.adopt(new Element('span').appendText(this.options.months[cal.month]));
			

			if (navigation.next.month) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(month); }

			var year = new Element('span').addClass(this.classes.year).injectInside(caption);

			if (navigation.prev.year) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', -1); }.pass(cal, this)).injectInside(year); }
			
			year.adopt(new Element('span').appendText(cal.year));

			if (navigation.next.year) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', 1); }.pass(cal, this)).injectInside(year); }
		}*/

		else { // 1 or 0
			if (navigation.prev.month && this.options.navigation) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(caption); }

			caption.adopt(new Element('span').addClass(this.classes.month).appendText(this.options.months[cal.month]));
			
			caption.adopt(new Element('span').addClass(this.classes.year).appendText(cal.year));
			
			if (navigation.next.month && this.options.navigation) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(caption); }

		}

		return caption;
	},


	// changed: run when a select value is changed
	// @param cal (obj)

	changed: function(cal) {
		cal.val = this.read(cal); // update calendar val from inputs	

		$extend(cal, this.values(cal)); // update bounds - based on curr month

		this.rebuild(cal); // rebuild days select

		if (!cal.val) { return; } // in case the same date was clicked the cal has no set date we should exit		

		if (cal.val.getDate() < cal.days[0]) { cal.val.setDate(cal.days[0]); }
		if (cal.val.getDate() > cal.days.getLast()) { cal.val.setDate(cal.days.getLast()); }
		
		cal.els.each(function(el) {	// then we can set the value to the field
			el.value = this.format(cal.val, el.format); 		
		}, this);
		
		this.check(cal); // checks other cals

		this.calendars.each(function(kal) { // update cal graphic if visible
			if (kal.visible) { this.display(kal); }
		}, this);
	},


	// check: checks other calendars to make sure no overlapping values
	// @param cal (obj)

	check: function(cal) {
		this.calendars.each(function(kal, i) {
			if (kal.val) { // if calendar has value set
				var change = false;
			
				if (i < cal.id) { // preceding calendar
					var bound = new Date(Date.parse(cal.val));
					
					bound.setDate(bound.getDate() - (this.options.pad * (cal.id - i)));

					if (bound < kal.val) { change = true; }
				}
				if (i > cal.id) { // following calendar
					var bound = new Date(Date.parse(cal.val));
					
					bound.setDate(bound.getDate() + (this.options.pad * (i - cal.id)));
					
					if (bound > kal.val) { change = true; }
				}

				if (change) {
					if (kal.start > bound) { bound = kal.start; }
					if (kal.end < bound) { bound = kal.end; }

					kal.month = bound.getMonth();
					kal.year = bound.getFullYear();		

					$extend(kal, this.values(kal));			

					// TODO - IN THE CASE OF SELECT MOVE TO NEAREST VALID VALUE
					// IN THE CASE OF INPUT DISABLE

					// if new date is not valid better unset cal value
					// otherwise it would mean incrementally checking to find the nearest valid date which could be months / years away
					kal.val = kal.days.contains(bound.getDate()) ? bound : null;

					this.write(kal);

					if (kal.visible) { this.display(kal); } // update cal graphic if visible
				}
			}
			else {
				kal.month = cal.month;
				kal.year = cal.year;
			}
		}, this);
	},
	

	// clicked: run when a valid day is clicked in the calendar
	// @param cal (obj)

	clicked: function(td, day, cal) {
		cal.val = (this.value(cal) == day) ? null : new Date(cal.year, cal.month, day); // set new value - if same then disable

		this.write(cal); 


		// ok - in the special case that it's all selects and there's always a date no matter what (at least as far as the form is concerned)
		// we can't let the calendar undo a date selection - it's just not possible!!
		if (!cal.val) { cal.val = this.read(cal); }

		if (cal.val) {
			this.check(cal); // checks other cals						
			this.toggle(cal); // hide cal
		} 
		else { // remove active class and replace with valid
			td.addClass(this.classes.valid);
			td.removeClass(this.classes.active);
		}
	},
	

	// display: create calendar element
	// @param cal (obj)

	display: function(cal) {
		// 1. header and navigation
		this.calendar.empty(); // init div

		this.calendar.className = this.classes.calendar + ' ' + this.options.months[cal.month].toLowerCase();

		var div = new Element('div').addClass('innerEl').injectInside(this.calendar); // a wrapper div to help correct browser css problems with the caption element

		var table = new Element('table').injectInside(div).adopt(this.caption(cal));
		
		
				
		// 2. day names		
		var thead = new Element('thead').injectInside(table);

		var tr = new Element('tr').injectInside(thead);
		
		for (var i = 0; i <= 6; i++) {
			var th = this.options.days[(i + this.options.offset) % 7];
			
			tr.adopt(new Element('th', { 'title': th }).appendText(th.substr(0, 1)));
		}

		// 3. day numbers
		var tbody = new Element('tbody').injectInside(table);
		var tr = new Element('tr').injectInside(tbody);

		var d = new Date(cal.year, cal.month, 1);
		var offset = ((d.getDay() - this.options.offset) + 7) % 7; // day of the week (offset)
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
		var prev = new Date(cal.year, cal.month, 0).getDate(); // last day of previous month
		var active = this.value(cal); // active date (if set and within curr month)
		var valid = cal.days; // valid days for curr month
		var inactive = []; // active dates set by other calendars
		var hilited = [];
		this.calendars.each(function(kal, i) {
			if (kal != cal && kal.val) {
				if (cal.year == kal.val.getFullYear() && cal.month == kal.val.getMonth()) { inactive.push(kal.val.getDate()); }

				if (cal.val) {
					for (var day = 1; day <= last; day++) {
						d.setDate(day);
						
						if ((i < cal.id && d > kal.val && d < cal.val) || (i > cal.id && d > cal.val && d < kal.val)) { 
							if (!hilited.contains(day)) { hilited.push(day); }
						}
					}
				}
			}
		}, this);
		var d = new Date();
		var today = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime(); // today obv 
		
		for (var i = 1; i < 43; i++) { // 1 to 42 (6 x 7 or 6 weeks)
			if ((i - 1) % 7 == 0) { tr = new Element('tr').injectInside(tbody); } // each week is it's own table row

			var td = new Element('td').injectInside(tr);
						
			var day = i - offset;
			var date = new Date(cal.year, cal.month, day);
			
			var cls = '';
			
			if (day === active) { cls = this.classes.active; } // active
			else if (inactive.contains(day)) { cls = this.classes.inactive; } // inactive
			else if (valid.contains(day)) { cls = this.classes.valid; } // valid
			else if (day >= 1 && day <= last) { cls = this.classes.invalid; } // invalid

			if (date.getTime() == today) { cls = cls + ' ' + this.classes.today; } // adds class for today

			if (hilited.contains(day)) { cls = cls + ' ' + this.classes.hilite; } // adds class if hilited

			td.addClass(cls);

			if (valid.contains(day)) { // if it's a valid - clickable - day we add interaction
				td.setProperty('title', this.format(date, 'D j.m.Y'));
				
				td.addEvents({
					'click': function(td, day, cal) { 
						this.clicked(td, day, cal); 
					}.pass([td, day, cal], this),
					'mouseover': function(td, cls) { 
						td.addClass(cls); 
					}.pass([td, this.classes.hover]),
					'mouseout': function(td, cls) { 
						td.removeClass(cls); 
					}.pass([td, this.classes.hover])
				});
			}

			// pad calendar with last days of prev month and first days of next month
			if (day < 1) { day = prev + day; }
			else if (day > last) { day = day - last; }

			td.appendText(day);
		}
		
		this.element(this.calendars[0].monthSelectId, 'n', this.calendars[0]);			
		this.element(this.calendars[0].yearSelectId, 'Y', this.calendars[0]);		
	},


	// element: helper function
	// @param el (string) element id
	// @param f (string) format string
	// @param cal (obj)

	element: function(el, f, cal) {
		if ($type(f) == 'object') { // in the case of multiple inputs per calendar
			for (var i in f) { 
				if (!this.element(i, f[i], cal)) { return false; }		
			}
			
			return true;
		}

		el = $(el);

		if (!el) { return false; }
		
		el.format = f;
		
		if (el.get('tag') == 'select') { // select elements allow the user to manually set the date via select option
			el.addEvent('change', function(cal) { this.changed(cal); }.pass(cal, this));
		}
		else { // input (type text) elements restrict the user to only setting the date via the calendar
			el.readOnly = true;
			el.addEvent('focus', function(cal) { this.toggle(cal); }.pass(cal, this));
		}

		cal.els.push(el);

		return true;
	},


	// format: formats a date object according to passed in instructions
	// @param date (obj)
	// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
	// @returns string

	format: function(date, format) {
		var str = '';
		
		if (date) {
			var j = date.getDate(); // 1 - 31
      var w = date.getDay(); // 0 - 6
			var l = this.options.days[w]; // Sunday - Saturday
			var n = date.getMonth() + 1; // 1 - 12
			var f = this.options.months[n - 1]; // January - December
			var y = date.getFullYear() + ''; // 19xx - 20xx
			
			for (var i = 0, len = format.length; i < len; i++) {
				var cha = format.charAt(i); // format char
				
				switch(cha) {
					// year cases
					case 'y': // xx - xx
						y = y.substr(2);
					case 'Y': // 19xx - 20xx
						str += y;
						break;
	
					// month cases
					case 'm': // 01 - 12
						if (n < 10) { n = '0' + n; }
					case 'n': // 1 - 12
						str += n;
						break;
	
					case 'M': // Jan - Dec
						f = f.substr(0, 3);
					case 'F': // January - December
						str += f;
						break;
	
					// day cases
					case 'd': // 01 - 31
						if (j < 10) { j = '0' + j; }
					case 'j': // 1 - 31
						str += j;
						break;
	
					case 'D': // Sun - Sat
						l = l.substr(0, 2);
					case 'l': // Sunday - Saturday
						str += l;
						break;
	
					case 'N': // 1 - 7
						w += 1;
					case 'w': // 0 - 6
						str += w;
						break;

					case 'S': // st, nd, rd or th (works well with j)
						if (j % 10 == 1 && j != '11') { str += 'st'; }
						else if (j % 10 == 2 && j != '12') { str += 'nd'; }
						else if (j % 10 == 3 && j != '13') { str += 'rd'; }
						else { str += 'th'; }
						break;
	
					default:
						str += cha;
				}
			}
		}

	  return str; //  return format with values replaced
	},


	// navigate: calendar navigation
	// @param cal (obj)
	// @param type (str) m or y for month or year
	// @param n (int) + or - for next or prev

	navigate: function(cal, type, n) {
		switch (type) {
			case 'm': // month
					if ($type(cal.months) == 'array') {
						var i = cal.months.indexOf(cal.month) + n; // index of current month
						
						if (i < 0 || i == cal.months.length) { // out of range
							if (this.options.navigation == 1) { // if type 1 nav we'll need to increment the year
								this.navigate(cal, 'y', n);		
							}
		
							i = (i < 0) ? cal.months.length - 1 : 0;
						}

						cal.month = cal.months[i];
					}
					else { 
						var i = cal.month + n;
		
						if (i < 0 || i == 12) {
							if (this.options.navigation == 1) {
								this.navigate(cal, 'y', n);	
							}
		
							i = (i < 0) ? 11 : 0;
						}
						
						cal.month = i;
					}		
					break;

				case 'y': // year
					if ($type(cal.years) == 'array') {
						var i = cal.years.indexOf(cal.year) + n;

						cal.year = cal.years[i]; 
					}
					else { 
						cal.year += n;
					}						
					break;		
		}

		$extend(cal, this.values(cal));

		if ($type(cal.months) == 'array') { // if the calendar has a months select
			var i = cal.months.indexOf(cal.month); // and make sure the curr months exists for the new year

			if (i < 0) { cal.month = cal.months[0]; } // otherwise we'll reset the month
		}


		this.display(cal);
	},


	// read: compiles cal value based on array of inputs passed in
	// @param cal (obj)
	// @returns date (obj) or (null)

	read: function(cal) {
		var arr = [null, null, null];

		cal.els.each(function(el) {
			// returns an array which may contain empty values
			var values = this.unformat(el.value, el.format);
			
			values.each(function(val, i) { 
				if ($type(val) == 'number') { arr[i] = val; }
			}); 
		}, this);

		// we can update the cals month and year values
		if ($type(arr[0]) == 'number') { cal.year = arr[0]; }
		if ($type(arr[1]) == 'number') { cal.month = arr[1]; }

		var val = null;

		if (arr.every(function(i) { return $type(i) == 'number'; })) { // if valid date
			var last = new Date(arr[0], arr[1] + 1, 0).getDate(); // last day of month

			if (arr[2] > last) { arr[2] = last; } // make sure we stay within the month (ex in case default day of select is 31 and month is feb)
			
			val = new Date(arr[0], arr[1], arr[2]);
		}

		return (cal.val == val) ? null : val; // if new date matches old return null (same date clicked twice = disable)
	},

	
	// rebuild: rebuilds days + months selects
	// @param cal (obj)

	rebuild: function(cal) {
		cal.els.each(function(el) {			
			/*
			if (el.get('tag') == 'select' && el.format.test('^(F|m|M|n)$')) { // special case for months-only select
				if (!cal.options) { cal.options = el.clone(); } // clone a copy of months select
			
				var val = (cal.val) ? cal.val.getMonth() : el.value.toInt();

				el.empty(); // initialize select

				cal.months.each(function(month) {
					// create an option element
					var option = new Element('option', {
						'selected': (val == month),
						'value': this.format(new Date(1, month, 1), el.format);
					}).appendText(day).injectInside(el);
				}, this);
			}
			*/

			if (el.get('tag') == 'select' && el.format.test('^(d|j)$')) { // special case for days-only select
				var d = this.value(cal);

				if (!d) { d = el.value.toInt(); } // if the calendar doesn't have a set value, try to use value from select

				el.empty(); // initialize select

				cal.days.each(function(day) {
					// create an option element
					var option = new Element('option', {
						'selected': (d == day),
						'value': ((el.format == 'd' && day < 10) ? '0' + day : day)
					}).appendText(day).injectInside(el);
				}, this);
			}
		}, this); 
	},


	// sort: helper function for numerical sorting

	sort: function(a, b) {
		return a - b;
	},


	// toggle: show / hide calendar 
	// @param cal (obj)

	toggle: function(cal) {
		document.removeEvent('mousedown', this.fn); // always remove the current mousedown script first
			
		if (cal.visible) { // simply hide curr cal						
			cal.visible = false;
			cal.button.removeClass(this.classes.active); // active
			
			this.fx.start('opacity', 1, 0);
		}
		else { // otherwise show (may have to hide others)
			// hide cal on out-of-bounds click
			this.fn = function(e, cal) { 
				var e = new Event(e);
			
				var el = e.target;
				var stop = false;
				
				while (el != document.body && el.nodeType == 1) {
					if (el == this.calendar) { stop = true; }
					this.calendars.each(function(kal) {
						if (kal.button == el || kal.els.contains(el)) { stop = true; }
					});

					if (stop) { 
						e.stop();
						return false;
					}
					else { el = el.parentNode; }
				}
				
				this.toggle(cal);
			}.create({ 'arguments': cal, 'bind': this, 'event': true });				

			document.addEvent('mousedown', this.fn);

			this.calendars.each(function(kal) {
				if (kal == cal) {
					kal.visible = true;
					kal.button.addClass(this.classes.active); // css c-icon-active
				}
				else {
					kal.visible = false;
					kal.button.removeClass(this.classes.active); // css c-icon-active
				}
			}, this);
			
			var size = window.getScrollSize();
			
			var coord = cal.button.getCoordinates();

			var x = coord.right + this.options.tweak.x;
			var y = coord.top + this.options.tweak.y;

			// make sure the calendar doesn't open off screen
			if (!this.calendar.coord) { this.calendar.coord = this.calendar.getCoordinates(); }

			if (x + this.calendar.coord.width > size.x) { x -= (x + this.calendar.coord.width - size.x); }
			if (y + this.calendar.coord.height > size.y) { y -= (y + this.calendar.coord.height - size.y); }
			
			this.calendar.setStyles({ left: x + 'px', top: y + 'px' });

			if (Browser.Engine.trident && Browser.Engine.version < 5) { 
				this.iframe.setStyles({ height: this.calendar.coord.height + '100px', left: x + 'px', top: y + 'px', width: this.calendar.coord.width + 'px' }); 
			}
			this.display(cal);
			
			this.fx.start('opacity', 0, 1);
		}
	},


	// unformat: takes a value from an input and parses the d, m and y elements
	// @param val (string)
	// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
	// @returns array
	
	unformat: function(val, f) {
		f = f.escapeRegExp();
		
		var re = {
			d: '([0-9]{2})',
			j: '([0-9]{1,2})',
			D: '(' + this.options.days.map(function(day) { return day.substr(0, 3); }).join('|') + ')',					
			l: '(' + this.options.days.join('|') + ')',
			S: '(st|nd|rd|th)',
			F: '(' + this.options.months.join('|') + ')',
			m: '([0-9]{2})',
			M: '(' + this.options.months.map(function(month) { return month.substr(0, 3); }).join('|') + ')',					
			n: '([0-9]{1,2})',
			Y: '([0-9]{4})',
			y: '([0-9]{2})'
		}

		var arr = []; // array of indexes

		var g = '';

		// convert our format string to regexp
		for (var i = 0; i < f.length; i++) {
			var c = f.charAt(i);
			
			if (re[c]) {
				arr.push(c);

				g += re[c];
			}
			else {
				g += c;
			}
		}

		// match against date
		var matches = val.match('^' + g + '$');
		
		var dates = new Array(3);

		if (matches) {
			matches = matches.slice(1); // remove first match which is the date

			arr.each(function(c, i) {
				i = matches[i];
				
				switch(c) {
					// year cases
					case 'y':
						i = '19' + i; // 2 digit year assumes 19th century (same as JS)
					case 'Y':
						dates[0] = i.toInt();
						break;

					// month cases
					case 'F':
						i = i.substr(0, 3);
					case 'M':
						i = this.options.months.map(function(month) { return month.substr(0, 3); }).indexOf(i) + 1;
					case 'm':
					case 'n':
						dates[1] = i.toInt() - 1;
						break;

					// day cases
					case 'd':
					case 'j':
						dates[2] = i.toInt();
						break;
				}
			}, this);
		}

		return dates;
	},


	// value: returns day value of calendar if set
	// @param cal (obj)
	// @returns day (int) or null

	value: function(cal) {
		var day = null;

		if (cal.val) {
			if (cal.year == cal.val.getFullYear() && cal.month == cal.val.getMonth()) { day = cal.val.getDate(); }
		}

		return day;
	},
	

	// values: returns the years, months (for curr year) and days (for curr month and year) for the calendar
	// @param cal (obj)
	// @returns obj	

	values: function(cal) {
		var years, months, days;

		cal.els.each(function(el) {	
			if (el.get('tag') == 'select') {		
				if (el.format.test('(y|Y)')) { // search for a year select
					years = [];

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
					}, this);
	
					years.sort(this.sort);
				}
	
				if (el.format.test('(F|m|M|n)')) { // search for a month select
					months = []; // 0 - 11 should be

					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);
	
						if ($type(values[0]) != 'number' || values[0] == cal.year) { // if it's a year / month combo for curr year, or simply a month select
							if (!months.contains(values[1])) { months.push(values[1]); } // add to months array
						}
					}, this);
	
					months.sort(this.sort);
				}
				
				if (el.format.test('(d|j)') && !el.format.test('^(d|j)$')) { // search for a day select, but NOT a days only select
					days = []; // 1 - 31
					
					el.getChildren().each(function(option) { // get options
						var values = this.unformat(option.value, el.format);

						// in the special case of days we dont want the value if its a days only select
						// otherwise that will screw up the options rebuilding
						// we will take the values if they are exact dates though
						if (values[0] == cal.year && values[1] == cal.month) {
							if (!days.contains(values[2])) { days.push(values[2]); } // add to days array
						}
					}, this);
				}
			}
		}, this);
		
		// we start with what would be the first and last days were there no restrictions
		var first = 1;
		var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of the month
		
		// if we're in an out of bounds year
		if (cal.year == cal.start.getFullYear()) {
			// in the special case of improved navigation but no months array, we'll need to construct one
			if (months == null && this.options.navigation == 2) {
				months = [];
				
				for (var i = 0; i < 12; i ++) { 
					if (i >= cal.start.getMonth()) { months.push(i); } 
				}
			}
			
			// if we're in an out of bounds month
			if (cal.month == cal.start.getMonth()) { 
				first = cal.start.getDate(); // first day equals day of bound
			}
		}		
		if (cal.year == cal.end.getFullYear()) {
			// in the special case of improved navigation but no months array, we'll need to construct one
			if (months == null && this.options.navigation == 2) {
				months = [];
				
				for (var i = 0; i < 12; i ++) { 
					if (i <= cal.end.getMonth()) { months.push(i); } 
				}
			}

			if (cal.month == cal.end.getMonth()) { 
				last = cal.end.getDate(); // last day equals day of bound
			}
		}

		// let's get our invalid days
		var blocked = this.blocked(cal);

		// finally we can prepare all the valid days in a neat little array
		if ($type(days) == 'array') { // somewhere there was a days select
			days = days.filter(function(day) {
				if (day >= first && day <= last && !blocked.contains(day)) { return day; }
			});
		}
		else { // no days select we'll need to construct a valid days array
			days = [];
			
			for (var i = first; i <= last; i++) { 
				if (!blocked.contains(i)) { days.push(i); }
			}
		}		

		days.sort(this.sort); // sorting our days will give us first and last of month

		return { 'days': days, 'months': months, 'years': years };
	},


	// write: sets calendars value to form elements
	// @param cal (obj)

	write: function(cal) {
		this.rebuild(cal);	 // in the case of options, we'll need to make sure we have the correct number of days available
		
		cal.els.each(function(el) {	// then we can set the value to the field
			el.value = this.format(cal.val, el.format); 
		}, this);
	}
});

Calendar.implement(new Events, new Options);

/**
 * Highlight für Tabellenzelle, wenn per Checkbox ausgewählt
 */
var Highlight = new Class({
	initialize: function(els) {
		els.each(function(el) {
			var theTr = el.getParents('tr');
			if (el.checked){theTr.addClass('gelb')}
			el.addEvent('click', function() {theTr.toggleClass('gelb')});
		});
    }
})

/**
* Lesezeichen hinzufuegen
*/
function addBookmark(){
  
  var bookmarkURL = self.location;
  var bookmarkText = document.title;
  
  if (window.sidebar)
    {
    // firefox
    window.sidebar.addPanel(bookmarkText,bookmarkURL, "");
    }
  else if(window.opera && window.print)
    {
    // opera
    var elem = document.createElement('a');
    elem.setAttribute('href',bookmarkURL);
    elem.setAttribute('title',bookmarkText);
    elem.setAttribute('rel','sidebar');
    elem.click();
    }
  else if(document.all)
    {
    // ie
    window.external.AddFavorite(bookmarkURL,bookmarkText);
    }
}
/**
 * Startseitenteaser Variante
 */
var Startseite = new Class({
	initialize: function(lis, boxes) {
			
							
		lis.each(function(item, index) {
			var thisIndex = lis.indexOf(item);
			
			item.addEvent('click', function() {
				var thisIndex = lis.indexOf(item);
				lis.removeClass('aktiv');
				boxes.addClass('jsHide');
				item.addClass('aktiv');
				boxes[thisIndex].removeClass('jsHide');
			});
		});
    }
	
})
