/*[version]2008-08-28 19:48[/version]*/
/**
 * Module Acu.js Anema Core Utils
 *
 */

Acu = {};

Acu.registerEvent = function( element, eventType, handler ){
	if( !element ) return;

	if( element.addEventListener ){
		element.addEventListener( eventType, handler, false );
	}else if( element.attachEvent ){
		element.attachEvent( "on" + eventType, handler );
	}else{
		element["on"+eventType] = handler;
	}
};

Acu.unregisterEvent = function( element, eventType, handler ){
	if( !element ) return;

	if( element.removeEventListener ){
		element.removeEventListener( eventType, handler, false );
	}else if( element.detachEvent ){
		element.detachEvent( "on" + eventType, handler );
	}else{
		element["on"+eventType] = null;
	}
};

Acu.getCurrentStyles = function( obj ){
	var styles = null;

	if( !obj ) return null;

	if( window.getComputedStyle ){
		styles = window.getComputedStyle(obj, null);
	}else if( obj.currentStyle ){
		styles = obj.currentStyle;
	}

	return styles;
};

Acu.getHttpRequest = function(){
    if( window.XMLHttpRequest ){
        return new XMLHttpRequest();
    } else if( window.ActiveXObject ){
        return new ActiveXObject( "Microsoft.XMLHTTP" );
    }else{
	    return null;
    }
};


// Die folgenden Methoden sind vom Definitive Guide geklaut (CSSClass.js).
Acu.hasCssClass = function( e, c ){
	if( typeof e == "string" ) e = document.getElementById( e );	// element id

	// Before doing a regexp search, optimize for a couple of common cases.
	var classes = e.className;
	if( !classes ) return false;	// Not a member of any class
	if( classes == c ) return true;	// Member of just this one class

	// Otherwise, use a regular expression to search for c as a word by itself
	// \b in a regular expression requires a match at a word boundary.
	return e.className.search( "\\b" + c + "\\b" ) != -1;
};

// Add class c to the className of element e if it is not already there.
Acu.addCssClass = function( e, c ){
	if( typeof e == "string" ) e = document.getElementById( e );	// element id
	if( Acu.hasCssClass(e, c) ) return;	// If already a member, do nothing
	if( e.className ) c = " " + c;	// Whitespace separator, if needed
	e.className += c;				// Append the new class to the end
};

// Remove all occurrences (if any) of class c from the className of element e
Acu.removeCssClass = function( e, c ){
	if( typeof e == "string" ) e = document.getElementById( e );	// element id
	// Search the className for all occurrences of c and replace with "".
	// \s* matches any number of whitespace characters.
	// "g" makes the regular expression match any number of occurrences
	e.className = e.className.replace( new RegExp("\\b"+c+"\\b\\s*", "g"), "" );
};

/**
Opacity wird als Dezimalwert angegeben, z.B. "0.7".
*/
Acu.setOpacity = function( element, opacity ){
	if( element && element.style ){
		var style = element.style;
		var ie_opacity = Math.round( opacity * 100 );
		style.opacity = "" + opacity;
		style.filter = "alpha(opacity=" + ie_opacity + ")";
	}
};


// Setzt voraus, dass das Element in Pixel dimensioniert wurde.
// Bzw. dass es einheitliche GrÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¶ÃƒÆ’Ã†â€™Ãƒâ€¦Ã‚Â¸enangaben hat.
Acu.getDomElementTotalWidth = function( obj ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );
	if( !obj ) return;

	var styles = Acu.getCurrentStyles( obj );

	var totalWidth = parseInt( styles.width );
	totalWidth = isNaN(totalWidth) ? 0 : totalWidth;

	var val = parseInt( styles.paddingLeft );
	if( !isNaN(val) ) totalWidth += val;
	val = parseInt( styles.paddingRight );
	if( !isNaN(val) ) totalWidth += val;
	val = parseInt( styles.borderLeftWidth );
	if( !isNaN(val) ) totalWidth += val;
	val = parseInt( styles.borderRightWidth );
	if( !isNaN(val) ) totalWidth += val;

	return totalWidth;
};

// Setzt voraus, dass das Element in Pixel dimensioniert wurde.
// Bzw. dass es einheitliche GrÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¶ÃƒÆ’Ã†â€™Ãƒâ€¦Ã‚Â¸enangaben hat.
Acu.getDomElementTotalHeight = function( obj ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );
	if( !obj ) return;

	var styles = Acu.getCurrentStyles( obj );

	var totalHeight = parseInt( styles.height );
	totalHeight = isNaN(totalHeight) ? 0 : totalHeight;

	var val = parseInt( styles.paddingTop );
	if( !isNaN(val) ) totalHeight += val;
	val = parseInt( styles.paddingBottom );
	if( !isNaN(val) ) totalHeight += val;
	val = parseInt( styles.borderTopWidth );
	if( !isNaN(val) ) totalHeight += val;
	val = parseInt( styles.borderBottomWidth );
	if( !isNaN(val) ) totalHeight += val;

	return totalHeight;
};


// Durchsucht ein DOM-Element und seine Kindknoten nach einem Element mit der
// angegebenen ID.
Acu.searchDomElementForId = function( obj, id ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );
	if( !obj ) return null;

	if( obj.id == id ) return obj;

	for( var n=obj.firstChild; n!=null; n=n.nextSibling ){
		if( n.id == id ) return n;
	}

	// Keiner der Kinder war's, wie sieht's mit den Kindeskindern aus?
	for( var n=obj.firstChild; n!=null; n=n.nextSibling ){
		var result = searchDomElementForId( n, id );
		if( result && result.id == id ) return result;
	}

	return null;
};

Acu.hideDiv = function( obj ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );
	if( !obj ) return;
	obj.style.display = 'none';
};

Acu.showDiv = function( obj ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );
	if( !obj ) return;
	obj.style.display = '';
};

Acu.toggle = function( obj ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );	// element id
	var status = obj.style.display;
	if (status == 'none') {
		obj.style.display = '';
	}else{
		obj.style.display = 'none';
	}
};

Acu.in_array = function( value, arr ){
	for( var i=0; i<arr.length; i++ ){
		if( value == arr[i] ){
			return true;
		}
	}
	return false;
};

/* Die XML-Funktionen sind wieder Mal aus dem schlauen Buch geklaut. */
Acu.createNewXmlDocument = function( rootTagName ){
	if( !rootTagName ) rootTagName = "";

	if( document.implementation && document.implementation.createDocument ){
		// "" statt einer namespaceURL
		return document.implementation.createDocument( "", rootTagName, null );
	}else{
		var doc = new ActiveXObject( "MSXML2.DOMDocument" );
		var text = "<" + rootTagName + " />";
		doc.loadXML( text );
		return doc;
	}
};

Acu.xmlNodeToString = function( node ){
	if( typeof XMLSerializer != "undefined" ){
		return (new XMLSerializer()).serializeToString( node );
	}else if( node.xml ){	// IE
		return node.xml;
	}else{
		throw "Acu.xmlNodeToString is not supported.";
	}
};

Acu.parseXmlStringIntoDocument = function( text ){
	if( typeof DOMParser != "undefined" ){
		// Mozilla, Firefox and related browsers.
		return (new DOMParser()).parseFromString( text, "application/xml" );
	}else if( typeof ActiveXObject != "undefined" ){
		// Internet Explorer.
		//var doc = XML.newDocument();
		var doc = new ActiveXObject( "MSXML2.DOMDocument" );
/*		if( doc.documentElement ){
			alert( 'hat root node' );
		}else{
			alert( 'nix root node' );
		}*/
//		text = '< ?xml version="1.0" encoding="utf-8" ?>' + text;
		doc.loadXML( text );
		return doc;
	}else{
		// As a last resort, try loading the document from a data: URL
		var url = "data:text/xml;charset=utf-8," + encodeURIComponent( text );
		var request = new XMLHttpRequest();
		request.open( "GET", url, false );
		request.send( null );
		return request.responseXML;
	}
};


// Die beiden folgenden Funktionen sind von http://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm geklaut.
function decode_utf8(utftext) {
	var plaintext = ""; var i=0; var c=c1=c2=0;
	// while-Schleife, weil einige Zeichen uebersprungen werden
	while(i<utftext.length)
	{
		c = utftext.charCodeAt(i);
		if (c<128) {
			plaintext += String.fromCharCode(c);
			i++;}
			else if((c>191) && (c<224)) {
			c2 = utftext.charCodeAt(i+1);
			plaintext += String.fromCharCode(((c&31)<<6) | (c2&63));
			i+=2;
		}
		else {
			c2 = utftext.charCodeAt(i+1); c3 = utftext.charCodeAt(i+2);
			plaintext += String.fromCharCode(((c&15)<<12) | ((c2&63)<<6) | (c3&63));
			i+=3;
		}
	}
	return plaintext;
}

        function encode_utf8(rohtext) {
             // dient der Normalisierung des Zeilenumbruchs
             rohtext = rohtext.replace(/\r\n/g,"\n");
             var utftext = "";
             for(var n=0; n<rohtext.length; n++)
                 {
                 // ermitteln des Unicodes des  aktuellen Zeichens
                 var c=rohtext.charCodeAt(n);
                 // alle Zeichen von 0-127 => 1byte
                 if (c<128)
                     utftext += String.fromCharCode(c);
                 // alle Zeichen von 127 bis 2047 => 2byte
                 else if((c>127) && (c<2048)) {
                     utftext += String.fromCharCode((c>>6)|192);
                     utftext += String.fromCharCode((c&63)|128);}
                 // alle Zeichen von 2048 bis 66536 => 3byte
                 else {
                     utftext += String.fromCharCode((c>>12)|224);
                     utftext += String.fromCharCode(((c>>6)&63)|128);
                     utftext += String.fromCharCode((c&63)|128);}
                 }
             return utftext;
         }

Acu.prepareForAjaxTransmit = function( data ){
	//data = Acu.replaceAjaxProblemChars( data );
	//data = escape( data );
	//data = encodeURI( data );
	var regexp = /%20/g;	// A regular expression to match an encoded space
	// The global function encodeURIComponent does almost what we want,
	// but it encodes spaces as %20 instead of as "+". We have to
	// fix that with String.replace()
	data = encodeURIComponent( data ).replace( regexp, "+" );
	return data;
};

Acu.phpUrlEncode = function( text ){
	var regexp = /%20/g;	// A regular expression to match an encoded space
	// The global function encodeURIComponent does almost what we want,
	// but it encodes spaces as %20 instead of as "+". We have to
	// fix that with String.replace()
	text = encodeURIComponent( text ).replace( regexp, "+" );
	return text;
};

Acu.phpUrlDecode = function( text ){
	var regexp = /\+/g;
	text = decodeURIComponent( text.replace( regexp, "%20" ) );
	return text;
};


Acu.replaceAjaxProblemChars = function( string ){
   // Folgende Zeichen verursachen Probleme: % ? + &
   // Drum ersetzen wir sie einfach durch selbstgebastelte Sequenzen.
   var regex;
   regex = /\%/gi;
   string = string.replace( regex, '[anemacode-prozent]' );

   regex = /\€/gi;
   string = string.replace( regex, '[anemacode-euro]' );

   regex = /\+/gi;
   string = string.replace( regex, '[anemacode-plus]' );

   regex = /\&/gi;
   string = string.replace( regex, '[anemacode-ampersand]' );

   regex = /\ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¾/gi;
   string = string.replace( regex, '[anemacode-apounten]' );

   regex = /\ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã¢â‚¬Å“/gi;
   string = string.replace( regex, '[anemacode-apooben]' );

   return string;
};

Acu.insertAjaxProblemChars = function( string ){
   var regex;
   regex = /\[anemacode-prozent\]/gi;
   string = string.replace( regex, '%' );

   regex = /\[anemacode-euro\]/gi;
   string = string.replace( regex, '€' );

   regex = /\[anemacode-plus\]/gi;
   string = string.replace( regex, '+' );

   regex = /\[anemacode-ampersand\]/gi;
   string = string.replace( regex, '&' );

   regex = /\[anemacode-apounten\]/gi;
   string = string.replace( regex, 'ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã‚Â¾' );

   regex = /\[anemacode-apooben\]/gi;
   string = string.replace( regex, 'ÃƒÆ’Ã‚Â¢ÃƒÂ¢Ã¢â‚¬Å¡Ã‚Â¬Ãƒâ€¦Ã¢â‚¬Å“' );

   return string;
};

Acu.swapZIndex = function( obj1, obj2 ){
	if( typeof obj1 == "string" ) obj1 = document.getElementById( obj1 );
	if( typeof obj2 == "string" ) obj2 = document.getElementById( obj2 );
	if( !obj1 || !obj2 ) return false;

	var styles = Acu.getCurrentStyles( obj1 );
	if( !styles ) return false;
	var z1 = styles.zIndex;

	styles = Acu.getCurrentStyles( obj2 );
	if( !styles ) return false;
	var z2 = styles.zIndex;

	obj1.style.zIndex = z2;
	obj2.style.zIndex = z1;

	return true;
};

Acu.getSelectedOptionValue = function( select ){
	if( typeof select == "string" ) select = document.getElementById( select );

	/*if( !select || select.tagName != "select" ){
		return null;
	}

	var options = select.options;
	for( var i=0; i<options.length; i++ ){
		if( options[i].selected ) return options[i].value;
	}

	return null;*/

	return select.options[select.selectedIndex].value;
};

Acu.selectDropdownOption = function( select, value ){
	if( typeof select == "string" ) select = document.getElementById( select );

	if( !select ){
		return false;
	}

	var options = select.options;
	for( var i=0; i<options.length; i++ ){
		if( options[i].value == value ){
			options[i].selected = true;
			return true;
		}
	}

	return false;
};

Acu.setValue = function( obj, value ){
	if( typeof obj == "string" ) obj = document.getElementById( obj );	// element id
	if( !obj ) return;

	obj.value = value;
};

/**
 * Brute-force -Suche!
 */
Acu.indexOf = function( value, array/*, isSorted */ ){
	// Wenn sortiert, binäre Suche anwenden.
	for( var i=0; i<array.length; i++ ){
		if( array[i] == value ){
			return i;
		}
	}
	return -1;
};

Acu.log = function( text, url ){
	if( !text ) throw "[ACU] Nothing to log";
	if( !url ) throw "[ACU] Missing url for logging";
	var request = Acu.getHttpRequest();
	request.open( "POST", url, false );
	request.setRequestHeader( "Content-type","application/x-www-form-urlencoded" );
	request.setRequestHeader( "Connection","close" );
	var regexp = /%20/g;
	var params = 'm=' + encodeURIComponent( text ).replace( regexp, "+" );
	request.send( params );
};


Acu.replaceHtmlBrackets = function( text ){
	text = text.replace( /\</g, '&lt;' );
	return text.replace( /\>/g, '&gt;' );
};

Acu.include = function( /*...*/ ) {
	if( arguments.length == 0 ) return;	// Keine Scripts angegeben, die geladen werden sollen.

	var request = Acu.getHttpRequest();
	for( var i=0; i<arguments.length; i++ ){
		var url = arguments[i];
		if( Acu.include.includedScripts[url] ){
			if( Acu.include.ignoreMultipleIncludes ) return;	// Ist schon importiert.
			throw "[Acu / include] Script already loaded: " + url;
		}else{
			Acu.include.includedScripts[url] = true;
		}

		request.open( "GET", url, false );
		request.send( null );

		if( request.status != 200 ){
			throw "[Acu / include] Error retrieving " + url + ": " + request.statusText;
		}

		var script = request.responseText;
		if( window.execScript ){
			window.execScript( script );
		}else{
			//eval( script );
			try{
				eval.call( window, script );
			}catch( e ){
				eval( script, window );
			}
		}
	}
};
Acu.include.includedScripts = {};
Acu.include.ignoreMultipleIncludes = true;

/**
 * FireFox hat eine maximale Länge von 4096 Bytes fÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¼r den NodeValue
 * eines XML-Knotens. Um grÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¶ÃƒÆ’Ã†â€™Ãƒâ€¦Ã‚Â¸ere Datenmengen zu verstauen, werden
 * Kindknoten erzeugt.
 *
 * Die Funktion sammelt die Daten aller Kindknoten und liefert sie
 * als Gesamtheit zurÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¼ck.
 *
 */
Acu.extractCompleteXMLNodeData = function( xmlNode ){
	var data = "";

	for( var i=0; i<xmlNode.childNodes.length; i++ ){
		data += xmlNode.childNodes[i].nodeValue;
	}

	return data;
};

/**
 * Zeigt Infos aus dem window.navigator-Objekt.
 * ÃƒÆ’Ã†â€™Ãƒâ€¦Ã¢â‚¬Å“ber den optionalem Parameter obj kann ein DOM-Element
 * angegeben werden, als dessen innerHTML die Infos angezeigt
 * werden sollen.
 * Wird obj nicht angegeben, werden die Infos mittels alert()
 * ausgegeben.
 *
 */
Acu.displayNavigatorData = function( /*obj=null*/ ){
	var info = "";
	var obj = arguments[0] ? arguments[0] : null;
	for( var p in window.navigator ){
		info += p + ": " + window.navigator[p];
		if( obj ){	// Wenn obj gesetzt, soll in einem DOM-Element ausgegeben werden.
			info += "<br />";
		}else{
			info += "\n";
		}
	}
	if( obj ){
		obj.innerHTML = info;
	}else{
		alert( info );
	}
};


Acu.detectEnterKeyPressed = function( e ){
	if( !e ) e = window.event;
	var code = 0;
	if( e.which ){
		code = e.which;
	}else if( e.keyCode ){
		code = e.keyCode;
	}
	if( code == 13 ){
		return true;
	}
	return false;
};

Acu.nl2br = function( str ){
	if( typeof str != "string" ) str = "" + str;
	str = str.replace( /\n\r/g, "<br />" );
	str = str.replace( /\r\n/g, "<br />" );
	str = str.replace( /\r/g, "<br />" );
	str = str.replace( /\n/g, "<br />" );
	return str;
}


