/*
  Autor:  Michael Donabaum
  Datum:  28.04.2006
  home:   http://www.rauter-it.at/  
  edit:   18.07.2008 (Darstellungsbug im Firefox 3 bzw. Opera 9.5 behoben)
  
  Eine kleine Klasse, mit der man einfach mehrere Elemente (mittels derer Ids)
  darstellen oder unsichtbar schalten kann!
  
  Hinzugefügt werden diese Elemente mit der Funktion add(). Dargestellt mit 
  show() und ausgeblendet mit hide().
    
    add(ID, top, left, upperId);          // absolute Angabe der Koordinaten; wenn upperId dann sind die Angaben relativ zu der Position vom upperId-Element
    show(ID);                             // darstellen des gegebenen ID-Elements
    hide(ID);                             // ausblenden des gegebenen ID-Elements
    
    getIdData(id);                        // liefert die gespeicherten Daten zu einer id
    getData(id);                          // wie getIdData(id)
    
    contains(id);                         // übernimmt Objekt, oder Id; Rückgabewert: wenn in der Liste darzustellender Elemente enthalten dann true ansonsten false
    includes(id);                         // übernimmt Objekt, oder Id; Rückgabewert: wie contains(id), liefert auch true wenn das Objekt bzw. Id ein Unterobjekt von einem der Objekte in Liste darzustellender Elemente ist
  
*/
function Display(tmpZI)
{
  this.show = Display_show;
  this.hide = Display_hide;
  this.move = Display_moveObj;
  
  this.add = Display_add;
  this.addPosition = Display_addPosition;
  
  this.getLastIdData = Display_getLastIdData;
  
  this.del = Display_del;
  this.delUpperId = Display_delUpperId;
  
  this.update = Display_update;
  this.updatePosition = Display_updatePosition;
  
  this.getIdData = Display_getIdData;
  this.getData = Display_getIdData;         // Aliasname
  this.getId = Display_getIdData;           // Aliasname
  
  this.assertId = Display_assertId;
  
  this.contains = Display_contains;
  this.includes = Display_includes;
  
  this.zIndex = (typeof(tmpZI)=="undefined")?1000:tmpZI;
  this.ids = new Array();                     // Liste darzustellender Elemente
  this.forceReCalc=Display.forceReCalc;
}

// statische Klassevariablen
Display.forceReCalc=false;        // ob standardmäßig immer neu berechnet wird
Display.defaultForce=2;           // jedes Element wird auf den darstellbaren Bereich begrenz





/*
  Element mit der gegebenen Id wird dargestellt.
  Zuerst wird das Element dargestellt, dann werden die 
  top und left - Attribute kontrolliert. Wenn diese Strings sind,
  dann werden diese mittels eval ausgeführt, um die relative 
  Positionierung zu bekommen.
  Wenn kein upperId-Element angegeben wurde, dann sind 
  top und left als absolut anzusehen, ansonsten als relativ zu
  dem upperId-Element
  
  Es wird entweder die Id angegeben, oder direkt das gesuchte IdData-Objekt!
*/
function Display_show(id){
  if( typeof(id)=="undefined" )
    var d=this.getLastIdData();
  else
    var d=(typeof(id)=="object")?(id):(this.getIdData(id));
  
  if( !d )
    return;
  
  if( !d.obj )
    d.obj=document.getElementById(d.id);
  var o = d.obj;
  
  if( o ){
  	
  	// Fix für Fehler bei der Darstellung Firefox 3 Opera 9.5
	  // Werte von vornherein mit 0 initialisieren, sonst kommt es zu Problemen
	  // mit Firefox 3 bzw. Opera 9.5; -> Hüpfen/Reload/Zucken der Seite beim 
	  // ersten Erscheinen des darzustellenden Containers (HTML-Objekt)
	  try{
		  o.style.top="0px";
		  o.style.left="0px";
		}catch(e){}
  	
    if( o.style.zIndex == 0 && this.zIndex!=0){
      o.style.zIndex = this.zIndex;
    }
    o.style.visibility = "hidden";
    this.move(d);
    o.style.visibility = "";
  }
  ieLayerBugDestroyer(id);
  return this;
}


/**
 * Verschiebt ein Element. Ohne dass entschieden wird, ob es dargestellt wird,
 * oder nicht. (obj.style.visibility bleibt unverändert!)
 * Es wird ein gültiges IdData - Objekt übergeben.
 */
function Display_moveObj(idData){
  
  var d = idData;
  var o = d.obj;
  
  var oUpper = (d.upperObj)?(d.upperObj):(d.upperObj=document.getElementById(d.upperId));
  var cUpper = getAbsolute(oUpper);
  var sUpper = new ScrollOffset(oUpper);       // nur die Scroll-Offsets von dem gegebenen Id-Element ohne die globalen(=window)-Scroll-Offsets
  var s = new ScrollOffset();                   // globale Scroll-Offsets
  var recalcPos = true;
  
  
  // wenn die alten Coordinates existieren, und nix erzwungen ist
  if( !this.forceReCalc )
  if( d.oldCoordinatesFromUpperObj && d.oldScrollOffsetFromUpperObj && d.oldScrollOffsetGlobal){
    // checken ob sich die Position verändert hat
    if( d.oldCoordinatesFromUpperObj.equals(cUpper) && d.oldScrollOffsetFromUpperObj.equals(sUpper) && d.oldScrollOffsetGlobal.equals(s) )
      recalcPos=false;
  }
  
  o.style.position = "absolute";
  o.style.display = "block";
  
  if( 1|| recalcPos){
    
    if( d.top != null && d.left != null ){
      var tmpTop = (typeof(d.top)=="string")?(eval(d.top)):(d.top);
      var tmpLeft = (typeof(d.left)=="string")?(eval(d.left)):(d.left);
      var c = new Coordinates(tmpTop+cUpper.top, tmpLeft+cUpper.left);
    }else{
      var c = (typeof(d.where)=="object" && d.where)?(new Coordinates().copy(d.where)):(new WherePosition(d.where).getCoordinates(o, oUpper, d.force==2));
    }
    
    if( !oUpper || !oUpper.style || oUpper.style.position != "absolute"){
      c.top-=sUpper.yOffset;
      c.left-=sUpper.xOffset;
    }
    
    // hier wird noch eine Begrenzung auf den zur Verfügung stehenden Raum durchgeführt!
    if( d.force >= 1 ){
      var max = new WidthAndHeight().setToMax();
      var id_WH = new WidthAndHeight().set(o);
      
      if( c.top<0 )
        c.top = 0;
      if( c.left<0 )
        c.left = 0;
      
      if( c.top + id_WH.height > max.height+s.yOffset ){
        c.top = max.height+s.yOffset-id_WH.height;
      }
      if( c.left + id_WH.width > max.width+s.xOffset ){
        c.left = max.width+s.xOffset-id_WH.width;
      }
    }
    
    o.style.top = c.top.toString()+"px";
    o.style.left = c.left.toString()+"px";
    
    if( !this.forceReCalc ){
      d.oldCoordinatesFromUpperObj = cUpper;
      d.oldScrollOffsetFromUpperObj = sUpper;
      d.oldScrollOffsetGlobal=s;
      d.upperObj=oUpper;
    }
  }
  
  if( d.onOpen )
    try{eval(d.onOpen);}catch(e){}
  
  try{
    return this;
  }catch(exception){}
}


/*
  blendet das Element mit der gegebenen Id wieder aus.
*/
function Display_hide(id){

  if( typeof(id)=="undefined" )
    var d=this.getLastIdData();
  else
    var d=(typeof(id)=="object")?(id):(this.getIdData(id));
  
  if(!d)
    return;
  
  if(typeof(d.obj) != "object")
    d.obj=document.getElementById(d.id);
  o=d.obj;
  
  if( o ){
    o.style.visibility="hidden";
    o.style.display="none";
  }
  if(d.onClose)
    try{eval(d.onClose);}catch(e){}
  ieLayerBugDestroyer(d.id);
}


/**
 * Stellt sicher, dass gegebenes Objekt eine eindeutige Id hat, oder 
 * eine Id (also ein String), ist! 
 */
function Display_assertId(obj){
  var ret="";
  if( typeof(obj) == "object" ){
    // der IE 6 braucht auch die Abfrage: obj.id == "null" :-(
    if( typeof(obj.id) == "undefined" || obj.id=="null" || obj.id=="" || obj.id == null ){
      
      var newId = "";
      var i=0;
      do{
        newId = "my_funny_Display_id_"+(i++);
      }while( document.getElementById(newId) != null );
      ret = newId;
      obj.id = newId;
    }else{
      ret = obj.id;
    }
  }else{
    ret = obj;
  }
  return ret;
}



/*
  fügt ein Element (id, Positionsangeben, usw.) zu der 
  Liste darzustellender Elemente hinzu.
  
  Beschreibung für die Parameter: siehe Klasse "IdData"
  zusätzlich dazu:
    
    "top" und "left" können Zahlen sein mit 
    relativen bzw. absoluten Positionierungsangaben,
    je nach dem ob eine upperId angegeben wurde, 
    oder nicht!
    
    Sie können aber auch Strings sein, welche 
    ausgeführt (mit eval) werden, wenn das 
    Element dargestellt wird. Somit kann man zum 
    Darstellungszeitpunkt die Positionierung abhängig 
    von aktuelle Daten anderer Elemente machen.
    
    D.h. man kann eine eigene Funktion schreiben, die 
    entweder "top", oder "left" (Integer in Pixel ohne "px") 
    zurückgibt, und welche dann bei der Darstellung 
    ausgeführt wird!
*/
function Display_add(id, top, left, upperId, onOpen, onClose){
  var d = new IdData(this.assertId(id),top,left,upperId);
  d.onOpen = onOpen;
  d.onClose = onClose;
  d.force=Display.defaultForce;
  
  this.ids.push(d);
  return this;
}


/*
  Wie add, nur statt "top" und "left" wird ein String erwartet, der 
  einen der Zustände von dem Attribut "states" in der Klasse "WherePosition"
  ("upper_left", "lower_right", ...) haben kann.
    
    Das Id-Element wird dann dem Zustand entsprechend platziert:
      
      "left_upper": links von upperId, nach oben orientiert; 
      "lower_right": unter upperId, nach rechts orientiert;
      "upper_left": überhalv von upperId, nach links orintiert;
      usw.
  
  Wenn der String keiner dieser Zustände ist, wird er als ausführbarer Code 
  angenommen, welcher ein "Coordinates"-Objekt zurückgibt, in welchem dann die 
  realtiven Positionsangaben zu dem upperId-Element sind.
  
  Wenn kein upperId-Element angegeben wird, dann werden diese Angaben, wie 
  "top" und "left" bei "Display.add()", als absolut angesehen.
*/
function Display_addPosition(id,where,upperId, onOpen, onClose){
  var d = new IdData(this.assertId(id),null,null,upperId);
  d.where = where;
  d.onOpen = onOpen;
  d.onClose = onClose;
  d.force=Display.defaultForce;
  
  this.ids.push(d);
  return this;
}



/**
 * Gibt die IdData vom letzten eingefügten Element zurück
 */
function Display_getLastIdData(){return this.ids[this.ids.length-1];}





/*
  Löschen des Eintrages mit der Id!
  ACHTUNG: style.display & style.position haben sich
  geändert, und werden hier nicht zurückgesetzt!
*/
function Display_del(id){
  for(var i in this.ids){
    if( this.ids[i].id == id )
      delete(this.ids[i]);
  }
}
/*
  Löschen aller Einträge mit der upperId
  sonst siehe "Display.del()"
*/
function Display_delUpperId(upperId){
  for(var i in this.ids){
    if( this.ids[i].upperId == upperId )
      delete(this.ids[i]);
  }
}
/*
  neu Setzen von Ids; siehe add und addPosition
*/
function Display_update(id, top, left, upperId, force){
  this.del(id);
  this.add(id, top, left, upperId, force);
}
function Display_updatePosition(id,where,upperId, force){
  this.del(id);
  this.addPosition(id,where,upperId, force)
}









/*
  liefert die Daten zu einer ID
  der optionale Parameter gibt an, ob nur die ID, 
  nur die übergeordnete ID oder beide IDs durchsucht 
  werden sollen.
  
  isUpperId:  0 (default) nur ID
              1 nur upperId
              2 upperId und Id werden 
                gesucht, sobald eines stimmt, 
                werden die Daten zu dieser 
                Ergebnis zurückgegeben
  
  id kann auch ein Objekt, das eine gültige Eigenschaft id hat, sein!
*/
function Display_getIdData(id, isUpperId){
  if( typeof(id) == "undefined")
    return false;
  if( typeof(id) == "object" && id.id)
    id=id.id;
  if( typeof(isUpperId) == "undefined")
    isUpperId = 0;
  
  switch(isUpperId){
    
    case 2:
      for( var i in this.ids)
        if( id==this.ids[i].upperId || id==this.ids[i].id)
          return this.ids[i];
    break;
    
    case 1:
      for( var i in this.ids)
        if( id==this.ids[i].upperId)
          return this.ids[i];
    break;
    
    case 0:
    default:
      for( var i in this.ids)
        if( id==this.ids[i].id)
          return this.ids[i];
  }
  return false;
}












/*
  überprüft, ob gegebenes Objekt in den angegebenen IDs enthalten ist
  der optionale Parameter alsoUpperId gibt an ob auch die übergeordneten
  Ids durchsucht werden sollen.
  alsoUpperId:  true    // übergeordnete Ids werden mitdurchsucht
                false   // übergeordnete Ids werden nicht mitdurchsucht
  
  Wenn die Id gefunden wurde, wird ein IdData-Objekt zurückgegeben, 
  ansonsten false!
*/
function Display_contains(obj,alsoUpperId){
  if( typeof(obj) == "undefined")
    return false;
  
  alsoUpperId = ( typeof(alsoUpperId) == "undefined")?true:alsoUpperid;
  if( !obj.id)
    return false;
  else
    var id=obj.id;
  
  return this.getIdData(id, (alsoUpperId)?2:0 );
}


/*
  überprüft, ob gegebenes Objekt in den angegebenen IDs enthalten ist, 
  oder ob es ein Unterobjekt von den angegebenen IDs ist!
  Ansonsten wie "contains(obj,alsoUpperId)"
  
  Wenn die Id gefunden wurde, wird ein IdData-Objekt zurückgegeben, 
  ansonsten false!
*/
function Display_includes(obj,alsoUpperId){
  var ret;
  
  while(obj){
    if( (ret=this.contains(obj,alsoUpperId)) != false)
      return ret;
    else
      obj=obj.parentNode;
  }
  return false;
}














// Hilfsfunktionen -------------------------------------------------------------
// liefert die Höhe vom gegebenen Objekts bzw. vom Element hinter einer Id
function getHeight(id){
  try{
    var obj = ( typeof(id)=="string" )?(document.getElementById(id)):(id);
    return obj.offsetHeight;
  }catch(e){
    return 0;
  }
}
// liefert die Höhe vom gegebenen Objekts bzw. vom Element hinter einer Id
function getWidth(id){
  try{
    var obj = ( typeof(id)=="string" )?(document.getElementById(id)):(id); 
    return obj.offsetWidth;
  }catch(e){
    return 0;
  }
}

// gibt absolute Position vom Element hinter einer Id bzw. vom gegebenen Objekt
// berückschtigt nicht die Scroll-Offsets
function getAbsolute(id){
  var obj = ( typeof(id)=="string" )?(document.getElementById(id)):(id);
  if(!obj) return new Coordinates;
  
  var top = obj.offsetTop;
  var left = obj.offsetLeft;
  var parent = obj.offsetParent;
  
  while( parent ){
    top += parent.offsetTop;
    left += parent.offsetLeft;
    parent=parent.offsetParent;
  }
  return new Coordinates(top,left);
}
// gibt das Objekt zurück, auf den ein Event ausgelöst wurde
function getEventObject(e){
  var ev = getCurrentEvent(e);
  var ziel=	(ev.target) ? ev.target:ev.srcElement;
//   var ziel=	(window.Event) ? ev.target:ev.srcElement;
  return ziel;
}
// liefert das ausgelöste Ereignis
function getCurrentEvent(e){
	if(window.event) return window.event;
  return (window.Event) ? e: window.event;
}

// berücksichtigt schon die Scroll-Offsets
function getAbsolutePos(el){
  var SL=0;
  var ST=0;
  
  var is_div=/^div$/i.test(el.tagName);
  if(is_div&&el.scrollLeft)SL=el.scrollLeft;
  if(is_div&&el.scrollTop)ST=el.scrollTop;
  
  var c = new Coordinates(parseInt(el.offsetTop)-ST,parseInt(el.offsetLeft)-SL);
  if(el.offsetParent){
    var tmp=getAbsolutePos(el.offsetParent);
    c.left+=tmp.left;
    c.top+=tmp.top;
  }
  return c;
}

// blendet die überschneidende Select-Felder aus (für IE 6)
function ieLayerBugDestroyer(drag_drop_Obj){
  if( !new Browser().ie ){
    return;
  }
    
  var object_name= new Array ();
  object_name[0]="select";
  object_name[1]="applet";
  object_name[2]="embed";
  object_name[3]="object";
//   object_name[4]="iframe";
  
  drag_drop_Obj=(drag_drop_Obj&&typeof(drag_drop_Obj)!="object")?(document.getElementById(drag_drop_Obj)):(drag_drop_Obj);
  if( drag_drop_Obj )
  for( var y=0; y<object_name.length; y++ ){
    
    var arrObjects = document.getElementsByTagName(object_name[y]);
    for( var i=0; i<arrObjects.length;i++ ){
      if( arrObjects[i] && arrObjects[i].style ){
        
        var cDDO = getAbsolutePos(drag_drop_Obj);         // Scroll-Offsets schon berücksichtigt!
        var cAnObject = getAbsolutePos(arrObjects[i]);
        var whDDO = new WidthAndHeight().set(drag_drop_Obj);
        var whAnObject = new WidthAndHeight().set(arrObjects[i]);
        
        var visible=true;
        if(
          (cDDO.top <= cAnObject.top+whAnObject.height) &&
          (cAnObject.top <= cDDO.top+whDDO.height) && 
          (cDDO.left <= cAnObject.left+whAnObject.width) &&
          (cAnObject.left <= cDDO.left+whDDO.width) 
        ){
          visible=false;
          p=arrObjects[i].parentNode;
          while(p){
            if( p == drag_drop_Obj ){
              visible=true;
              break;
            }
            p=p.parentNode;
          }
        }
        
        try{
          arrObjects[i].style.visibility=(!visible)?("hidden"):("");
        }catch(e){}
      }
    }
  }
}



















// Hilfsklassen ----------------------------------------------------------------

/*
  ein Satz Koordinaten 
    top
    left
*/
function Coordinates(myTop,myLeft){
  // Datenelemente
  this.top=0;
  this.left=0;
  
  this.set= function(id){
    this.copy(getAbsolute(id));
    return this;
  };
  this.setId = this.set;         // Aliasname
  
  this.copy=function(c){
    if( c && typeof(c)=="object" && typeof(c.getTop)=="function" && typeof(c.getLeft)=="function" ){
      this.setTop(c.getTop());
      this.setLeft(c.getLeft());
    }
    return this;
  };
  
  this.getTop=function(){return this.top;}
  this.getLeft=function(){return this.left;}
  this.setTop=function(myTop){this.top=myTop;}
  this.setLeft=function(myLeft){this.left=myLeft;}
  
  this.equals=function(o){return this.top==o.top && this.left==o.left;}
  
  // Konstruktor-Beginn -------------------
  if( myTop && typeof(myTop)=="object" && typeof(myTop.getTop)=="function" && typeof(myTop.getLeft)=="function" ){
    this.copy(myTop);
  }else{
    if( typeof(myTop) == "undefined")
      myTop=0;
    if( typeof(myLeft) == "undefined")
      myLeft=0;

    this.setTop(myTop);
    this.setLeft(myLeft);
  }
}





/*
  die Klasse für die Daten einer Id
    id          die Id des darzustellenden Elements
    top         wieviele Pixel von oben
    left        wieviele Pixel von links
    upperId     id des Elements, nach dem sich das 
                darzustellende Element relativ zu
                positionieren hat.
                Wenn hier null steht, dann sind
                top und left absolute Angaben.
                Wenn hier eine gültige Id angegeben
                wird, dann sind top und left
                relativ zu der Position
                des Elements mit dieser Id.
    force       kennt 3 Zustände: 0, 1, 2
                0 --> Das Element wird unabhängig 
                vom zur Verfügung stehenden Platz dargestellt
                1 --> Das Element wird so weit links und 
                rechts verschoben, das es nocht dargestellt
                werden kann
                2 --> (standard; nur bei addPosition()) wenn für das 
                Element auf der Seite, auf der es dargestellt
                werden soll kein Platz mehr ist, dann wird es 
                auf der anderen Seite dargestellt. Die 
                Funktionalität von force == 1 bleibt auch 
                erhalten. D.h. es wird versucht das Element 
                richtig darzustellen.
    
    onOpen      String welcher mit eval() ausgeführt wird, wenn Element 
                eingeblendet wird.
    onClose     String welcher mit eval() ausgeführt wird, wenn Element 
                ausgeblendet wird.
*/
function IdData(id,top,left,upperId, where, force){
  if( typeof(id) == "undefined"){
    id=null;
  }
  if( typeof(left) == "undefined"){
    left=null;
  }
  if( typeof(top) == "undefined"){
    top=null;
  }
  if( typeof(upperId) == "undefined"){
    upperId=null;
  }
  if( typeof(where) == "undefined"){
    where = null;
  }
  if( typeof(force) == "undefined"){
    force = 2;
  }
  
  
  if( id && typeof(id) == "object" ){
    this.obj=id;
    this.id=id.id;
  }else{
    this.id=id;
    this.obj=document.getElementById(id);
    try{
      this.obj.style.display='none';
    }catch(e){}
  }
  
  if( upperId && typeof(upperId) == "object" ){
    this.upperObj=upperId;
    this.upperId=upperId.id;
  }else{
    this.upperId=upperId;
    this.upperObj=document.getElementById(upperId);
  }
  
  this.top=top;
  this.left=left;
  this.upperId=upperId;
  this.where = where;
  this.force = force;
  this.onOpen = null;
  this.onClose = null;
}




/*
  Eine Klasse, die dafür sorgt dass nur ein Element in einer Sammlung von 
  Elementen (=Display-Objekt) dargestellt wird!
  Erwartet eine Sammlung von darzustellenden Elementen in Form eines
  Display-Objekts.
  
  Im Konstruktor wird das zu verwendende Display-Objekt übergeben.
  Der optionale Parameter "closeIfNotFits", gibt an ob ein Element nur
  gelöscht werden soll, wenn ein anderes Element aus der Sammlung dargestellt
  wird (false), oder ob es immer gelöscht werden soll, wenn der Event nicht auf 
  das dargestellte Element zutrifft (true; default-Wert).
*/
function ShowJustOneObj(dispObj,closeIfNotFits){
  this.oldEvent = null;
  this.openId = '';
  this.closeIfNotFits = (typeof(closeIfNotFits) == "undefined")?true:closeIfNotFits;
  
  if( typeof(dispObj) != "object" || !dispObj.ids)
    this.d = new Display();
  else
    this.d = dispObj;
  
  /*
    Diese Funktion wird in der Event-Funktion ausgeführt. Als Parameter wird
    das Objekt übergeben, auf welches der Event ausgelöst wurde 
    (getEventObject()). Die Funktion trifft die Entscheidung, ob auf ein Element
    in der Sammlung (Display-Objekt), oder auf eines der Unterelemente in dieser
    Sammlung, geklickt wurde, und stellt das geklickte Element (bzw. Unter-
    Element) dar, bzw. versteckt ein bereits dargestelltes Element.
    
    Gibt true zurück, wenn ein Element dargestellt wird, und false wenn keines 
    dargestellt wird.
  */
  this.work = function (o){
    
    if( (idDataToShow=this.d.includes(o)) != false ){
      var idToShow = idDataToShow.id;
      if( this.openId != idToShow ){
        this.d.hide(this.openId);
        this.d.show(idToShow);
        this.openId = idToShow;
      }
    }else{
      if( this.closeIfNotFits ){
        this.d.hide(this.openId);
        this.openId='';
      }
    }
    
    return this.openId!='';
  }
}


/*
  weitere Hilfsklasse für Breite und Höhe
*/
function WidthAndHeight(w,h){
  // Datenelemente
//   this.width = 0;
//   this.height = 0;
  
  // Setter & Getter
  this.setHeight=function(h){
    this.height = (typeof(h)!="number")?0:h;
    return this;
  };
  this.setWidth=function(w){
    this.width = (typeof(w)!="number")?0:w;
    return this;
  };
  this.getWidth=function(){return this.width;};
  this.getHeight=function(){return this.height;};
  
  this.copy = function(w){
    if( w && typeof(w)=="object" && typeof(w.getWidth)=="function" && typeof(w.getHeight)=="function" ){
      this.setWidth(w.getWidth());
      this.setHeight(w.getHeight());
    }
    return this;
  };
  this.setId=function(id){
    this.setWidth(getWidth(id));
    this.setHeight(getHeight(id));
    return this;
  };
  this.set=function(id){return this.setId(id)};
  this.setToMax=function(){
    var w,h;
    if (window.innerHeight || window.innerWidth){
      // all except Explorer
    	try{
        w = (window.innerWidth<top.window.innerWidth)?window.innerWidth:top.window.innerWidth;
        h = (window.innerHeight<top.window.innerHeight)?window.innerHeight:top.window.innerHeight;
      }catch(e){
        w = window.innerWidth;
        h = window.innerHeight;
      }
    }else if (document.documentElement && (document.documentElement.clientHeight||document.documentElement.clientHeight) ){
      // Explorer 6 Strict Mode
    	try{
        w = (document.documentElement.clientWidth<top.document.documentElement.clientWidth)?document.documentElement.clientWidth:top.document.documentElement.clientWidth;
        h = (document.documentElement.clientHeight<top.document.documentElement.clientHeight)?document.documentElement.clientHeight:top.document.documentElement.clientHeight;
      }catch(e){
        w = document.documentElement.clientWidth;
      	h = document.documentElement.clientHeight;
      }
    }else if (document.body){
      // other Explorers
    	w = document.body.clientWidth;
    	h = document.body.clientHeight;
    	try{
        w = (document.body.clientWidth<top.document.body.clientWidth)?document.body.clientWidth:top.document.body.clientWidth;
        h = (document.body.clientHeight<top.document.body.clientHeight)?document.body.clientHeight:top.document.body.clientHeight;
      }catch(e){
        w = document.body.clientWidth;
        h = document.body.clientHeight;
      }
    }
    
    this.setWidth(w);
    this.setHeight(h);
    return this;
  };
  
  this.equals=function(o){return this.width==o.width && this.height==o.height;}
  
  
  // Konstruktor-Beginn --------------------------
  this.setWidth(w);
  this.setHeight(h);
}
function ElementWidthAndHeight(el){
	var wh=(typeof(el)=="undefined")?(new WidthAndHeight()):(new WidthAndHeight().set(el));
	// remember parent functions
	for(var i in wh){
		this[i]=wh[i];
	}	
	this.base=wh;
	
	
	this.setEl=function(el){ this.el=( typeof(el)=="string" )?(document.getElementById(el)):(el); return this;}
	this.getEl=function(){return this.el;}
	this.setId=function(b){
		this.setEl(b);
		this.base.setId(b);																			// set local w & h
		return this;
	}
	this.setWidth=function(w){
		this.base.setWidth(w);																		// set local w
		try{
			this.getEl().style.width=this.base.getWidth()+"px";			// set el width
		}catch(e){}
		return this;
	}
	this.setHeight=function(h){
		this.base.setHeight(h);																	// set local h
		try{
			this.getEl().style.height=this.base.getHeight()+"px";		// set el height
		}catch(e){}
		return this;
	}
	this.equals=function(o){return this.base.equals(o) && this.getEl()==o.getEl();}
	this.copy=function(o){
		this.base.copy(o);
		this.setEl(o.getEl());
		return this;
	}
	
	// Konstruktor-Beginn
	this.setEl(el);
}





/*
  eine Klasse für die gültigen Positionen
*/
function WherePosition(where){
      
  this.state = '';
  this.states = new Array("undefined",
    "lower_left","lower_right","upper_left","upper_right",
    "left_lower","left_upper","right_lower","right_upper",
    "upper_center","lower_center","right_center","left_center");
  
  this.set = function(where){
    if( typeof(where) == "string" ){
      var state = '';
      for(var i in this.states){
        if( where.toLowerCase() == this.states[i]){
          state = this.states[i];
          break;
        }
      }
      if( state.length == 0)
        this.state = where;
      else
        this.state = state;
    }
    return this;
  };
  
  this.getCoordinates = function(id, upperId, flip){
    if( typeof(id) == "undefined"){
      return new Coordinates();
    }
    
    flip = (typeof(flip)=="boolean")?flip:false;
    upperId = ( typeof(upperId) == "undefined" )?null:upperId;
    
    var id_WH = new WidthAndHeight().set(id);
    var upperId_WH = (upperId != null)?new WidthAndHeight().set(upperId):new WidthAndHeight();
    var upperId_C = (upperId != null)?new Coordinates().set(upperId):new Coordinates();
    var max = new WidthAndHeight().setToMax();
        
    var s = this.state;
    var states = this.states;
    var top=0;
    var left=0;
    
    
    if(s == states[1]){
      //lower_left
      top=upperId_C.top + upperId_WH.height
      left=upperId_C.left - (( id_WH.width > upperId_WH.width )?(id_WH.width-upperId_WH.width):0);
      if(flip && top + id_WH.height > max.height){
        top=upperId_C.top-id_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[2]){
      //lower_right
      top=upperId_C.top+upperId_WH.height
      left=upperId_C.left;
      if(flip && top + id_WH.height > max.height){
        top=upperId_C.top-id_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[3]){
      //upper_left
      top = upperId_C.top - id_WH.height;
      left = upperId_C.left - (( id_WH.width > upperId_WH.width )?(id_WH.width-upperId_WH.width):0);
      if(flip && top < 0 ){
        top=upperId_C.top+upperId_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[4]){
      //upper_right
      top=upperId_C.top-id_WH.height
      left=upperId_C.left;
      if(flip && top < 0){
        top=upperId_C.top+upperId_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[5]){
      //left_lower
      top=upperId_C.top;
      left=upperId_C.left-id_WH.width;
      if(flip && left < 0 ){
        left=upperId_C.left+upperId_WH.width;
      }
      return new Coordinates(top,left);
    }
    if(s == states[6]){
      //left_upper
      top=upperId_C.top-((id_WH.height>upperId_WH.height)?(id_WH.height-upperId_WH.height):(0))
      left=upperId_C.left-id_WH.width;
      if(flip && left < 0 ){
        left=upperId_C.left+upperId_WH.width;
      }
      return new Coordinates(top,left);
    }
    if(s == states[7]){
      //right_lower
      top=upperId_C.top;
      left=upperId_C.left+upperId_WH.width;
      if(flip && left + id_WH.width > max.width ){
        left=upperId_C.left-id_WH.width;
      }
      return new Coordinates(top,left);
    }
    if(s == states[8]){
      //right_upper
      top=upperId_C.top-((id_WH.height>upperId_WH.height)?(id_WH.height-upperId_WH.height):(0))
      left=upperId_C.left+upperId_WH.width;
      
      if(flip && left + id_WH.width > max.width ){
        left=upperId_C.left-id_WH.width;
      }
      return new Coordinates(top,left);
    }
    if(s == states[9]){
      //upper_center
      top=upperId_C.top-id_WH.height;
      left=upperId_C.left+(upperId_WH.width/2)-(id_WH.width/2);
      if(flip && top < 0){
        top=upperId_C.top+upperId_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[10]){
      //lower_center
      top=upperId_C.top+upperId_WH.height;
      left=upperId_C.left+(upperId_WH.width/2)-(id_WH.width/2);
      if(flip && top + id_WH.height > max.height ){
        top=upperId_C.top-id_WH.height;
      }
      return new Coordinates(top,left);
    }
    if(s == states[11]){
      //right_center
      top=upperId_C.top+(upperId_WH.height/2)-(id_WH.height/2);
      left=upperId_C.left+upperId_WH.width;
      if(flip && left + id_WH.width > max.width ){
        left=upperId_C.left-id_WH.width;
      }
      return new Coordinates(top,left);
    }
    if(s == states[12]){
      //left_center
      top=upperId_C.top+(upperId_WH.height/2)-(id_WH.height/2);
      left=upperId_C.left-id_WH.width;
      if(flip && left + id_WH.width > max.width ){
        left=upperId_C.left+upperId_WH.width;
      }
      return new Coordinates(top,left);
    }
    
    
    try{
      
      var ret = eval(s);       // hier soll man ein Coordinates - Objekt zurückbekommen
      ret = new Coordinates(upperId_C.top+ret.top, upperId_C.left+ret.left);
      
    }catch(e){
      var ret = new Coordinates();
    }
    return ret;
  }
  
  this.set(where);
}



/*
  findet heraus, um wieviel gescrollt wurde
*/
function ScrollOffset(id)
{
  this.equals=function(o){return this.yOffset==o.yOffset && this.xOffset==o.xOffset;}
  
  if( typeof(id)=="undefined" ){
    
    if ( window.pageXOffset||window.pageYOffset ){
      // all except Explorer
    	this.xOffset = window.pageXOffset;
    	this.yOffset = window.pageYOffset;
    }else if (document.documentElement && (document.documentElement.scrollLeft||document.documentElement.scrollTop) ){
      // Explorer 6 Strict
    	this.xOffset = document.documentElement.scrollLeft;
    	this.yOffset = document.documentElement.scrollTop;
    }else if (document.body && (document.body.scrollLeft||document.body.scrollTop) ){
      // all other Explorers
    	this.xOffset = document.body.scrollLeft;
    	this.yOffset = document.body.scrollTop;
    }else{
      this.xOffset = 0;
    	this.yOffset = 0;
    }
    
  }else{
    
    var el=(typeof(id)=="object")?(id):(document.getElementById(id));
    var tmpTop=0;
    var tmpLeft=0;
//     var temp='';
    while( el ){
      if( el!=document.getElementsByTagName("body")[0]){
//         temp+=" "+el.tagName+":"+el.id+"|"+el.scrollTop+"\n";
        tmpTop +=(typeof el.scrollTop == "number")?el.scrollTop:0;
        tmpLeft +=(typeof el.scrollLeft == "number")?el.scrollLeft:0;
        el=el.parentNode;
      }else
        break;
    }
    this.yOffset=tmpTop;
    this.xOffset=tmpLeft;
//     alert(id + " " + temp+"\n"+this.yOffset+"/"+this.xOffset);
  }
}





/*
  Zum Auslesen der Mauskoordinaten; Erwartet Event-Objekt
  (siehe getCurrentEvent(e));
*/
function getMouseTopLeft(e){
  var top=e.pageY?e.pageY:e.clientY;
  var left=e.pageX?e.pageX:e.clientX;
  return new Coordinates(top,left);
}
/**/












/*
  Eine statische Klasse zum Drag'n'Droppen!
*/
function DragDrop(){
}
DragDrop.obj = null;
DragDrop.moveme = false;
DragDrop.offset = new Coordinates();
DragDrop.oldOnMouseMove = null;
DragDrop.oldOnMouseUp = null;

DragDrop.grab=function(e){
  var event = getCurrentEvent(e);
  var el=getEventObject(e);
  var co = getAbsolute(el);
  
  while(el){
    if(el.style && el.style.position=="absolute"){
      DragDrop.obj = el;
      break;
    }
    el=el.parentNode;
  }

  var body = document.getElementsByTagName('body');
  if(body && body[0])
    body = body[0];
  
  if(body && DragDrop.obj && DragDrop.obj.style.position=="absolute"){
    try{
      if( !new Browser().ie){
        var p = DragDrop.obj.parentNode;
        p.removeChild(DragDrop.obj);
        body.appendChild(DragDrop.obj);
      }
    }catch(ex){}
   
    DragDrop.moveme=true;
    
    var cm = getMouseTopLeft(event);
    DragDrop.offset.left=cm.left-co.left;
    DragDrop.offset.top=cm.top-co.top;
    
    
    // damit das Selektieren, unterbunden wird!
    DragDrop.oldOnSelectStart=document.onselectstart;
    DragDrop.oldOnMouseDown=document.onmousedown;
    // IE
    document.onselectstart=function(){try{DragDrop.oldOnSelectStart()}catch(e){};return false;}
    // others
    document.onmousedown=function(){try{DragDrop.oldOnMouseDown()}catch(e){};return false;}
    
    
    DragDrop.oldOnMouseMove=document.onmousemove;
    DragDrop.oldOnMouseUp=document.onmouseup;
    document.onmousemove=DragDrop.move;
    document.onmouseup=DragDrop.drop;
  }
}
DragDrop.move=function(e){
	try{DragDrop.oldOnMouseMove()}catch(_e){};
  if(DragDrop.moveme){
    var cm = getMouseTopLeft(getCurrentEvent(e));
    var co = getAbsolute(DragDrop.obj);
    var whMax = new WidthAndHeight().setToMax();
    var whObj = new WidthAndHeight().set(DragDrop.obj);
    var sOffset = new ScrollOffset();
    
    whMax.height+=sOffset.yOffset;
    whMax.width+=sOffset.xOffset;
    
    var top = cm.top-DragDrop.offset.top;
    var left = cm.left-DragDrop.offset.left;
    
    if( left + whObj.width > whMax.width )
      left = whMax.width-whObj.width;
    
    if( top + whObj.height > whMax.height )
      top = whMax.height-whObj.height;
    
    if(top<0)
      top=0;
    if(left<0)
      left=0;
    
    DragDrop.obj.style.top=top+"px";
    DragDrop.obj.style.left=left+"px";
    
    ieLayerBugDestroyer(DragDrop.obj);
  }
}
DragDrop.drop=function(e){
  try{DragDrop.oldOnMouseUp()}catch(_e){};
  DragDrop.moveme=false;
  document.onmousemove=DragDrop.oldOnMouseMove;
  document.onmouseup=DragDrop.oldOnMouseUp;
  
  document.onselectstart=DragDrop.oldOnSelectStart;
  document.onmousedown=DragDrop.oldOnMouseDown;
  
  DragDrop.obj = null;
  DragDrop.offset=new Coordinates;
}
DragDrop.add=function(id){
  var o=(typeof(id)=="object")?(id):document.getElementById(id);
  if(o){
    o.onmousedown=DragDrop.grab;
  }
}





/**
 * Prüft ob das angegebene Objekt o innerhalb der Koordinaten von box ist.
 * (zur Überprüfung ob Mauszeiger innerhalb eines Bereichs ist)
 */
function isWithin(o,box){
	var c=getMouseTopLeft(o);
	var cBox=getAbsolute(box);
	var whBox=new WidthAndHeight().set(box);
	var ret=true;
	
	if( c.left<cBox.left || c.left>cBox.left+whBox.width ){
		ret=false;
	}else if( c.top<cBox.top || c.top>cBox.top+whBox.height ){
		ret=false;
	}
	return ret;
}







// deprecated Stuff: -----------------------------------------------------------
