/**
 * JavaScript Framework
 *
 * @copyright Holger Schöttle 2006
 * @author Holger Schöttle
 */
function js()
{
	//#################//
	//# Public Member #//
	//#################//
	
	// Browser Identifier
	this.ns		= (document.layers);
	this.ie		= (document.all);
	this.w3 	= (document.getElementById && !this.ie);
	this.opera 	= (navigator.userAgent.search( "Opera" ) != -1);
	this.safari	= (navigator.userAgent.search( "AppleWebKit" ) != -1);
	
	/**
	 * Prüft, ob es sich bei dem Parameter um einen String handelt
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */
	this.isString = function( value )
	{
		return (typeof( value ) == 'string');
	}
	
	/**
	 * Prüft, ob es sich bei dem Parameter um ein Objekt handelt
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */
	this.isObject = function( value )
	{
		return (typeof( value ) == 'object');
	}
	
	/**
	 * Prüft, ob es sich bei dem Parameter um eine Zahl handelt
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */
	this.isNumber = function( value )
	{
		return (typeof( value ) == 'number');
	}
	
	/**
	 * Prüft, ob es sich bei dem Parameter um einen Bool'schen Wert handelt
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */
	this.isBoolean = function( value )
	{
		return (typeof( value ) == 'boolean');
	}
	
	/**
	 * Prüft, ob es sich bei dem Parameter um einen undefinierten Typ handelt
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */ 
	this.isUndefined = function( value )
	{
		return (typeof( value ) == 'undefined');
	}
	
	/**
	 * Prüft, ob der angegebene Parameter leer ist
	 *
	 * @param Mixed value zu prüfender Parameter
	 * @return Bool
	 */
	this.isEmpty = function( value )
	{
		if ( this.isString( value ) && ( value == '' || value == 'undefined' ) )
			return true;
		
		if ( this.isUndefined( value ) )
			return true;
			
		if ( this.isBoolean( value ) )
			return !value;
			
		if ( this.isObject( value ) && value.length == 0 )
			return true;
			
		// Rückgabe
		return false;
	}
	
	/**
	 * Alias für getElementById
	 *
	 * @param String id ID des HTML-Elements
	 * @return Object HTML-Element
	 */	
	this.e = function( id )
	{
		return document.getElementById( id );		
	}

	/**
	 * Alias für getElementsByName
	 *
	 * @param String name Name der HTML-Elemente
	 * @return Array mit HTML-Elements
	 */	
	this.n = function( name )
	{
		return document.getElementsByName( name );
	}
	
	/**
	 * Alias für getElementsByTagName
	 *
	 * @param String name Der Tag-Name des gesuchten HTML-Elements
	 * @return Array mit HTML-Elementen
	 */
	this.tn = function( name )
	{
		return document.getElementsByTagName( name );
	}
	
	/**
	 * Ersetzt den innerHTML-Value eines HTML-Elements
	 *
	 * @param String id ID des HTML-Elements
	 * @param String value Neuer innerHTML-Value
	 */
	this.replace = function( id, value )
	{
		if ( !_idExists( id ) )
			return;
		
		// innerHTML setzen
		this.e( id ).innerHTML = value;
	}
	
	/**
	 * Blendet ein Element aus bzw. ein
	 *
	 * @param String id ID des HTML-Elements
	 */
	this.toggle = function( id )
	{
		if ( !_idExists( id ) )
			return;
		
		// Nicht ausgeblendet?
		if ( this.e( id ).style.display != 'none' )
			this.e( id ).style.display = 'none';
		else // Auf Standard zurücksetzen
			this.e( id ).style.display = '';
	}
	
	/**
	 * Gibt den Typ eines Elements zurück
	 *
	 * @param String id ID des Elements
	 * @return String Typ-Bezeichnung
	 */
	this.getType = function( id )
	{
		if ( !_idExists( id ) )
			return;
		
		// Rückgabe
		return typeof this.e( id );
	}
	
	/**
	 * Gibt den Tag-Namen eines Elements zurück
	 *
	 * @param String id ID des Elements
	 * @return String Tag-Name
	 */
	this.tagName = function( id )
	{
		if ( !_idExists( id ) )
			return;
		
		// Rückgabe
		return this.e( id ).tagName;
	}
	
	/**
	 * Prüft, ob sich ein bestimmtes Element im Array befindet
	 *
	 * @param Mixed elem zu suchendes Element
	 * @param Array array zu durchsuchendes Array
	 * @return Bool Element im Array enthalten ja/nein
	 */
	this.inArray = function( elem, array )
	{
		if ( !this.isObject( array ) )
		{
			alert( 'Als zweiter Parameter wird ein Array erwartet: ' + this.getType( array ) );
			return;
		}
		
		// Array prüfen
		for( var i = 0; array[i]; ++i )
			if ( array[i] == elem )
				return true;
		
				
		return false;
	}
	
	/**
	 * Löscht ein Element aus einem Array
	 *
	 * @param Mixed elem Zu löschendes Element im Array
	 * @param Array array Das Array
	 * @return Array
	 */
	this.unsetArrayElem = function( elem, array )
	{
		if ( !this.isObject( array ) )
		{
			alert( 'Als zweiter Parameter wird ein Array erwartet: ' + this.getType( array ) );
			return;
		}
		
		var new_array = new Array();
		
		for ( var i = 0; array[i]; ++i )
			if ( array[i] != elem )
				new_array.push( array[i] );
				
		// Rückgabe
		return new_array;
	}
	
	/**
	 * Öffnet ein Popup mit Focus
	 *
	 * @param String url URL der Seite im Popup
	 * @param String name Name des Popups
	 * @param Integer width Breite des Popups (Standard: 400)
	 * @param Integer height Höhe des Popups (Standard: 300)
	 * @param Bool scollbars Scrollbalken ja/nein
	 * @param Bool resizable Skalierbar ja/nein
	 * @param Bool status Statusbar ja/nein
	 * @return Window-Handle
	 */
	this.popup = function( url, name, width, height, scrollbars, resizable, status )
	{
		return _openWindow( url, name, width, height, scrollbars, resizable, status, true );
	}
	
	/**
	 * Öffnet ein Popup ohne Focus
	 *
	 * @param String url URL der Seite im Popup
	 * @param String name Name des Popups
	 * @param Integer width Breite des Popups (Standard: 400)
	 * @param Integer height Höhe des Popups (Standard: 300)
	 * @param Bool scollbars Scrollbalken ja/nein
	 * @param Bool resizable Skalierbar ja/nein
	 * @param Bool status Statusbar ja/nein
	 * @return Window-Handle
	 */
	this.popunder = function( url, name, width, height, scrollbars, resizable, status )
	{
		return _openWindow( url, name, width, height, scrollbars, resizable, status, false );
	}
	
	/**
	 * Legt einen Layer mit 85% Suchtbarkeit über die Seite
	 *
	 * @param Bool display Layer sichtbar ja/nein
	 * @param Integer zindex Z-Index
	 */	
 	this.contentOverlay = function( display, zindex )
 	{
		if ( this.e( 'jslib_layer_hidecontent' ) )
 			iframe = this.e( 'jslib_layer_hidecontent' );
 		else 
 			iframe = document.createElement( 'iframe' );
 		
		iframe.style.display	= ( display ) ? 'block' : 'none';
		
		if ( display ) 
		{
			var i 						= 85;
			var i_ff 					= i / 100;
			
			if ( this.ie ) 
			{
				xoffset 				= _trueBody().scrollLeft;
				yoffset 				= _trueBody().scrollTop;
				documentWidth			= _trueBody().offsetWidth;
				documentHeight			= _trueBody().offsetHeight;
			}
			else {
				xoffset 				= window.pageXOffset;
				yoffset 				= window.pageYOffset;
				documentWidth			= window.innerWidth;
				documentHeight			= window.innerHeight;		
			}			
			
			var contentHeight = Math.max( _trueBody().scrollHeight, documentHeight );
			var contentWidth  = Math.max( _trueBody().scrollWidth, documentWidth );
			
			if ( this.ie && !this.opera )
			{
				contentWidth -= 21;
				contentHeight -= 4;
			}
			else if ( _trueBody().scrollHeight > documentHeight )
				contentWidth -= 17;
				
			if ( _trueBody().scrollWidth > documentWidth )
				contentHeight -= (this.ie ? 21 : 17);
			
			iframe.id					= 'jslib_layer_hidecontent';
			iframe.setAttribute( 'src', 'about:blank' );
			iframe.setAttribute( 'border', '0' );
			iframe.setAttribute( 'frameborder', '0' );
			iframe.setAttribute( 'marginheight', '0' );
			iframe.setAttribute( 'marginwidth', '0' );
			iframe.frameborder 			= 0;
			iframe.marginheight			= 0;
			iframe.marginwidth			= 0;
			iframe.style.zIndex 		= ( zindex ? zindex : 1 ),
			iframe.style.position 		= 'absolute';
			iframe.style.background 	= '#FFFFFF';			
			iframe.style.border			= '0px none';			
			iframe.style.padding		= '0px';			
			iframe.style.margin			= '0px';
			iframe.style.left			= '0px';			
			iframe.style.top			= '0px';
			iframe.style.width 			= contentWidth + 'px';
			iframe.style.height 		= contentHeight + 'px';
			iframe.style.filter			= "alpha(opacity=" + i + ")";
			iframe.style.opacity 		= i_ff;
			iframe.style.mozopacity 	= i_ff
			iframe.style.khtmlopacity 	= i_ff	
		}
		
		// iFrame als erstes Element in den Body schreiben
		_trueBody().insertBefore( iframe, _trueBody().firstChild );
		
		this.moveElem( iframe, 'near', 'near', contentWidth, contentHeight );
 	}	
	
	/**
	 * Positioniert ein Element an eine bestimmte Position
	 *
	 * @param String id ID des Elements
	 * @param String posX X-Positionierung (near, far, center)
	 * @param String posY Y-Positionierung (near, far, center)
	 * @param Integer width Breite des Elements
	 * @param Integer height Höhe des Elements
	 */
 	this.moveElem = function( elem, posX, posY, width, height )
	{
		var id = false;
		
		if ( typeof( elem ) == 'string' )
			id = elem;
			
		if ( id && !_idExists( id ) )
			return;
		
		if ( id )
			elem = this.e( id );
			
		if ( elem.style.display != 'block' )
			return;
			
		// Element ausrichten
		elem.style.top 	= this.calcOffsetY( posY, height ) + 'px';
		elem.style.left = this.calcOffsetX( posX, width ) + 'px';
	}
	
	/**
	 * Berechnet die Bildschirm-X-Koordinate
	 *
	 * @param String pos Positionierung (near, far, center)
	 * @param Integer width Breite
	 * @return Integer
	 */
	this.calcOffsetX = function( pos, width )
	{
		var xoffset 	= 0;
		var docWidth 	= 0;
		var returner	= 0;
		
		// Versuchen Breite automatisch zu ermitteln
		if ( !width )
			width = elem.offsetWidth;
		
		if ( this.ie ) 
		{
			xoffset 	= _trueBody().scrollLeft;
			docWidth	= _trueBody().offsetWidth;
		}
		else 
		{
			xoffset 	= window.pageXOffset;
			docWidth	= window.innerWidth;		
		}	
		
		switch( pos )
		{
			case 'near':
				returner = xoffset;
				break;
			case 'far':
				returner = xoffset + docWidth - width;
				break;
			case 'center':
				returner = Math.floor((docWidth / 2) - (width / 2) + xoffset);
				break;
		}
		
		// Rückgabe
		return returner;
	}
	
	/**
	 * Berechnet die Bildschirm-Y-Koordinate
	 *
	 * @param String pos Positionierung (near, far, center)
	 * @param Integer height Höhe
	 * @return Integer
	 */
	this.calcOffsetY = function( pos, height )
	{
		var yoffset		= 0;
		var docHeight	= 0;
		var returner	= 0;
		
		// Versuchen Höhe automatisch zu ermitteln
		if ( !height )
			height = elem.offsetHeight;
		
		if ( this.ie )
		{
			yoffset		= _trueBody().scrollTop;
			docHeight	= _trueBody().offsetHeight;
		}
		else
		{
			yoffset		= window.pageYOffset;
			docHeight	= window.innerHeight;
		}
		
		switch( pos )
		{
			case 'near':
				returner = yoffset;
				break;
			case 'far':
				returner = yoffset + docHeight - height;
				break;
			case 'center':
				returner = Math.floor((docHeight / 2) - (height / 2) + yoffset);
				break;
		}
		
		// Rückgabe
		return returner;
	}
	
 	/**
	 * Lädt ein JS-File in den Head nach
	 * --> Prüft, ob die Datei bereits included wurde
	 *
	 * @param String file Dateipfad
	 */
	this.loadJSFile = function( file )
	{
		if ( !this.isString( file ) )
			return;
		
		var script_tags = this.tn( 'script' );
		
		// Prüfen, ob die Datei schon geladen wurde
		for ( i = 0; script_tags[i]; ++i )
		{
			if ( !script_tags[i].src )
				continue;
			if ( script_tags[i].src.match(file) )
				return;
		}
		
		// Datei nachladen
		var head 	= js.tn( 'head' )[0];
		var script 	= document.createElement( 'script' );
			script.setAttribute( 'language', 'JavaScript' );
			script.setAttribute( 'type', 'text/javascript' );
			script.setAttribute( 'src', file );
			
		// Script in den Head schreiben
		head.appendChild( script );
	}
	
	/**
	 * Lädt ein JS-File in den Head nach
	 * --> Prüft, ob die Datei bereits included wurde
	 *
	 * @param String file Dateipfad
	 */
	this.loadCSSFile = function( file )
	{
		if ( !this.isString( file ) )
			return;
		
		var tags = this.tn( 'link' );
		
		// Prüfen, ob die Datei schon geladen wurde
		for ( i = 0; tags[i]; ++i )
		{
			if ( !tags[i].rel != 'stylesheet' )
				continue;
			if ( tags[i].href.match( file ) )
				return;
		}
		
		// Datei nachladen
		var head 	= js.tn( 'head' )[0];
		var link 	= document.createElement( 'link' );
			link.setAttribute( 'rel', 'stylesheet' );
			link.setAttribute( 'type', 'text/css' );
			link.setAttribute( 'href', file );
			
		// Script in den Head schreiben
		head.appendChild( link );
	}
	
	//####################//
	//# Private Methoden #//
	//####################//
	
	/**
	 * Behebt IE fehler für die Fenstergröße
	 *
	 * @return Object
	 */	
	function _trueBody()
	{
		return ( document.compatMode && document.compatMode != 'BackCompat' ) 
				 ? document.documentElement : document.body;
	}	
	
	
	/**
	 * Prüft, ob ein Element zu einer angegebenen ID existiert
	 *
	 * @param String id ID des Elements
	 * @return Bool
	 */
	function _idExists( id )
	{
		if ( !js.e( id ) ) {
			alert( 'There is no Element with id "' + id + '"' );
			return false;
		}
			
		return true;
	}
	
	/**
	 * Öffnet ein Popup mit/ohne Focus
	 *
	 * @param String url URL der Seite im Popup
	 * @param String name Name des Popups
	 * @param Integer width Breite des Popups (Standard: 400)
	 * @param Integer height Höhe des Popups (Standard: 300)
	 * @param Bool scollbars Scrollbalken ja/nein
	 * @param Bool resizable Skalierbar ja/nein
	 * @param Bool status Statusbar ja/nein
	 * @return Window-Handle
	 */
	function _openWindow( url, name, width, height, scrollbars, resizable, status, focus )
	{
		var params = new Array(
			'width=' + ( width ? width : 400 ),
			'height=' + ( height ? height : 300 ),
			'scollbars=' + ( scrollbars ? 'yes' : 'no' ),
			'resizable=' + ( resizable ? 'yes' : 'no' ),
			'status=' + ( status ? 'yes' : 'no' ),
			'menubar=no',
			'toolbar=no'
		);
		
		// Popup erstellen
		wnd = window.open( url, name, params.join( ',' ) );
		
		// Fokussieren?
		if ( focus )
			wnd.focus();
		else
			wnd.blur();
		
		// Rückgabe
		return wnd;
	}
}

// Klasse instanziieren
var js = new js();
