

	/* Copyright 2007-2009 ADsignum */

	/* ---------------------------------------------------------------------- */
	function getObj(n) {
		return document.getElementById(n);
	}

	function getStyle(o, s) {
		return          document.defaultView.getComputedStyle(o, null).getPropertyValue(s) ;
	};

	function getStyleI(o, s) {
		return parseInt(document.defaultView.getComputedStyle(o, null).getPropertyValue(s));
	}

	function getInnerHeight(o) {
		return o.offsetHeight - getStyleI(o, 'padding-top' ) - getStyleI(o, 'padding-bottom') - getStyleI(o, 'border-top-width'  ) - getStyleI(o, 'border-bottom-width' ); }
	function getInnerWidth(o) {
		return o.offsetWidth  - getStyleI(o, 'padding-left') - getStyleI(o, 'padding-right' ) - getStyleI(o, 'border-left-width' ) - getStyleI(o, 'border-right-width'  ); }
	function getOuterHeight(o) {
		return o.offsetHeight + getStyleI(o, 'margin-top'  ) + getStyleI(o, 'margin-bottom' ) /*+ getStyleI(o, 'outline-top-width' ) + getStyleI(o, 'outline-bottom-width')*/; }
	function getOuterWidth(o) {
		return o.offsetWidth  + getStyleI(o, 'margin-left' ) + getStyleI(o, 'margin-right'  ) /*+ getStyleI(o, 'outline-left-width') + getStyleI(o, 'outline-right-width' )*/; }
	function getAroundHeight(o) {
		return                  getStyleI(o, 'margin-top'  ) + getStyleI(o, 'margin-bottom' ) + getStyleI(o, 'padding-top' ) + getStyleI(o, 'padding-bottom') + getStyleI(o, 'border-top-width'  ) + getStyleI(o, 'border-bottom-width' ) }
	function getAroundWidth(o) {
		return                  getStyleI(o, 'margin-left' ) + getStyleI(o, 'margin-right'  ) + getStyleI(o, 'padding-left') + getStyleI(o, 'padding-right' ) + getStyleI(o, 'border-left-width' ) + getStyleI(o, 'border-right-width'  ); }

	/* ---------------------------------------------------------------------- */
	function parentalCheck(trg, obj) {
		do {
			if (trg == obj)
				return true;
		} while (trg && (trg = trg.parentNode));

		return false;
	}

	/* ---------------------------------------------------------------------- */
	var skipAnims = getCookieValue('skipAnims', 'false') == 'false' ? false : true;
	var skipSwitch = getObj('off');

	if (skipSwitch) {
		skipSwitch.title = 'switch animations ' + (skipAnims ? 'on' : 'off');
		skipSwitch.className = (skipAnims ? 'on' : 'off');
		skipSwitch.addEventListener('click', function (e) {
			skipAnims = !skipAnims;

			skipSwitch.title = 'switch animations ' + (skipAnims ? 'on' : 'off');
			skipSwitch.className = (skipAnims ? 'on' : 'off');

			if (skipAnims) {
				sAmount = sHU - sH;
				pAmount = pB - pBL;
			}
			else {
				sAmount = 7;
				pAmount = 3;
			}

			setCookieValue('skipAnims', skipAnims);
		}, false);
	}

	/* ---------------------------------------------------------------------- */
	var selV = getObj('selectorV');
	var selT = getObj('selectorT');
	var selP = getObj('selectorP');
	var selA = selT.firstChild;

	function set(elem, sect) {
		if (selV.style.display != '')
			sect = 'Projects';
		if (!contentT[sect])
			return;

		var
		extract = document.createElement('div');
		extract.innerHTML = contentT[sect].link;
		contentT[sect].href = extract.firstChild.href;

		selA.href      = contentT[sect].href;
		selA.innerHTML = contentT[sect].title;
		selP.innerHTML = contentT[sect].description;

		if (!elem)
			return;

		elem.href      = contentT[sect].href;
		elem.title     = contentT[sect].title;
	}

	function unset(elem, sect) {
		set(elem, 'Projects');
	}

	function click(sect) {
	//	if (selV.style.display == '')
	//		alert(contentT[sect].link);

		return (selV.style.display == '');
	}

	/* ---------------------------------------------------------------------- */
	var sizer = null, sAmount = 7;
	var cntt = getObj('content'), cT;
	var snav = getObj('container'), sH, sHU, sHL;
	var lerO = getObj('layerO');
	var lerW = getObj('layerW');
	var lerN = getObj('layerN');
	var lerM = getObj('layerM');
	var lerG = getObj('layerG');
	var lerL = getObj('layerL'), hL;
	var lerS = getObj('layerS'), hS;

	if (snav) {
		cT  = parseInt(cntt.style.top);
		sH  = parseInt(snav.style.height);
		sHL = parseInt(snav.style.height) << 0;
		sHU = parseInt(snav.style.height) << 1;
		hL  = parseInt(lerL.style.height);
		hS  = parseInt(lerS.style.height);

		if (skipAnims)
			sAmount = sHU - sH;
	}

	function freeze() {
		if (sizer) {
			clearInterval(sizer); sizer = null;
		}
	}

	function grow() {
		if (sH < sHU) {
			snav.style.height = Math.floor(sH +=  sAmount         ) + 'px';
			cntt.style.top    = Math.floor(cT +=  sAmount         ) + 'px';
			lerL.style.height = Math.floor(hL += (sAmount * 1) / 7) + 'px';
			lerS.style.height = Math.floor(hS += (sAmount * 8) / 7) + 'px';
		}
		else {
			selV.style.display = '';
			lerL.src = 'pics/logo.png';

			freeze();
		}
	}

	function shrink() {
		if (sH < sHU) {
			selV.style.display = 'none';
			lerL.src = 'pics/logoS.png';
		}

		if (sH > sHL) {
			snav.style.height = Math.floor(sH -=  sAmount         ) + 'px';
			cntt.style.top    = Math.floor(cT -=  sAmount         ) + 'px';
			lerL.style.height = Math.floor(hL -= (sAmount * 1) / 7) + 'px';
			lerS.style.height = Math.floor(hS -= (sAmount * 8) / 7) + 'px';
		}
		else
			freeze();
	}

	function growing  (e) { if ( parentalCheck(e.target       , lerM)) { freeze(); sizer = setInterval(grow,   1); return true; } return false; }
	function shrinking(e) { if (!parentalCheck(e.relatedTarget, snav)) { freeze(); sizer = setInterval(shrink, 1); return true; } return false; }

	/* ---------------------------------------------------------------------- */
	var pulser = null, pAmount = 3;
	var mnuM = getObj('menu');
	var mnuS = getObj('submenu'), pB, pBU, pBL;
	var lrhW = getObj('layerWh');

	if (mnuS) {
		pB  = parseInt(mnuS.style.bottom);
		pBL = parseInt(mnuS.style.bottom) - 26;
		pBU = parseInt(mnuS.style.bottom) -  0;

		if (skipAnims)
			pAmount = pB - pBL;
	}

	function stop() {
		if (pulser) {
			clearInterval(pulser); pulser = null;
		}
	}

	function expulse() {
		if (pB > pBL) {
			mnuS.style.bottom = (pB -= pAmount) + 'px';
			lerN.style.bottom =  pB             + 'px';
		}
		else {
			mnuS.style.display = '';

			stop();
		}
	}

	function impulse() {
		if (pB > pBL)
			mnuS.style.display = 'none';

		if (pB < pBU) {
			mnuS.style.bottom = (pB += pAmount) + 'px';
			lerN.style.bottom =  pB             + 'px';
		}
		else
			stop();
	}

	function expulsing(e) { if ( parentalCheck(e.target       , lrhW)) { stop(); pulser = setInterval(expulse, 10); return true; } return false; }
	function impulsing(e) { if (!parentalCheck(e.relatedTarget, lrhW)) { stop(); pulser = setInterval(impulse, 10); return true; } return false; }

	/* ---------------------------------------------------------------------- */
	function remenu() {
		var e, entry, ehtml = '';
		for (e in menuT) { if ((entry = menuT[e]).link) {
			var echk = document.createElement('div'); echk.innerHTML = entry.link;
			var eact = (window.location.href.substr(0, echk.firstChild.href.length) == echk.firstChild.href);

			/* collect the sub-menu HTML */
			var c, child, chtml = '';
			for (c in entry.childs) { if ((child = entry.childs[c]).link) {
				var cchk = document.createElement('div'); cchk.innerHTML = child.link;
				var cact = (window.location.href.substr(0, cchk.firstChild.href.length) == cchk.firstChild.href);

				chtml += child.link.replace('href="', 'style="opacity: ' + (cact ? '1.0' : '0.5') + ';" href="');

				/* detect selections */
				eact = eact || cact;
			}}

			/* register the sub-menu HTML */
			menuT[e].innerHTML = chtml;

			ehtml += entry.link.replace('href="', 'style="opacity: ' + (eact ? '1.0' : '0.5') + ';" onmouseover="mnuS.innerHTML = menuT[\'' + e + '\'].innerHTML;" href="');
		}}

		mnuM.innerHTML = ehtml;
	}

	/* ---------------------------------------------------------------------- */
	var smaller = false, repeated = false, bootstrapped = false;
	var position = 0, positions = new Array();

	var subs = getObj('reflow');
	var line = getObj('linetab');
	var scrl = getObj('scroller');
	var icon = getObj('scrollicon');
	var fthr = subs.parentNode;
	var fthrGrps = [document.createElement('div'), document.createElement('div')];

	function rescroll() {
		/* .................................................................. */
		var body = document.body;
		var bodyWidth  = body.offsetWidth;
		var bodyHeight = body.offsetHeight;
		var subsWidth  = subs.offsetWidth;
		var fthrWidth  = getInnerWidth (fthr);
		var fthrHeight = getInnerHeight(fthr);
		var ih = 26, iw;
		var d = false, dx, dy, sx, sw, fx, fw = subsWidth - fthrWidth,
			/* moving the mouse over half the window, should scroll the whole area */
			factor = subsWidth / (bodyWidth / 2);

		line.style.display = 'none';
		icon.style.width = (iw = Math.max( 0, ((ih * bodyWidth) / bodyHeight))    ) + 'px';
		scrl.style.width = (sw = Math.max(iw, ((iw * subsWidth) / fthrWidth )) + 3) + 'px'; /*'75%';*/

		/* preserve position on re-scroll */
		setPos(subs.style.left ? -parseInt(subs.style.left) : 0);
		endPos();

		function setPos(posi) {
			iw = parseInt(icon.style.width);
			sw = parseInt(scrl.style.width);
		//	fw = subsWidth - fthrWidth;
			fw = subs.offsetWidth - getInnerWidth(subs.parentNode);

			if (fw < 0) fw = 0;

			if (posi <  0) posi =  0;
			if (posi > fw) posi = fw;

			if (fw) {
				icon.style.left = ( posi * ((sw - 3 - iw) / fw)) + 'px';
				subs.style.left = (-posi                       ) + 'px';
			}
			else {
				icon.style.left = '0px';
				subs.style.left = '0px';
			}
		}

		function endPos() {
			sx = parseInt(icon.style.left);
			fx = parseInt(subs.style.left);

			position = 0;
			for (var p = 0; p < positions.length; p++)
				if (positions[p] <= (-fx))
					position = p;
		}

		if (!bootstrapped) {
			getObj("scBegin").addEventListener('mousedown', function (e) {
				setPos(positions[position = (                                                                        0)]);
				endPos(); e.stopPropagation(); }, false);
			getObj("scPPrev").addEventListener('mousedown', function (e) {
				setPos(-fx - fthrWidth);
				endPos(); e.stopPropagation(); }, false);
			getObj("scRPrev").addEventListener('mousedown', function (e) {
				setPos(positions[position = (position - 1 >                    0 ? position - 1 :                    0)]);
				endPos(); e.stopPropagation(); }, false);
			getObj("scRNext").addEventListener('mousedown', function (e) {
				setPos(positions[position = (position + 1 < positions.length - 1 ? position + 1 : positions.length - 1)]);
				endPos(); e.stopPropagation(); }, false);
			getObj("scPNext").addEventListener('mousedown', function (e) {
				setPos(-fx + fthrWidth);
				endPos(); e.stopPropagation(); }, false);
			getObj("scEnd").addEventListener('mousedown', function (e) {
				setPos(positions[position = (                                                     positions.length - 1)]);
				endPos(); e.stopPropagation(); }, false);

			scrl.addEventListener('mousedown', function (e) {
				if (!d) {
					if (e.preventDefault)
						e.preventDefault();

					var posi = e.clientX - scrl.offsetLeft - scrl.parentNode.offsetLeft;

					if (posi < (sx))
						setPos(-fx - fthrWidth);
					else if (posi > (sx + iw))
						setPos(-fx + fthrWidth);

					endPos(); e.stopPropagation();
				}
			}, false);

			line.addEventListener('resize', function (e) {
//				alert('x');
			}, false);

			icon.addEventListener('mousedown', function (e) {
				if (!d) { d = true;
					if (e.preventDefault)
						e.preventDefault();

					dx = e.clientX;
					dy = e.clientY;

					body.style.cursor = 'move';
					scrl.style.cursor = 'move';
					icon.style.cursor = 'move';
				}
			}, false);

			body.addEventListener('mousemove', function (e) {
				if (d) {
					if (e.preventDefault)
						e.preventDefault();

					var dist = factor * (e.clientX - dx);
					var posi = -fx + dist;

					setPos(posi);
				}
			}, false);

			body.addEventListener('mouseup', function (e) {
				if (d) { d = false;
					if (e.preventDefault)
						e.preventDefault();

					endPos();

					body.style.cursor = 'default';
					scrl.style.cursor = '';
					icon.style.cursor = '';
				}
			}, false);

			body.addEventListener('DOMMouseScroll', function (e) {
				if (!d) {
					if (e.preventDefault)
						e.preventDefault();

					var dist = factor * (e.detail * 2);
					var posi = -fx + dist;

					setPos(posi);
					endPos();
				}
			}, false);

			bootstrapped = true;
		}

		fthr.style.overflowX = 'hidden';
		line.style.display = '';
	}

	function reflow() {
		/* .................................................................. */
		var fthrWidth  = getInnerWidth (fthr);
		var fthrHeight = getInnerHeight(fthr) -
						 getOuterHeight(fthrGrps[0]) -
						 getOuterHeight(fthrGrps[1]);
		var sum = 0, max = 0; positions = new Array();
		var idx;

		fthr.className = fthr.className.replace(/vertical/, 'bound');
		subs.style.height = '';
		subs.style.width = '32767px';
		subs.style.marginTop = '';
		subs.style.marginBottom = '';

		/* .................................................................. */
		for (idx = 0; idx < subs.childNodes.length; idx++) {
			var s = subs.childNodes[idx];

			if (s && s.style) {
				var modifier = (!smaller ? 16384 : parseInt(s.style.width) >> 1);

				/* make this to secure that the reflown styles are used */
				if (!s.className.match(/reflown/))
					s.className += ' reflown';

				/* invisible internal scrolling */
				s.style.overflow = 'hidden';

				/* 32767 = 16384 + 8192 + 4096 + ... 4 + 2 + 1 */
				s.style.height = '';
				s.style.width  = (!smaller ? '32767px' : parseInt(s.style.width) + 'px');
				s.style.marginTop = '';
				s.style.marginBottom = '';

				/* we want to go untill here */
				var reachHeight = fthrHeight - getAroundHeight(s);

				/* these are our boundaries */
				var miniWidth =   64;	// TODO: min-width
				var maxiWidth = 1024;	// TODO: max-width

				/* container for possible splits */
				var subGrps = document.createElement('div');

				/* unsplit previous splits */
				var g = s.nextSibling;
				/* find next brother of entry */
				while (g && !((g.nodeType != 3) && (g.nodeType != 8)))
					g = g.nextSibling;
				/* reintegrate splitted */
				if (g && g.className && g.className.match(/generated/)) {
					var sc;

					while ((sc = g.firstChild)) {
						g.removeChild(sc); if (!sc.className || !sc.className.match(/generated/))
						s.appendChild(sc);
					}

					subs.removeChild(g);
				}

				/* do as long as we have to */
				do {
//					s.style.border = '1px dashed white';
					while (modifier) {
//						alert('step ' + modifier + ' -> ' + parseInt(s.style.width) + ' (' + s.offsetHeight + '/' + reachHeight + ')');

						/* make it more narrow */
						if (s.offsetHeight < reachHeight)
							s.style.width = Math.max(1, parseInt(s.style.width) - modifier) + 'px';
						/* make it more wide */
						if (s.offsetHeight > reachHeight)
							s.style.width = Math.max(1, parseInt(s.style.width) + modifier) + 'px';

						/* we received internal scrolling, we can't go below that */
						if (s.offsetWidth < s.scrollWidth)
							s.style.width = Math.max(1, parseInt(s.style.width) + modifier) + 'px';

						/* we reached what we wanted */
						if (s.offsetHeight == reachHeight)
							break;

						modifier >>= 1;
					}
//					s.style.border = '';

//					alert((s.offsetWidth + ':' + maxiWidth) + ' / ' + (s.offsetHeight + ':' + reachHeight));

					/* remove elements untill we have space */
					if (s.offsetWidth > maxiWidth) {
						var sc, tc = s.lastChild;

						while (tc != s.firstChild) {
							if (tc.tagName && (tc.tagName.toLowerCase() == 'p'))
								break;
							tc = tc.previousSibling;
						}

						/* one element minimum */
						if (tc != s.firstChild) {
							do {
								s.removeChild(sc = s.lastChild);

								/* no empty plain-texts, no comments */
								if ((sc.nodeType != 3) && (sc.nodeType != 8))
									subGrps.insertBefore(sc, subGrps.firstChild);
							} while(tc != sc);

							modifier = s.offsetWidth << 1;
							continue;
						}
						else
							break;
					}
					else
						break;

				} while (s.offsetWidth > maxiWidth);

				/* append removed elements afterwards */
				if (subGrps.hasChildNodes()) {
					/* find header, if possible */
					var g = s.firstChild;
					/* find next brother of entry */
					while (g && !((g.nodeType != 3) && (g.nodeType != 8)))
						g = g.nextSibling;

					/* put prefix-header _only_ if with header */
					if (g && g.tagName && g.tagName.toLowerCase().match(/h[1-6]/)) {
						var h = document.createElement(g.tagName.toLowerCase());
						h.innerHTML = '&nbsp;';
						h.className = 'generated';

						subGrps.insertBefore(h, subGrps.firstChild);
					}

					subGrps.className = s.className + ' generated';
					subGrps.style.cssText = s.style.cssText;
					subs.insertBefore(subGrps, s.nextSibling);
				}

				/* record the mid-points of each reflown element */
				positions[positions.length] = sum + (getOuterWidth(s) >> 1) - (fthrWidth >> 1);

				/* sum up the whole width */
				sum += 1 + getOuterWidth(s);
				/* max out any height */
				max  = Math.max(max, getOuterHeight(s));

			//	subs.style.left = -sum + 'px';
			}
		}

		/* apply alignment */
		switch (getStyle(subs, 'vertical-align')) {
			case 'top'   : subs.style.marginTop = (                    getStyleI(subs, 'margin-top'   )) + 'px'; break;
			case 'middle': subs.style.marginTop = ((fthrHeight - max) >> 1)                              + 'px'; break;
			case 'bottom': subs.style.marginTop = ( fthrHeight - max - getStyleI(subs, 'margin-bottom')) + 'px'; break;
		}

		/* apply better calculatability */
		subs.style.marginBottom = ((fthrHeight - max) - getStyleI(subs, 'margin-top') - getStyleI(subs, 'margin-bottom')) + 'px';

		/* check if we still have space */
/*		if (parseInt(subs.style.marginTop) < 0) {
			fthr.innerHTML = 'you should make your browser a bit bigger, or turn off the horizontal layout \<a href=""\>here\<\/a\>';
			return;
		}*/

		/* finalize the changes */
		subs.style.height = (fthrHeight - getAroundHeight(subs)) + 'px';
		subs.style.width = sum + 'px';
		fthr.className = fthr.className.replace(/bound/, 'horizontal');

		/* .................................................................. */
		for (idx = 0; idx < subs.childNodes.length; idx++) {
			var s = subs.childNodes[idx];

			if (s && s.style) {
				max = getStyleI(subs, 'height');

				/* apply alignment */
				switch (getStyle(s, 'vertical-align')) {
					case 'top'   : s.style.marginTop = (                           getStyleI(s, 'margin-top'   )) + 'px'; break;
					case 'middle': s.style.marginTop = ((max - getInnerHeight(s)) >> 1)                           + 'px'; break;
					case 'bottom': s.style.marginTop = ( max - getInnerHeight(s) - getStyleI(s, 'margin-bottom')) + 'px'; break;
				}

				/* apply better calculatability */
				s.style.marginBottom = ((max - getInnerHeight(s)) - getStyleI(s, 'margin-top') - getStyleI(s, 'margin-bottom')) + 'px';
			}
		}

		/* .................................................................. */
	//	if (!repeated)
	//		return repeated = setTimeout(reflow, 0);

		/* .................................................................. */
		rescroll();
	}

	function deflow() {
		/* .................................................................. */
		while ((s = fthr.firstChild) != subs) {
			fthr.removeChild(s);
			/* no empty plain-texts, no comments */
			if ((s.nodeType != 3) &&
				(s.nodeType != 8))
				fthrGrps[0].appendChild(s);
		}

		while ((s = fthr.lastChild) != subs) {
			fthr.removeChild(s);
			/* no empty plain-texts, no comments */
			if ((s.nodeType != 3) &&
				(s.nodeType != 8))
				fthrGrps[1].insertBefore(s, fthrGrps[1].firstChild);
		}

		/* .................................................................. */
		if (fthrGrps[0].hasChildNodes()) {
			fthrGrps[0].id = 'prefix';
			fthr.insertBefore(fthrGrps[0], subs);
		}

		if (fthrGrps[1].hasChildNodes()) {
			fthrGrps[1].id = 'suffix';
			fthr.appendChild(fthrGrps[1]);
		}

		/* .................................................................. */
		reflow();
	}

	function align() {
		for (idx = 0; idx < subs.childNodes.length; idx++) {
			var s = subs.childNodes[idx];

			if (s && s.style) {
				/* make this to secure that the reflown styles are used */
				if (!s.className.match(/aligned/))
					s.className += ' aligned';
			}
		}
	}

	/* ---------------------------------------------------------------------- */
	function inits() {
		remenu();
		set(null, 'Projects');
	}

//	window.addEventListener('resize', reflow, false);
//	window.addEventListener('load',   deflow, false);
	window.addEventListener('load',   align,  false);
	window.addEventListener('load',   inits,  false);

	if (snav) {
		snav.addEventListener('mouseout',  function (e) { return !shrinking(e); }, false);
		snav.addEventListener('mouseover', function (e) { return !growing  (e); }, false);

		document.body.addEventListener('mouseout',  function (e) { return !shrinking(e); }, false);
	}

	if (lrhW && mnuS && mnuS.hasChildNodes()) {
		lrhW.addEventListener('mouseout',  function (e) { return !impulsing(e); }, false);
		lrhW.addEventListener('mouseover', function (e) { return !expulsing(e); }, false);
	}
