function shout(el) {
	var ret = "";
	var brk	= "\r\n";
	if (typeof el == "object"
	||	typeof el == "array")
		for (e in el)
			ret+= e + ":" + el[e] + brk;
	else ret+= el + brk;
	alert(ret);
}

var tjg	= new Object();
	tjg.Options = new Object({
		Animation:	new Object({
			duration:	1
		}),
		Scroll:		new Object({
			duration:	3,
			offset:		100
		}),
		Illus:		new Array()
	});
// !tjg.Background
	tjg.Background = Class.create({
		initialize: function(el) {
			this.element	= $(el);
		},
		setHeight: function(newH) {
			
		}
	});
// !tjg.Core
	tjg.Core = Class.create({
		initialize: function(el) {
			this.element		= $(el);
			if (this.element)
				this.element.obj	= this;
			this.handlers		= new Array();
		},
		registerHandler: function(el, offsets) {
			var handler			= $(el);
				handler.offsets	= offsets || 0;
				handler.href	= 'javascript: void(0);';
			// Begin Callback
			if (this.beginRegisterHandler)
				this.beginRegisterHandler(handler);

			this.observeHandler(handler);
			if (this.handlers.push(handler)) {
				// Finish Callback
				if (this.finishRegisterHandler)
					this.finishRegisterHandler(handler);
				return handler;
			} else return false;
		},
		freezeAllHandlers: function() {
			document.body.style.cursor = 'wait';
			this.group.each((function(obj) {
				if (typeof obj.handlers == 'object')
					obj.handlers.invoke('stopObserving');
			}).bind(this));
		},
		observeAllHandlers: function() {
			document.body.style.cursor = 'default';
			this.group.each((function(obj) {
				if (typeof obj.handlers == 'object')
					obj.handlers.each((function(handler) {
						obj.observeHandler(handler);
					}).bind(this));
			}).bind(this));
		},
		observeHandler: function(el) {
			document.body.style.cursor = 'default';
			var handler = el;
				handler.observe('click', (function() {
					this.onClick(handler);
					this.handlers.invoke('removeClassName', 'active');
					handler.addClassName('active');
				}).bind(this));
		},
		adjustHeight: function(el, theight, callback) {
			var element		= $(el);
			var sheight		= element.getHeight();
			var callback	= callback || Prototype.emptyFunction;
			var beforeStart, afterFinish;

			if (Prototype.Browser.IE)
				$('main-bg').setStyle({ 'height': $('content').getHeight() + 'px' });

			/*if (sheight < theight)
				beforeStart	= callback;
			else if (theight < sheight)
				afterFinish	= callback;
			else if (sheight == theight) {
				callback();
				return;
			}

			new Effect.Tween(
				null,
				sheight,
				theight, {
					duration: tjg.Options.Animation.duration,
					beforeStart: (function() {
						$('footer').down('.toplink').hide();
						if (beforeStart && typeof beforeStart == 'function')
							beforeStart();
						this.toggleIllus(sheight);
					}).bind(this),
					afterFinish: (function() {
						$('footer').down('.toplink').show();
						if (afterFinish && typeof afterFinish == 'function')
							afterFinish();
						this.toggleIllus(theight);
					}).bind(this)
				}, (function(h) {
					element.setStyle({ height: h + 'px' });
				}).bind(this)
			);*/
			this.toggleIllus($('content').getHeight());
			callback();
		},
		toggleIllus: function(hght) {
			tjg.Options.Illus.each((function(illuId) {
				var illu = $(illuId);
				//alert(((illu.offsetTop + illu.getHeight()) < hght) + " (" + illu.offsetTop + " + " + illu.getHeight() + " [" + (illu.offsetTop + illu.getHeight()) + "])" + " < " + hght);
				if ((illu.offsetTop + illu.getHeight()) < hght)
					illu.removeClassName('invisible');
				else illu.addClassName('invisible');
			}).bind(this));
		}
	});
// !tjg.Scroller
	tjg.Scroller = Class.create(tjg.Core, {
		parseOffsets: function(targets) {
			if (Object.isString(targets) || Object.isElement(targets))
				return new Array(this.element.scrollLeft, $(targets).offsetLeft, this.element.scrollTop, $(targets).offsetTop);
			else return targets;
		},
		isFocused: function(targets) {
			var offsets = this.parseOffsets(targets);
			if (offsets[1] == this.element.scrollLeft
			&&	offsets[3] == this.element.scrollTop)
				return true;
			else return false;
		},
		scroll: function(targets, callback) {
			var offsets = this.parseOffsets(targets);
			if (typeof targets == "string" && window.location.hash.split('/')[1] != targets)
				window.location.hash = '/' + targets;

			if (!this.isFocused(offsets)) {
				this.adjustHeight(
					'main-bg',
					$(targets).getHeight() + $('footer').getHeight(),
					(function() {
						new Effect.Tween(
							null,
							0,
							1, {
								duration: tjg.Options.Scroll.duration,
								beforeStart: (function() { this.handlers.invoke('stopObserving'); }).bind(this),
								afterFinish: (function() {
									if (callback && typeof callback == 'function')
										callback();
									else this.observeAllHandlers();
								}).bind(this)
							},
							(function(p) {
								this.element.scrollLeft	= offsets[0] + ((offsets[1] - offsets[0]) * p);
								this.element.scrollTop	= offsets[2] + ((offsets[3] - offsets[2]) * p);
							}).bind(this)
						);
					}).bind(this)
				);
			} else if (callback && typeof callback == 'function')
				this.adjustHeight(
					'main-bg',
					$(targets).getHeight() + $('footer').getHeight(),
					callback
				);
			else this.adjustHeight(
					'main-bg',
					$(targets).getHeight() + $('footer').getHeight(),
					this.observeAllHandlers.bind(this)
				);
		},
		onClick: function(handler) {
			if (this.isFocused(handler.offsets))
				handler.addClassName('active');
			this.scroll(handler.offsets);
		}
	});
// !tjg.Toggler
	tjg.Toggler = Class.create(tjg.Core, {
		onClick: function(handler, clbk) {
			var callback	= clbk || 0;
			this.freezeAllHandlers();
			if (!this.element.visible()) {
				if (!this.group.find((function(sibling) {
					if (sibling.element !== this.element
					&&	sibling.element.visible())
						return sibling.close((function() {
							this.open(callback);
						}).bind(this));
					else return false;
				}).bind(this)))
					this.open(callback);
			} else this.close(callback);
		},
		open: function(callback) {
			var topFrom		= document.viewport.getScrollOffsets()[1];
			var topTo		= this.element.up(0).viewportOffset()[1];
			var open		= (function() {
				var hash	= window.location.hash.split('/');
					hash[this.hashindex] = this.itemindex;
				window.location.hash = hash.join('/');

				
				new Effect.SlideDown(this.element, {
					duration: tjg.Options.Animation.duration,
					afterFinish: (function() {
						this.handlers.invoke('addClassName', 'active');
						this.adjustHeight('content');
						if (callback && typeof callback == 'function')
							callback();
						else this.observeAllHandlers();
					}).bind(this)
				});
			}).bind(this);
			if (topFrom != topTo) {
				new Effect.ScrollTo(this.element.up(0), {
					duration: tjg.Options.Animation.duration,
					offset: tjg.Options.Scroll.offset * -1,
					afterFinish: open
				});
			} else open();
			return this;
		},
		close: function(callback) {
			new Effect.SlideUp(this.element, {
				duration: tjg.Options.Animation.duration,
				afterFinish: (function() {
					this.handlers.invoke('removeClassName', 'active');
					this.observeAllHandlers();
					this.adjustHeight('content', 0, callback);

					var hash	= window.location.hash.split('/');
					if (hash[this.hashindex] == this.itemindex) {
						hash	= hash.without(this.itemindex);
						window.location.hash = hash.length > 1 ? hash.join('/') : '/';
					}
				}).bind(this)
			});
			return this;
		}
	});
// !tjg.Expander
	tjg.Expander = Class.create(tjg.Toggler, {
		onClick: function(handler, clbk) {
			var callback	= clbk || 0;
			this.freezeAllHandlers();
			if (!this.element.opened) {
				if (!this.group.find((function(sibling) {
					if (sibling.element !== this.element
					&&	sibling.element.opened)
						return sibling.close((function() {
							this.open(callback);
						}).bind(this));
					else return false;
				}).bind(this)))
					this.open(callback);
			} else this.close(callback);
		},
		open: function(callback) {
			var topFrom		= document.viewport.getScrollOffsets()[1];
			var topTo		= this.element.viewportOffset()[1];
			var open		= (function() {
				var hash	= window.location.hash.split('/');
					hash[this.hashindex] = this.itemindex;
				window.location.hash = hash.join('/');
				this.element.oh	= this.element.getHeight();

				new Effect.Tween(
					null,
					this.element.oh,
					this.element.down(0).getHeight(), {
						duration: tjg.Options.Animation.duration,
						beforeStart: (function(ef) {
							this.adjustHeight(
								'main-bg',
								$('main-bg').getHeight() + $('footer').getHeight() + ef.options.to
								//$('content').getHeight() + $('footer').getHeight() + ef.element.getHeight()
							);
						}).bind(this),
						afterFinish: (function() {
							this.element.opened = true;
							this.handlers.invoke('addClassName', 'active');
							if (callback && typeof callback == 'function')
								callback();
							else this.observeAllHandlers();
						}).bind(this)
					},
					(function(h) {
						this.element.setStyle({ height: h + 'px' });
					}).bind(this)
				);
			}).bind(this);
			if (topFrom != topTo) {
				new Effect.ScrollTo(this.element, {
					duration: tjg.Options.Animation.duration,
					offset: tjg.Options.Scroll.offset * -1,
					afterFinish: open
				});
			} else open();
			return this;
		},
		close: function(callback) {
			new Effect.Tween(
				null,
				this.element.getHeight(),
				this.element.oh, {
					duration: tjg.Options.Animation.duration,
					afterFinish: (function() {
						this.element.opened = false;
						this.handlers.invoke('removeClassName', 'active');
						if (callback && typeof callback == 'function')
							this.adjustHeight(
								'main-bg',
								$(this.element.up('.container')).getHeight() + $('footer').getHeight(),
								callback
							);
						else this.adjustHeight(
							'main-bg',
							$(this.element.up('.container')).getHeight() + $('footer').getHeight(),
							this.observeAllHandlers.bind(this)
						);
					}).bind(this)
				},
				(function(h) {
					this.element.setStyle({ height: h + 'px' });
				}).bind(this)
			);
			return this;
		}
	});
// !tjg.Sorter
	tjg.Sorter = Class.create(tjg.Core, {
		initialize: function(el, classname, container, type) {
			this.sorting	= 0;				// 0 = unsorted, 1 = sorted ASC, 2 = sorted DESC (reversed)
			this.type		= type || 'ABC';	// 'ABC' | '123'
			this.handlers	= new Array();
			this.elements	= new Array();
			this.element	= $(el);
			this.element.select('.' + classname).collect((function(item) {
				var value	= item.title || '';
				if (value.blank() && (valueable = item.recursivelyCollect('lastChild')))
					value		= valueable.length ? valueable.last().innerHTML : item.innerHTML;

				this.elements.push({
					element:	(item.hasClassName(container) ? item : item.up(container)),
					value:		value.stripTags(),
					remove:		function() {
						if (whites = this.element.select('.white'))
							whites.invoke('removeClassName', 'white').invoke('addClassName', 'mint');
						this.element.removeClassName('first').removeClassName('highlight').remove();
					}
				});
			}).bind(this));
		},
		finishRegisterHandler: function(handler) {
			handler.addClassName('sort');
		},
		sort: function(a, b) {
			switch(this.type) {
				case 'ABC':
					var x = a.value.toLowerCase();
					var y = b.value.toLowerCase();
					var r = ((x < y) ? -1 : ((x > y) ? 1 : 0));
					break;
				case '123':
					var x = parseInt(a.value.substr(3));
						x = (!isNaN(x)) ? x : 0;
					var y = parseInt(b.value.substr(3));
						y = (!isNaN(y)) ? y : 0;
					var r = x - y;
			}
			return r;
		},
		onClick: function() {
			//this.freezeAllHandlers();
			this.group.each((function(sorter) {
				if (sorter !== this)
				sorter.sorting	= 0;
				sorter.handlers.invoke('removeClassName', 'active');
				sorter.handlers.invoke('removeClassName', 'asc');
				sorter.handlers.invoke('removeClassName', 'desc');
			}).bind(this));
			this.elements.invoke('remove');
			this.elements.sort(this.sort.bind(this));

			if (this.sorting == 0 || this.sorting == 2) {
				this.sorting = 1;
				this.handlers.invoke('removeClassName', 'desc');
				this.handlers.invoke('addClassName', 'asc');
			} else if (this.sorting == 1) {
				this.sorting = 2;
				this.handlers.invoke('removeClassName', 'asc');
				this.handlers.invoke('addClassName', 'desc');
				this.elements.reverse();
			}

			this.elements.first().element.addClassName('first');
			this.elements.each((function(el, index) {
				this.element.insert({ bottom: el.element });
				if (index % 2) {
					var el	= this.element.childElements().last();
						el.addClassName('highlight');
						if (els = el.select('.mint'))
							els.invoke('removeClassName', 'mint').invoke('addClassName', 'white');
				}
			}).bind(this));
			//this.observeAllHandlers();
		}
	});
// !tjg.Toplink
	tjg.Toplink = Class.create(tjg.Core, {
		onClick: function(handler, clbk) {
			this.freezeAllHandlers();
			new Effect.ScrollTo('viewport', {
				duration: tjg.Options.Animation.duration,
				offset: 0,
				afterFinish: this.observeAllHandlers.bind(this)
			});
		}
	});
// !tjg.Slideshow
	tjg.Slideshow = Class.create({
		initialize: function(el) {
			this.handlers	= new Array();
			this.container	= $(el);
			this.image		= 0;
			this.images		= this.container.select('img').invoke('hide').invoke('removeClassName', 'noscript');
			this.imagecount	= this.images.size();
			this.ltr		= this.container.down('.ltr');
			this.rtl		= this.container.down('.rtl');
			this.container.title = this.images[this.image].alt;

			this.images[this.image].show();
			if (this.imagecount > 1) {
				this.ltr.observe('mouseout', this.out);
				this.ltr.observe('mouseover', this.over);
				this.ltr.observe('click', this.previous.bind(this));
				this.rtl.observe('mouseout', this.out);
				this.rtl.observe('mouseover', this.over);
				this.rtl.observe('click', this.next.bind(this));
				
			} else {
				this.ltr.hide();
				this.rtl.hide();
			}
		},
		over: function() {
			this.addClassName('view');
		},
		out: function() {
			this.removeClassName('view');
		},
		next: function() {
			this.images[this.image].hide();
			this.image = (this.image >= (this.imagecount - 1)) ? 0 : this.image + 1;
			this.images[this.image].show();
			this.container.title = this.images[this.image].alt;
		},
		previous: function() {
			this.images[this.image].hide();
			this.image = (this.image <= 0) ? (this.imagecount - 1) : this.image - 1;
			this.images[this.image].show();
			this.container.title = this.images[this.image].alt;
		}
	});
// !tjg.Input
	tjg.Input = Class.create({
		initialize: function(el) {
			this.element	= $(el);
			this.element.observe('focus', this.empty.bind(this));
			this.element.observe('blur', this.fill.bind(this));
			this.stdval		= this.element.alt || this.element.value;
		},
		empty: function() {
			this.element.addClassName('active').removeClassName('error');
			if (this.element.value == this.stdval)
				this.element.value = '';
		},
		fill: function() {
			if (this.element.value.blank()) {
				this.element.value = this.stdval;
				this.element.removeClassName('active');
			}
		}
	});
// !tjg.Sound
	tjg.Sound = Class.create({
		initialize: function(el) {
			this.element	= $(el);
			this.element.observe('click', this.play.bind(this));
		},
		play: function() {
			Sound.enable();
			Sound.play('/media/mp3/tjg-jingle.mp3', { replace: true });

			this.element.stopObserving();
			this.element.setStyle({ 'background-image': 'url(/media/user/Hintergrund/bg-sound.gif)' });
			this.element.observe('click', this.stop.bind(this));

			this.playing	= window.setTimeout(this.stop.bind(this), 4 * 1000);
		},
		stop: function() {
			Sound.enable();
			Sound.play('', { replace: true });
			Sound.disable();
			this.element.setStyle({ 'background-image': 'url(/media/user/Hintergrund/bg-sound.jpg)' });
			this.element.observe('click', this.play.bind(this));
			window.clearTimeout(this.playing);
		}
	});
// !tjg.Controller
	tjg.Controller = Class.create({
		initialize: function() {
			this.objects	= new Object();
			this.onload		= Prototype.emptyFunction;

			var topper		= this.registerObject(new tjg.Toplink());
			//var sound		= new tjg.Sound('sound');
			$$('.toplink').collect((function(toplink) {
				topper.registerHandler(toplink);
			}).bind(this));
			$$('input.text', '.textarea').collect((function(input) {
				this.registerObject(new tjg.Input(input), 'inputs');
			}).bind(this));
			$$('.images').collect((function(images) {
				this.registerObject(new tjg.Slideshow(images), 'slideshows');
			}).bind(this));
		},
		registerObject: function(obj, opts) {
			var opts			= opts || 0;
			var options			= new Object();
				options.group	= opts.group || 'global';

			if (!this.objects[options.group])
				this.objects[options.group]	= new Array();
			if (typeof obj == 'object' && !this.objects[options.group][obj] && this.objects[options.group].push(obj)) {
				this.objects[options.group].last().group = this.objects[options.group];
				return obj;
			} else if (this.objects[options.group][obj])
				return this.objects[options.group][obj];
			else return false;
		}
	});