


// === Smooth Scroll Script v2.2.3 ===

// Beinhaltet:
// -- Streckenberechnung mit Array und Rundungsfehlerbeseitigung 
// -- Hack gg. .offsetTop-Bug
// -- Glätten der Kurve
// -- Schutz vor nahe liegenden Ankern
// -- Rollen mit scrollTo und Aufaddition der einzelnen Schritte (für Safari bei Vergrößerung – alles gezoomt) und
// -- Änderung der Reihenfolge der Y-Wert-Bestimmung für Safari bei vergrößerter Schrift (nur Schrift gezoomt)

// Bearbeiter: Paul Schächterle <mailto:paul.schaechterle@uni-greifswald.de>

// Teilweise basierend auf einem Skript von Stuart Langridge, <http://www.sitepoint.com/article/scroll-smoothly-javascript/>



// --- Browserchecks ---
// Für den ".offsetTop"-Bug in Safari und Mozilla

webkit = (navigator.appVersion.search(/AppleWebKit/)!=-1);
gecko = ((navigator.userAgent.search(/Gecko/)!=-1) && (!webkit));



/* -- Ereignis-Bearbeiter hinzufügen -- */

function ss_fixAllLinks() {
	// Get a list of all links in the page
	var allLinks = document.getElementsByTagName("a");
	// Walk through the list
	for (var i = 0; i < allLinks.length; i++) {
		var lnk = allLinks[i];
		if ((lnk.href && lnk.href.indexOf("#") != -1) &&
		((lnk.pathname == location.pathname) ||
		("/" + lnk.pathname == location.pathname)) &&
		(lnk.search == location.search)) {
			// If the link is internal to the page (begins in #)
			// then attach the smoothScroll function as an onclick
			// event handler
			ss_addEvent(lnk, "click", smoothScroll);
		}
	}
}

function ss_addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
{
	if (elm.addEventListener) {
		elm.addEventListener(evType, fn, useCapture);
		return true;
	} else if (elm.attachEvent) {
		var r = elm.attachEvent("on" + evType, fn);
		return r;
	}
}

ss_addEvent(window, "load", ss_fixAllLinks);



/* -- Roll-Funktionen -- */

// Von dieser Funktion benötigte globale Variablen
var ss_INTERVAL;
var xpos; // Nicht nötig, wenn scrollBy verwendet wird.
function smoothScroll(e) {

	// This is an event handler; get the clicked on element, in a cross-browser fashion
	if (window.event) {
		target = window.event.srcElement;
	} else if (e) {
		target = e.target;
	} else return;

	// Make sure that the target is an element, not a text node
	// within an element
	if (target.nodeType == 3) {
		target = target.parentNode;
	}

	// Paranoia; check this is an A tag
	if (target.nodeName.toLowerCase() != "a") return;

	// Find the <a name> tag corresponding to this href
	// First strip off the hash (first character)
	anchor = target.hash.substr(1);

	// === Eigener Einschub für #top-Anker ===
	if(anchor!="top") {
	
		// Now loop all A tags until we find one with that name
		var allLinks = document.getElementsByTagName("a");
		var destinationLink = null;
		for (var i = 0; i < allLinks.length; i++) {
			var lnk = allLinks[i];
			if (lnk.name && (lnk.name == anchor)) {
				destinationLink = lnk;
				break;
			}
		}
	
		// If we didn’t find a destination, give up and let the browser do
		// its thing
		if (!destinationLink) return true;
	
		// Find the destination’s position
		var destx = destinationLink.offsetLeft;
		var desty = destinationLink.offsetTop;
		var thisNode = destinationLink;
		while (thisNode.offsetParent &&
		(thisNode.offsetParent != document.body)) {
			thisNode = thisNode.offsetParent;
			destx += thisNode.offsetLeft;
			desty += thisNode.offsetTop;
		}
		
		// Hack! ".offsetTop"-Bug in Mozilla und Safari ausgleichen
		if((webkit)||(gecko)) { desty+=10; } // 10px ist der Rand des divs "Rahmen"
	
	} else {
		destx=0; desty=0;
	}
	
	// Stop any current scrolling
	clearInterval(ss_INTERVAL);
	
	// === Korrektur für Anker, die am unteren Ende der Seite liegen ===
	dh = getDocHeight();
	wh = document.documentElement.clientHeight; // Diese Höhe stimmt auch, wenn das Fenster einen horizontalen Rollbalken hat.
	maxd = dh - wh;
	if(desty>maxd) desty = maxd;
	
	cypos = ss_getCurrentYPos();
	
	// Damit nicht immer nach links geschwenkt wird. Nicht nötig, wenn scrollBy verwendet wird.
	xpos = ss_getCurrentXPos();
	
	// === Eigene Berechnung der Schritte ===
	distanz = desty - cypos;
	
	// Abbruch, wenn keine Distanz
	if(distanz==0) return true;
	
	// Richtungseinheit bestimmen (u)
	if(distanz < 0) { u = -1; } else { u = 1; }
	
	// Positiv fassen
	distanz = Math.abs(distanz);
	
	// Distanz muß gerade sein, wenn nicht wird sie um 1px verkürzt
	if(distanz % 2 !=0) { distanz -= 1; } // alert("Ungerade Distanz, verkürzt.");
	
	// Schrittzahl und Durchschnittsschrittlänge berechnen
	schrittZahl = Math.round(Math.sqrt(Math.abs(distanz))*0.5)+7; // Geschwindigkeit festlegen (1/2)
	if(schrittZahl > distanz) schrittZahl = distanz; // Für den Fall eines sehr nahe liegenden Ankers (z.B. Seite nur ganz leicht gerollt)
	if(schrittZahl % 2 != 0) { schrittZahl += 1; } // Gerade Schrittzahl erzeugen
	schrittDS = distanz / schrittZahl;
	
	// Die erste Hälfte des Laufes berechnen
	lauf = new Array();
	laufStrecke = 0;
	s = -1;
	for (i=1; i <= (schrittZahl/2); i++) {
		s += 1;
		beschl = Math.cos( ((i/schrittZahl)-(0.5/schrittZahl)) * 2 * Math.PI - Math.PI ) + 1;
		schritt = Math.round(schrittDS * beschl);
		if(schritt==0) schritt=1;
		lauf[s] = schritt;
		laufStrecke += schritt;
	}
	
	// Rundungsfehler ermitteln
	diff = (distanz/2) - laufStrecke;
	
	// Rundungsfehler beseitigen
	lauf[s] += diff;
	
	// Glättung der Kurve (Nur wenn die Differenz negativ ist, d.h. der letzte Schritt verkleinert wird)
	for(i=s; i>(s+diff); i--) {
		while(lauf[i-1] > lauf[i]) {
			lauf[i-1] -=1; lauf[i] +=1;
		}
	}
	
	// -- Debugging -- 
	/* laufStreckeNeu = laufStrecke + diff;
	diffNeu = (distanz/2) - laufStreckeNeu;
	alert(
		"Halbe Distanz: "+distanz/2+
		"\nSchrittzahl: "+schrittZahl/2+
		"\nLauf: "+lauf+
		"\nLaufstrecke: "+laufStrecke+
		"\nDifferenz: "+diff+
		"\nLaufstrecke neu: "+laufStreckeNeu+
		"\nDifferenz neu: "+diffNeu+
		"\nArray-Länge: "+lauf.length
	); */
	
	// Lauf starten
	idx = -1;
	posAdd = ss_getCurrentYPos(); // Für Safari alles gezoomt
	ss_INTERVAL = setInterval(function(){ss_scrollWindow(lauf, anchor, u)}, 15); // Geschwindigkeit festlegen (2/2)
	
	// And stop the actual click happening
	if (window.event) {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
	if (e && e.preventDefault && e.stopPropagation) {
		e.preventDefault();
		e.stopPropagation();
	}
}

// Von dieser Funktion benötigte globale Variable
var idx;
var posAdd; // für die Positionierung in Safari bei Vergrößerung (alles gezoomt)
function ss_scrollWindow(lauf, anchor, u) {
	idx = idx + 1;
	// wascypos = ss_getCurrentYPos(); // Nicht nötig, wenn scrollBy verwendet wird; ersetzt durch posAdd.
	if (idx < lauf.length) {
		scramount = lauf[idx]*u;
		posAdd = posAdd + scramount;
		window.scrollTo(xpos, posAdd); // alert("AUF Schritt "+(idx+1)+": "+posAdd);
	} else if (idx < (lauf.length*2)) {
		id = (lauf.length*2) - 1 - idx;
		scramount = lauf[id]*u;
		posAdd = posAdd + scramount;
		window.scrollTo(xpos, posAdd); // alert("AB Schritt "+(idx+1)+": "+posAdd);
	} else {
		// Cancel repeating timer
		clearInterval(ss_INTERVAL);
		// Next turn jump to the link directly so the URL is right
		window.setTimeout(function(){location.hash = anchor;}, 15); // Vgl. Geschwindigkeit einstellen (2/2)
	}
}

// Allgemeine Funktionen

function ss_getCurrentYPos() {
	if (window.pageYOffset)
		return window.pageYOffset;
	if (document.body && document.body.scrollTop)
		return document.body.scrollTop;
	if (document.documentElement && document.documentElement.scrollTop)
		return document.documentElement.scrollTop;
	return 0;
}

function ss_getCurrentXPos() {
	if (window.pageXOffset)
		return window.pageXOffset;
	if (document.body && document.body.scrollLeft)
		return document.body.scrollLeft;
	if (document.documentElement && document.documentElement.scrollLeft)
		return document.documentElement.scrollLeft;
	return 0;
}

function getDocHeight() {
	var D = document;
	return Math.max(
		Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
		Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
		Math.max(D.body.clientHeight, D.documentElement.clientHeight)
	);
}


