/*
 * The semicolon.at DHTML-Library
 * Copyright (C) 2005 Sylvester Keil
 * http://myself.semicolon.at/contact
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * A copy of the GNU General Public License in electronic form is
 * available at http://www.gnu.org/licenses/gpl.html; Alternatively,
 * you can write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

function SimpleObject(id) {
  if (document.getElementById && id && document.getElementById(id)) {
    this.dom = document.getElementById(id);
		if (this.dom == null) return null;
    this.css = this.dom.style;
    this.ref = id + 'Object'; eval(this.ref + "= this");
  }
  else return null;
}

function DHTMLObject(id) {
  this.base = SimpleObject;
  this.base(id);
	if (this.dom == null) return null;

  this.x = this.dom.offsetLeft;
  this.y = this.dom.offsetTop;

  // width/height box model adjustments
  if (window.getComputedStyle) {
    this.w = parseInt(window.getComputedStyle(this.dom,null).getPropertyValue("width"));
    this.h = parseInt(window.getComputedStyle(this.dom,null).getPropertyValue("height"));
  }
  else {  // this happens in ie konqueror/safari.. too bad
    this.w = this.dom.offsetWidth;
    this.h = this.dom.offsetHeight;
  }

  this.__dd = { x: 0, y: 0 };
  this.__slide = { active: false, timeout: 10, speed: 10, x: 0, y: 0 };
  this.__morph = { active: false, timeout: 10, speed: 10, w: 0, h: 0 };
  this.__scroll = { init: false, timeout: null, speed: 20, y: 0,
                    t: 0, b: 0, r: 0, l: 0, org: 0, lim: 0 };

  /* general remark to behaviour of movement/resize functions:
   *
   * commit change to position or dimenstion coordinates
   * only when necessary, i.e. don't change css values on
   * change of zero px.
   *
   * this hides browser quirks.
   *
   * it does NOT solve the problem. in cases where such a
   * change is desirable, differing browser behaviour needs
   * to be addressed by calling functions (or alteration of
   * following functions).
   */
  this.move = function(x,y) {
    this.move_to(this.x + x, this.y + y);
  }
  this.move_to = function(x,y) {
    if (x != this.x) {
	this.x = x;
	this.css.left = this.x + "px";
    }
    if (y != this.y) {
      this.y = y;
      this.css.top = this.y + "px";
    }
  }

  this.slide = function(x,y,fn) {
    this.slide_to(this.x + x, this.y + y,fn);
  }
  this.slide_to = function(x,y,fn) {
    if (!this.__slide.active) {
      var dx = x - this.x;
      var dy = y - this.y;
      var d = Math.sqrt(dx*dx + dy*dy) / this.__slide.speed;
      this.__slide.x = dx / d;
      this.__slide.y = dy / d;
      this.__slide.active = true; 
      this._slide(x,y,fn)
    }
  }
  this._slide = function(x,y,fn) {
    if (this.__slide.active) {
      if (Math.abs(this.__slide.x) < Math.floor(Math.abs(this.x - x)) ||
          Math.abs(this.__slide.y) < Math.floor(Math.abs(this.y - y))) {
        this.move(this.__slide.x, this.__slide.y);
        window.setTimeout(this.ref+"._slide("+x+","+y+",'"+fn+"')",this.__slide.timeout)
      }
      else {
        this.__slide.active = false; 
        this.move_to(x,y);
        if (fn) eval(fn);
      }
    }
  }

  this.resize = function(w,h) {
    this.resize_to(this.w + w, this.h + h);
  }
  this.resize_to = function(w,h) {
    if (w != this.w) {
      this.w = w;
      this.css.width = this.w + "px";
    }
    if (h != this.h) {
      this.h = h;
      this.css.height = this.h + "px";
    }
  }

  this.morph = function(w,h,fn) {
    this.morph_to(this.w + w, this.h + h,fn);
  }
  this.morph_to = function(w,h,fn) {
    if (!this.__morph.active) {
      var dw = w - this.w;
      var dh = h - this.h;
      var d = Math.sqrt(dw*dw + dh*dh) / this.__morph.speed;
      this.__morph.w = dw / d;
      this.__morph.h = dh / d;
      this.__morph.active = true; 
      this._morph(w,h,fn)
    }
  }
  this._morph = function(w,h,fn) {
    if (this.__morph.active) {
      if (Math.abs(this.__morph.w) < Math.floor(Math.abs(this.w - w)) ||
          Math.abs(this.__morph.h) < Math.floor(Math.abs(this.h - h))) {
        this.resize(this.__morph.w, this.__morph.h);
        window.setTimeout(this.ref+"._morph("+w+","+h+",'"+fn+"')",this.__morph.timeout)
      }
      else {
        this.__morph.active = false; 
        this.resize_to(w,h);
        if (fn) eval(fn);
      }
    }
  }

  this.dd_enable = function() {
    this.dom.onmousedown = new Function('e', this.ref+".dd_start(e)");
  }

  this.dd_disable = function() {
    this.dom.onmousedown = null;
  }

  this.dd_start = function(e) {
    if (!e) e = window.event;
    this.__dd.x = e.clientX - this.x;
    this.__dd.y = e.clientY - this.y;
    document.onmousemove = new Function('e', this.ref + ".dd_drag(e)");
    document.onmouseup = new Function(this.ref + ".dd_drop()");
  }

  this.dd_drag = function(e) {
    if (!e) e = window.event;
    this.move_to(e.clientX - this.__dd.x, e.clientY - this.__dd.y);
  }

  this.dd_drop = function() {
    document.onmousemove = null;
    document.onmouseup = null;
  }

  this.scroll_init = function(t,r,b,l) {
    this.__scroll.init = true;
    this.__scroll.t = t;
    this.__scroll.r = r;
    this.__scroll.b = b;
    this.__scroll.l = l;
    this.__scroll.org = this.x;
    this.__scroll.lim = this.x - this.w + this.__scroll.b;
    this.css.clip = "rect("+t+"px "+r+"px "+b+"px "+l+"px)";
  }

  this.scroll = function(x) {
    if (this.__scroll.init) {
      this.__scroll.x = x;
      this._scroll();
    }
  }
  this.scroll_stop = function() {
    if (this.__scroll.timeout != null) {
      window.clearTimeout(this.__scroll.timeout);
      this.__scroll.timeout = null;
    }
  }
  this._scroll = function() {
    if (this.x - this.__scroll.x >= this.__scroll.lim && this.x - this.__scroll.x <= this.__scroll.org) {
      this.__scroll.l += this.__scroll.x;
      this.__scroll.r += this.__scroll.x;
      this.move((-1 * this.__scroll.x), 0);
      this.css.clip = "rect("+this.__scroll.t+"px "+this.__scroll.r+"px "
                             +this.__scroll.b+"px "+this.__scroll.l+"px)";
      this.__scroll.timeout = window.setTimeout(this.ref+"._scroll()",this.__scroll.speed)
    }
    else {
      this.__scroll.timeout = null;
    }
  }
}
DHTMLObject.prototype = new SimpleObject;


