/*
 © 2004 Struppi
 URL: http://home.nexgo.de/struebig/computer/javascript
 Datum: 02.08.04

*/


/*
   Die Zugriffsfunktionen für die verschiedenen Objektmodelle.
   so muss die Überprüfung welches genutzt wird nur einmal erfolgen
*/

var F         = new Object();
F['offset']   = new Object();
F['page']     = new Object();
F['layers']   = new Object();

F['offset'].left = function(obj) { var l = 0; while (obj) { l += parseInt(obj.offsetLeft ); obj = obj.offsetParent; } return l; };
F['offset'].top = function(obj) { var l = 0; while (obj) {   l += parseInt(obj.offsetTop ); obj = obj.offsetParent;  } return l; };

F['offset'].width = function(obj) {  return obj.offsetWidth; };
F['offset'].height = function(obj) {  return obj.offsetHeight; };

F['page'].left = function(obj) { return parseInt(obj.pageX); };
F['page'].top = function(obj) { return parseInt(obj.pageY); };

F['layers'].left = function(obj) { return parseInt(obj.left || obj.x); };
F['layers'].top = function(obj) { return parseInt(obj.top || obj.y); };
F['layers'].width = function(obj) { return obj.width || obj.clip.width; };
F['layers'].height = function(obj) { return obj.height || obj.clip.height; };
// F['layers'].width = function(obj) { return obj.clip.width; };
// F['layers'].height = function(obj) { return obj.clip.height; };


var Px = document.childNodes ? 'px' : '';
var showError = true;
var NL = '\n';

////////////////////////////////////////////////////////////
//
// Point(x, y)
// Point.copy (Point)
// Point.equal (Point)
// Point.smaller (Point)
// Point.greater (Point)
// Point.top (top)
// Point.left (left)

function Point(y, x) {
    if(typeof x == 'object' ) this.copy(x);
    else { this.x = x || 0; this.y = y || 0;}
}
Point.prototype.copy = function (p) { this.x = p.x || 0; this.y = p.y || 0; }
Point.prototype.equal = function (p) { return this.x == p.x  && this.y == p.y; }
Point.prototype.smaller = function (p) {return (this.x <= p.x && this.y <= p.y ) }
Point.prototype.greater = function (p) {return (this.x >= p.x && this.y >= p.y ) }
Point.prototype.top = function (y) {if( defined( y )) {this.y = y;} return this.y;}
Point.prototype.left = function (x) {if( defined( x ) ) {this.x = x;} return this.x;}
Point.prototype.info = function () { return '\nTop/Left: ' + this.top() + Px + '/' + this.left() + Px;}

////////////////////////////////////////////////////////////
//
// Rect(top, left, height, width)
// Rect.ini()
// Rect.check()
// Rect.top( t )
// Rect.left(l )
// Rect.width( w )
// Rect.height( h )
// Rect.isIn( Rect )
// Rect.info()

function Rect(top, left, height, width)
{
    this.l = left;
    this.t = top;
    this.w = width;
    this.h = height;
    this.ini();
}
Rect.prototype.ini = function()
{
}
Rect.prototype.top = function(p) { if(defined(p)) this.t = p; return this.t;};
Rect.prototype.left = function(p) { if(defined(p)) this.l = p; return this.l;};
Rect.prototype.width = function(p) { if(defined(p)) this.w = p; return this.w;};
Rect.prototype.height = function(p) { if(defined(p)) this.h = p; return this.h;};
Rect.prototype.right = function(p) {  if(defined(p)) this.left(p - this.width() ); return this.left() + this.width();};
Rect.prototype.bottom = function(p) {  if(defined(p)) this.top(p - this.height() ); return this.top() + this.height();};
Rect.prototype.info = function()
{
    this.p1 = new Point(this.top(), this.left());
    this.p2 = new Point(this.right(), this.bottom());
    return 'Rect:\np1: ' + this.p1.info() + '\np2:' + this.p2.info()
    + '\nw x h ' + this.width() +  ' x ' + this.height()
    ;
}

/*
  Methoden:
  DOM_Layer.width( width )
  DOM_Layer.height( height )
  DOM_Layer.top( top )
  DOM_Layer.left( left )
  DOM_Layer.size(width, height)
  DOM_Layer.moveTo(top, left)
  DOM_Layer.style(name, attr)
*/
function DOM_Layer(obj, win)
{
    this.ini(obj, win);
}
DOM_Layer.prototype.ini = function ( obj, win )
{
    if(!obj) return;
    this.obj = obj;
    this.win = win;
    this.rect = new Rect();

    // IE Boxmodell Bug im Quirks Mode (Opera macht es auch)
    this.boxBug = !!(!(this.win.document.compatMode && this.win.document.compatMode == "CSS1Compat") && document.all);

    // Zuweisung der Zugriffsfunktionen
    this.getTop = defined( this.obj.pageY ) ? F['page'].top
    : defined( this.obj.top ) ? F['layers'].top
    : defined(this.obj.offsetTop) ? F['offset'].top
    : defined( this.obj.y) ? F['layers'].top
    : function() { return 0; }
    ;

    this.getLeft = defined(this.obj.offsetLeft) ? F['offset'].left
    : defined( this.obj.pageX ) ? F['page'].left
    : defined( this.obj.left) ? F['layers'].left
    : defined( this.obj.x) ? F['layers'].left
    : function() { return 0; }
    ;
    this.getWidth = defined(this.obj.offsetWidth) ? F['offset'].width
    : defined( document.layers) ? F['layers'].width
    : function() { return 0; }
    ;
    this.getHeight = defined(this.obj.offsetHeight) ? F['offset'].height
    : defined( document.layers) ? F['layers'].height
    : function() { return 0; }
    ;
    this.rect.top( this.getTop(this.obj) );
    this.rect.left( this.getLeft(this.obj) );
    this.rect.width( this.getWidth(this.obj) );
    this.rect.height( this.getHeight(this.obj) );
}

DOM_Layer.prototype.style = function(name, attr)
{
    if(!this.obj) return;
    var s = this.obj.style ? this.obj.style : this.obj;
    if(  attr != 'null' && defined( attr ))
    {
         if(document.all && !window.opera ) s.setAttribute(name, attr);
         else s[name] = attr;
    }
    return s[name];
}
DOM_Layer.prototype.width = function ( w )
{
    if( defined( w ) ) {
         w -= this.borderH();
         if( this.obj.resizeTo ) this.obj.resizeTo(w, this.height());
         else this.style('width', w + Px);
    }
    return this.rect.width( this.getWidth( this.obj)) ;
}

DOM_Layer.prototype.height = function ( h )
{
    if( defined( h ) )
    {
         h -= this.borderV();
         if( this.obj.resizeTo ) this.obj.resizeTo(this.width(), h);
         else this.style('height', h + Px);
    }
    return this.rect.height(this.getHeight( this.obj) );
}
DOM_Layer.prototype.top = function ( t )
{
    if( defined( t ) )
    {
         this.style('top', t + Px);
    }
    return this.rect.top( this.getTop(this.obj) );
}
DOM_Layer.prototype.left = function ( l )
{
    if( defined( l ) )
    {
         this.style('left', l + Px);
    }
    return this.rect.left( this.getLeft( this.obj) );
}
DOM_Layer.prototype.right = function ( r )
{
   if( defined(r) )
   {
        this.left( r - this.width() );
   }
   return this.rect.right();
}
DOM_Layer.prototype.bottom = function ( b )
{
   if( defined(b) )
   {
        this.top( b - this.height() );
   }
   return this.rect.bottom();
}
DOM_Layer.prototype.moveOn = function ( )
{
/*
    window.status = 'top:' + this.top() + ' left:' + this.left()
    + ' endtop:' + this.endTop
    + ' endLeft:' + this.endLeft
    + ((this.top() < this.endTop) && (this.left() < this.endLeft))
    ;
*/
    if(this.step > 0)
    {
    if(this.top() < this.endTop) this.top( this.top() + this.step);
    if(this.left() < this.endLeft) this.left( this.left() + this.step);
    return ( this.top() > this.endTop && this.left()  > this.endLeft);
    }
    else
    {
    if(this.top() > this.endTop) this.top( this.top() + this.step);
    if(this.left() > this.endLeft) this.left( this.left() + this.step);
    return (this.left() > this.endLeft)
    ;
    }
}
DOM_Layer.prototype.moveTo = function ( t, l , time, step)
{
    if(time)
    {
         this.endTop = t;
         this.endLeft = l;
         this.step = step || 1;

         setTimerCall(this, time);
    }
    else
    {
         this.left(l);
         this.top(t);
    }
    return this.rect;
}

var timer_obj = new Array();

function setTimerCall(obj, time)
{
var i = timer_obj.length;
timer_obj[i] = obj;
TimerCall(i, time);
}
function TimerCall(i, t)
{
if(typeof timer_obj[i] != 'object') return;
if( timer_obj[i].moveOn() ) window.setTimeout('TimerCall(' + i + ',' + t  + ')', t);
else alert('fertig');
}

DOM_Layer.prototype.size = function ( h, w )
{
    this.height(h);
    this.width(w);
    this.left();
    this.top();
    return this.rect;
}
DOM_Layer.prototype.borderH = function (  )
{
    return this.boxBug  ? 0 :// beim falschen Boxmodell muss der Rahmen nicht abgezogen weren
    parseInt( this.style('borderLeftWidth') || 0 )
    + parseInt( this.style('borderRightWidth') || 0)
    + parseInt( this.style('marginLeft')  || 0)
    + parseInt( this.style('marginRight') || 0)
    + parseInt( this.style('paddingLeft')  || 0)
    + parseInt( this.style('paddingRight') || 0)
    ;
}
DOM_Layer.prototype.borderV = function (  )
{
    return this.boxBug ? 0 :
    parseInt( this.style('borderTopWidth') || 0 )
    + parseInt( this.style('borderBottomWidth') || 0)
    + parseInt( this.style('marginTop')  || 0)
    + parseInt( this.style('marginBottom') || 0)
    + parseInt( this.style('paddingTop')  || 0)
    + parseInt( this.style('paddingBottom') || 0)
    ;
}
/*
 DOM Object

 Anwendung:
 var o = getObjById(id [,win]);


 show( true/false )
 hide()
 color( fore, back)
 drag( true/ false )
 innerHTML( HTML )
 addEvent
*/
function DOM(obj, win)
{
    if(!obj) return Error('ungültiges Objekt');
    this.ini(obj, win);

    this.evt = new Object();

    this.body =  getBody(this.win);
    this.drop = false;
    this.z;

    this.style('position', 'absolute');

}
DOM.prototype = new DOM_Layer();
DOM.prototype.constructor = DOM;

DOM.prototype.innerHTML = function(code)
{
    if(defined(this.obj.innerHTML))
    {

         if(typeof code != 'undefined') this.obj.innerHTML = code;
         return this.obj.innerHTML;
    }
    else if (defined(document.layers))
    {
         if(typeof code != 'undefined')  {
         this.obj.document.open();
         this.obj.document.write(code);
         this.obj.document.close();
         }
         return code;
    }
    else
    {
         Error('Der Browser kann den Inhalt eines Elementes nicht austauschen');
         return 'Fehler. Browser kann die Funktion nicht';
    }
}
DOM.prototype.addEvent = function(e, f)
{
    this.evt[e];
}
DOM.prototype.Style = function()
{
    if(!this.obj) return;
    if(this.obj.style) return this.obj.style; else return this.obj;
}
DOM.prototype.show = function(m)
{
    if(m == false) this.style('visibility', 'hidden')
    else this.style('visibility', document.layers ? 'show' : 'visible' )
}
DOM.prototype.hide = function()
{
    this.show(false);
}
DOM.prototype.color = function(fg, bg)
{
    if(fg) this.style('color', fg);
    if(bg) this.style('backgroundColor', bg);
    if(document.layers) this.style('bgColor', bg);
}
DOM.prototype.clone = function()
{
    var id = 'id' + parseInt( Math.random() * 1000 ) ;
    var html = '<div id="' + id + '" style="position:absolute">'
    + this.innerHTML() + '</div>'
    ;
    if(document.layers)
    {
         // Netscape 4
         this.win.document.layers[id] = new Layer(this.width());
         this.win.document.layers[id].bgColor = this.style('bgColor');

         this.win.document.layers[id].document.open()
         this.win.document.layers[id].document.write('dieser Browser kann den Inhalt nicht kopieren')
         this.win.document.layers[id].document.close()

    }
    else if (this.obj.cloneNode && this.body && this.body.appendChild)
    {
         var test = this.obj.cloneNode(true);
         test.id = id;
         this.win.document.body.appendChild(test);
    }
    // Es muss immer heißen document.body egal ob im strict oder Quirks Mode
    else if (document.body.insertAdjacentHTML)
    {
         this.win.document.body.insertAdjacentHTML("afterBegin", html);
    }
    else if (this.body && this.body.innerHTML) this.body.innerHTML += this.innerHTML();

    var n = getObjById(id, this.win);
    if(!n) return alert('Fehler');
    if (document.body.insertAdjacentHTML)
    {
         // var s = this.Style();
         //for( var i in  s) { alert(i + '=' + s[i]); if(typeof s[i] == 'string' ) n.setStyle(i, s[i] ); }
         n.setStyle('cssText', this.style('cssText'));

    }

    /*
    n.moveTo( this.top(), this.left() );
    n.size( this.height() ,this.width() );
    */
    n.show(true);

    /*
    var s = this.Style();
    var x = 0;
    if(s.item)
    {
          while(i = s.item(x++) ) n.setStyle(i, s.getPropertyValue(i) );
    }
    else
    {
    }
    */
    return n;
}


// umwandeln eines CSS Atrtributes in die JS schreibweise
DOM.prototype.setStyle = function(n, v)
{
    if(!v) return;
    var name = '';
    var start = 0;
    var end = 0;

    while( end > -1 )
    {
         end = n.indexOf('-', start);
         var txt = n.substring(start, end > - 1 ? end : n.length);
         if(name) txt = txt.substring(0,1).toUpperCase() + txt.substring(1);
         name += txt;
         start = end + 1;
    }
    return this.style(name, v);
}
DOM.prototype.drag = function(m, drop, view)
{
    if(typeof mouse_pos == undef )
         return Error('Für die Dragfunktion muss die Mouse Bibliothek eingebunden werden');

    if(m)
    {
        this.obj.DOM = this;
        this.drop = drop ? true : false;
        this.view = view ? view.size() : null;

        if(this.obj.captureEvents) this.obj.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP);
        this.obj.onmousedown = function(e) { this.DOM.startDrag(e); }
        this.obj.onmouseup = function(e) { this.DOM.stopDrag(e); }
    }
    else
    {
        if(this.obj.captureEvents) this.obj.releaseEvents(Event.MOUSEDOWN | Event.MOUSEUP);
        this.obj.onmousedown = this.obj.onmouseup = null;
    }
    window.wait = 1;
    return true;
}

DOM.prototype.startDrag = function(e)
{
    var p = mouse_pos(e);
    this.startPos = new Point(this.top() - p.scrollTop, this.left() - p.scrollLeft);

    // Wenn das Dokument kleiner ist als das Fenster
    // wird als view das Fenster genommen
    if(!this.view) this.view = Doc(this.win );

    this.win.document.DOM = this;
    this.z = this.style('zIndex') || 0;
    this.style('zIndex', 1);


    if(this.win.document.captureEvents) this.win.document.captureEvents(Event.MOUSEMOVE);
    this.win.document.onmousemove = function(e) { this.DOM.move(e); }

    if ( defined(document.all) )
       this.win.document.onselectstart = this.win.document.ondragstart = function () { return false; };

}
DOM.prototype.move = function(e)
{
    var p = mouse_pos(e);

    var top = p.scrollTop + this.startPos.top();
    var left = p.scrollLeft + this.startPos.left();

    if(left < this.view.left() ) left = this.view.left();
    else if( left + this.width() > this.view.right()) left = this.view.right() - this.width();

    if( top < this.view.top() ) top = this.view.top();
    else if( top + this.height() > this.view.bottom() ) top = this.view.bottom() - this.height();

    this.top( top);
    this.left( left);
    // window.status = 'move left:' + (left + this.width() )    + 'right:' + this.view.right()    ;
}

DOM.prototype.stopDrag = function(e)
{
    // Events entfernen
    if(this.win.document.captureEvents) this.win.document.releaseEvents(Event.MOUSEMOVE);
    this.win.document.onmousemove = null;

    if ( defined( document.all ) )  this.win.document.onselectstart = this.win.document.ondragstart = null;
    if(this.drop) this.style('zIndex', this.z);
}

DOM.prototype.info = function()
{
    if(!this.obj) return 'Objekt nicht definiert';

    return '\nDOM Objekt:\n\n'
    + 'id = ' + this.obj.id + '\n'
    + 'name = ' + this.obj.name + '\n'
    + 'class = ' + this.obj.clasName + '\n'
    + '\nMaße:\n' + this.rect.info()
    ;
}



/////////////////////////////////////////////////
// Funktion ob das Objekt aus dem Dokument abzufragen
function getObjById(id, win)
{
    if(!win) win = window;
    var obj = searchObj(id, win);
    if(obj != null) return new DOM(obj, win); else return null;
}
/////////////////////////////////////////////////
function searchObj(id, win)
{
    var obj = null;
    if(id && win)
    {
         if(typeof id != 'object')
         {
              if( document.layers )
              {
                   if( win.document.layers[id] )
                   {
                        obj = win.document.layers[id];
                   } else
                   {
                        for( var x = 0; !obj && x < win.document.layers.length; x++ )  obj = searchObj( id ,win.document.layers[x]);
                   }
                   if( !obj )
                   {
                        obj = win.document.images[id];
                   }
              }
              if( document.getElementById ) obj = win.document.getElementById(id);
              if( document.all ) obj = win.document.all[id];
              if( win.document[id] ) obj = win.document[id];
         }
         else
         {
              obj = id;
         }
    }
    return obj;
}

function Win(w)
{
    if(!w) w = window;
    var r = new Rect();
    var b = getBody(w);

    if(typeof w.pageXOffset != 'undefined')
    {
         // Mozilla/Netscape
         r.left( w.pageXOffset );
         r.top( w.pageYOffset );
         r.width( w.innerWidth );
         r.height( w.innerHeight );
    }
    else if( b )
    {
         r.left( b.scrollLeft );
         r.top( b.scrollTop );
         r.width( parseInt(b.clientWidth) );
         r.height( parseInt(b.clientHeight) );
    }
    return r;
}
function Doc(w)
{
    if(!w) w = window;

    var r = new Rect(0,0,0,0);
    var b = getBody(w);

    if (typeof document.height != 'undefined')
    {
        r.width(w.document.width);
        r.height( w.document.height);
    }
    else if(b)
    {
        r.width( parseInt( b.scrollWidth) );
        r.height( parseInt( b.scrollHeight) );
    }
    return r;
}

function getBody(w)
{
    return (w.document.compatMode && w.document.compatMode == "CSS1Compat") ? w.document.documentElement : w.document.body || null;
}
var undef = 'undefined';
function defined(arg) { return (typeof arg != undef) };

function Error(msg)
{
    if(showError) alert(msg);
    return false;
}

/*
LOG:

24.08.04

* IE 4 Anpassungen in der Funktion clone()

*/
