<public:component lightweight="true">
<public:attach event="onmousedown" onevent="element_onmousedown()"/>
<public:attach event="onmousemove" onevent="element_onmousemove()"/>
<public:attach event="onmouseup" onevent="element_onmouseup()"/>
<public:attach event="onmouseout" onevent="element_onmouseup()"/>
<public:attach event="onselectstart" onevent="element_onselectstart()"/>
<public:attach event="ondragstart" onevent="element_ondragstart()"/>
<public:attach event="onload" for="window" onevent="Init()"/>
<public:method name="moveMe"/>
<public:property name="clickPoint" get="get_clickPoint" put="put_clickPoint"/>
<public:property name="interval" get="get_interval" put="put_interval"/>

<script language="JScript">
varm_bStarted = false;
varm_bMoving = false;

varm_clickPoint = null;
varm_tStart = 0;
varm_tEnd = 0;
varm_ptStart = null;
varm_Slope = null;
varm_interval = 0;
varm_isMoving = false;
varm_trash = 0;
varm_dX = 0; varm_dY = 0;
varm_vectX = 0; varm_vectY = 0;
varm_pNode = null;
varm_bounds = [];
var BOUNDS = {"left":0,"top":1,"right":2,"bottom":3};
varm_dimensions = [];
var DIMS = {"width":0,"height":1};

function Init() {
    element.id = element.document.uniqueId;
    varm_pNode = element.parentNode;
    m_bounds = [   
                0,
                0,
                parseInt(m_pNode.currentStyle.width),
                parseInt(m_pNode.currentStyle.height)
                ];
    m_dimensions = [
                parseInt(element.offsetWidth),
                parseInt(element.offsetHeight)
                ];
}

function element_onmousedown() {
    m_bStarted = true;
    m_tStart = new Date();
    clearInterval(m_interval);
    m_Slope = null;
    m_ptStart = null;
    m_trash = 0;
    m_dX = 0; m_dY = 0;
    m_vectX = 0; m_vectY = 0;
    m_clickPoint = new Point(event.x, event.y);
    m_ptStart = new Point(parseInt(element.currentStyle.left), parseInt(element.currentStyle.top));
}
function element_onmouseup() {
    if (!m_bMoving) return;
    m_bMoving = false; m_bStarted = false;
    m_tEnd = new Date();
    var t = m_tEnd.valueOf() - m_tStart.valueOf();
    varlPoint = new Point(event.x, event.y);
    m_Slope = Geometry.slope(m_clickPoint, lPoint);
    varptEnd = m_Slope.add(m_ptStart);
    element.style.left = ptEnd.posX + "px";
    element.style.top = ptEnd.posY + "px";
    varspd = 0;
    if (m_Slope.deltaX != 0 && m_Slope.deltaY != 0)
        spd = Math.sqrt(Math.pow(m_Slope.deltaX, 2) + Math.pow(m_Slope.deltaY,
2))/t;
    else
        spd = (m_Slope.deltaX + m_Slope.deltaY)/t;
    if (spd > 1) spd = 1;
    m_dX = m_Slope.deltaX;
    m_dY = m_Slope.deltaY;
    if (m_dX != 0) m_vectX = (m_dX > 0) ? 2 : -2;
    if (m_dY != 0) m_vectY = (m_dY > 0) ? 2 : -2;
    startMove(element, parseInt(1/spd));
}
function element_onmousemove() {
    m_bMoving = m_bStarted;
    if (!m_bMoving) return;
    varlPoint = new Point(event.x, event.y);
    varlSlope = Geometry.slope(m_clickPoint, lPoint);
    varptEnd = lSlope.add(m_ptStart);
    element.style.left = ptEnd.posX + "px";
    element.style.top = ptEnd.posY + "px";
}
function element_onselectstart() {
    event.returnValue = false;
    return false;
}
function element_ondragstart() {
    event.returnValue = false;
    return false;
}
function get_clickPoint() {
    return m_clickPoint;
}
function put_clickPoint(o) {
    if (typeof(o) == "object" && o.constructor == "Point") {
        m_clickPoint = o;
    } else {
        alert("Expected Point.");
    }
}
function get_interval() {
    return m_interval;
}
function put_interval(n) {
    m_interval = n;
}

function moveMe() {
    if (m_isMoving) return;
    setTimeout("m_isMoving = true;", 1);
    varnewX = parseInt(element.currentStyle.left);
    varnewY = parseInt(element.currentStyle.top);
    vardXabs = Math.abs(m_dX);
    vardYabs = Math.abs(m_dY);
    if (dXabs > dYabs) {
        //divide both by deltaX
        //each call move X by 1 and Y by Y/X
        //if iteration > 1, then move Y by 1
        //and add remainder back on Y
        newX += m_vectX;
        varl_step = (m_dY/m_dX) * 2;
        m_trash = m_trash + l_step;
        if (m_trash > 2 || m_trash < -2) {
            newY += m_vectY;
            m_trash -= m_vectX;
        }
    } else {
        //vice-versa
        newY += m_vectY;
        varl_step = (m_dX/m_dY) * 2;
        m_trash = m_trash + l_step;
        if (m_trash > 2 || m_trash < -2) {
            newX += m_vectX;
            m_trash -= m_vectX;
        }
    }
    if (newX <= m_bounds[BOUNDS.left]) {
        newX = m_bounds[BOUNDS.left] + 1;
        m_vectX *= -1;
    } else if ((newX + m_dimensions[DIMS.width]) >= m_bounds[BOUNDS.right]) {
        newX = m_bounds[BOUNDS.right] - m_dimensions[DIMS.width] - 1;
        m_vectX *= -1;
    }
    if (newY <= m_bounds[BOUNDS.top]) {
        newY = m_bounds[BOUNDS.top] + 1;
        m_vectY *= -1;
    } else if ((newY + m_dimensions[DIMS.height]) >= m_bounds[BOUNDS.bottom]) {
        newY = m_bounds[BOUNDS.bottom] - m_dimensions[DIMS.height] - 1;
        m_vectY *= -1;
    }
    element.style.left = newX + "px";
    element.style.top = newY + "px";
    setTimeout("m_isMoving = false;", 1);
}
</script>

</public:component>