var Drag = {

  obj : null,
  ring : null,

  init : function(o, minX, maxX, minY, maxY, width, height, r, minXr, minYr, thumbWidth, thumbHeight, ringWidth, ringHeight )
  {
    o.onmousedown  = Drag.start;

    o.root = o;
    if ( r != null ) {
        r.root = r;
        Drag.ring = r;
    }
    o.ratio = thumbWidth / width;

    if (isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
    if (isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
    if (isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
    if (isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

    if ( r != null ) {
        if (isNaN(parseInt(r.root.style.left  ))) r.root.style.left   = minXr + "px";
        if (isNaN(parseInt(r.root.style.top   ))) r.root.style.top    = minYr + "px";
        if (isNaN(parseInt(r.root.style.right ))) r.root.style.right  = "0px";
        if (isNaN(parseInt(r.root.style.bottom))) r.root.style.bottom = "0px";
    }

    o.minX  = typeof minX != 'undefined' ? minX : null;
    o.minY  = typeof minY != 'undefined' ? minY : null;
    o.maxX  = typeof maxX != 'undefined' ? maxX : null;
    o.maxY  = typeof maxY != 'undefined' ? maxY : null;

    if ( r != null ) {
        r.minX  = typeof minXr != 'undefined' ? minXr + 1 : null;
        r.minY  = typeof minYr != 'undefined' ? minYr + 1 : null;
        r.maxX  = (typeof thumbWidth != 'undefined' && typeof ringWidth != 'undefined') ? minXr + thumbWidth - ringWidth + 2: null;
        r.maxY  = (typeof thumbHeight != 'undefined' && typeof ringHeight != 'undefined') ? minYr + thumbHeight - ringHeight + 2 : null;
    }

    o.minXa = o.maxX - width;
    o.maxXa = o.minX;
    o.minYa = o.maxY - height;
    o.maxYa = o.minY;

    o.style.clip = 'rect(0px,'+(o.maxX-o.minX)+'px,'+(o.maxY-o.minY)+'px,0px)'

    o.root.onDragStart  = new Function();
    o.root.onDragEnd  = new Function();
    o.root.onDrag    = new Function();
  },

  start : function(e)
  {
    var o = Drag.obj = this;
    var r = Drag.ring;
    e = Drag.fixE(e);
    var y = o.root.style.top;
    var x = o.root.style.left;
    var yr = o.root.style.top;
    var xr = o.root.style.left;
    o.root.onDragStart(x, y);

    o.lastMouseX  = e.clientX;
    o.lastMouseY  = e.clientY;

    document.onmousemove  = Drag.drag;
    document.onmouseup    = Drag.end;

    return false;
  },

  drag : function(e)
  {
    e = Drag.fixE(e);
    var o = Drag.obj;
    var r = Drag.ring;

    var ey  = e.clientY;
    var ex  = e.clientX;
    var y = o.root.style.top;
    var x = o.root.style.left;
    var yr = null;
    var xr = null;
    if ( r != null ) {
        yr = r.root.style.top;
        xr = r.root.style.left;
    }
    if ( !Drag.isNumeric(x) ) x = Drag.removePX(x);
    if ( !Drag.isNumeric(y) ) y = Drag.removePX(y);
    if ( r != null ) {
        if ( !Drag.isNumeric(xr) ) xr = Drag.removePX(xr);
        if ( !Drag.isNumeric(yr) ) yr = Drag.removePX(yr);
    }
    var nx, ny, nxr, nyr;

    nx = x + (ex - o.lastMouseX);
    ny = y + (ey - o.lastMouseY);

    if ( r != null ) {
        nxr = xr - (ex - o.lastMouseX)*o.ratio;
        nyr = yr - (ey - o.lastMouseY)*o.ratio;
    }

    nx = ((nx > o.maxXa ) ? o.maxXa : nx );
    nx = ((nx < o.minXa ) ? o.minXa : nx );
    ny = ((ny > o.maxYa ) ? o.maxYa : ny );
    ny = ((ny < o.minYa ) ? o.minYa : ny );

    if ( r != null ) {
        nxr = ((nxr > r.maxX ) ? r.maxX : nxr );
        nxr = ((nxr < r.minX ) ? r.minX : nxr );
        nyr = ((nyr > r.maxY ) ? r.maxY : nyr );
        nyr = ((nyr < r.minY ) ? r.minY : nyr );
    }

    Drag.obj.root.style["left"] = nx + "px";
    Drag.obj.root.style["top"] = ny + "px";
    Drag.obj.lastMouseX  = ex;
    Drag.obj.lastMouseY  = ey;

    if ( r != null ) {
        Drag.ring.root.style["left"] = nxr + "px";
        Drag.ring.root.style["top"] = nyr + "px";
    }

    Drag.obj.style.clip = 'rect('+(o.minY-ny)+'px,'+(o.maxX-nx)+'px,'+(o.maxY-ny)+'px,'+(o.minX-nx)+'px)'

    Drag.obj.root.onDrag(nx, ny);
    return false;
  },

  removePX : function(sText)
  {
    return parseFloat(sText.substr(0,sText.length-2));
  },

  isNumeric : function(sText)

  {
    var ValidChars = "0123456789.-";
    var IsNumber=true;
    var Char;


    for (i = 0; i < sText.length && IsNumber == true; i++)
    {
      Char = sText.charAt(i);
      if (ValidChars.indexOf(Char) == -1)
      {
        IsNumber = false;
      }
    }
    return IsNumber;

  },

  end : function()
  {
    document.onmousemove = null;
    document.onmouseup   = null;
    Drag.obj.root.onDragEnd(  parseInt(Drag.obj.root.style["left"]),
                  parseInt(Drag.obj.root.style["top"]));
    Drag.obj = null;
  },

  fixE : function(e)
  {
    if (typeof e == 'undefined') e = window.event;
    if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
    if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
    return e;
  }
};