// Input: einzelner Klassenname
// Output: Array aller DOM-Elemente, bei denen der Klassenname in class="..." vorkommt.
/*
function getElementsByClassName(class_name) {
	var all_obj, ret_obj = new Array(), j = 0, teststr;

	if (document.all) {
		all_obj = document.all;
	} else if (document.getElementsByTagName && !document.all) {
		all_obj=document.getElementsByTagName("*");
	}

	for (i = 0; i < all_obj.length; i ++) {
		if (all_obj[i].className.indexOf(class_name) != -1) {
			teststr = "," + all_obj[i].className.split(" ").join(",") + ",";
			if (teststr.indexOf("," + class_name + ",") != -1) {
				ret_obj[j] = all_obj[i];
				j++;
	    	}
	  	}
	}
	return ret_obj;
}
*/

// Diese Funktion durchläuft das gesamte DOM einer HTML-Seite und wendet auf alle Knoten eine Funktion an.
// Aufruf z.B.:
// walkTheDOM( document.body, function(node) { ... } );
function walkTheDOM(node, func) {
	func(node);
	node = node.firstChild;
	while (node) {
		walkTheDOM(node, func);
		node = node.nextSibling;
	}
}

// Diese Funktion macht ein weiteres Objekt aus einem bereits bestehenden Objekt.
// Dabei wird das alte Objekt zum Prototyp des neuen Objekts.
function object(o) {
	function F() {}
	F.prototype = o;
	return new F();
}

// Diese Funktion ersetzt {}-Konstruktionen in ein einem Templatestring durch konkrete Werte.
// Anwendungsbeispiel:
// var template = '<table border="{border}">' +
//   '<tr><th>Last</th><td>{last}</td></tr>' +
//   '<tr><th>First</th><td>{first}</td></tr>' +
//   '</table>';
//
// var data = {
//   "first": "Carl",
//   "last": "Hollywood",
//   "border": "2"
// };
//
// mydiv.innerHTML = template.supplant(data);
String.prototype.supplant = function (o) {
	return this.replace(/{([^{}]*)}/g,
		function (a, b) {
			var r = o[b];
			return typeof r === 'string' ?
				r : a;
		}
	);
}

// Die folgende Funktion kann dazu benutzt werden, einem Objekt Methoden hinzuzufügen.
// Aufruf z.B.: Constructor.method('first_method', function (a, b) { ... });
Function.prototype.method =
	function (name, func) {
		this.prototype[name] = func;
		return this;
	};

// Fügt dem String-Objekt eine trim()-Methode hinzu. Aufruf z.B.: str = str.trim()
String.prototype.trim = function () {
	return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1');
};

// Aufruf z.B. objs = getElementsByClassName('myClass');
// Zurückgeliefert wird ein Array, das entweder leer ist oder aber Referenzen auf
// die Objekte enthält, die den gesuchten Klassennamen enthalten.
function getElementsByClassName(className, node) {
	var results = [];
	walkTheDOM(node || document.body, function (node) {
		var a, c = node.className, i;
		if (c) {
			a = c.split(' ');
			for (i = 0; i < a.length; i += 1) {
				if (a[i] === className) {
					results.push(node);
					break;
				}
			}
		}
	});
	return results;
}

// Liefert den tatsächlichen Wert für ein Style-Attribut eines Tags zurück.
// Aufruf z.B.: myDivFontSize = getCurrentStyle(document.getElementById('myDiv'), 'fontSize');
function getCurrentStyle(node, attr) {
	if (node.tagName != undefined) {
		if (node.currentStyle) { // IE
			if (node.currentStyle[attr] != undefined) {
				return node.currentStyle[attr];
			}
		} else if (document.defaultView) { // everything else
			// camelCase in Hyphenation umwandeln, z.B. fontStyle => font-style
			attr = attr.replace( /[A-Z]/, function (match) { return '-' + match.toLowerCase(); } );
			return document.defaultView.getComputedStyle(node, '').getPropertyValue(attr);
		}
	} else return false;
}

Array.prototype.inArray = function(needle) {
	for (var key in this) {
		if (this[key] == needle) {
			return true;
		}
	}
	return false;
}

Array.prototype.searchArray = function(needle) {
	for (c = 0; c < this.length; c += 1) {
		if (this[c] == needle) {
			return c;
		}
	}
	return false;
}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

// Diese Funktion rundet eine Zahl num auf dig Stellen hinter dem Komma.
// Wird dig nicht angegeben (oder ist gleich 0), so verhält sich diese Funktion
// wie Math.round(). Kann eines der Argumente nicht als Zahl identifiziert
// werden, so ist das Ergebnis gleich NaN.
function roundNum(num, dig) {
	if (arguments.length < 2) dig = 0;
	var mult = Math.pow(10, dig);
	return Math.round(parseFloat(num) * mult) / mult;
}

// Verwendung von lrnFontSizer wie folgt:
// In das BODY-Tag das Attribut onload="lrnFontSizer.init()" einfügen.
// In das HTML dann an irgendeiner Stelle z.B. folgendes einfügen:
// <p>
//   <a href="JavaScript: lrnFontSizer.adjust(-10)">A-</a>&nbsp;&nbsp;
//   <a href="JavaScript: lrnFontSizer.reset()">A</a>&nbsp;&nbsp;
//   <a href="JavaScript: lrnFontSizer.adjust(+10)">A+</a>
// </p>
// Die Funktion lrnFontSizer.reset() setzt die Schriftgrößen auf die ursprünglichen Werte zurück.
// Die Funktion adjust() erhält einen positiven oder negativen Prozentwert:
// Z.B. wird durch lrnFontSizer.adjust(-10) die Schrift um 10% verkleinert,
// durch lrnFontSizer.adjust(10) um 10% vergrößert.
lrnFontSizer = function() {
	var aspect = 1;
	var fontPropArr = [];

	function doResize() {
		var node, fs, fu, lh, lu, bt;
		for (i = 0; i < fontPropArr.length; i += 5) {
			node = fontPropArr[i]; bt = (node.tagName == 'BODY');
			if (fontPropArr[i + 1] == '') fs = ''; else fs = roundNum(fontPropArr[i + 1] * aspect, 1);
			fu = fontPropArr[i + 2];
			if (bt || (fu != '%' && fu != 'em')) node.style.fontSize = ''.concat(fs, fu);
			if (fontPropArr[i + 3] == '') lh = ''; else lh = roundNum(fontPropArr[i + 3] * aspect, 1);
			lu = fontPropArr[i + 4];
			if (bt || (lu != '%' && lu != 'em')) node.style.lineHeight = ''.concat(lh, lu);
		}
	}
	
	return {
		init : function () {
			var fsu, fs, fu, lhu, lh, lu;
			var fSize = lrnGetCookie('lrnFontSizeAspect');
			aspect = !isNaN(roundNum(fSize, 1)) ? roundNum(fSize, 1) : 1;
			fontPropArr = [];
			walkTheDOM(document.body, function(node) {
				if (node.tagName != undefined) {
					if (node.currentStyle) { // IE only
						if (node.currentStyle['fontSize']   != undefined) fsu = node.currentStyle['fontSize'];
						if (node.currentStyle['lineHeight'] != undefined) lhu = node.currentStyle['lineHeight'];
					} else if (document.defaultView) { // all other browsers except IE
						fsu = document.defaultView.getComputedStyle(node, '').getPropertyValue('font-size');
						lhu = document.defaultView.getComputedStyle(node, '').getPropertyValue('line-height');
					}
					fs = roundNum(fsu, 1); if (isNaN(fs)) fs = '';
					fu = fsu.replace(/[0-9\.]/g, '');
					lh = roundNum(lhu ,1); if (isNaN(lh)) lh = '';
					lu = lhu.replace(/[0-9\.]/g, '');
					fontPropArr.push(node, fs, fu, lh, lu);
				}
			});
			doResize();
		},
		
		adjust : function(percent) { // percent can be plus or minus
			if (percent == 0) return;
			aspect = aspect * (1 + percent / 100);
		    lrnSetCookie('lrnFontSizeAspect', aspect, 180, '/');
			doResize();
		},
		
		reset : function () {
			aspect = 1;
		    lrnDeleteCookie('lrnFontSizeAspect', '/');
			doResize();
		}
	}
}();

// Modified from Bill Dortch's Cookie Functions (hidaho.com) 
// (found in JavaScript Bible)
function lrnSetCookie(name, value, days, path, domain, secure) {
	var expires, date;
	if (typeof days == 'number') {
		date = new Date();
		date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
		expires = date.toGMTString();
	}
	document.cookie = name + '=' + escape(value) +
		((expires) ? '; expires=' + expires : '') +
		((path) ? '; path=' + path : '') +
		((domain) ? '; domain=' + domain : '') +
		((secure) ? '; secure' : '');
}

// Modified from Jesse Chisholm or Scott Andrew Lepera ?
// (found at both www.dansteinman.com/dynapi/ and www.scottandrew.com/junkyard/js/)
function lrnGetCookie(name) {
	var nameq = name + '=';
	var c_ar = document.cookie.split(';');
	for (var i=0; i < c_ar.length; i++) {
		var c = c_ar[i];
		while (c.charAt(0) == ' ') c = c.substring(1, c.length);
		if (c.indexOf(nameq) == 0) return unescape(c.substring(nameq.length, c.length));
	}
	return null;
}

// from Bill Dortch's Cookie Functions (hidaho.com)
function lrnDeleteCookie(name, path, domain) {
	if (lrnGetCookie(name)) {
		document.cookie = name + '=' +
			((path) ? '; path=' + path : '') +
			((domain) ? '; domain=' + domain : '') +
			'; expires=Thu, 01-Jan-70 00:00:01 GMT';
	}
}

