var oBox = {
    bTrace: false,
    sWaitImgId: null,
    sWaitImgLoc: null,
    bDrawingEnabled: true, 
    bInSuspense: false,
    fnOnClick: null, 
    fnOnDrawEnd: null, 
    sLineTransparentImg: 'images/transparent.gif', 
    sLineColor: "#FF0000", 
    iLineThickness: 2, 
    iMouseJitter: null,
    iCrossHairSize: 10, 
    aMap: [], 
    oCurMap: null, 
        oMouse: {iLastX: -1, 
             iLastY: 0,
             iCurX:0,
             iCurY:0},

        oNewCrossHairDown: {iX: null, iY: null}, 
    oBound: {iStartX:0, iStartY:0, iEndX:0, iEndY:0}, 
    bAdjustingBox: false, 
    oLeftBorder: null,
    oRightBorder: null,
    oTopBorder: null,
    oBottomBorder: null,
    getObj: function(sName) {
        var oObj = ((document.all && !window.opera)
                    ? document.all[sName]
                    : (document.getElementById
                       ? document.getElementById(sName)
                       : eval('document.' + sName)));
        if (typeof(oObj) == 'undefined') {
            alert('Error(oBox): ' + sName + ' not found!');
        }
        return oObj;
    },
    showObj: function(oObj) {
        if (oObj.visibility) {
            oObj.visibility = 'visible';
        } else if (oObj.style) {
            oObj.style.visibility = 'visible';
        }
        return true;
    },
    hideObj: function(oObj) {
        if (oObj.visibility) {
            oObj.visibility = 'hidden';
        } else if (oObj.style) {
            oObj.style.visibility = 'hidden';
        }
        return true;
    },
    getWidth: function(oObj) {
        return ((oObj.offsetWidth)
                ?                   oObj.offsetWidth
                : ((oObj.style && oObj.style.pixelWidth)
                   ?                      oObj.style.pixelWidth
                   : ((oObj.clip && oObj.clip.right)
                      ?                         oObj.clip.right
                      : '0')));
    },
    getHeight: function(oObj) {
        return ((oObj.offsetHeight)
                ?                   oObj.offsetHeight
                : ((oObj.style && oObj.style.pixelHeight)
                   ?                      oObj.style.pixelHeight
                   : ((oObj.clip && oObj.clip.bottom)
                      ?                         oObj.clip.bottom
                      : '0')));
    },
    moveLine: function(oLine, iLeft, iTop) {
        if (oLine.style) {
            if (typeof(oLine.style.left) == 'string') {
                oLine.style.left = iLeft + 'px';
                oLine.style.top = iTop + 'px';
            } else if (typeof(oLine.style.pixelLeft) != 'undefined') {
                oLine.style.pixelLeft = iLeft + 'px';
                oLine.style.pixelTop = iTop + 'px';
            }
        } else if (typeof(oLine.left) != 'undefined') {
            oLine.left = iLeft;
            oLine.top = iTop;
        }
        return true;
    },
    clipLine: function(oLine, iTop, iRight, iBottom, iLeft) {
        if (oLine.style &&
            (typeof(oLine.style.clip) != 'undefined')) {
            
            oLine.style.clip = 'rect(' + iTop + 'px ' +
                                        iRight + 'px ' +
                                        iBottom + 'px ' +
                                        iLeft + 'px)';
        } else if (typeof(oLine.clip) != 'undefined') {
            
            oLine.clip.top = iTop;
            oLine.clip.right = iRight;
            oLine.clip.bottom = iBottom;
            oLine.clip.left = iLeft;
        }
        return true;
    },
    newCursorPos: function(evt) {
        if (oBox.bInSuspense) {
            return true;
        }
        if (oBox.cursorInWin(evt)) {
            oBox.oMouse.iLastX = ((evt)
                                 ? evt.pageX
                                 : event.clientX +
                                   ((document.compatMode == "CSS1Compat")
                                    ? document.documentElement.scrollLeft
                                    : document.body.scrollLeft));
            oBox.oMouse.iLastY = ((evt)
                                 ? evt.pageY
                                 : event.clientY +
                                   ((document.compatMode == "CSS1Compat")
                                    ? document.documentElement.scrollTop
                                    : document.body.scrollTop));
                        if (oBox.bTrace) {
                window.status = ((oBox.oCurMap)
                                 ? "Map (" + oBox.oCurMap.sName + "): " +
                                   oBox.oCurMap.iLeft + ',' + oBox.oCurMap.iTop +
                                   ", "
                                 : "") +
                                "Mouse: " + oBox.oMouse.iLastX + "," +
                                oBox.oMouse.iLastY;
            }
        }
        return true;
    },
    getCurMap: function(iCursorX, iCursorY) {
        var oCurMap = null;
        for (var i=0; i<oBox.aMap.length; i++) {
            if ((iCursorX >= oBox.aMap[i].iLeft) &&
                (iCursorX <= oBox.aMap[i].iRight) &&
                (iCursorY >= oBox.aMap[i].iTop) &&
                (iCursorY <= oBox.aMap[i].iBottom)) {
                oCurMap = oBox.aMap[i];
                break;
            }
        }
        return oCurMap;
    },

        cursorInWin: function(evt) {
        var bInWin = false;
        if (evt) {
                        iScreenX = evt.pageX - window.pageXOffset;
            iScreenY = evt.pageY - window.pageYOffset;
            iWinWidth = document.body.clientWidth;
            iWinHeight = document.body.clientHeight;
            bInWin = ((iScreenX <= iWinWidth) && (iScreenY <= iWinHeight));
        } else {
                        iScreenX = event.clientX;
            iScreenY = event.clientY;
            iWinWidth = ((document.compatMode == "CSS1Compat")
                         ? document.documentElement.clientWidth
                         : document.body.clientWidth);
            iWinHeight = ((document.compatMode == "CSS1Compat")
                          ? document.documentElement.clientHeight
                          : document.body.clientHeight);
            bInWin = ((iScreenX >= 0) &&
                      (iScreenX <= iWinWidth) &&
                      (iScreenY >= 0) &&
                      (iScreenY <= iWinHeight));
        }
        return bInWin;
    },
    startBox: function(evt) {
        if (oBox.bInSuspense) {
            return true;
        }
        var bBubbleEvent = true;
        if (oBox.cursorInWin(evt)) {
            if (oBox.oMouse.iLastX < 0) {
                oBox.newCursorPos(evt);
            }
            if (oBox.bDrawingEnabled) {
                oBox.oCurMap = oBox.getCurMap(oBox.oMouse.iLastX, oBox.oMouse.iLastY);
                if (oBox.oCurMap) {
                    oBox.bAdjustingBox = true;
                    oBox.oMouse.iCurX = oBox.oBound.iStartX = oBox.oMouse.iLastX;
                    oBox.oMouse.iCurY = oBox.oBound.iStartY = oBox.oMouse.iLastY;
                    oBox.drawCrossHair(oBox.iLineThickness, oBox.iCrossHairSize,
                                      oBox.oMouse.iCurX, oBox.oMouse.iCurY);
                    document.onmousemove = oBox.makeBox;

                                        bBubbleEvent = false;
                }
            } else {
                oBox.oNewCrossHairDown.iX = oBox.oMouse.iLastX;
                oBox.oNewCrossHairDown.iY = oBox.oMouse.iLastY;
            }
        }
        return bBubbleEvent;
    },
    endBox: function(evt) {
        if (oBox.bInSuspense) {
            return true;
        }
        var oMap = oBox.oCurMap;
        if (oMap &&
            (oBox.oMouse.iLastX >= oMap.iLeft) &&
            (oBox.oMouse.iLastX <= oMap.iRight) &&
            (oBox.oMouse.iLastY >= oMap.iTop) &&
            (oBox.oMouse.iLastY <= oMap.iBottom)) {
            oBox.bAdjustingBox = false;
            oBox.oBound.iEndX = oBox.oMouse.iCurX - oMap.iLeft;
            oBox.oBound.iEndY = oBox.oMouse.iCurY - oMap.iTop;
            oBox.oBound.iStartX -= oMap.iLeft;
            oBox.oBound.iStartY -= oMap.iTop;
            document.onmousemove = oBox.newCursorPos;

            oBox.oBound.iStartX -=  oBox.iLineThickness;
            oBox.oBound.iStartY -=  oBox.iLineThickness;
            oBox.oBound.iEndX -=  oBox.iLineThickness;
            oBox.oBound.iEndY -=  oBox.iLineThickness;
            if ((oBox.oBound.iStartX == oBox.oBound.iEndX) &&
                (oBox.oBound.iStartY == oBox.oBound.iEndY)) {
                if (!oBox.bInSuspense && oBox.fnOnClick) {
                    
                    var oParam = {
                        sMapName: oBox.oCurMap.sName,
                        oCursor: {

                                                        iX:                                 ((evt)
                                 ? evt.pageX
                                 : event.clientX +
                                   ((document.compatMode == "CSS1Compat")
                                    ? document.documentElement.scrollLeft
                                    : document.body.scrollLeft)),

                            iY:                                 ((evt)
                                 ? evt.pageY
                                 : event.clientY +
                                   ((document.compatMode == "CSS1Compat")
                                    ? document.documentElement.scrollTop
                                    : document.body.scrollTop))
                            
                        }
                    }
                    oBox.fnOnClick(oParam);
                }
            } else {
                if (!oBox.bInSuspense && oBox.fnOnDrawEnd) {
                    
                    var oParam = {
                        sMapName: oBox.oCurMap.sName,
                        oBound: oBox.oBound
                    }
                    oBox.fnOnDrawEnd(oParam);
                }
            }
        }
        return true;
    },
    newCrossHair: function(evt) {
        if (oBox.bInSuspense) {
            return true;
        }
        var bBubbleEvent = true;
        var iX = ((evt)
                  ? evt.pageX
                  : event.clientX +
                    ((document.compatMode == "CSS1Compat")
                     ? document.documentElement.scrollLeft
                     : document.body.scrollLeft));
        var iY = ((evt)
                  ? evt.pageY
                  : event.clientY +
                    ((document.compatMode == "CSS1Compat")
                     ? document.documentElement.scrollTop
                     : document.body.scrollTop));
        oBox.oCurMap = oBox.getCurMap(iX, iY);
        if (oBox.oCurMap &&
            ((Math.abs(iX - oBox.oNewCrossHairDown.iX) < oBox.iMouseJitter) &&
             (Math.abs(iY - oBox.oNewCrossHairDown.iY) < oBox.iMouseJitter))) {
            oBox.drawCrossHair(oBox.iLineThickness, oBox.iCrossHairSize, iX, iY);
            if (!oBox.bInSuspense && oBox.fnOnClick) {
                
                var oParam = {
                    sMapName: oBox.oCurMap.sName,
                    oCursor: {
                        iX: iX,
                        iY: iY
                    }
                }
                oBox.fnOnClick(oParam);
            }
            bBubbleEvent = false;
        }
        return bBubbleEvent;
    },
    makeBox: function(evt) {
        var oMap = oBox.oCurMap;
        if (oBox.cursorInWin(evt) &&
            oMap &&
            oBox.bAdjustingBox) {
            var oMapAnchor = oMap.oAnchor;
            oBox.oMouse.iCurX = ((evt)
                                ? evt.pageX
                                : event.clientX +
                                  ((document.compatMode == "CSS1Compat")
                                   ? document.documentElement.scrollLeft
                                   : document.body.scrollLeft));
            oBox.oMouse.iCurX = ((oBox.oMouse.iCurX < oMap.iLeft)
                                ? oMap.iLeft
                                : ((oBox.oMouse.iCurX > oMap.iRight)
                                   ? oMap.iRight
                                   : oBox.oMouse.iCurX));
            oBox.oMouse.iCurY = ((evt)
                                ? evt.pageY
                                : event.clientY +
                                  ((document.compatMode == "CSS1Compat")
                                   ? document.documentElement.scrollTop
                                   : document.body.scrollTop));
            oBox.oMouse.iCurY = ((oBox.oMouse.iCurY < oMap.iTop)
                                ? oMap.iTop
                                : ((oBox.oMouse.iCurY > oMap.iBottom)
                                   ? oMap.iBottom
                                   : oBox.oMouse.iCurY));
            var iBoxWidth = ((oBox.oBound.iStartX > oBox.oMouse.iCurX)
                             ? oBox.oBound.iStartX - oBox.oMouse.iCurX
                             : oBox.oMouse.iCurX - oBox.oBound.iStartX);
            var iBoxHeight = ((oBox.oBound.iStartY > oBox.oMouse.iCurY)
                              ? oBox.oBound.iStartY - oBox.oMouse.iCurY
                              : oBox.oMouse.iCurY - oBox.oBound.iStartY);
            if ((iBoxWidth > oBox.iMouseJitter) || (iBoxHeight > oBox.iMouseJitter)) {
                var iBoxLeft = ((oBox.oBound.iStartX < oBox.oMouse.iCurX)
                                ? oBox.oBound.iStartX
                                : oBox.oMouse.iCurX);
                var iBoxTop = ((oBox.oBound.iStartY < oBox.oMouse.iCurY)
                               ? oBox.oBound.iStartY
                               : oBox.oMouse.iCurY);
                oBox.drawBox(oBox.iLineThickness, iBoxLeft, iBoxTop,
                            iBoxWidth, iBoxHeight);
            } else {
                oBox.oMouse.iCurX = oBox.oBound.iEndX = oBox.oBound.iStartX;
                oBox.oMouse.iCurY = oBox.oBound.iEndY = oBox.oBound.iStartY;
                oBox.drawCrossHair(oBox.iLineThickness, oBox.iCrossHairSize,
                                  oBox.oMouse.iCurX, oBox.oMouse.iCurY);
            }
        }
        return false;
    },
    drawBox: function(iLineThickness,
                      iBoxPosX, iBoxPosY,
                      iBoxWidth, iBoxHeight) {
        if (oBox.bTrace) {
            document.title = 'Box at ' + iBoxPosX + ',' + iBoxPosY + ' (w:' +
                            iBoxWidth + ',h:' +
                            iBoxHeight + ')';
        }
        var oLeft = oBox.oLeftBorder;
        var oRight = oBox.oRightBorder;
        var oTop = oBox.oTopBorder;
        var oBottom = oBox.oBottomBorder;

                oBox.resizeLine(oLeft, iLineThickness, iBoxHeight);
        oBox.resizeLine(oRight, iLineThickness, iBoxHeight);
        oBox.resizeLine(oTop, iBoxWidth, iLineThickness);
        oBox.resizeLine(oBottom, iBoxWidth, iLineThickness);

                oBox.moveLine(oLeft, iBoxPosX - iLineThickness,
                            iBoxPosY - iLineThickness);
        oBox.moveLine(oRight, iBoxPosX + iBoxWidth - iLineThickness,
                             iBoxPosY);
        oBox.moveLine(oTop, iBoxPosX,
                           iBoxPosY - iLineThickness);
        oBox.moveLine(oBottom, iBoxPosX - iLineThickness,
                              iBoxPosY + iBoxHeight - iLineThickness);

                oBox.showObj(oLeft);
        oBox.showObj(oRight);
        oBox.showObj(oTop);
        oBox.showObj(oBottom);
        return true;
    },
    drawCrossHair: function(iLineThickness, iCrossHairSize, iPosX, iPosY) {
        iPosX -= oBox.iLineThickness;
        iPosY -= oBox.iLineThickness;
        var oLeft = oBox.oLeftBorder;
        var oRight = oBox.oRightBorder;
        var oTop = oBox.oTopBorder;
        var oBottom = oBox.oBottomBorder;

                oBox.resizeLine(oLeft, iLineThickness, iCrossHairSize);
        oBox.resizeLine(oTop, iCrossHairSize, iLineThickness);

                oBox.moveLine(oLeft, iPosX,
                            iPosY - iCrossHairSize/2 + iLineThickness/2);
        oBox.moveLine(oTop, iPosX - iCrossHairSize/2 + iLineThickness/2,
                           iPosY);

                oBox.showObj(oLeft);
        oBox.showObj(oTop);

                oBox.hideObj(oRight);
        oBox.hideObj(oBottom);
        return true;
    },
    resizeLine: function(oLine, iWidth, iHeight) {
        if (oLine.style) {
            oLine.style.width = iWidth + 'px';
            oLine.style.heigth = iHeight + 'px';
        } else if (oLine.clip) {
            oLine.clip.width = iWidth + 'px';
            oLine.clip.heigth = iHeight + 'px';
        }
        oBox.clipLine(oLine, 0, iWidth, iHeight, 0);
        return true;
    },
    enableDraw: function() {
        oBox.bDrawingEnabled = true;
        document.onmouseup = oBox.endBox;
        return true;
    },
    disableDraw: function() {
        oBox.bDrawingEnabled = false;
        document.onmouseup = oBox.newCrossHair
        return true;
    },
    setCursor: function(sCursor) {
                for (var i=0; i<oBox.aMap.length; i++) {
            oBox.aMap[i].oImg.style.cursor = sCursor;
                    }
    },
    showImgWait: function() {
        if (oBox.sWaitImgId != null) {
            var oImg = document.getElementById(oBox.sWaitImgId);
            if (oImg) {
                if (oImg.style) {
                    oImg.style.visibility = 'visible';
                    oImg.style.zIndex = '1000';
                }
                setTimeout('document.getElementById(oBox.sWaitImgId).src=oBox.sWaitImgLoc',
                           200);
            }
        }
    },
    hideImgWait: function() {
        var oImg = document.getElementById(oBox.sWaitImgId);
        if (oImg && oImg.style) {
            oImg.style.visibility = 'hidden';
            oImg.style.zIndex = '-1000';
        }
    },
    initBorder: function(oBorder, iWidth, iHeight) {
        var sImgCode = '<img src="' + oBox.sLineTransparentImg + '" ' +
                             'border="0" ' +
                             'width="' + iWidth + '" ' +
                             'height="' + iHeight + '" >';
        if (typeof(oBorder.innerHTML) != 'undefined') {
            oBorder.innerHTML = sImgCode;
        } else if (document.layers) {
            oBorder.document.open();
            oBorder.document.write(sImgCode);
            oBorder.document.close();
        }
        if (oBorder.style) {
            oBorder.style.backgroundColor = oBox.sLineColor;
        } else {
            oBorder.bgColor = oBox.sLineColor;
        }
        return true;
    },
    suspend: function() {
        oBox.bInSuspense = true;
    },
    resume: function() {
        oBox.bInSuspense = false;
    },
    init: function(oParam) {
        oBox.bTrace = oParam.bTrace || oBox.bTrace;

        oBox.sWaitImgId = oParam.sWaitImgId;
        oBox.sWaitImgLoc = oParam.sWaitImgLoc;

        oBox.fnOnClick = oParam.fnOnClick || oBox.fnOnClick;
        oBox.fnOnDrawEnd = oParam.fnOnDrawEnd || oBox.fnOnDrawEnd;
        oBox.sLineColor = oParam.sLineColor || oBox.sLineColor;
        oBox.iLineThickness = oParam.iLineThickness || oBox.iLineThickness;
        if (oBox.iLineThickness % 2) {

                        oBox.iLineThickness++;
        }
        oBox.iCrossHairSize = oParam.iCrossHairSize || oBox.iCrossHairSize;
        if (oBox.iCrossHairSize % 2) {

                        oBox.iCrossHairSize++;
        }

        if (oParam.sLineTransparentImg) {
            oBox.sLineTransparentImg = oParam.sLineTransparentImg;
        } else {
            alert('Error(oBox): missing transparent image for line drawing.')
        }
        var iMaxMapWidth = 0;
        var iMaxMapHeight = 0;
        for (var i=0; i<oParam.aMap.length; i++) {
            oBox.aMap[i] = {
                sName: oParam.aMap[i].sAnchorId,
                oAnchor: oBox.getObj(oParam.aMap[i].sAnchorId),
                oImg: oBox.getObj(oParam.aMap[i].sImgId),
                iLeft: 0,
                iRight: 0,
                iTop: 0,
                iBottom: 0
            }
            var oMap = oBox.aMap[i];
            var oMapAnchor = oMap.oAnchor;
            oMap.iLeft += ((typeof(oMapAnchor.pageX) != 'undefined')
                           ? oMapAnchor.pageX
                           : ((typeof(oMapAnchor.offsetLeft) != 'undefined')
                              ? oMapAnchor.offsetLeft
                              : 0));
            oMap.iTop += ((typeof(oMapAnchor.pageY) != 'undefined')
                           ? oMapAnchor.pageY
                           : ((typeof(oMapAnchor.offsetTop) != 'undefined')
                              ? oMapAnchor.offsetTop
                              : 0));
            if (oMapAnchor.offsetParent) {

                                oAnchorParent = oMapAnchor.offsetParent;
                while (oAnchorParent) {
                    oMap.iLeft += oAnchorParent.offsetLeft;
                    oMap.iTop += oAnchorParent.offsetTop;
                    oAnchorParent = oAnchorParent.offsetParent;
                }
            }
            if (oMapAnchor.style &&
                typeof(oMapAnchor.style.cursor) != 'undefined') {
                
                                oMapAnchor.style.cursor =
                    ((document.all && !window.opera)
                     ? "url('map/images/cross_r.cur')"
                     : 'crosshair');

            }
            var iMapWidth = oBox.getWidth(oMapAnchor);
            if (iMapWidth > iMaxMapWidth) {
                iMaxMapWidth = iMapWidth;
            }
            var iMapHeight = oBox.getHeight(oMapAnchor);
            if (iMapHeight > iMaxMapHeight) {
                iMaxMapHeight = iMapHeight;
            }
            oMap.iRight = oMap.iLeft + iMapWidth;
            oMap.iBottom = oMap.iTop + iMapHeight;
            if (oBox.bTrace) {
                document.title = 'map at ' +
                      oMap.iLeft + ',' + oMap.iTop + '/' +
                      oMap.iRight + ',' + oMap.iBottom;
            }
        }
        oBox.oLeftBorder = oBox.getObj(oParam.sLeftBorder);
        oBox.initBorder(oBox.oLeftBorder, oBox.iLineThickness, iMaxMapHeight);

        oBox.oRightBorder = oBox.getObj(oParam.sRightBorder);
        oBox.initBorder(oBox.oRightBorder, oBox.iLineThickness, iMaxMapHeight);

        oBox.oTopBorder = oBox.getObj(oParam.sTopBorder);
        oBox.initBorder(oBox.oTopBorder, iMaxMapWidth, oBox.iLineThickness);

        oBox.oBottomBorder = oBox.getObj(oParam.sBottomBorder);
        oBox.initBorder(oBox.oBottomBorder, iMaxMapWidth, oBox.iLineThickness);
        oBox.iMouseJitter = oBox.iLineThickness * 3;

                if (document.captureEvents) {
            document.captureEvents(Event.MOUSEMOVE | Event.MOUSEDOWN |
                                   Event.MOUSEUP);
        }
        document.onmousemove = oBox.newCursorPos;
        document.onmousedown = oBox.startBox;

        if (oBox.bDrawingEnabled) {
            oBox.enableDraw();
        } else {
            oBox.disableDraw();
        }
        return true;
    }
};
