var btgs = new Brain();

var BTGS_FANCYBOX = "FancyBox";
var BTGS_DYNAPANE = "DynaPane";
var BTGS_AJAXLOAD = "AjaxRequest";
var BTGS_POPUP    = "PopUp";
var BTGS_ZOOMBOX  = "ZoomBox";
var BTGS_TIMELINE = "TimeLine";

  ////////////////////////
 // BRAIN ///////////////
////////////////////////

function Brain() {

  this.objects = new Array();

  // GET AN INSTANCE OF AN OBJECT BY NAME
  this.get = function(key, type, config) {
    // SEARCH IN ASSOC-ARRAY FOR INSTANCE BY NAME
    var btgsObject = this.objects[key];

    // IF INSTANCE FOUND RETURN IT
    if ( btgsObject ) {
      return btgsObject;
    }

    // WE CONTINUE IF INSTANCE NEEDS TO BE CREATED!!!

    // IF NO TYPE IS SET WE EXIT AND GIVE AN ERROR
    if ( !type ) {
      throw("Objekt \"" + key + "\" nicht gefunden! Bitte initialisieren Sie das Objekt!\n\nTypen:\n\nBTGS_FANCYBOX\nBTGS_DYNAPANE\nBTGS_AJAXLOAD\nBTGS_POPUP\nBTGS_ZOOMBOX\nBTGS_TIMELINE");
      return;
    }

    // CREATE STRING FROM GIVEN CONFIG / EMPTY STRING IF NO CONFIG IS GIVEN
    var configStr = "";
    if ( config ) {
      for ( var propertykey in config ) {
        if ( configStr != "" )
          configStr += ", ";
        configStr += '"'+ propertykey +'" : "' + config[propertykey] + '"';
      }
    }

    // IF CONFIG STRING EXISTS APPEND A COLON
    if ( configStr )
      configStr += ", ";

    // APPEND ID TO CONFIG
    configStr += '"id" : "'+ key +'"';
    configStr = "{ "+configStr+" }";

    // CREATE OBJECT USING THE CONFIG-STRING ADD INSTANCE TO ASSOC ARRAY AND RETURN INSTANCE
    var btgsObject = eval("(new " + type + "("+configStr+"))");
    this.objects[key] = btgsObject;
    return btgsObject;
  }

  // RETURN ARRAY WITH AVAILABLE INSTANCE KEYS
  this.keys = function() {
    var result = new Array();
    for (key in this.objects) { 
      result.push(key);
    }
    return result;
  }

}

  ////////////////////////
 // POPUP ///////////////
////////////////////////

// CONSTANTS FOR HORIZONTAL ALIGNMENT
var POPUP_LEFT   = 0;
var POPUP_CENTER = 1;
var POPUP_RIGHT  = 2;

// CONSTANTS FOR VERTICAL ALIGNMENT
var POPUP_TOP    = 0;
var POPUP_MIDDLE = 1;
var POPUP_BOTTOM = 2;

// POPUP CLASS
function PopUp(config) {

  // LOCAL VARIABLES
  this.config   = config;
  this.popupWin = null;

  // INIT
  this.init = function() {
    // INITIALIZIE DEFAULTS IF CONFIG IS NOT FILLED IN
    if ( !this.config.dependent )
      this.config.dependent = false;
    if ( !this.config.height )
      this.config.height = 100;
    if ( !this.config.hotkeys )
      this.config.hotkeys = true;
    if ( !this.config.location )
      this.config.location = false;
    if ( !this.config.left )
      this.config.left = 0;
    if ( !this.config.menubar )
      this.config.menubar = false;
    if ( !this.config.resizable )
      this.config.resizable = true;
    if ( !this.config.scrollbars )
      this.config.scrollbars = true;
    if ( !this.config.status )
      this.config.status = true;
    if ( !this.config.toolbar )
      this.config.toolbar = false;
    if ( !this.config.top )
      this.config.top = 0;
    if ( !this.config.width )
      this.config.width = 100;
    if ( !this.config.target )
      this.config.target = "_BLANK";
    if ( !this.config.url )
      this.config.url = "about:blank";
  }

  // TOGGLE FUNCTION
  this.toggle = function(showConfig) {
    if ( this.popupWin ) {
      this.close();
    } else {
      this.open(showConfig);
    }
  }

  // OPEN FUNCTION
  this.open = function(showConfig) {
	if ( !showConfig ) {
		showConfig = this.config;
	} else {
		// COPY KEYS OF INITIAL CONFIGURATION INTO CURRENT CONFIGURATION IF NOT SET
		for (key in this.config) {
			if ( !showConfig[key] )
				showConfig[key] = this.config[key];
		}
	}

	// COMPUTE HORIZONTAL ALIGNMENT IF SET
    if ( showConfig.align ) {
      if ( showConfig.align == POPUP_CENTER ) {
        showConfig.left = screen.width / 2 - showConfig.width / 2;
      } else if ( showConfig.align == POPUP_RIGHT ) {
        showConfig.left = screen.width - showConfig.width;
      } else if ( showConfig.align == POPUP_LEFT ) {
        showConfig.left = 0;
      }
    }

	// COMPUTE VERTICAL ALIGNMENT IF SET
    if ( showConfig.valign ) {
      if ( showConfig.valign == POPUP_MIDDLE ) {
        showConfig.top = screen.height / 2 - showConfig.height / 2;
      } else if ( showConfig.valign == POPUP_BOTTOM ) {
        showConfig.top = screen.height - showConfig.height;
      } else if ( showConfig.valign == POPUP_TOP ) {
        showConfig.top = 0;
      }
    }

	// BUILD POPUP PARAMETERSTRING
    var params = "";
    params += "width=" + showConfig.width;
    params += ",height=" + showConfig.height;
    params += ",left=" + showConfig.left;
    params += ",top=" + showConfig.top;
    params += ",dependent=" + (("true" == showConfig.dependent) ? "yes" : "no");
    params += ",hotkeys=" + (("true" == showConfig.hotkeys) ? "yes" : "no");
    params += ",location=" + (("true" == showConfig.location) ? "yes" : "no");
    params += ",menubar=" + (("true" == showConfig.menubar) ? "yes" : "no");
    params += ",resizable=" + (("true" == showConfig.resizable) ? "yes" : "no");
    params += ",scrollbars=" + (("true" == showConfig.scrollbars) ? "yes" : "no");
    params += ",status=" + (("true" == showConfig.status) ? "yes" : "no");
    params += ",toolbar=" + (("true" == showConfig.toolbar) ? "yes" : "no");

	// CALL POPUP COMMAND
    this.popupWin = window.open(showConfig.url, showConfig.target, params);

  }

  // CLOSE FUNCTION
  this.close = function() {
    if ( this.popupWin ) {
      this.popupWin.close();
      this.popupWin = null;
    }
  }

  // CALL TO INIT
  this.init();

}

  ////////////////////////
 // FANCYBOX ////////////
////////////////////////

function FancyBox(config) {

  // LOCAL VARIABLES
  this.config        = config;
  this.parentElement = null;
  this.wrapper       = null;
  this.backWrapper   = null;

  this.isopen        = false;
  this.element       = null;

  this.closed = new Array();
  this.opened = new Array();
  
  this.url = "about:blank";

  // INIT FUNCTION
  this.init = function() {
    // INIT DEFAULT CONFIG WHERE NOT SET
    if ( !this.config.element ) 
      this.config.element = document.getElementById(this.config.id);
    if ( !this.config.width )
      this.config.width  = 200;
    if ( !this.config.height )
      this.config.height = 200;
    if ( !this.config.time )
      this.config.time   = 500;
    if ( !this.config.url )
      this.config.url    = "about:blank";
    if ( this.config.parentElement )
      this.parentElement = document.getElementById(this.config.parentElement);
    else
      this.parentElement = document.body;
	if ( !this.config.mayClose && this.config.mayClose != "false" )
	  this.config.mayClose = "true";
	  
	// INIT LOCAL URL
	this.url = this.config.url;
	
	// CREATE BACKGROUND WRAPPER ELEMENT
	this.backWrapper = document.createElement("div");
	if ( this.config.bgClass )
	  this.backWrapper.className = this.config.bgClass;
	this.backWrapper.style.position = "absolute";
    this.backWrapper.style.display = "none";  
	
	// CREATE WRAPPER ELEMENT
    this.wrapper = document.createElement("div");
	if ( this.config.boxClass )
	  this.wrapper.className = this.config.boxClass;
	else
      this.wrapper.className = "mainTableBG";
    this.wrapper.style.overflow = "hidden";
    this.wrapper.style.position = "absolute";
    this.wrapper.style.display = "none";
    this.wrapper.innerHTML = "";
    this.wrapper.appendChild(this.createContent());

	// APPEND WRAPPER TO BODY
    this.parentElement.appendChild(this.backWrapper);
    this.parentElement.appendChild(this.wrapper);
  }

  this.toggle = function(element, url, width, height) {
    this.element = element;
    if ( this.isopen )
      this.hide();
    else
      this.show(element, url, width, height);
  }

  this.show = function(element, url, width, height) {
    // INIT NOT SET VARIABLES FROM CONFIG
    if ( !url )
      url = this.config.url;
    if ( !element )
      element = this.config.element;
	if ( !element )
	  element = document.body;
    if ( !width )
      width  = parseInt(this.config.width);
    if ( !height )
      height = parseInt(this.config.height);

	var docWidth = document.body.scrollWidth;
	var docHeight = document.body.scrollHeight;
	var box = this;
	
	if ( this.config.modal ) {
	  if ( this.config.mayClose == "true" )
	    this.backWrapper.onclick = function() { box.hide() };
      this.backWrapper.style.width = docWidth + "px";
	  this.backWrapper.style.height = docHeight + "px";
	  this.backWrapper.style.top = "0px";
	  this.backWrapper.style.left = "0px";
      this.backWrapper.style.display = "block";
	  this.backWrapper.style.zIndex = "998";
	
	  this.wrapper.style.zIndex = "999";
	}
	
/*	
	document.onresize = function() {
	  var docWidth = document.body.scrollWidth;
	  var docHeight = document.body.scrollHeight;
	  box.backWrapper.style.width = docWidth + "px";
	  box.backWrapper.style.height = docHeight + "px";
	}
	
	document.body.onresize = function() {
	  var docWidth = document.body.scrollWidth;
	  var docHeight = document.body.scrollHeight;
	  box.backWrapper.style.width = docWidth + "px";
	  box.backWrapper.style.height = docHeight + "px";
	}
*/
	  
	// COMPUTE START POSITION AND VALUES
    var closedPos = findPos(element);
    this.closed.left    = closedPos[0];
    this.closed.top     = closedPos[1];
    this.closed.width   = element.offsetWidth;
    this.closed.height  = element.offsetHeight;
    this.closed.opacity = 0;

	// COMPUTE ALPHA IF USED
    if ( !this.config.useAlpha )
      this.closed.opacity = 1;

	// COMPUTE END VALUES
    this.opened.width   = width;
    this.opened.height  = height;
    this.opened.opacity = 1;

	// COMPUTE END POSITION
    this.opened.left = document.body.clientWidth / 2 - width / 2;
    this.opened.top  = this.closed.top + this.closed.height / 2 - height / 2;
    if ( this.opened.top + this.opened.height > document.body.scrollHeight )
      this.opened.top = document.body.scrollHeight - this.opened.height;
    if ( this.opened.top < 0 )
      this.opened.top = 0;

	// SET OPEN AND URL
    this.isopen = true;
	this.url    = url;

	// ANIMATE THE BOX
    this.shiftBox(this.closed, this.opened);
  }

  this.hide = function() {
    // UNSET OPEN
    this.isopen = false;
	
	// COMPUTE END POSITION AND VALUES IF SOURCEELEMENT IS SET
	if ( this.element != null ) {
      var closedPos = findPos(this.element);
      this.closed.left    = closedPos[0];
      this.closed.top     = closedPos[1];
      this.closed.width   = this.element.offsetWidth;
      this.closed.height  = this.element.offsetHeight;
      this.closed.opacity = 0;
	}
	
	// COMPUTE ALPHA IF USED
	if ( !this.config.useAlpha )
	  this.closed.opacity = 1;
	
	// ANIMATE THE BOX
    this.shiftBox(this.opened, this.closed);
  }

  this.shiftBox = function(start, end) {
    // ABORT TWEEN IF ALREADY RUNNING
    if ( this.tween != null )
      this.tween.abort();

	// CREATE NEW TWEEN FROM GIVEN VALUES
    this.tween = new Tween(start, end, 50, this.config.time);

	// SET VARIABLES FOR CLOSURES
    var box         = this;
    var wrapper     = this.wrapper;
	var backWrapper = this.backWrapper;

	// TWEEN STARTING FUNCTION
    this.tween.onTweenStart = function() {
	  // CLEAR WRAPPER (SMOOTHER ANIMATION)
      wrapper.innerHTML = "";	  
    }

	// ON EACH FRAME
    this.tween.onTween = function(interpolation) {
	  // SET WRAPPER ATTRIBUTES FOR ANIMATION FRAME
      wrapper.style.display = "block";
      wrapper.style.left    = interpolation.left + "px";
      wrapper.style.top     = interpolation.top + "px";
      wrapper.style.width   = interpolation.width + "px";
      wrapper.style.height  = interpolation.height + "px";
	  if ( box.config.useAlpha == "true" ) {
        wrapper.style.opacity = interpolation.opacity;
	    wrapper.style.filter='alpha(opacity='+(interpolation.opacity * 100)+')';
      }
    }

	// TWEEN FINISHING FUNCTION
    this.tween.onTweenComplete = function() {
	  // IF BOX IS CLOSED
	  if ( !box.isopen ) {
	    // CLEAR WRAPPER, HIDE WRAPPER
	    wrapper.innerHTML     = "";
        wrapper.style.display = "none";
		backWrapper.style.display = "none";
		wrapper.style.zIndex = "";
        backWrapper.style.zIndex = "";
		document.body.onresize = function() {};
		box.onHide();
      } else {
	    // RECREATE CONTENT OF WRAPPER AND UPDATE INNERHTML (FOR IE)
	    wrapper.appendChild(box.createContent());
	    wrapper.innerHTML = wrapper.innerHTML;
		box.onShow();
      }
    }

	// START ANIMATION
    this.tween.execute();
  }
  
  this.onHide = function() {
	// DO NOTHING HERE CAN BE OVERWRITTEN
  }
  
  this.onShow = function() {
	// DO NOTHING HERE CAN BE OVERWRITTEN
  }
  
  // FUNCTION CREATECONTENT TO CREATE THE IFRAME ETC.
  this.createContent = function() {
    // CREATE IFRAME
    iframe = document.createElement("iframe");
    iframe.src = this.url;
    iframe.style.width = "100%";
    iframe.style.height = "100%";
    iframe.border = "0";
    iframe.frameborder = "0";
    iframe.style.border = "0px";
    if ( this.config.scrolling == null || this.config.scrolling == undefined )
      config.scrolling = true;
    if ( this.config.scrolling )
      iframe.scrolling = "auto";
    else
      iframe.scrolling = "no";

	// CREATE WRAPPER TABLE FOR IFRAME
	table = document.createElement("table");
    table.style.height  = "100%";
    table.style.width   = "100%";
	table.cellpadding   = "0";
	table.cellspacing   = "0";
    table.id            = this.config.id + "_table";
	  
    // CREATE HEADER CELL WITH CLOSE-LINK	  
    var tdHead = document.createElement("td");
    tdHead.style.height = "1px";
    tdHead.style.width  = "100%";
    tdHead.style.textAlign = "right";
	if ( this.config.closeLink )
	  tdHead.innerHTML = this.config.closeLink;
	else {
	  if ( this.config.mayClose == "true" )
        tdHead.innerHTML = '<a href="javascript:void(0);" onclick="btgs.get('+"'"+this.config.id+"'"+').hide();">[ Fenster schliessen ]</a>';
	}

	// CREATE HEADER ROW & APPEND HEADER CELL
    var trHead = table.insertRow(0); // INSERTROW IS USED FOR COMPATIBILITY TO IE TABLE BUILDING VIA DOM
    trHead.appendChild(tdHead);

	// CREATE CONTENT TD FOR IFRAME
    var tdContent = document.createElement("td");
	if ( this.config.frameClass )
	  tdContent.className = this.config.frameClass;
	tdContent.id = this.config.id + "_frame";
    tdContent.appendChild(iframe);

	// CREATE CONTENT ROW & APPEND CONTENT CELL
    var trContent = table.insertRow(1); // INSERTROW IS USED FOR COMPATIBILITY TO IE TABLE BUILDING VIA DOM
    trContent.appendChild(tdContent);
	
    // RETURN THE TABLE
	return table;
  }

  // CALL TO INIT FUNCTION
  this.init();

}

  ////////////////////////
 // ZOOMBOX /////////////
////////////////////////

var ZOOMBOX_LEFT   = 0;
var ZOOMBOX_CENTER = 1;
var ZOOMBOX_RIGHT  = 2;

var ZOOMBOX_TOP    = 0;
var ZOOMBOX_MIDDLE = 1;
var ZOOMBOX_BOTTOM = 2;

var ZOOMBOX_SCALENONE   = 0;
var ZOOMBOX_SCALEBOTH   = 1;
var ZOOMBOX_SCALEWIDTH  = 2;
var ZOOMBOX_SCALEHEIGHT = 3;

function ZoomBox(config) {

  this.config = config;
  this.sourceDiv = document.getElementById(config.id);
  
  this.zoomDiv  = null;
//  this.clickDiv = null;
  
  this.isopen = false;
  this.tween = null;
  
  this.closeTimer = null;
    
  this.init = function() {
    if ( !this.config.time )
	  this.config.time = 500;
	if ( !this.config.closeTime )
	  this.config.closeTime = 200;
    if ( !this.config.align )
	  this.config.align = ZOOMBOX_LEFT;
	if ( !this.config.valign )
	  this.config.valign = ZOOMBOX_TOP;
	if ( !this.config.aspect )
	  this.config.aspect = ZOOMBOX_SCALENONE;
  
    this.zoomDiv = document.createElement("div");
    this.zoomDiv.id = config.id + "_zoom";
    this.zoomDiv.style.position = "absolute";
    this.zoomDiv.innerHTML = this.sourceDiv.innerHTML;
	this.zoomDiv.style.display = "none";
	document.body.appendChild(this.zoomDiv);
	
	this.zoomDiv.onmouseover = this.sourceDiv.onmouseover;
	this.zoomDiv.onmouseout  = this.sourceDiv.onmouseout;
	this.zoomDiv.onclick     = this.sourceDiv.onclick; 
  }
  
  this.toggle = function(config) {
    if ( this.isopen )
	  this.close();
	else
	  this.open(config);
  }
  
  this.open = function(config) {  

    this.zoomDiv.style.zIndex = "999";
  
    this.abortClose();
  
    if ( this.isopen )
	  return;
  
    this.isopen = true;
  
    if ( !config )
	  config = this.config;

    if ( !config.width )
	  config.width = this.config.width;
	if ( !config.height )
	  config.height = this.config.height;
	if ( !config.align && config.align != ZOOMBOX_LEFT )
	  config.align = this.config.align;
	if ( !config.valign && config.valign != ZOOMBOX_TOP )
	  config.valign = this.config.valign;
	if ( !config.aspect )
	  config.aspect = this.config.aspect;

    var sourcePos = findPos(this.sourceDiv);

	var start = [];
	start["left"]    = sourcePos[0];
	start["top"]     = sourcePos[1];
	start["width"]   = this.sourceDiv.clientWidth;
	start["height"]  = this.sourceDiv.clientHeight;
	start["opacity"] = 0;

	var zoomed = [];

	zoomed.width  = config.width;
	zoomed.height = config.height;

	if ( config.aspect != ZOOMBOX_SCALENONE ) {
	  var aspect = start.width / start.height;
	  if ( config.aspect == ZOOMBOX_SCALEBOTH ) {
	    if ( aspect > 1 ) {
		  zoomed.height = zoomed.width / aspect;
		} else {
		  zoomed.width  = zoomed.height * aspect;
		}
	  } else if ( config.aspect == ZOOMBOX_SCALEWIDTH ) {
	    zoomed.width = zoomed.height / aspect;
	  } else if ( config.aspect == ZOOMBOX_SCALEHEIGHT ) {
        zoomed.height = zoomed.width / aspect;
	  }
	}

	if ( config.align == ZOOMBOX_RIGHT )
	  zoomed.left = (start.left + start.width) - zoomed.width;
	else if ( config.align == ZOOMBOX_CENTER )
	  zoomed.left = (start.left + start.width / 2) - (zoomed.width / 2);
	else
	  zoomed.left = start.left;

    if ( config.valign == ZOOMBOX_BOTTOM )
	  zoomed.top = (start.top + start.height) - zoomed.height;
	else if ( config.valign == ZOOMBOX_MIDDLE )
	  zoomed.top = (start.top + start.height / 2) - (zoomed.height / 2);
	else
	  zoomed.top = start.top;

	zoomed.opacity = 1;
	
	this.animate(start, zoomed);
  }
  
  this.close = function() {
    this.zoomDiv.style.zIndex = "";
    
	this.abortClose();
	var zoomBox = this;
	this.closeTimer = window.setTimeout(function() { zoomBox.doClose(); }, this.config.closeTime);
  }
  
  this.abortClose = function() {
    if ( this.closeTimer ) {
	  window.clearTimeout(this.closeTimer);
	  this.closeTimer = null;
	}
  }
  
  this.doClose = function() {
  
    if ( !this.isopen )
	  return;
  
    this.isopen = false;
    
    var sourcePos = findPos(this.sourceDiv);
  
    var closed = [];
   
	closed["left"]    = sourcePos[0];
	closed["top"]     = sourcePos[1];
	closed["width"]   = this.sourceDiv.clientWidth;
	closed["height"]  = this.sourceDiv.clientHeight;
	closed["opacity"] = 0;
	
	var start = [];
	
    start["left"]    = this.zoomDiv.offsetLeft;
	start["top"]     = this.zoomDiv.offsetTop;
	start["width"]   = this.zoomDiv.clientWidth;
	start["height"]  = this.zoomDiv.clientHeight;
	start["opacity"] = 1;
	
	this.zoomDiv.style.zIndex = "";
	
	this.animate(start, closed);  
  }
  
  this.animate = function(start, end) {
    var box = this;
	var zoomDiv  = this.zoomDiv;
	
    if ( !this.isopen )	{
      zoomDiv.style.display  = "block";
	}
	
	this.tween = new Tween(start, end, 50, this.config.time);
	
    this.tween.onTween = function(interpolation) {
	  zoomDiv.style.display = "block";
	  zoomDiv.style.width   = interpolation.width + "px";
	  zoomDiv.style.height  = interpolation.height + "px";
	  zoomDiv.style.left    = interpolation.left + "px";
	  zoomDiv.style.top     = interpolation.top + "px";
	  if ( box.config.useAlpha == "true" ) {
	    zoomDiv.style.opacity = interpolation.opacity;
		zoomDiv.style.filter  = "alpha(opacity="+(interpolation.opacity * 100)+")";
      }
    }

	
    this.tween.onTweenComplete = function() {
	  if ( !box.isopen ) {
	    zoomDiv.style.display = "none";
      }
    }	
	
	this.tween.execute();  
  }
  
  this.init();

}

  ////////////////////////
 // DYNAPANE ////////////
////////////////////////

var DYNAPANE_HORIZONTAL = 0;
var DYNAPANE_VERTICAL   = 1;
var DYNAPANE_BOTH       = 2;

var DYNAPANE_LEFT   = 0;
var DYNAPANE_TOP    = 1;
var DYNAPANE_RIGHT  = 2;
var DYNAPANE_BOTTOM = 3;
var DYNAPANE_CENTER = 4;

function DynaPane(config) {

  this.config = config;
  this.div = document.getElementById(config.id);

  this.contentdiv = document.createElement("div");
  this.contentdiv.id = config.id + "_content";
  this.contentdiv.style.position = "relative";

  this.isopen;
  this.animation = null;

  this.tween = null;

  this.opened = new Array();
  this.closed = new Array();

  this.init = function() {
    this.contentdiv.innerHTML = this.div.innerHTML;
    this.div.innerHTML = "";
    this.div.appendChild(this.contentdiv);

    if ( !this.config.startOpen )
      this.config.startOpen = "false";

    this.isopen = this.config.startOpen == "true";

    if ( !this.config.time )
      this.config.time = 500;

	/*
    if ( !this.config.width )
      this.config.width  = this.div.clientWidth;
    if ( !this.config.height )
      this.config.height = this.div.clientHeight;
	*/

    if ( !this.config.minimumWidth )
      this.config.minimumWidth = 0;
    if ( !this.config.minimumHeight )
      this.config.minimumHeight = 0;

    this.div.style.overflow = "hidden";
    if ( !this.isopen ) {
      /*
      if ( this.config.direction != DYNAPANE_VERTICAL )
        this.div.style.width = this.config.minimumWidth + "px";
      if ( this.config.direction != DYNAPANE_HORIZONTAL )
        this.div.style.height = this.config.minimumHeight + "px";
	  */
	  var tmpTime = this.config.time;
	  this.config.time = 0;
	  this.close(this.config.direction);
	  this.config.time = tmpTime;
      this.shiftContent(new Array(this.config.minimumWidth - this.config.width, this.config.minimumHeight - this.config.height), this.config.direction);
	  /*
      if ( this.config.scaleContent ) {
        this.contentdiv.style.width  = this.config.minimumWidth;
        this.contentdiv.style.height = this.config.minimumHeight;
      }
	  */
    } else {
      if ( this.config.width )
        this.div.style.width = this.config.width + "px";
      if ( this.config.height )
        this.div.style.height = this.config.height + "px";
    }

    if ( !this.config.scaleContent ) {
	  if ( this.config.width || this.config.width == 0 )
        this.contentdiv.style.width  = this.config.width;
      if( this.config.height || this.config.height == 0 )
        this.contentdiv.style.height = this.config.height;
    }

    this.config.spt = this.div.style.position;
  }

  this.toggle = function(direction) {
    if ( !direction && direction != 0 )
      direction = this.config.direction;

    if ( this.isopen )
      this.close(direction);
    else
      this.open(direction);
  }

  this.open = function(direction) {
    if ( !direction && direction != 0 )
      direction = this.config.direction;

	if ( direction != DYNAPANE_HORIZONTAL ) {
	  if ( !this.config.height )
        this.config.height = this.contentdiv.offsetHeight;  // this.div.clientHeight;
      this.opened.height     = this.config.height;
      this.opened.top        = this.config.top;
	  this.opened.contenttop = 0;
      this.closed.height     = this.config.minimumHeight;
      this.closed.top        = this.config.top;
      this.closed.contenttop = this.config.minimumHeight - this.config.height;
	  
	  this.closed.height     = this.div.clientHeight;
	  this.closed.contenttop = this.contentdiv.offsetTop;
	}
	if ( direction != DYNAPANE_VERTICAL ) {
	  if ( !this.config.width )
        this.config.width  = this.div.clientWidth;
      this.opened.width       = this.config.width;
      this.opened.left        = this.config.left;
      this.opened.contentleft = 0;
      this.closed.width       = this.config.minimumWidth;
      this.closed.left        = this.config.left;
      this.closed.contentleft = this.config.minimumWidth - this.config.width;
	  
	  this.closed.width  	  = this.div.clientWidth;
	  this.closed.contentleft = this.contentdiv.offsetLeft;
	}

	/*
    if ( direction == DYNAPANE_HORIZONTAL ) {
      this.closed.height     = this.opened.height;
      this.closed.contenttop = this.opened.contenttop;
    } else if ( direction == DYNAPANE_VERTICAL ) {
      this.closed.width       = this.opened.width;
      this.closed.contentleft = this.opened.contentleft;
    }
	*/   

    this.isopen = true;

    if ( this.config.openAbsolute ) {
      this.div.style.position = "absolute";
      var pos = findPos(this.div);
      this.div.style.left = pos[0] + "px";
      this.div.style.top  = pos[1] + "px";
    }

    this.shiftBox(this.closed, this.opened);

  }

  this.close = function(direction) {
  
    if ( !direction && direction != 0 )
      direction = this.config.direction;
  
    if ( direction != DYNAPANE_HORIZONTAL ) {
	  if ( !this.config.height )
        this.config.height = this.div.clientHeight;
      this.opened.height     = this.config.height;
      this.opened.contenttop = 0;    
      this.closed.height     = this.config.minimumHeight;
      this.closed.contenttop = this.config.minimumHeight - this.config.height;
	}
	if ( direction != DYNAPANE_VERTICAL ) {
	  if ( !this.config.width )
        this.config.width  = this.div.clientWidth;
	  this.opened.width       = this.config.width;
	  this.opened.contentleft = 0;
	  this.closed.width       = this.config.minimumWidth;
	  this.closed.contentleft = this.config.minimumWidth - this.config.width;
	}

    var sourceSize = new Array(this.div.clientWidth, this.div.clientHeight);

	/*
    if ( direction == DYNAPANE_HORIZONTAL ) {
      this.closed.height = this.opened.height;
      this.closed.contenttop = this.opened.contenttop;
	  this.opened.width  = this.div.clientWidth;
	  this.opened.contentleft = this.contentdiv.offsetLeft;
    } else if ( direction == DYNAPANE_VERTICAL ) {
      this.closed.width  = this.opened.width;
      this.closed.contentleft = this.opened.contentleft;
	  this.opened.height = this.div.clientHeight;
	  this.opened.contenttop = this.contentdiv.offsetTop;
    }
	*/

    this.isopen = false;

    this.shiftBox(this.opened, this.closed);
  }

  this.shiftBox = function(start, end) {
    if ( this.tween != null )
      this.tween.abort();

    this.tween = new Tween(start, end, 50, this.config.time);

    var div        = this.div;
    var contentdiv = this.contentdiv;
    var config     = this.config;
    var isOpen     = this.isOpen;

    this.tween.onTween = function(interpolation) {
	  if ( interpolation.width || interpolation.width == 0 )
        div.style.width = interpolation.width + "px";
      if ( interpolation.height || interpolation.height == 0 )
        div.style.height = interpolation.height + "px";

      if ( config.scaleContent ) {
        contentdiv.style.width = interpolation.width + "px";
        contentdiv.style.height = interpolation.height + "px";
      }

      if ( config.contentAlign == DYNAPANE_RIGHT )
        contentdiv.style.left = interpolation.contentleft + "px";
      if ( config.contentAlign == DYNAPANE_BOTTOM )
        contentdiv.style.top = interpolation.contenttop + "px";
    }

    this.tween.onTweenComplete = function() {
      if ( !isOpen )
        if ( config.openAbsolute == "true" ) {
          div.style.position = "relative";
          div.style.left = "0px";
          div.style.top  = "0px";
        }
    }

    this.tween.execute();
  }

  this.shiftContent = function(stepSize, direction) {
    var currentPosition = new Array(this.div.clientLeft, this.div.clientTop);

    if ( this.config.align == DYNAPANE_RIGHT && direction != DYNAPANE_VERTICAL )
      this.div.style.left = (currentPosition[0] + stepSize[0]) + "px";
    if ( this.config.align == DYNAPANE_BOTTOM && direction != DYNAPANE_HORIZONTAL )
      this.div.style.top = (currentPosition[1] + stepSize[1]) + "px";

    var currentPosition = new Array(this.contentdiv.clientLeft, this.contentdiv.clientTop);

    if ( this.config.contentAlign == DYNAPANE_RIGHT && this.config.align == DYNAPANE_LEFT && direction != DYNAPANE_VERTICAL )
      this.contentdiv.style.left = (currentPosition[0] + stepSize[0]) + "px";
    if ( this.config.contentAlign == DYNAPANE_BOTTOM && this.config.align == DYNAPANE_TOP && direction != DYNAPANE_HORIZONTAL )
      this.contentdiv.style.top  = (currentPosition[1] + stepSize[1]) + "px";
  }

  this.init();

}

  ////////////////////////
 // AJAXREQUEST /////////
////////////////////////

function AjaxRequest(config) {
  this.config = config;
  this.url = null;
  this.async = true;
  this.method = 'GET';
  this.body = null;
  this.error = "";
  this.id = config.id

  var a = this;

  if (window.XMLHttpRequest) {
    this.request = new XMLHttpRequest();
  } else if(window.ActiveXObject) {
    this.request = new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    this.error = "AJAX konnte nicht initialisiert werden!";
  }

  this.open = function(url, met, async, func) {
    this.url = url;
	
	if ( !met )
		met = "GET";
		
	if ( met.toUpperCase() != 'GET' && met.toUpperCase() != 'POST' )
		this.method = 'GET';
	else
		this.method = met.toUpperCase();
    //if(this.method.toUpperCase() != 'POST' || this.method.toUpperCase() != 'GET') this.method = 'GET';
    this.async = (async == false) ? false : true;

    //anfrage vorbereiten
    try {
      this.request.open(this.method.toUpperCase(), this.url, this.async);
    } catch(e) {
      this.error = e.toString();
      return false;
    }
    if ( func )
      this.request.onreadystatechange = func;
    else
      this.request.onreadystatechange = this.onready;

  }

  this.send = function(req) {
	if(!req) 
		req = this.body;

	if(this.method == 'POST') {
		this.request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		this.request.setRequestHeader("Content-length", req.length);
		this.request.setRequestHeader("Connection", "close");
	}

	try {
        this.request.send(req);
    } catch(e) {
      this.error = "Fehler beim senden der AJAX-Anfrage!";
      return false;
    }
  }

  this.getError = function() {
    return this.error;
  }

  this.onready = function() {
    if(a.request.readyState == 4) { //übertragung komplett
      if(a.request.status == 200) { //anfrage erfolgreich
        a.onsuccess(a.request.responseText, a.request.responseXML);
        return true;
      } else { //anfrage fehlgeschlagen
        a.onfail(a.request.responseText, a.request.status, a.request.responseXML);
        return false;
      }
    }
    return false;
  }

  this.onsuccess = function(txt, xml) {
    this.error="AJAX-Anfrage erfolgreich! Bitte implementiere AjaxRequest.onsuccess()!";
  }

  this.onfail = function(txt, status, xml) {
    this.error="AJAX-Anfrage fehlgeschlagen mit Code " + status + "! Bitte implementiere AjaxRequest.onfail()!";
  }

  this.abort = function() {
    this.request.abort();
    return true;
  }
};

  ////////////////////////
 // ANIMATOR ////////////
////////////////////////

function TimeLine(config) {
	
	this.config = config;
	this.frames = [];
	this.tweens = [];
	this.framesPlayed = 0;
	this.dirty  = false;
	
	this.init = function() {
		if ( this.config.autoreset != "false" )
			this.config.autoreset = "true";
		if ( !this.config.rate ) 
			this.config.rate = 20;
	}
	
	this.addFrame = function(values) {
		this.frames.push(values);
		this.dirty = true;
	}
	
	this.recompute = function() {
		
		var animId = this.config.id;
		
		var tweens = [];
		for ( var i = 0; i < this.frames.length; i++ ) {
			var frame = this.frames[i];
			var time = frame.time;
			var rate = frame.rate;
			if ( !rate )
				rate = this.config.rate;
			
			var start = [];
			var end   = [];
			
			for ( key in frame ) {
				var command = frame[key];
				
				if ( command.indexOf("=>") > -1 ) {
					var values = command.split("=>");
					
					try {
						start[key] = parseFloat(values[0]); // .trim()
						end[key]   = parseFloat(values[1]); // .trim()
					} catch (e) {
						start[key] = null;
						end[key]   = null;
					}
				} else {
					var value  = parseFloat(command); // .trim()
					start[key] = value;
					end[key]   = value;
				}
			}
			
			var tween = new Tween(start, end, rate, time);
			
			tween.onTween = function(interpolation) {
				for ( key in interpolation ) {
					if ( key.indexOf("#") > -1 ) {
						var idStart = key.indexOf("#") + 1;
						var idEnd   = key.indexOf(".");
						var value   = parseFloat(interpolation[key]);
						if ( idStart == 1 && idStart > -1 ) {
							var id       = key.substring(idStart, idEnd);
							var property = key.substring(idEnd + 1);
						
							var command = "document.getElementById('"+id+"')."+property+" = "+value+";";
							try {
								eval(command);
							} catch ( error ) {
								// TODO IMPLEMENT ERROR LOGGING!
							}
						}
					} else if ( key.indexOf("$") == 0 ) {
						var commandStart = key.indexOf("$") + 1;
						var command = key.substring(commandStart) + " = " + value + ";";
						try {
							eval(command);
						} catch ( error ) {
							// TODO IMPLEMENT ERROR LOGGING!
						}
					}
				}
			}
						
			tween.onTweenComplete = function() {
				btgs.get(animId).playFrame();
			}
			
			tweens[i] = tween;
		}
		
		this.tweens = tweens;
		this.dirty 	= false;
		
	}
	
	this.playFrame = function() {
		if ( this.framesPlayed >= this.tweens.length ) {
			this.onComplete();
			if ( this.config.autoreset )
				this.reset();
			return;
		}
		
		this.tweens[this.framesPlayed].execute();
		this.framesPlayed++;
	}
	
	this.onComplete = function() {
	}
	
	this.reset = function() {
		this.framesPlayed = 0;
	}
	
	this.play = function() {
		if ( this.dirty )
			this.recompute();
		this.playFrame(0);
	}
	
	this.init();
	
}


  ////////////////////////
 // TWEEN ///////////////
////////////////////////

function Tween(start, end, updateTime, time) {

  this.start      = start;
  this.end        = end;
  this.updateTime = updateTime;
  this.time       = time;

  this.startTime  = 0;
  this.frames     = [];
 
  this.init = function() {
    if ( !this.updateTime )
      this.updateTime = 50;
    if ( !this.time && this.time != 0 )
      this.time = 500;
	  
	this.recompute(this.start, this.end);
  }
 
  this.recompute = function(startValues, endValues) {
    this.steps = Math.ceil(this.time / this.updateTime);
			
    this.frames[0] = new Frame(startValues, 0, this, function() { this.onTweenStart(); });
	for ( var i = 1; i < this.steps; i++ ) {
	  var values = [];
	  var time   = this.updateTime * (i);
	  for ( key in startValues ) {
	    var startValue = parseFloat(startValues[key]);
		var endValue   = parseFloat(endValues[key]);
		var distance   = endValue - startValue;
		var stepsize   = distance / this.steps;
		values[key]    = startValue + parseFloat(stepsize * (i));
	  }
	  this.frames[i] = new Frame(values, time, this);
	}
	this.frames[this.steps] = new Frame(endValues, time, this, function() { this.abort();this.onTweenComplete(); });
	
  }
 
  this.execute = function() {
    this.aborted = false;
    this.startTime = new Date().getTime();
	
	for ( var i = 0; i < this.frames.length; i++ ) {
	  this.frames[i].call();
	}
  }
  
  this.abort = function() {
    for ( var i = 0; i < this.frames.length; i++ ) {
	  this.frames[i].abort();
	}
  }
 
  this.onTweenStart = function() {
  }

  this.onTween = function(interpolation) {
    var message = "";
    for ( key in properties ) {
      message += key + ": " + properties[key] + "\n";
    }
    alert(message);
  }

  this.onTweenComplete = function() {
    alert("Tween ausgeführt in " + (new Date().getTime() - this.startTime) + "ms...\nBitte implementiere Tween.onTweenComplete()");
  }
 
  this.init();
 
}

function Frame(values, time, tween, endFunc) {

  this.values  = values;
  this.time    = time;
  this.timeout = null;
  this.tween   = tween;
  this.aborted = false;
  this.endFunc = endFunc;
  
  this.call = function() {
    this.clear();
	
	this.aborted = false;
	
	var frame = this;
	var func  = function() { frame.play(); };
    this.timeout = window.setTimeout(func, this.time);
  }

  this.clear = function() {
    if ( this.timeout )
	  window.clearTimeout(this.timeout);
  }
  
  this.play = function() {
    if ( this.aborted )
	  return;
    this.tween.onTween(this.values);
	if ( this.endFunc )
	  this.endFunc.apply(tween);
  }
  
  this.abort = function() {
    this.aborted = true;
    this.clear();
  }
  
}

/* PROTOTYPE OF REALTIME TWEEN... HOWEVER THE CALCULATION (ACTUALLY ITS THE BROWSER TIMINGS FAULT!) IS BUGGY
function Tween2(start, end, updateTime, time) {

  this.start      = start;
  this.end        = end;
  this.updateTime = updateTime;
  this.time       = time;

  this.lastTime  = -1;
  this.startTime = -1;

  this.aborted   = false;
  
  this.interpolation = [];
  this.useBuffer  = true;
  this.steps;

  this.init = function() {
    if ( !this.updateTime )
      this.updateTime = 50;
    if ( !this.time )
      this.time = 500;
	  
	this.interpolation = this.computeInterpolation(this.start, this.end);
  }

  this.abort = function() {
    this.aborted = true;
    this.clearTimeout();
  }

  this.execute = function() {
    this.aborted = false;
    this.startTime = new Date().getTime();
    this.lastTime = this.startTime;

    var stepping = new Array();
    for ( key in this.start ) {
      stepping[key] = 0;
    }

    this.onTweenStart();
    this.onTween(this.start, stepping);

    this.callTimeout(this.start, this.end, this.time, 0);
  }

  this.computeInterpolation = function(startValues, endValues) {
    this.steps = this.time / this.updateTime;
    debug(this.steps + "<br/>");	
		
	for ( var i = 1; i < this.steps; i++ ) {
	  this.interpolation[i] = [];
	  for ( key in startValues ) {
	    var startValue = parseFloat(startValues[key]);
		var endValue   = parseFloat(endValues[key]);
		var distance   = endValue - startValue;
		var stepsize   = distance / this.steps;
		var result     = startValues[key] + (stepsize * i);
		
		//debug();
		
		this.interpolation[i][key] =  result;
		//if ( key == "width" )
		//debug(stepsize + " | " + startValues[key] + " + " + distance + " / " + " (" + (i) + ") = " + this.interpolation[i][key] + "<br/>");
		//debug(key + "[" + i + "]: " + endValue + " - " + startValues[key] + " = " + distance + "/" + (steps - i) + " = " + result + "<br/>");
	  }
	}
  }
  
  this.interpolate = function(properties, end, time, frame) {
    if ( this.useBuffer ) {
	  if ( frame >= this.steps )
	    this.onTween(end);
      else {
	    this.onTween(this.interpolation[frame]);
		this.callTimeout(this.interpolation, end, time, frame);
	  }
	} else {
      var currentTime = new Date().getTime();
      time = time - (currentTime - this.lastTime);
      this.lastTime = currentTime;

      var tweenComplete = true;
      var stepping      = new Array();
      var interpolation = new Array();
      for ( key in properties ) {
        // GET endValue AND value
        var endValue = parseInt(end[key]);
        var value    = parseInt(properties[key]);

        // COMPUTE stepsize
        var steps    = Math.round(time / this.updateTime); // is time / frequency (t / f)
        var distance = endValue - value;
        var stepsize = distance / steps;
	    //if ( key == "height" )
	      //debug(endValue + " / " + value + " | " + distance + " / " + steps + "<br/>");

        // COMPUTE newValue AND DETERMINE IF TWEEN IS COMPLETE
        var newValue = value + stepsize; // parseInt(this.start[key]) + (distance - (stepsize * steps));
	    //debug((distance - (stepsize * steps)) + " - " + steps + " - " + stepsize + "<br/>");
        if ( stepsize > 0 ) {
          if ( newValue >= endValue )
            newValue == endValue;
          else
            tweenComplete = false;
        } else if ( stepsize < 0 ) {
          if ( newValue <= endValue )
            newValue == endValue;
          else
            tweenComplete = false;
        }

        stepping[key]      = stepsize;
        interpolation[key] = newValue;
      }

      if ( tweenComplete || time <= 0 ) {
        this.onTween(end, stepping);
        this.onTweenComplete();
        return;
      } else
        this.onTween(interpolation, stepping);

      this.callTimeout(interpolation, end, time);
	}
  }

  this.callTimeout = function(start, end, time, frame) {
    this.clearTimeout();
    if ( this.aborted )
      return;
    var tween = this;
    var func = function() { tween.interpolate(start, end, time, frame); };
    this.timeout = window.setTimeout(func, this.updateTime);
  }

  this.clearTimeout = function() {
    if ( this.timeout )
      window.clearTimeout(this.timeout);
  }

  this.onTweenStart = function() {
  }

  this.onTween = function(interpolation, stepping) {
    var message = "";
    for ( key in properties ) {
      message += key + ": " + properties[key] + "\n";
    }
    alert(message);
  }

  this.onTweenComplete = function() {
    alert("Tween finished in " + (new Date().getTime() - this.startTime) + "ms...\nPlease implement Tween.onTweenComplete()");
  }

  this.init();

}
*/

  ////////////////////////
 // HELPERS /////////////
////////////////////////

function findPos(obj) {
  var curleft = curtop = 0;
  if (obj.offsetParent) {
    do {
      curleft += obj.offsetLeft;
      curtop += obj.offsetTop;
    } while (obj = obj.offsetParent);
  }
  return [curleft,curtop];
}
