/******************************************************************
 * DragBox.js
 *****************************************************************/

/******************************************************************
 * class DragBox
 *****************************************************************/
// Default speed and distance of movement
var stepSize  = 5;      // Largest movement increment in px
var stepSpeed = 30;     // Refresh delay (smaller=faster) DO NOT SET TO 0 {zero)
                        // 30 ms = 33 steps per second should look smooth.

// Timed movement debugging variables
var dragDebug = false;
var startTime = null;
var stopTime = null;

// Static registry
DragBox.REGISTRY = new Object();
var DragItem = DragBox.REGISTRY;

// z-index for dragable div items
DragBox.zIndex = 0;

function DragBox (id, content, allowMove, allowResize, allowClose) {
    if (DragBox.REGISTRY[id] === undefined) {
        this.init(id, content, allowMove, allowResize, allowClose);
    } else {
        return false;
    }
}

DragBox.prototype.init = function (id, content, allowMove, allowResize, allowClose) {
    if (!id) return;

    this.id = id;

    // Settings
    this.allowMove = (allowMove === undefined) ? true : allowMove;
    this.allowResize = (allowResize === undefined) ? true : allowResize;
    this.allowClose = (allowClose === undefined) ? true : allowClose;

    // Quick and dirty browser check method
    this.isIE = (document.all) ? true : false;
    if (this.isIE) {
        var detect = navigator.userAgent.toLowerCase();
        var string= "msie";
        var place = detect.indexOf(string) + 1;
        version = detect.charAt(place + string.length);
    }
    this.isIE7 = (this.isIE  && (version >= 7)) ? true : false;
    this.isNS = (!document.all && document.getElementById) ? true : false;

    // Create nodes and event handlers
    this.createContainer();

    // Link to div item
    this.node = document.getElementById(this.id);

    // don't insert until show() is called, save this content to be
    // reinserted if necessary on reshow after clearOnHide()
    this.content = content;
    this.empty = true;

    // Default setting for handling scrolled visible content area
    this.handleScroll = true;
    this.inMotion = false;

    // Timeout holder for motion effect
    this.timeout = null;

    // Hold information about motion that's in progress
    this.stepSize = stepSize;
    this.stepSpeed = stepSpeed;
    this.arrivalTime = null;
    this.subPixelX = 0;
    this.subPixelY = 0;

    // Holders for drag positioning
    this.cursorStartX = null;
    this.cursorStartY = null;
    this.elemntStartX = null;
    this.elemntStartY = null;

    // event triggers

    // set this to true if you want the box to automatically clear its
    // contents on hiding (e.g. to get IE to stop flash from playing)
    this.clearOnHide = false;

    // callback functions
    this.onHide = null;

    // Start with item hidden
    this.visible = false;
    this.hide();

    // register self
    this.register();
}

// Register self for lookups
DragBox.prototype.register = function () {
    DragBox.REGISTRY[this.id] = this;
    //alert("Registering drag instance with ID: '" + this.id + "'");
}

/**
 * callback functions must take one arg: the DragBox instance that is
 * making the callback.  Returns true iff the function is defined
 */
DragBox.prototype.callback = function (fn) {
    if (typeof fn == "function") {
        fn.call(null, this);
        return true;
    }
    return false;
}

// Show div instance
DragBox.prototype.show = function () {
    if (this.node) {
        // Insert content
        if (this.content && this.empty) {
            this.insertContent(this.content);
            this.empty = false;
        }
        this.node.style.display = "block";
        this.visible = true;


        // Update position (current style location) to use scroll handler if needed
        var x = this.currentX();
        var y = this.currentY();
        this.inMotion = false;
        this.setPosition(x, y);
    }
}

// Hide div instance
DragBox.prototype.hide = function () {
    if (this.node) {
        this.node.style.display = "none";
        this.visible = false;
        this.callback(this.onHide);
        if (this.clearOnHide) {
            this.clearContent();
            this.empty = true;
        }
    }
}

// Determine current X location
DragBox.prototype.currentX = function () {
    if (this.node) {
        var locX = parseInt(this.node.style.left, 10);
        if (isNaN(locX)) locX = this.node.offsetLeft;
        return locX;
    } else {
        return 0;
    }
}

// Determine current Y location
DragBox.prototype.currentY = function () {
    if (this.node) {
        var locY = parseInt(this.node.style.top, 10);
        if (isNaN(locY)) locY = this.node.offsetTop;
        return locY;
    } else {
        return 0;
    }
}

// Determine current width of parent div
DragBox.prototype.currentWidth = function () {
    if (this.node) {
        var w = parseInt(this.node.style.width, 10);
        if (isNaN(w)) w = this.node.offsetWidth;
        return w;
    } else {
        return 0;
    }
}

// Determine current height of parent div
DragBox.prototype.currentHeight = function () {
    if (this.node) {
        var h = parseInt(this.node.style.height, 10);
        if (isNaN(h)) h = this.node.offsetHeight;
        return h;
    } else {
        return 0;
    }
}

// Stop any ongoing movement
DragBox.prototype.stop = function () {
    clearTimeout(this.timeout);
    this.timeout = null;
    this.arrivalTime = null;
    this.subPixelX = 0;
    this.subPixelY = 0;
}

// Increase z-index to push item to top
DragBox.prototype.raise = function () {
    this.node.style.zIndex = ++DragBox.zIndex;
}

// Move instantly to the specified location
DragBox.prototype.snapTo = function (x, y) {
    if (x === undefined || y === undefined || !this.node) { return; }
    this.stop();
    this.raise();

    this.inMotion = true;
    temp = setTimeout("DragItem['" + this.id + "'].setPosition(" + x + "," + y + ")", 35);

    //this.setPosition(x,y);
    //xxx
    //this.node.style.left = x + "px";
    //this.node.style.top = y + "px";
}

// Slide to specified location
DragBox.prototype.moveTo = function (x, y, delay) {
    if (x === undefined || y === undefined || !this.node) { return; }
    this.stop();
    this.raise();
    if (x == this.currentX() && y == this.currentY()) return;

    // If hidden, ignore any timing and move immediately
    if (this.node.style.display == "none") {
        this.snapTo(x, y);
        return;
    }

    if (this.isIE && !this.isIE7) {
        this.inMotion = true;
        var sLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
        var sTop  = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
        x = x + sLeft;
        y = y + sTop;
    }

    if (delay !== undefined) {
        // Keep track of when the movement is supposed to be finished.
        this.arrivalTime = new Date().getTime() + delay;
        // Determine how often we need to move to achieve this
        this.stepSpeed = this.timedStepSpeed (x, y, delay);
    } else {
        this.arrivalTime = null;
        this.stepSpeed = stepSpeed; // default speed
    }

    if (dragDebug) {
        startTime = new Date().getTime();
    }

    // Set timeout for appropriate speed
    this.timeout = setTimeout("DragItem['" + this.id + "'].slideTo(" + x + "," + y + ")",
                              this.stepSpeed);

}

// Slide by specified direction/distance
DragBox.prototype.moveBy = function (x, y, delay) {
    this.moveTo (this.currentX() + x, this.currentY() + y, delay);
}

//Slide relative to a given object
// id - object to place item in relation (specify ID of target object)
// x  - vertical distance offset
// y  - horizontal distance offset
// v  - vertical relation (top, middle, bottom)
// h  - horizontal relation (left, center, right)
// delay - time over which to move item
DragBox.prototype.moveRelative = function (id, x, y, h, v, delay) {
    if (!document.getElementById(id)) {
		alert ("no such target element: " + id);
		return;
	}

	var destination = this.calculateDestination (id, x, y, h, v);
    this.moveTo (destination[0], destination[1], delay);
}

// Return (X, Y) for relative movement
DragBox.prototype.calculateDestination = function (id, x, y, h, v) {
    // Determine coordinates of target object
    var targetItem = targetCoords(id);
    if (targetItem == false) return;

    var myWidth  = parseInt(this.node.style.width, 10);
    if (isNaN(myWidth)) { myWidth = this.node.offsetWidth; }

    var myHeight = parseInt(this.node.style.height, 10);
    if (isNaN(myHeight)) { myHeight = this.node.offsetHeight; }

    switch (h) {
        case "left":   { // align my right edge with target's left edge
            targetX = targetItem.targetLeft - myWidth;   break; }
        case "center": { // align centers
            targetX = targetItem.targetCenter - myWidth/2; break; }
        case "right":  {
            targetX = targetItem.targetRight;  break; }
        default:  return; // invalid mode
    }
    switch (v) {
        case "top":    { // align my bottom with target's top
            targetY = targetItem.targetTop - myHeight;      break; }
        case "middle": {
            targetY = targetItem.targetMiddle - myHeight/2; break; }
        case "bottom": {
            targetY = targetItem.targetBottom;              break; }
        default: return; // invalid mode
    }
	return new Array(targetX+x, targetY+y);
}

// Determine step timing for moving to the given coordinates in the given amount of time
DragBox.prototype.timedStepSpeed = function (x, y, delay) {

    var distance = Math.max (Math.abs(this.currentX()-x), Math.abs(this.currentY()-y));

    // At default step speed, how many steps?
    var steps = delay / stepSpeed;

    // Are there more steps than pixels?
    if (steps > distance) {
        // if so, give a slower step speed, so movement will be 1 pixel at a time.
        return (delay/distance);
    }
    // otherwise return default speed and let distance be adjusted.
    return stepSpeed;
}

// Called by timeout() to animate the slide to specified location
DragBox.prototype.slideTo = function (x, y) {
    if (!this.node) {
        return;
    }

    // Current location.  We keep track of sub-pixel location to make movement smoother.
    var currX = this.currentX() + this.subPixelX;
    var currY = this.currentY() + this.subPixelY;

    // Where to go in this step
    var newX;
    var newY;

    // Do we have a target arrival time?
    if (this.arrivalTime != null) {

        // How many more steps will there be?
        var stepsRemaining = Math.floor((this.arrivalTime - new Date().getTime()) / this.stepSpeed);
        if (stepsRemaining <= 0) {
            // we should be there already
            newX = x;
            newY = y;
        } else {
            // Move part way, based on number of steps left
            newX = currX + (x-currX)/stepsRemaining;
            newY = currY + (y-currY)/stepsRemaining;
        }

    } else {
        // How far do we have to go?
        var totalDist = Math.sqrt ((x-currX)*(x-currX) + (y-currY)*(y-currY));

        // Move by standard amount divided among X and Y directions
        var moveX = (x-currX) * this.stepSize/totalDist;
        var moveY = (y-currY) * this.stepSize/totalDist;

        // But make sure we don't overshoot
        if (Math.abs(moveX)>Math.abs(x-currX)) {
            newX = x;
        } else {
            newX = currX + moveX;
        }

        // Don't overshoot Y either
        if (Math.abs(moveY)>Math.abs(y-currY)) {
            newY = y;
        } else {
            newY = currY + moveY;
        }
    }

    this.node.style.left = Math.floor(newX) + "px";
    this.node.style.top  = Math.floor(newY) + "px";

    this.subPixelX = newX-Math.floor(newX);
    this.subPixelY = newY-Math.floor(newY);


    // If not at final coords, call slideTo() again for next coords step
    if ((newX != x) || (newY != y )) {
        this.timeout = setTimeout("DragItem['" + this.id + "'].slideTo(" + x + "," + y + ")",
                                  this.stepSpeed);
    } else {
        this.stop();
        if (this.isIE && !this.isIE7 && this.handleScroll) {
            this.inMotion = false;
            this.updatePosition(x, y, true);
        }
        if (dragDebug) {
            stopTime = new Date().getTime();
            alert("stepSpeed= " + this.stepSpeed + "ms; time=" + (stopTime-startTime)/1000 + "s");
        }
    }
}

// Create the parent container and child elements
DragBox.prototype.createContainer = function () {
    // Create parent node div
    var parentDiv = document.createElement("DIV");
    parentDiv.setAttribute("id", this.id, 0);
    parentDiv.className = "dragparent";

    if (this.allowMove || this.allowClose) {
        // Add keyboard accessible item
        var accessA = document.createElement("A");
        accessA.setAttribute("href", "#" + this.id, 0);
        accessA.className = "dragtabpop";
        parentDiv.appendChild(accessA);

        // Show tab controls on keyboard nav
        accessA.onfocus = function() {
            this.parentNode.className += (this.parentNode.className.length>0? " ": "") + "draghover";
        }

        // Create tab controls
        var controlDiv = document.createElement("DIV");
        controlDiv.className = "dragtab";
    }

    if (this.allowMove) {
        // Add movement tab
        var moveDiv = document.createElement("DIV");
        moveDiv.className = "dragmove";
        controlDiv.appendChild(moveDiv);
        //moveDiv.innerHTML = "Move";
        // Add move link to move tab
        var moveA = document.createElement("A");
        //moveA.setAttribute("href", "#", 0);
        moveA.setAttribute("href", "javascript:void(0);", 0);
        moveA.setAttribute("onclick", "javascript:return false;", 0);
        moveA.setAttribute("onmouseover", "javascript:window.status=''; return true;", 0);
        moveA.className = "dragmovelink";
        moveA.innerHTML = "Move";
        moveDiv.appendChild(moveA);

        // Add drag handler to move tab
        moveA.onmousedown = dragStart;
        //if (moveDiv.captureEvents) moveDiv.captureEvents(Event.MOUSEDOWN);

        // Add keyboard drag handler to move tab
        moveA.onkeydown = keyMove;

        // Hide tab controls on keyboard nav
        if (!this.allowClose) {
            moveA.onblur = function() {
                this.parentNode.parentNode.parentNode.className = this.parentNode.parentNode.parentNode.className.replace(new RegExp("( ?|^)draghover\\b"), "");
            }
        }
    }

    if (this.allowClose) {
        // Add close tab
        var closeDiv = document.createElement("DIV");
        closeDiv.className = "dragclose";
        controlDiv.appendChild(closeDiv);
        // Add close link to close tab
        var closeA = document.createElement("A");
        closeA.setAttribute("href", "javascript:DragItem['" + this.id + "'].hide();", 0);
        closeA.setAttribute("onmouseover", "javascript:window.status=''; return true;", 0);
        closeA.className = "dragcloselink";
        closeA.innerHTML = "X";
        closeDiv.appendChild(closeA);

        // Add click handler to close tab
        //closeDiv.onclick = function() {
        //    DragItem[this.parentNode.parentNode.id].hide();
        //}

        // Hide tab controls on keyboard nav
        closeA.onblur = function() {
            this.parentNode.parentNode.parentNode.className = this.parentNode.parentNode.parentNode.className.replace(new RegExp("( ?|^)draghover\\b"), "");
        }
    }

    if (this.allowMove || this.allowClose) {
        // Add tab controls to parent div
        parentDiv.appendChild(controlDiv);
    }

    // Add content container
    var contentDiv = document.createElement("DIV");
    contentDiv.setAttribute("id", this.id + "content", 0);
    contentDiv.className = "dragcontent";
    parentDiv.appendChild(contentDiv);

    // Show/hide tab controls on mouseover/mouseout
    parentDiv.onmouseover = function() {
        this.className += (this.className.length > 0 ? " " : "") + "draghover";
    }
    parentDiv.onmouseout = function() {
        this.className = this.className.replace(new RegExp("( ?|^)draghover\\b"), "");
    }

    // Insert new item into document
    document.body.appendChild(parentDiv);
}

// Insert/update content in specified item, returning previous
// contents for saving if desired
DragBox.prototype.insertContent = function (content) {
    if (content === undefined) return;
    if (this.node) {
        var contentElt = document.getElementById(this.id + 'content');
        if (contentElt) {
            var oldContent = contentElt.innerHTML;
            contentElt.innerHTML = content;
            return oldContent;
        }
    }
    return null;
}

// clear out content from specified item, returning previous contents
// for saving if desired
DragBox.prototype.clearContent = function () {
    return this.insertContent("");
}

// Update content in movement control tab
DragBox.prototype.updateMoveTab = function (content) {
    if (content === undefined) return;
    if (this.node) {
        var subEls = this.node.getElementsByTagName("A");
        for (var i=0; i < subEls.length; i++) {
            if (subEls[i].className.indexOf("dragmovelink") >= 0) {
                subEls[i].innerHTML = content;
            }
        }
    }
}

// Update content in close control tab
DragBox.prototype.updateCloseTab = function (content) {
    if (content === undefined) return;
    if (this.node) {
        var subEls = this.node.getElementsByTagName("A");
        for (var i=0; i < subEls.length; i++) {
            if (subEls[i].className.indexOf("dragcloselink") >= 0) {
                subEls[i].innerHTML = content;
            }
        }
    }
}

// Update parent container position and handle scrolling if set
DragBox.prototype.setPosition = function (x, y) {
    if (this.handleScroll) {
        if (this.isIE && !this.isIE7) {
            this.node.style.position = "absolute";
            this.inMotion = false;
            this.updatePosition(x, y);
        } else {
            this.node.style.position = "fixed";
            this.node.style.left = x + "px";
            this.node.style.top = y + "px";
        }
    } else {
        this.node.style.position = "absolute";
        this.node.style.left = x + "px";
        this.node.style.top = y + "px";
    }
}

// Looping function to keep agent positioned in IE
DragBox.prototype.updatePosition = function (x, y, ignoreScroll) {
    var sLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
    var sTop  = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;

    if (!ignoreScroll) {
        var newX = sLeft + x;
        var newY = sTop + y;
    } else {
        var newX = x;
        var newY = y;
        x = x - sLeft;
        y = y - sTop
    }

    this.node.style.left = newX + "px";
    this.node.style.top = newY + "px";

    if (!this.inMotion && this.handleScroll) {
        temp = setTimeout("DragItem['" + this.id + "'].updatePosition(" + x + "," + y + ")", 30);
    }
}

// Determine if item is contained within an array
// Snippet from:  http://andrew.hedges.name/experiments/javascript_optimization/in_array.html
// Further modifications found in comments at: http://code.mikebrittain.com/?p=8
Array.prototype.in_array_minus = function (search_term) {
   var i = this.length;
   do {
      if (this[i] === search_term) {
         return true;
      }
   } while (i--);
   return false;
}

// -------------------------------------- set callbacks

// must set explicitly false or result is true
DragBox.prototype.setClearOnHide = function (bool) {
    this.clearOnHide = (bool === false ? false : true);
}

// -------------------------------------- set callbacks

DragBox.prototype.setOnHide = function (fn) {
    this.onHide = fn;
};



/******************************************************************
 * Drag controls - hooks to div, not the object - does use object for some value lookups
 *****************************************************************/
var DragNode = null;
var DragObject = null;

function dragStart(e, divID) {
    var x, y;

    if (!e) var e = window.event;

    // Attach to div, with hook to drag object
    if (divID) {
        DragNode = document.getElementById(divID);
        DragObject = DragItem[divID];
    } else {
        if (e.srcElement) {
            DragObject = DragItem[e.srcElement.parentNode.parentNode.parentNode.id];
            DragNode = e.srcElement.parentNode.parentNode.parentNode;
        }
        if (e.target) {
            DragObject = DragItem[e.target.parentNode.parentNode.parentNode.id];
            DragNode = e.target.parentNode.parentNode.parentNode;
        }
    }

    // Set flag to indicate the object is currently being dragged
    if (DragObject.isIE && !DragObject.isIE7) {
        DragObject.inMotion = true;
    }

    // Get mouse pointer position within the page
    if (DragObject.isIE) {
        x = e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
        y = e.clientY + document.documentElement.scrollTop + document.body.scrollTop;
    }
    if (DragObject.isNS) {
        x = e.clientX + window.scrollX;
        y = e.clientY + window.scrollY;
    }

    // Save starting positions of cursor and element.
    DragObject.cursorStartX = x;
    DragObject.cursorStartY = y;
    DragObject.elStartLeft  = parseInt(DragNode.style.left, 10);
    DragObject.elStartTop   = parseInt(DragNode.style.top,  10);

    if (isNaN(DragObject.elStartLeft)) DragObject.elStartLeft = DragNode.offsetLeft;
    if (isNaN(DragObject.elStartTop))  DragObject.elStartTop  = DragNode.offsetTop;

    if (isNaN(DragObject.elStartLeft)) DragObject.elStartLeft = 0;
    if (isNaN(DragObject.elStartTop))  DragObject.elStartTop  = 0;

    // Increase z-index to push item on top of other elements
    DragNode.style.zIndex = ++DragBox.zIndex;

    // Capture mousemove and mouseup events on the page.
    if (DragObject.isIE) {
        document.attachEvent("onmousemove", dragGo);
        document.attachEvent("onmouseup",   dragStop);
        e.cancelBubble = true;
        e.returnValue = false;
    }
    if (DragObject.isNS) {
        document.addEventListener("mousemove", dragGo,   true);
        document.addEventListener("mouseup",   dragStop, true);
        e.preventDefault();
    }
}

function dragGo(e) {
    var x, y;

    if (!e) var e = window.event;

    // Get cursor position with respect to the page.
    if (DragObject.isIE) {
        x = e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
        y = e.clientY + document.documentElement.scrollTop + document.body.scrollTop;
    }
    if (DragObject.isNS) {
        x = e.clientX + window.scrollX;
        y = e.clientY + window.scrollY;
    }

    // Move drag element by the same amount the cursor has moved.
    DragNode.style.left = (DragObject.elStartLeft + x - DragObject.cursorStartX) + "px";
    DragNode.style.top  = (DragObject.elStartTop  + y - DragObject.cursorStartY) + "px";

    if (DragObject.isIE) {
        e.cancelBubble = true;
        e.returnValue = false;
    }
    if (DragObject.isNS) {
        e.preventDefault();
    }
}

function dragStop(divID) {
    // Stop capturing mousemove and mouseup events.
    if (DragObject.isIE) {
        document.detachEvent("onmousemove", dragGo);
        document.detachEvent("onmouseup",   dragStop);
    }
    if (DragObject.isNS) {
        document.removeEventListener("mousemove", dragGo,   true);
        document.removeEventListener("mouseup",   dragStop, true);
    }

    // Unset flag to indicate the object is no longer being dragged
    // Also restart IE position updater
    if (DragObject.isIE && !DragObject.isIE7 && DragObject.handleScroll) {
        DragObject.inMotion = false;
        DragObject.updatePosition(DragObject.currentX(), DragObject.currentY(), true);
    }
}

/******************************************************************
 * Keyboard (accessible) movement/resize controls
 *****************************************************************/
// Animate the slide to specified location
function keyMove(e) {
    if (!e) var e = window.event;

    // Attach to div, with hook to drag object
    if (e.srcElement) {
        DragObject = DragItem[e.srcElement.parentNode.parentNode.parentNode.id];
        DragNode = e.srcElement.parentNode.parentNode.parentNode;
    }
    if (e.target) {
        DragObject = DragItem[e.target.parentNode.parentNode.parentNode.id];
        DragNode = e.target.parentNode.parentNode.parentNode;
    }

    var key = null;
    if (DragObject.isIE) {
        key = e.keyCode;
    }
    if (DragObject.isNS) {
        key = e.which;
    }

    key = "" + key;
    switch(key) {
        case '37': {
            // Left
            DragObject.moveBy(-stepSize,0);
            break;
        }
        case '38': {
            // Up
            DragObject.moveBy(0,-stepSize);
            break;
        }
        case '39': {
            // Right
            DragObject.moveBy(stepSize,0);
            break;
        }
        case '40': {
            // Down
            DragObject.moveBy(0,stepSize);
            break;
        }
        default: {
            // Do nothing if not understood
            break;
        }
    }
}

/******************************************************************
 * Determine coordinate items of a given target object
 *****************************************************************/

 // Class: targetObject
function targetObject() {
    this.targetTop = null;
    this.targetBottom = null;
    this.targetMiddle = null;
    this.targetCenter = null;
    this.targetRight = null;
    this.targetLeft = null;
}

function targetCoords(objectID) {
    if (!document.getElementById(objectID)) return false;

    var targetNode = document.getElementById(objectID);
    var targetResults = new targetObject();

    // Top
    var tempTop = parseInt(targetNode.style.top, 10);
    if (isNaN(tempTop)) tempTop = targetNode.offsetTop;
    targetResults.targetTop = tempTop;

    // Left
    var tempLeft = parseInt(targetNode.style.left, 10);
    if (isNaN(tempLeft)) tempLeft = targetNode.offsetLeft;
    targetResults.targetLeft = tempLeft;

    // Right
    var tempWidth = parseInt(targetNode.style.width, 10);
    if (isNaN(tempWidth)) tempWidth = targetNode.offsetWidth;
    targetResults.targetRight = tempLeft + tempWidth;

    // Bottom
    var tempHeight = parseInt(targetNode.style.height, 10);
    if (isNaN(tempHeight)) tempHeight = targetNode.offsetHeight;
    targetResults.targetBottom = tempTop + tempHeight;

    // Center
    var tempCenter = parseInt(tempWidth / 2, 10);
    targetResults.targetCenter = tempLeft + tempCenter;

    // Middle
    var tempMiddle = parseInt(tempHeight /2, 10);
    targetResults.targetMiddle = tempTop + tempMiddle;

    if (dragDebug) {
        alert("Top: " + targetResults.targetTop + "\n" +
          "Right: " + targetResults.targetRight + "\n" +
          "Bottom: " + targetResults.targetBottom + "\n" +
          "Left: " + targetResults.targetLeft + "\n" +
          "Center: " + targetResults.targetCenter + "\n" +
          "Middle: " + targetResults.targetMiddle + "\n"
         );
    }

    return targetResults;
}
