// display_map.js
/*
COPYRIGHT 1995-2005 ESRI

TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL
Unpublished material - all rights reserved under the 
Copyright Laws of the United States.

For additional information, contact:
Environmental Systems Research Institute, Inc.
Attn: Contracts Dept
380 New York Street
Redlands, California, USA 92373

email: contracts@esri.com
*/

var mapMoveIncrement = 3;
if (isNav) mapMoveIncrement *=2;
var navDir = "";
var nav_active = false;
var nx = 0;
var ny = 0;
var tempToolMode = "MapZoomIn";
var nav_active = false;
var nav_dir = "";
var xDir = 0;
var yDir = 0;
var mouseDirection = "";
var panStartLeft = 0;
var panStartTop = 0;
var panStartCenterX = 0;
var panStartCenterY = 0;
var reloadTimer;
var m_fadeInterval;
var cacheUpdateDelay = 500;
var dynamicUpdateDelay = 1000;
var vectortoolbar = "VectorToolbar";
var mouseWheelAwayZoomIn = true;
var mapUseZoomAnimation = true;
var mapUseKeyboardNavigation = true;
var mapDefaultResourceId = "webTierBlendingOfAllResources";
var mapDefaultZoomInMode = "esriDefaultMapShiftDrag";
var mapDefaultZoomOutMode = "esriDefaultMapAltDrag";
var mapDefaultZoomInAction = "DragRectangle";
var mapDefaultZoomOutAction = "DragRectangle"
var mapDefaultZoomInCursor= "crosshair";
var mapDefaultZoomOutCursor = "crosshair";

var esriJavaScriptDecimalDelimiter = ((("theChar is" + (10/100)).indexOf("."))==-1) ? "," : "."; // get decimal delimiter used by JavaScript on user machine


var esriDirectToCacheURL = true;

function MapObject(controlName, viewWidth, viewHeight, tileWidth, tileHeight, totalLevels, startColumns, startRows, tileServerUrl) {
    inheritsFrom(new ControlObject(controlName, "Map", 0, 0, viewWidth, viewHeight), this);
    this.index = 0;
    this.mapType = "tile";
    this.name = controlName;
    this.divId = "MapDiv_" + controlName;
    this.divId2 = "MapDiv2_" + controlName;
    this.divScaleId2 = "MapDiv2Table_" + controlName;
    this.imageId = "MapImage_" + controlName;
    this.imageId2 = "MapImage2_" + controlName;
    this.vectorDivId = "LineDiv_" + controlName;
    this.snapCircleId = "SnapCircle_" + controlName;
    this.containerDivId = "MapControlDiv_" + this.controlName;
    this.maptipDivId = "MapTipLayerDiv_" + this.controlName;
    this.overlayDivId = "MapOverlayDiv_" + this.controlName;
    this.mozillaLinkId = "MapMozillaLink_" + this.controlName;
    this.parentId = null;
    this.dragBoxColor = "Black";
    this.dragLineWidth = 3;
    this.imageSizeFactor = 1;   
    this.lastWidth = viewWidth;
    this.lastHeight = viewHeight;

    this.containerLeft = 0;
    this.containerTop = 0;

    this.backColor = "White";

    this.imgUrl = "";
    this.cursor = "pointer";
    this.mapMoveIncrement = mapMoveIncrement;
    this.panBuffer = 0;
    
    this.navigationEnabled = true;
    // action flags
    this.drawBox = false;
    this.dragImage = false;
    this.drawShape = false;
    this.showLoading = false;
    
    this.actionType = "DragImage";
    this.clientAction = "DragImage";
    this.mode = "MapPan";
    // holders for mouse/key combo events
    this.tempMode = "MapPan";
    this.tempCursor = "move";
    this.tempAction = "DragAction";
    // mouse/key combo events
        // shift.... mousedown/move/up ... default is MapZoomIn ... requires Map control has MapZoomIn/DragRectangle Tool Item
    this.shiftMode = mapDefaultZoomInMode;
    this.shiftAction = mapDefaultZoomInAction;
    this.shiftCursor = mapDefaultZoomInCursor;
    this.defaultShiftMode = mapDefaultZoomInMode;
    this.defaultShiftAction = mapDefaultZoomInAction;
        // ctrl .... mousedown only... click ... no default
    this.ctrlMode = "";
    this.ctrlAction = "Point";
    this.ctrlCurosr = "pointer";
    this.ctrlFunction = ""; // function to handle after mousedown
        // alt .... mousedown/move/up ... default is MapZoomOut ... requires Map control has MapZoomOut/DragRectangle Tool Item
    this.altMode = mapDefaultZoomOutMode;
    this.altAction = mapDefaultZoomOutAction;
    this.altCursor = mapDefaultZoomOutCursor;
    this.defaultAltMode = mapDefaultZoomOutMode;
    this.defaultAltAction = mapDefaultZoomOutAction;
    
    this.moveFunction = null;
    this.tempMoveFunction = null;
    this.preModeExecFunction = null;
    this.windowObject = mapWindow;
    
    // .NET ClientPostback properties
    this.pageID = "";
    this.forcePostBackEvent = "";
    
    // associated objects
    this.divObject = null;
    this.divObject2 = null;
    this.divScaleObject2 = null;
    this.imageObject = null;
    this.imageObject2 = null;
    this.vectorObject = null;
    this.snapCircleObject = null;
    this.loadingObject = null;
    this.containerObject = null;
    this.maptipObject = null;
    this.overlayObject = null;
//  this.backObject = null;
    this.mozillaLinkObject = null;
    
    this.callBackFunctionString = "";
    this.tileCallbackFunctionString = "";
    this.identifyCallbackFunctionString = "";
    this.vectorCallbackFunctionString = "";
    
   this.mapType = "tile";
   this.tileRequestType = "single"; // single or multiple
   this.viewWidth = viewWidth;
   this.viewHeight = viewHeight;
   this.viewLeft = 0;
   this.viewTop = 0;
   this.tileWidth = tileWidth;
   this.tileHeight = tileHeight;
   this.lastTileWidth = 0;
   this.lastTileHeight = 0;
   this.totalLevels = totalLevels;
   this.startColumns = startColumns;
   this.startRows = startRows;
   this.level = 0;
   this.columns = startColumns;
   this.rows = startRows
   this.continuousCallback = false;
   this.viewNumbers = new Array();
   
   this.columnsPerView = Math.ceil(viewWidth/tileWidth);
   this.rowsPerView = Math.ceil(viewHeight/tileHeight);
   this.lastColumnsPerView = 0;
   this.lastRowsPerView = 0;
   
   this.startColumn = 0;
   this.startRow = 0;
   this.startLeftOffset = 0;
   this.startTopOffset = 0;
   this.currentLeftColumn = 0;
   this.currentTopRow = 0;
   this.currentRightColumn = 0;
   this.currentBottomRow = 0;
   this.bufferLeftColumn = 0;
   this.bufferTopRow = 0;
   this.bufferRightColumn = 0;
   this.bufferBottomRow = 0;
   this.leftOffset = 0;
   this.topOffset = 0;
   this.gridWidth = 0;
   this.gridHeight = 0;
   
   this.useScrollWheel = true;
   
    this.currentLeftColumnBuffer = -9999999;
    this.currentTopRowBuffer = -9999999;
    this.currentRightColumnBuffer = -9999999;
    this.currentBottomRowBuffer = -9999999;
    this.currentXOffset = 0;
    this.currentYOffset = 0;
    this.lastLeftColumn = -9999999;
    this.lastTopRow = -9999999;             
    this.lastRightColumn = -9999999;
    this.lastBottomRow = -9999999; 
    this.lastLeftColumnBuffer = -9999999;
    this.lastTopRowBuffer = -9999999;               
    this.lastRightColumnBuffer = -9999999;
    this.lastBottomRowBuffer = -9999999; 
    
    this.baseTileColumn = 0;
    this.baseTileRow = 0;
    this.baseTileXOffset = 0;
    this.baseTileYOffset = 0;
    this.gridXOffset = 0;
    this.gridYOffset = 0;
   
   this.navDivId = "MapNavDiv_" + this.controlName;
   this.navDivObject = null;
   
   this.displayedTiles = new Array();
   this.requestedMapTipTiles = new Array();
   this.keyFocus = true;
//   this.TilesToGet = new Array();
//   this.TilesToClear = new Array();
//   this.TilesToHold = new Array();
   
   this.enableResizeEvent = false;
   this.widthSizeFactor = 1.0;
   this.heightSizeFactor = 1.0
   
   this.resizeExtent = false;
   this.lastViewBox = null;
   
   this.blankImagePath = esriBlankImagePath;
   this.blankImageObject = new Image();
   this.mapDiv2UpdateDelay = 1000;
   
   this.mapUnits = "Degrees";
   this.measureUnits = "Miles";
   this.clearDrawnVectors = true;
   this.currentVectorToolbarState = "hidden"; 
    
    this.tileServerUrl = tileServerUrl;
    this.enableTileCaching = true;
    
    this.decimalDelimiter = esriSystemDecimalDelimiter;
    this.useZoomAnimation = true;   
    //this.ie6AlphaDisplayType = "AlphaImageLoader"; // type of alpha display used on IE6... AlphaImageLoader or VML
    this.forcePngAlphaOnBase = false; // force IE6 alpha loader on png images on base animation later? False will speed in transparency is not needed
    
   this.startUp = true;
   this.clearLevelGridCount = 0;
   this.changeLevelGridCount = -1;
    
   this.createDivs = function(mapContainer, startResourceList, returnString) {
        var containerDiv = null;
        var vWidth1 = this.viewWidth + "px";
        var vHeight1 = this.viewHeight + "px";
        if (mapContainer!=null && mapContainer!="") 
                containerDiv = document.getElementById(mapContainer);
        
        if (returnString==null) returnString = false;
        if (startResourceList==null) startResourceList = mapDefaultResourceId + "||true|";
        var tempSize = 1;
        if (String(this.viewHeight).indexOf("%")!=-1) {
            tempSize = parseInt(this.viewHeight);
            vHeight1 = this.viewHeight;
            this.heightSizeFactor = tempSize / 100;
            this.enableResizeEvent = true;
            if (containerDiv!=null)
                this.viewHeight = Math.round(getElementHeight(containerDiv) * this.heightSizeFactor);
            else 
                this.viewHeight = Math.round(getWinHeight() * this.heightSizeFactor);
            this.height = this.viewHeight;
        }
        if (String(this.viewWidth).indexOf("%")!=-1) {
            vWidth1 = this.viewWidth;
            
            tempSize = parseInt(this.viewWidth);
            this.widthSizeFactor = tempSize / 100;
            this.enableResizeEvent = true;
            if (containerDiv!=null)
                this.viewWidth = Math.round(getElementWidth(containerDiv) * this.widthSizeFactor);
            else 
                this.viewWidth = Math.round(getWinWidth() * this.widthSizeFactor);
            this.width = this.viewWidth;
        }
        var vWidth2 = this.viewWidth + "px";
        var vHeight2 = this.viewHeight + "px";
        if (this.tileWidth==0) this.tileWidth = this.viewWidth;
        if (this.tileHeight==0) this.tileHeight = this.viewHeight;
        var d = this.divId;
        var s = "";
        s+='<div id="MapControlDiv_' + this.controlName +'" style="position:relative; background-color:' + this.backColor + '; overflow:hidden; width:' + vWidth1 + '; height: ' + vHeight1 + '; -moz-user-focus: normal;" ';
        s+=' onmouseover="Maps[\'' + this.controlName + '\'].keyFocus=true; ';
        if (isIE) s+= 'this.setActive();';
        s+= '" >\n';    
        s+= '<a id="' + this.mozillaLinkId + '" ' + ((isNav) ? 'onmouseover="this.focus()" style="-moz-user-focus: normal;"' : '') + '>';
        
        // backdrop for scaleable div.... hides main div when zooming
        s += '<div id="' + this.backDivId + '" style="position:absolute; left: 0px; top: 0px; width: ' + getWinWidth() + '; height: ' + getWinHeight() + '; visibility: hidden; background-color: ' + this.backColor + ';"  ><img src="' + this.blankImagePath + '" width="'+ getWinWidth() + '" height="' + getWinHeight() + '" hspace="0" vspace="0" /></div>\n';     
        // create scaleable div
        s += '<div id="' + this.divId2 + '" style="position:absolute; left:0px; top:0px;  width:' + vWidth1 + '; height:' + vHeight1 + '; visibility: hidden; background-color: ' + this.backColor + '; "  > \n';       
        //s += '<div id="' + this.divScaleId2 + '" style="position:absolute; left:0px; top:0px;  width:' + vWidth1 + '; height:' + vHeight1 + '; background-color: ' + this.backColor + ';" ></div></div>\n';
        s += '<div id="' + this.divScaleId2 + '" style="position:absolute; left:0px; top:0px;  width:' + vWidth1 + '; height:' + vHeight1 + '; background-color: ' + this.backColor + ';" >';
        s +='</div></div>\n';

            // Map div, container for the map images ... position is absolute within container
        s += '<div id="' + d + '" style="position:absolute; left:0px; top:0px;  width:' + vWidth1 + '; height:' + vHeight1 + '; "  >';
            // Resource divs... multiple 'layers' for client-side blending... defaults to a single layer
           var rcList = startResourceList.split(",");
          // rcList.reverse(); // take top-down list and reverse for bottom-up display
           for (var r=rcList.length-1; r>=0; r--) { 
                if (rcList[r].indexOf("|")==-1) rcList[r] += "||true|"; 
                var rid = rcList[r].split("|");
                if (rid[1]==null) rid[1] = "";
                if (rid[2]==null) rid[2] = true;
                if (rid[4]==null) 
                    rid[4] = "";
                else
                    rid[4] = rid[4].toLowerCase(); 
                if (rcList.length==1) mapDefaultResourceId = rid[0];
                if (r==rcList.length-1) this.baseResourceId = rid[0];
                this.ResourceCollection[r] = new ResourceObject(rid[0], r,  rid[2].toLowerCase(), this.controlName, rid[1], rid[3], rid[4]); 
                var resource = this.ResourceCollection[r];
                 s += '<div id="' + resource.divId + '" style="position:absolute; left:0px; top:0px;  width:' + vWidth1 + '; height:' + vHeight1 + '; "  ></div>\n';
           } 
        s += '</div>\n';        
        
        // create MapTip Layer
        s += '<div id="' + this.maptipDivId + '" style="position:absolute; left:0px; top:0px; visibility:hidden; background-color:transparent;" ></div>\n'; 
         
        var ldiv = "LineDiv_" + this.controlName;
        //create Map Vector Layer
        s += '<div id="' + ldiv + '" style="position:absolute; left:0px; top:0px; visibility: visible; background-color:transparent;" >\n';
        //if (isNav) s+= '<canvas id="Canvas_' + this.controlName + '" width="100%" height=100%"></canvas>\n';
        s += '</div>\n';    

        // create a snap circle
        if (isIE) {
            s += '<v:oval id="' + this.snapCircleId + '" style="width:2px; height: 2px; position: absolute; left: 100px; top: 100px; visibility: hidden; cursor: crosshair;"><v:stroke weight="2px" color="red"  dashstyle="solid" opacity="0.5" /><v:fill color="red" opacity="0.10" /></v:oval>\n';
        } else {
            // if Netscape 8, don't use canvas tag.... not supported
            if (nav8) 
                s += '<div id="' + this.snapCircleId + '" style="width:auto; height: auto; position: absolute; left: 100px; top: 100px; visibility: hidden; cursor: crosshair;  -moz-opacity: 0.5;"></div>';
            else   
                s += '<canvas id="' + this.snapCircleId + '" style="width:100px; height: 100px; position: absolute; left: 100px; top: 100px; visibility: hidden; cursor: crosshair;" width="100" height="100"></canvas>\n';
        }
        //create an Overlay Layer... place for icons, text, etc. to be positioned and moved with map... cleared on scale change
        s += '<div id="' + this.overlayDivId + '" style="position:absolute; left:0px; top:0px; visibility: visible; background-color:transparent;" ></div>\n';  
        
        s += '</a>\n'; 
        
        s+='</div>';
        //alert(s);
        if (returnString) {
            // just return the string....  map.setObjects() must be called manually
            return s;
            
        } else {
            if (mapContainer!=null && mapContainer!="") {
                var div = document.getElementById(mapContainer);
                div.innerHTML = s;
                var box = calcElementPosition(mapContainer);
                this.viewLeft = box.left;
                this.viewTop = box.top;
                //alert("View location: " + box.left + ", " + box.top);
            } else {
                document.writeln(s);
            }
        
            this.setObjects();
        }
        if (this.blankImagePath!=null && this.blankImagePath.length>0)
            this.blankImageObject.src = this.blankImagePath;
   } 
   
    this.setObjects = function () {
        // add vector object to map
        this.vectorObject = new VectorObject(this.vectorDivId);
        var v = this.vectorObject;
        this.vectorObject.vectordiv = document.getElementById(this.vectorDivId);
        this.vectorObject.linewidth = this.dragLineWidth;
        this.vectorObject.divColor = this.dragBoxColor;
        this.vectorObject.pixelObject = new PixelObject(this.controlName, this.left,this.top,this.width,this.height);
        this.vectorObject.xyCoord = new CoordsObject();
        this.snapCircleObject = document.getElementById(this.snapCircleId);
        //if (isNav && !nav8) {
        if (isNav) {
            if (nav8) {
                var svo = new  VectorObject(this.snapCircleId);
                svo.divColor = "Red";
                svo.circle(1,1,1);
                svo.draw();
                this.snapCircleObject.vectorObject = svo;
            } else {  
    //          this.vectorObject.canvas = document.getElementById("Canvas_" + this.controlName);
    //          if (this.vectorObject.canvas) this.vectorObject.context = this. vectorObject.canvas.getContext("2d");
                var ctx = this.snapCircleObject.getContext("2d");
                if (ctx!=null) {
                    var radius = Math.round(parseFloat(this.snapCircleObject.clientWidth) / 2); 
                    ctx.fillStyle = "rgba(255, 0, 0, 0.1)";
                    ctx.arc(radius, radius, radius, 0, Math.PI*2, true);
                    ctx.fill();
                    ctx.strokeStyle = "rgba(255, 0, 0, 0.5)";
                    ctx.lineWidth = 2;
                    ctx.arc(radius, radius, radius, 0, Math.PI*2, true);
                    ctx.stroke();
                }
              }
        }
        this.snapCircleObject.onmousedown = MapMouseDown;
        this.snapCircleObject.onmouseup = MapMouseUp;
        this.snapCircleObject.onmousemove = MapMouseMove;
        
        this.divObject = document.getElementById(this.divId);
        this.divObject2 = document.getElementById(this.divId2);
        this.divScaleObject2 = document.getElementById(this.divScaleId2);
        this.vectorObject.divObject = document.getElementById(this.vectorObject.divId);
        this.navDivObject = document.getElementById(this.navDivId);
        this.containerObject = document.getElementById(this.containerDivId);
        this.maptipObject = document.getElementById(this.maptipDivId);
        this.overlayObject = document.getElementById(this.overlayDivId);
        this.mozillaLinkObject = document.getElementById(this.mozillaLinkId);
        this.index = mapCount;
        this.pageLeft = parseInt(this.divObject.style.left);
        this.pageTop = parseInt(this.divObject.style.top);
        box = calcElementPosition(this.containerDivId);
        this.containerLeft = box.left;
        this.containerTop = box.top;
        if (isIE) {
            this.containerLeft+=2;
            this.containerTop+=2;
        }
        this.viewLeft = box.left;
        this.viewTop = box.top;
        //alert("Container location: " + box.left + ", " + box.top);
        var mcount = MapNames.length;
        MapNames[mcount] = this.controlName;
        mapCount = MapNames.length;
        if (mapUseKeyboardNavigation) {
           if (isIE) { 
                // if IE, use the map's container object div 
                this.containerObject.onkeydown = keyDown;
                this.containerObject.onkeyup = keyUp;
           } else {
                //  else use the map's link tag
                this.mozillaLinkObject.onkeydown = keyDown;
                this.mozillaLinkObject.onkeyup = keyUp;
           }
                        
        } 
        if (this.navigationEnabled) MapDragImage(this.controlName, 'Pan', false);
        if (this.enableResizeEvent) // && isNav)
            window.onresize = AutoResizeMap;
        var rc =  this.ResourceCollection;
        for (var i=0;i<rc.length;i++) {
             rc[i].divObject = document.getElementById(rc[i].divId);
             rc[i].mapObject = Maps[rc[i].mapId];
        }
         rc.mapDiv = this.divObject;
                
    }
    
    // sets the tool for user interaction
    this.setTool = function (mode, showLoading, clientAction, cursor, vectorMode, vectorToolbarState, statusMessage, clearDrawnVectors, vectorCallbackString) {
            // set up events for map div
            
            this.show();
            this.divObject.onclick = null;
            this.preModeExecFunction = null;
            this.divObject.onmousedown = this.MapMouseDown;
            
            this.divObject.style.cursor = cursor;
            this.containerObject.style.cursor = cursor;
            this.snapCircleObject.style.cursor = cursor;
            this.cursor = cursor;
            this.actionType = clientAction;
            this.mode = mode;
            this.tempMode = mode;
            this.tempAction = clientAction;
            this.tempCursor = cursor;
            if (vectorToolbarState==null) vectorToolbarState = "hidden";
            this.vectorCallbackFunctionString = (vectorCallbackString!=null) ? vectorCallbackString : ""; 
            this.currentVectorToolbarState = vectorToolbarState; 
            this.clearDrawnVectors = (clearDrawnVectors!=null) ? clearDrawnVectors : true;
            var v = this.vectorObject;
            if (v!=null) {
                v.mode = vectorMode;            
                if (vectorMode > -1) //for vectors
                {
                    v.clear();
                    v.draw();
                    showLayer(v.divId);
                    if (clientAction.toLowerCase()=="dragshape") {
                        // dragcircle, dragoval, dragbox - drag enabled
                        v.divObject.onclick = null;
                        v.divObject.onmousedown = MapMouseDown;
                    } else {
                        // line, polyline, polygon, circle, oval, box - click enabled
                        v.divObject.onmousedown = null;
                        this.divObject.onmousedown = null;
                        v.divObject.onmouseup = MapMouseUp;
                        this.divObject.onmouseup = MapMouseUp;
                    }
                    v.divObject.style.cursor = cursor;
    
                    v.vectorCount = 0;
    
                }
                else {
                    hideLayer(this.vectorObject.divId);
                }
            }
            //vector Toolbar
            var tb = document.getElementById(vectortoolbar);
            if (tb!=null) tb.style.visibility = this.currentVectorToolbarState;
            //set up mode and show loading
            this.drawBox = false;
            this.dragImage = false;
            var m = this.controlName + "_mode";
            this.mode = mode;
            //status bar message
            window.status = statusMessage;
    
    }
    
    this.hide = function() {
        hideLayer("MapControlDiv_" + this.controlName);
    }
    
    this.show = function() {
        showLayer("MapControlDiv_" + this.controlName);

    }
    
    this.getContainerRectangle = function() {
        // this gets the absolute page position and dimensions as a RectangleObject
        var box = calcElementPosition(this.containerDivId);
        this.containerLeft = box.left;
        this.containerTop = box.top
        if (isIE) {
            this.containerLeft+=2;
            this.containerTop+=2;
        }
        return box;
    }
    
    this.MapMouseDown = MapMouseDown;
    this.MapMouseMove = MapMouseMove;
    this.MapMouseUp = MapMouseUp;
    
    // TODO: Add comments
    this.setUpLevelGrid = function(level, columns, rows, startCol, startRow, leftOffset, topOffset, tileWidth, tileHeight, totalLevels, minCol, minRow, resourceLimits, resourceMapping) 
    {
        if (this.changeLevelGridCount != esriCurrentResponseCount) {
            this.minColumn = (minCol==null) ? 0 : minCol;
            this.minRow = (minRow==null) ? 0 : minRow;
            var doCreateMapDiv2 = false;
            keepZooming = false;
            if (totalLevels!=null) {
                this.totalLevels = totalLevels;
                
            }
            if (tileWidth!=null) {
                if (this.tileWidth!=tileWidth) doCreateMapDiv2 = true;
                this.tileWidth = tileWidth;
                this.columnsPerView = Math.ceil(this.viewWidth / this.tileWidth);
            }
            if (tileHeight!=null) {
                if (this.tileHeight!=tileHeight) doCreateMapDiv2 = true;
                this.tileHeight = tileHeight;
                this.rowsPerView = Math.ceil(this.viewHeight / this.tileHeight);
            }
            if (this.totalLevels>1)
                this.mapDiv2UpdateDelay = cacheUpdateDelay;
            else
                this.mapDiv2UpdateDelay = dynamicUpdateDelay;
            if (this.columnsPerView * this.rowsPerView > 6)
                this.mapDiv2UpdateDelay *= 2;
            //alert("totalLevels=" + totalLevels + "\ntileWidth=" + tileWidth + "\ntileHeight=" + tileHeight);
            this.level = level;
                this.columns = columns;
                this.rows = rows;
            //alert("Cols x Rows: " + this.columns + " x " + this.rows + "\nColumn/Row: " + startCol + ", " + startRow + "\nx,y: " + leftOffset + ", " + topOffset);
            this.startColumn = startCol;
            this.startRow = startRow;
            this.currentLeftColumn = startCol;
            this.currentTopRow = startRow;

            this.baseTileColumn = startCol;
            this.baseTileRow = startRow;
            this.baseTileXOffset = leftOffset;
            this.baseTileYOffset = topOffset;
            this.gridXOffset = this.tileWidth * startCol;
            this.gridYOffset = this.tileHeight * startRow;
            
            this.overlayObject.innerHTML = "";
            this.vectorObject.restart();
            var loff = 0 - leftOffset;
            var toff = 0 - topOffset;
            moveLayer(this.divId, loff, toff);
            moveLayer(this.maptipDivId, loff, toff);
            moveLayer(this.overlayDivId, loff, toff);
            
            //showLayer(this.divId);
            this.hideMapDiv2();
            
            lastX = loff;
            lasyY = toff;
            this.displayedTiles = new Array();
            this.requestedMapTipTiles = null;
            this.requestedMapTipTiles = new Array();
            this.pendingTiles.length = 0;     ///// Added for returned tiles check
            this.getTopLeftTile();
            if (resourceLimits==null) resourceLimits = "";    ///// Added for resource limit check
            var rcLimits = resourceLimits.split("|");             ///// Added for resource limit check
            var rc = this.ResourceCollection;
            var limits;                                                         ///// Added for resource limit check
            ///// Added for resource mapping check  
            if (resourceMapping==null) resourceMapping = "";
            var rcMappedLevels = resourceMapping.split("|");
                       
            ///// Added for resource mapping check 
            for (var i=0;i<rc.length;i++) {
                rc[i].displayedTiles = new Array();
                rc[i].pngTiles = new Array();  
                rc[i].divObject.innerHTML = "";
                ///// Added for resource limit check 
                if (rcLimits[i]!=null)
                    limits = rcLimits[i].split(",");  
                else 
                    limits = "";  
                if (rcLimits[i]="-99,-99,-99,-99") limits=""; 
                rc[i].gridLimits = rcLimits[i];                       
                if (limits.length==4) {
                    rc[i].setLimits(parseInt(limits[0]), parseInt(limits[1]), parseInt(limits[2]), parseInt(limits[3]));
                } else {
                   rc[i].setLimits(-99,-99,-99,-99);  
                } 
                ///// Added for resource limit check    
                ///// Added for resource mapping check
                rc[i].mappedLevel = (rcMappedLevels[i]!=null && rcMappedLevels[i].length>0) ? rcMappedLevels[i]  : level;     
                ///// Added for resource mapping check                                                      
            } 
            //this.divObject.innerHTML = "";
            this.addViewTiles(startCol, startRow, leftOffset, topOffset, true);
            
            if (this.totalLevels > 1) {
                if (hasZoomLevel) updateZoomLevelIcons(level, this.controlName);
            }
            
            //this.divObject.style.cursor = "progress";
            
            zoomAnimationDelay = false;
            this.changeLevelGridCount != esriCurrentResponseCount;
        }
    }

    this.shiftGrid = function(startCol, startRow, leftOffset, topOffset) {
        showLayer(this.divId);

        var xTilesOffset = this.startColumn - startCol;
        var yTilesOffset = this.startRow - startRow;
        this.currentLeftColumn = startCol;
        this.currentTopRow = startRow;

        var loff = (xTilesOffset * this.tileWidth) - leftOffset;
        var toff = (yTilesOffset * this.tileHeight) - topOffset;
        //alert(loff + ", " + toff);
        this.moveTiles(loff, toff, "");
        lastX = loff;
        lasyY = toff;
        
        this.updateView(true);
        
    }


    
    this.addViewTiles = function(startCol, startRow, leftOffset, topOffset, update) {
        if (update==null) update = false;
        var bottomRow = startRow + this.rowsPerView;
        var rightCol = startCol + this.columnsPerView;

        if (topOffset!=0) bottomRow++;
        if (leftOffset!=0) rightCol++;
        var lastRow = bottomRow - 1;
        var lastCol =   rightCol - 1;
        for (var r = startRow;r<bottomRow;r++) {
            for (var c = startCol;c<rightCol;c++) {
                if (update && r==lastRow && c==lastCol)
                    this.requestTile(c, r, true);
                else
                    this.requestTile(c, r);
            }
        }
    
    }
    
    this.updateView = function(update) {
        this.getTopLeftTile();
        this.addViewTiles(this.currentLeftColumn, this.currentTopRow, this.currentXOffset, this.currentYOffset, update);
        
        this.dragImage = false;
    }
    
    this.updateResource = function(resourceId) {
        this.getTopLeftTile();
        var startCol = this.currentLeftColumn;
        var startRow = this.currentTopRow;
        var leftOffset = this.currentXOffset;
        var topOffset = this.currentYOffset;
        var bottomRow = startRow + this.rowsPerView;
        var rightCol = startCol + this.columnsPerView;
        var rc = this.ResourceCollection;
        var resourceIndex = rc.getPosition(resourceId);
        if (resourceIndex!=-1) {
            if (rc[resourceIndex].visible) {
                if (topOffset!=0) bottomRow++;
                if (leftOffset!=0) rightCol++;
                var lastRow = bottomRow - 1;
                var lastCol =   rightCol - 1;
                for (var r = startRow;r<bottomRow;r++) {
                    for (var c = startCol;c<rightCol;c++) {
                        if (r==lastRow && c==lastCol)
                            this.requestResourceTile(c, r, resourceId, true);
                        else
                            this.requestResourceTile(c, r, resourceId);
                    }
                }
            } else
                if (this.useZoomAnimation) this.updateMapDiv2(); 
        } else {
            alert("Unable to find " + resourceId);
        }
        
    }
    
    this.showMapDiv2 = function() {
        this.divScaleObject2.style.width = m_imageWidth + "px";
        this.divScaleObject2.style.height = m_imageHeight + "px";

        showLayer(this.divId2);
    }
    
    this.hideMapDiv2 = function() {
        showLayer(this.divId);
        showLayer(this.vectorDivId);
        showLayer(this.maptipDivId);
        showLayer(this.overlayDivId);
    }
    
    this.clearLevelGrid = function(resourceId, resourceLimits) {
            var rc = this.ResourceCollection; 
            if (resourceLimits==null) resourceLimits = "";    ///// Added for resource limit check
            var rcLimits = resourceLimits.split("|");             ///// Added for resource limit check
            var limits;                                                         ///// Added for resource limit check             
            if (resourceId==null)   {
                if (this.clearLevelGridCount != esriCurrentResponseCount) {
                    this.showMapDiv2();
                    this.displayedTiles = new Array();
                    this.requestedMapTipTiles = null;
                    this.requestedMapTipTiles = new Array();
                    for (var i=0;i<rc.length;i++) {
                        rc[i].displayedTiles = new Array(); 
                        rc[i].pngTiles = new Array();
                        rc[i].divObject.innerHTML = ""; 
                        ///// Added for resource limit check 
                        if (rcLimits[i]!=null)
                            limits = rcLimits[i].split(",");  
                        else 
                            limits = "";                        
                        if (rcLimits[i]="-99,-99,-99,-99") limits=""; 
                        rc[i].gridLimits = rcLimits[i];                       
                       if (limits.length==4) {
                            rc[i].setLimits(parseInt(limits[0]), parseInt(limits[1]), parseInt(limits[2]), parseInt(limits[3]));
                        } else {
                            rc[i].setLimits(-99,-99,-99,-99);   
                        } 
                        ///// Added for resource limit check                     
                    }   
                    if (this.useZoomAnimation) this.updateMapDiv2(); 
                    this.updateView(true);
                    this.clearLevelGridCount = esriCurrentResponseCount; 
                } 
            } else {
                var resource = rc.find(resourceId);
                if (resource!=null && resource.checkCallbackCount != esriCurrentResponseCount) { 
                    resource.divObject.innerHTML = "";
                    resource.displayedTiles = new Array(); 
                    resource.pngTiles = new Array();
                    ///// Added for resource limit check 
                    if (rcLimits[0]!=null)
                        limits = rcLimits[0].split(",");  
                    else 
                        limits = "";                        
                    if (rcLimits[i]="-99,-99,-99,-99") limits=""; 
                    resource.gridLimits = rcLimits[i];                       
                    if (limits.length==4) {
                        resource.setLimits(parseInt(limits[0]), parseInt(limits[1]), parseInt(limits[2]), parseInt(limits[3]));
                    } else {
                        resource.setLimits(-99,-99,-99,-99);
                    } 
                    ///// Added for resource limit check                     
                    if (this.useZoomAnimation) this.updateMapDiv2();
                    this.updateResource(resourceId); 
                    resource.checkCallbackCount = esriCurrentResponseCount 
                } 
            }
            this.pendingTiles.length = 0;      ///// Added for returned tiles check
    }
    
    this.switchPostBackInterval = null;
    
    this.switchToLevel = function(newLevel) {
        if (newLevel<0) newLevel = 0;
        if (newLevel>=this.totalLevels) newLevel = this.totalLevels - 1;
        if (newLevel==this.level) return;

        var argument = "EventArg=ChangeLevel&coords=" + newLevel;
        var context = this.controlName; 
        this.coords = newLevel;
        postBack(this.controlName, "ChangeLevel");
    }
    
    this.redraw = function(resourceIndex) {
        var rc = this.ResourceCollection;
        if (resourceIndex == null) {
            for (var i=0;i<rc.length;i++) {
                rc[i].redraw();
            }  
        } else {
            rc[resourceIndex].redraw();
        }
    }
    
    this.zoomToFullExtent = function() {
        var argument = "ZoomToFullExtent";
        postBack(this.controlName, argument);
    }
   
    
   this.updateTileImage = function(c, r, imageUrl, update, resourceId, imageType) {
        var imageHtml =""; 
        if (update==null) update = false; 
        if (imageType==null) imageType = "";
        var supportedPng = false;
        var resouceSupportedPng = false;
        if (imageType.length>0) {
            if (imageType.indexOf("png")>-1 & imageType!="png24") supportedPng = true;
        } 
        if (resourceId==null) resourceId = mapDefaultResourceId;
        var rc = this.ResourceCollection;
        var resourceIndex = rc.getPosition(resourceId);
        var resource = this.ResourceCollection[resourceIndex];
        if (resource==null)return;
        if (resource.imageFormat.length>0) {
             if (resource.imageFormat.indexOf("png")>-1 & resource.imageFormat!="png24") resouceSupportedPng = true;
        }
        var left = (c * this.tileWidth) - this.gridXOffset;
        var top = (r * this.tileHeight) - this.gridYOffset;
        if (imageUrl == "") 
            imageUrl = this.blankImagePath;

        var imgObj = null;
        var pngUrl = "";
        var imageName = "MapTileImage_" + this.controlName + "_" + c + "_" + r + "_" + resourceId;
        var tileName = "MapTile_" + this.controlName + "_" + c + "_" + r;
        //if (isIE  && ieVersion < 7 && (imageType=="png32" || imageExtent=="png" || resource.imageFormat=="png32")) {
        if (isIE  && ieVersion < 7 && (supportedPng || resouceSupportedPng)) {
//                imageHtml = '<img id="' + imageName + '" name="' + imageName + '" src="' + this.blankImagePath + '" style="visibility: hidden; position: absolute; left: ' + left + 'px; top: ' + top + 'px; width: ' + this.tileWidth + 'px; height: ' + this.tileHeight + 'px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + imageUrl + '\');" border=0 vspace=0 hspace=0 ';
//                imageHtml += 'onload="this.style.visibility=\'visible\'; Maps[\'' + this.id + '\'].pendingTiles.remove(\'' + resourceId +  '_' + c + '_' + r + '\');" ';         ///// Added for returned tiles check
//                imageHtml += 'onerror="this.src=\'' + this.blankImagePath + '\'; Maps[\'' + this.id + '\'].ResourceCollection[\'' + resourceIndex + '\'].displayedTiles[\'' + tileName + '\']=\'' + this.blankImagePath + '\';" ';
//                imageHtml += ' />';
                imageHtml =  '<span id="' + imageName + '" ';
                imageHtml += 'name="' + imageName + '" ';
                imageHtml += 'style="position: absolute; left: ' + left + 'px; top: ' + top + 'px; width: ' + this.tileWidth + 'px; height: ' + this.tileHeight + 'px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + imageUrl + '\', sizingMethod=\'scale\');" ';
                imageHtml += '><img src="' + this.blankImagePath + '" ';
                imageHtml += 'onload="this.style.visibility=\'visible\'; Maps[\'' + this.id + '\'].pendingTiles.remove(\'' + resourceId +  '_' + c + '_' + r + '\');" ';         ///// Added for returned tiles check
                imageHtml += '/></span>';
                
           pngUrl = imageUrl;            
        } else {
            imageHtml = '<img id="' + imageName + '" name="' + imageName + '" src="' + imageUrl + '" style="visibility: hidden; position: absolute; left: ' + left + 'px; top: ' + top + 'px; width: ' + this.tileWidth + 'px; height: ' + this.tileHeight + 'px;" border=0 vspace=0 hspace=0 ';
            imageHtml += 'onload="this.style.visibility=\'visible\';Maps[\'' + this.id + '\'].pendingTiles.remove(\'' + resourceId +  '_' + c + '_' + r + '\');" ';          ///// Added for returned tiles check
            imageHtml += 'onerror="this.src=\'' + this.blankImagePath + '\'; Maps[\'' + this.id + '\'].ResourceCollection[\'' + resourceIndex + '\'].displayedTiles[\'' + tileName + '\']=\'' + this.blankImagePath + '\';" ';

            imageHtml += ' />';
        } 
        if (update)
            if (this.useZoomAnimation) window.setTimeout('Maps["' + this.controlName + '"].updateMapDiv2();', 250);
        if (resource.displayedTiles[tileName]!=null) {
            imgObj = document.getElementById(imageName); 
            if (imgObj!=null) {
                    imgObj.src = imageUrl;
            }else
                resource.divObject.insertAdjacentHTML("BeforeEnd", imageHtml);
        } else {
            //alert(tileName + "\n" + imageHtml);
            resource.divObject.insertAdjacentHTML("BeforeEnd", imageHtml); 
        }
        resource.displayedTiles[tileName] = imageUrl;
        resource.pngTiles[tileName] = pngUrl;
        this.divObject.style.visible = "visible";
        // Debug stuff that will be displayed in form element, if it exists
        var blurb = c + ", " + r + ", " + imageUrl + ", " + update + ", " +  resourceId + ", " + imageType;
    if (checkForFormElement(document, 0, "MapDebugBox")) document.forms[0].MapDebugBox.value += ("Tile Response: " + blurb + "\n"); 

   } 
   
   
   this.getTopLeftTile = function() {
        var box = calcElementPosition(this.divId);
        var xDist = (0 - parseInt(this.divObject.style.left)) + this.gridXOffset;
        var yDist = (0 - parseInt(this.divObject.style.top)) + this.gridYOffset;
        var cols = Math.floor(xDist / this.tileWidth);
        var rows = Math.floor(yDist / this.tileHeight);
        var xDist2 = xDist + this.viewWidth - 2;
        var yDist2 = yDist + this.viewHeight - 2;
        var cols2 = Math.floor(xDist2 / this.tileWidth);
        var rows2 = Math.floor(yDist2 / this.tileHeight);
        
        this.currentLeftColumn = cols;
        this.currentTopRow = rows;
        this.currentRightColumn = cols2;
        this.currentBottomRow = rows2;
        this.currentXOffset = Math.abs(xDist) - (Math.floor(Math.abs(xDist) / this.tileWidth) * this.tileWidth);
        this.currentYOffset = Math.abs(yDist) - (Math.floor(Math.abs(yDist) / this.tileHeight) * this.tileHeight);
        
    }
   
   this.moveTiles = function(newX, newY, direction, jumpToTile) {
            if (jumpToTile==null) jumpToTile = false;
            moveLayer(this.divId, newX, newY);
            moveLayer(this.maptipDivId, newX, newY);
            moveLayer(this.overlayDivId, newX, newY);
            var horizDir = newX - lastX;
            var vertDir = newY - lastY;
            lastX = newX;
            lastY = newY;
            this.getTopLeftTile();
            if (this.continuousCallback || jumpToTile) {
                    this.addViewTiles(this.currentLeftColumn, this.currentTopRow, this.currentXOffset, this.currentYOffset);
            }
            this.lastLeftColumn = this.currentLeftColumn;
            this.lastTopRow = this.currentTopRow;               
            this.lastRightColumn = this.currentRightColumn;
            this.lastBottomRow = this.currentBottomRow; 
            this.lastLeftColumnBuffer = this.currentLeftColumnBuffer;
            this.lastTopRowBuffer = this.currentTopRowBuffer;               
            this.lastRightColumnBuffer = this.currentRightColumnBuffer;
            this.lastBottomRowBuffer = this.currentBottomRowBuffer; 
                        
   }
   
   // Requests new tiles when a new tile enters the view.... creates buffer all around view
   this.addTiles = function(startCol, startRow, direction) {
        this.addViewTiles(startCol, startRow, this.currentXOffset, this.currentYOffset);

        if (direction==null) direction = "";
        var endRow = startRow + this.rowsPerView;
        var endCol = startCol + this.columnsPerView
        switch (direction) {
            case "up":
                if (startRow > this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, startRow - 1);
                    }
                }
                break;
            case "down":
                if (endRow < this.rows + this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, endRow);
                    }
                }
                break;
            case "left":
                if (startCol > this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(startCol - 1, r);
                    }
                }
                break;
            case "right":
                if (endCol < this.columns + this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(endCol, r);
                    }
                }
                break;
            case "ul":
                if (startRow > this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, startRow - 1);
                    }
                }
                if (startCol > this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(startCol - 1, r);
                    }
                }
                if (startRow > this.minRow && startCol > 0)
                    this.requestTile(startCol - 1, startRow - 1);
                break;
            case "ll":
                if (endRow < this.rows + this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, endRow);
                    }
                }
                if (startCol > this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(startCol - 1, r);
                    }
                }
                if (endRow < this.rows + this.minRow && startCol > 0)
                    this.requestTile(startCol - 1, endRow);
                break;
            case "ur":
                if (startRow > this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, startRow - 1);
                    }
                }
                 if (endCol < this.columns + this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(endCol, r);
                    }
                }
                if (startRow > 0 && endCol < this.columns + this.minColumn)
                    this.requestTile(endCol, startRow - 1);
               break;
            case "lr":
                if (endRow < this.rows + this.minRow) {
                    for (var c = startCol;c < endCol;c++) {
                        this.requestTile(c, endRow);
                    }
                }
                 if (endCol < this.columns + this.minColumn) {
                    for (var r = startRow;r < endRow;r++) {
                        this.requestTile(endCol, r);
                    }
                }
                if (startRow > 0 && endCol < this.columns + this.minColumn)
                    this.requestTile(endCol, endRow);
                break;
   
        }
   }
   
   this.requestTile = function(c, r, update) {
        if (update==null) update = false; 
        var tileName = "";
        var time = new Date();
        var rc = this.ResourceCollection;
        for (var i=rc.length-1; i>=0;i--) {
            tileName = 'MapTile_' + this.controlName + "_" + c + '_' + r;
                if (rc[i].displayedTiles[tileName]==null) {
                    rc[i].displayedTiles[tileName] = tileName;
                    if (rc[i].visible) {
                        if (rc[i].isWithinLimits(c, r) && rc[i].mappedLevel>-2) {     ///// Added for resource limit check
                            if ((rc[i].tileServerUrl.length>0 || rc[i].tileServerUrlGenerator.length>0) && this.totalLevels>0) { 
                                if (rc[i].mappedLevel>-1) { ///// Added for resource mapping check
                                    this.pendingTiles.add(rc[i].id + "_" + c + "_" + r);     ///// Added for returned tiles check                                    
                                    var imageUrl = "";
                                    if (c>=0 && r>=0) { // don't request a negative tile from a cached resource
                                        if (rc[i].tileServerUrl.length>0 && rc[i].tileServerUrlGenerator.length==0) {
                                            imageUrl = rc[i].tileServerUrl + "&level=" + rc[i].mappedLevel + "&column=" + c + "&row=" + r + "&time=" + time.getTime();  ///// Added for resource mapping check
                                        } else {
                                            var cacheCall = rc[i].tileServerUrlGenerator + "(" + rc[i].mappedLevel + ", " + c + ", " + r + ", '" + rc[i].tileServerUrl + "');";  ///// Added for resource mapping check
                                            imageUrl = eval(cacheCall);
                                        } 
//                                         if (imageUrl!=null && imageUrl.length>0 && imageUrl.toLowerCase().indexOf("http")==-1) {
//                                            alert(imageUrl);
//                                            imageUrl = "";
//                                        }
                                   } 
                                    this.updateTileImage(c, r, imageUrl, update, rc[i].id, false); 
                                }  else {
                                    this.dynamicTileRequest(rc[i].id, c, r, update);
                                }  ///// Added for resource mapping check 
                            } else {
                                this.dynamicTileRequest(rc[i].id, c, r, update);
                            } // end if
                        } else {
                            this.pendingTiles.add(rc[i].id + "_" + c + "_" + r);     ///// Added for returned tiles check 
                            this.updateTileImage(c, r, "", update, rc[i].id, false); //end if (rc[i].isWithinLimits(c, r))  ///// Added for resource limit check
                        }
                    } // end  if (rc[i].visible)
            } else if (update) 
                if (this.useZoomAnimation)  this.updateMapDiv2(); // end if (rc[i].displayedTiles[tileName]==null)
        } // end for
   }
  
    this.dynamicTileRequest = function(resourceId, column, row, update) {
            var argument = "EventArg=DrawTile&coords=" + column + "," + row + "&resource=" +resourceId;
            var context = this.controlName; 
            if (update)
                context += ",UpdateDiv2," +  resourceId;
            else
                context += ",," +  resourceId;  
            this.pendingTiles.add(resourceId + "_" + column + "_" + row);     ///// Added for returned tiles check
            window.setTimeout("var argument='" + argument + "'; var context='" + context + "'; eval(\"" + this.tileCallbackFunctionString + "\");", 0);
    }   
  
    this.requestResourceTile = function(c, r, resourceId, update) {
        if (update==null) update = false; 
        if (resourceId==null) resourceId = mapDefaultResourceId;
        var rc = this.ResourceCollection;
        var i = rc.getPosition(resourceId);
        if (i!=-1) {
            var tileName = 'MapTile_' + this.controlName + "_" + c + '_' + r;
            if (rc[i].displayedTiles[tileName]==null) {
                rc[i].displayedTiles[tileName] = tileName;
                if (rc[i].visible) {
                    if (rc[i].isWithinLimits(c, r) && rc[i].mappedLevel>-2) {        ///// Added for resource limit check
                        if ((rc[i].tileServerUrl.length>0 || rc[i].tileServerUrlGenerator.length>0) && this.totalLevels>0) { 
                            if (rc[i].mappedLevel>-1) { ///// Added for resource mapping check
                                this.pendingTiles.add(rc[i].id + "_" + c + "_" + r);     ///// Added for returned tiles check 
                                var imageUrl = "";
                                if (c>=0 && r>=0) { // don't request a negative tile from a cached resource
                                    if (rc[i].tileServerUrl.length>0 && rc[i].tileServerUrlGenerator.length==0) {
                                        imageUrl = rc[i].tileServerUrl + "&level=" + rc[i].mappedLevel + "&column=" + c + "&row=" + r + "&time=" + time.getTime(); ///// Added for resource mapping check 
                                    } else {
                                        var cacheCall = rc[i].tileServerUrlGenerator + "(" + rc[i].mappedLevel + ", " + c + ", " + r + ", '" + rc[i].tileServerUrl + "');";  ///// Added for resource mapping check 
                                        imageUrl = eval(cacheCall);
                                    } 
                                }
                                this.updateTileImage(c, r, imageUrl, update, rc[i].id, false); 
                            }  else {
                                this.dynamicTileRequest(rc[i].id, c, r, update);
                            }  ///// Added for resource mapping check
                            
                        } else {
                            this.dynamicTileRequest(rc[i].id, c, r, update);
                        } // end if
                    } else {
                        this.pendingTiles.add(rc[i].id + "_" + c + "_" + r);     ///// Added for returned tiles check 
                        this.updateTileImage(c, r, "", update, resourceId, false);  // end if (rc[i].isWithinLimits(c, r))       ///// Added for resource limit check
                    }
                } // end  if (rc[i].visible)
            } else if (update) 
                if (this.useZoomAnimation)  this.updateMapDiv2(); // end if (rc[i].displayedTiles[tileName]==null)
        } else {
            alert("Unable to find " + resourceId);
        } 
    }      
   
    // function for resizing the map object
    this.resize = function(width, height, adjustExtent) {
        if (adjustExtent==null) adjustExtent = false;
        this.lastViewBox = new RectangleObject("dummy", 0, 0, this.viewWidth, this.viewHeight);
        this.viewWidth = width;
        this.viewHeight = height;
        var enlargeView = false;
        var container = this.containerObject;
        if (container!=null) {
            container.style.width = width + "px";
            container.style.height = height + "px";
        }
        this.width = width;
        this.height = height;
        this.columnsPerView = Math.ceil(width/this.tileWidth);
        this.rowsPerView = Math.ceil(height/this.tileHeight);
        this.getTopLeftTile();
        if (this.lastWidth<width || this.lastHeight<height) enlargeView = true;
        this.lastWidth = width;
        this.lastHeight = height;
        this.resizeExtent = adjustExtent;
        if (this.boxObject!=null) {
            this.boxObject.style.width = width + "px";
            this.boxObject.style.height = height + "px";
        }
        this.createMapDiv2();
        var argument = "Resize&width=" + width + "&height=" + height + "&startup=" + this.startUp;
        if (enlargeView && !this.startUp) 
            this.updateView(width, height, true);
        this.startUp = false;

        postBack(this.controlName, argument);
    }
    
    this.resizeToBrowserWindow = function() {
        var width = getWinWidth();
        var height = getWinHeight();
        this.resize(width, height);
    }
    
    this.resizeToWindow = function() {
        if (this.enableResizeEvent ) {
            if (isNav) {
                // shrink the map temporarily for Moz so there are no scrollbars on smaller window
                this.containerObject.style.width = "1px";
                this.containerObject.style.height = "1px";
            }
            var width = getMapWidth(this.containerObject);
            var height = getMapHeight(this.containerObject);
            if (this.lastWidth!=width || this.lastHeight!=height)
                this.resize(width, height);
        }
    }
    
    this.resizeToParent = function() {
        if (this.enableResizeEvent ) {
            var topMapDiv = document.getElementById(this.id);
            var width = topMapDiv.parentElement.clientWidth;
            var height = topMapDiv.parentElement.clientHeight;  
            if (this.lastWidth!=width || this.lastHeight!=height)
                this.resize(width, height);
        }
    }
    
    // function to obtain array of positions of the tiles that are visible in view
    this.getViewTiles = function() {
        var vTiles = new Array();
        this.getTopLeftTile();
        var startCol = this.currentLeftColumn;
        var startRow = this.currentTopRow;
        var lastCol = this.currentRightColumn;
        var lastRow = this.currentBottomRow;
        //alert(startCol + ", " + startRow + ", " + lastCol + ", " + lastRow);
        var i = 0;
        for (var r=startRow;r<=lastRow;r++) {
            for (var c=startCol;c<=lastCol;c++) {
                vTiles[i] = new TileObject(c, r);
                i++;
            }
        }
        return vTiles;
    }
    
    this.getViewTilesString = function() {
        this.getTopLeftTile();
        var startCol = this.currentLeftColumn;
        var startRow = this.currentTopRow;
        var lastCol = this.currentRightColumn;
        var lastRow = this.currentBottomRow;
        //alert(startCol + ", " + startRow + ", " + lastCol + ", " + lastRow);
        var s = "";
        for (var r=startRow;r<=lastRow;r++) {
            for (var c=startCol;c<=lastCol;c++) {
                if (s.length>0) s += "|";
                //s += c + "," + r;
                s += "MapTileImage_" + this.controlName + "_" + c + "_" + r;
            }
        }
        return s;
    }
    

    this.createMapDiv2 = function() {
        var tw = this.columnsPerView + 1;
        var th = this.rowsPerView + 1;
        m_imageWidth = this.tileWidth * tw;
        m_imageHeight = this.tileHeight * th;
        m_centerX = m_imageLeft + Math.round(m_imageWidth / 2);
        m_centerY = m_imageTop + Math.round(m_imageHeight / 2);
        //alert(m_imageWidth + " x " + m_imageHeight);
        var s = '<table width="100%" height="100%" cellspacing="0" cellpadding="0" >\n';

        var rc = this.ResourceCollection;
        var ri = rc.getPosition(this.baseResourceId);
        //for (var ri=rc.length-1;ri>=0;ri++) {
        for (var r=0;r<th;r++) {
            s += '<tr height="' + (1 / th * 100) + '%">\n';
            for (var c=0;c<tw;c++) {
                s += '<td width="' + (1 / tw * 100) + '%" height="' + (1 / th * 100) + '%" >\n<div id="' + this.controlName + '_MapAnimationDiv_' + c + '_' + r + '" style="width:' + this.tileWidth + 'px; height:' + this.tileHeight + 'px; overflow: hidden;" >\n';
                //s += '<td width="' + (1 / tw * 100) + '%" height="' + (1 / th * 100) + '%" >\n<div id="' + this.controlName + '_MapAnimationDiv_' + c + '_' + r + '" style="width: 100%; height: 100%; overflow: hidden;" >\n';
                var imageName2 = "MapTileImage2_" + this.controlName + "_" + c + "_" + r + "_" + this.baseResourceId;
                    s +='<img id="' + imageName2 + '" name="' + imageName2 + '" style="width:100%; height:100%" border=0 vspace=0 hspace=0 src="' + this.blankImageObject.src + '" />';
                s += '</div></td>\n';
            }
            s += '</tr>\n';
        }
        //}
        
        s += '</table>\n';
        this.lastColumnsPerView = this.columnsPerView;
        this.lastRowsPerView = this.rowsPerView;
        this.lastTileWidth = this.tileWidth;
        this.lastTileHeight = this.tileHeight;
        this.divScaleObject2.style.width = m_imageWidth + "px";
        this.divScaleObject2.style.height = m_imageHeight + "px";
        
        this.divScaleObject2.innerHTML = s;
    }
    
    this.updateMapDiv2 = function() {
        hideLayer(this.divId2);
        var doCreateMapDiv2 = false;        
        if (this.tileWidth!=this.lastTileWidth) doCreateMapDiv2 = true;
        if (this.columnsPerView!=this.lastColumnsPerView) doCreateMapDiv2 = true;
        if (this.tileHeight!=this.lastTileHeight) doCreateMapDiv2 = true;
        if (this.rowsPerView!=this.lastRowsPerView) doCreateMapDiv2 = true;
        
        if (doCreateMapDiv2)
            this.createMapDiv2(); 
        this.divObject2.style.zoom = 1.0;
        this.divScaleObject2.style.zoom = 1.0;
        this.divScaleObject2.style.width = m_imageWidth + "px";
        this.divScaleObject2.style.height = m_imageHeight + "px";
        this.getTopLeftTile();
        var startCol = this.currentLeftColumn;
        var startRow = this.currentTopRow;
        var lastCol = this.currentRightColumn;
        var lastRow = this.currentBottomRow;
        var tw = this.columnsPerView + 1;
        var th = this.rowsPerView + 1;
        if (!isIE) {
            for (var r=0; r<th; r++) {
                for (var c=0; c< tw; c++) {
                    div = document.getElementById(map.controlName + '_MapAnimationDiv_' + c + '_' + r);
                    if (div!=null) {
                        div.style.width = map.tileWidth + "px";
                        div.style.height = map.tileHeight + "px"; 
                    }  
                } 
            } 
        }
        //alert(startCol + ", " + startRow + ", " + lastCol + ", " + lastRow);
        if (startCol<0)
            m_imageLeft = this.currentXOffset - this.tileWidth;
        else
            m_imageLeft = 0  - this.currentXOffset;
        if (startRow<0)
            m_imageTop = this.currentYOffset - this.tileHeight;
        else
            m_imageTop = 0 - this.currentYOffset;
        this.divObject2.style.left = m_imageLeft + "px";
        this.divObject2.style.top = m_imageTop + "px";
        //this.divObject2.style.top = "0px";
        this.divScaleObject2.style.width = m_imageWidth + "px";
        this.divScaleObject2.style.height = m_imageHeight + "px";
        var imageName, imageName2, imgObj, imgObj2, tileName; 
        var cc = startCol;
        var rr = startRow;
        var rc = this.ResourceCollection;
        var ri = rc.getPosition(this.baseResourceId);
        if (ri>=0) {                   ///// Added for dynamic resource addition/deletion 
            var rcBaseIndex = ri;
            if (!rc[ri].visible) 
                ri = rc.getBottomVisiblePosition();
            var forcePng = false;
            //for (var ri=rc.length;ri>=0;ri++) {
    //        if (rc[ri].visible) {
               for (var r=0;r<th;r++) {
                    for (var c=0;c<tw;c++) {
                        tileName = "MapTile_" + this.controlName + "_" + cc + "_" + rr;
                        imageName = "MapTileImage_" + this.controlName + "_" + cc + "_" + rr + "_" + this.baseResourceId;
                        imageName2 = "MapTileImage2_" + this.controlName + "_" + c + "_" + r + "_" + this.baseResourceId;
                        imgObj = document.getElementById(imageName);
                        imgObj2 = document.getElementById(imageName2);
                        forcePng = (rc[ri].pngTiles[tileName]!=null && rc[ri].pngTiles[tileName].length>0); 
                        if (imgObj!=null) { 
                            if (imgObj.src!=rc[ri].displayedTiles[tileName])
                                imgObj2.src = rc[ri].displayedTiles[tileName];
                            else  
                                imgObj2.src = imgObj.src;
                            if (rcBaseIndex!=ri || this.forcePngAlphaOnBase) 
                                alphaBlend(imgObj2, forcePng); 
                        } else 
                            imgObj2.src = this.blankImageObject.src
                        cc++;
                    }
                    rr++;
                    cc=startCol;
                }
           //} 
    //        }
      }         ///// Added for dynamic resource addition/deletion
     //alert(this.divObject2.outerHTML);
    // Debug stuff that will be displayed in form element, if it exists
    if (checkForFormElement(document, 0, "MapDebugBox")) document.forms[0].MapDebugBox.value += ("Updated MapDiv2\n"); 
    
        //this.divObject.style.cursor = this.cursor;
    }

    
    this.checkMapDiv2 = function() {
        this.getTopLeftTile();
        var startCol = this.currentLeftColumn;
        var startRow = this.currentTopRow;
        var lastCol = this.currentRightColumn;
        var lastRow = this.currentBottomRow;
        var imageName, imageName2, imgObj, imgObj2, tileName;
        var cc = startCol;
        var rr = startRow;
        var tw = this.columnsPerView + 1;
        var th = this.rowsPerView + 1;
        if (!isIE) {
            for (var r=0; r<th; r++) {
                for (var c=0; c< tw; c++) {
                    div = document.getElementById(map.controlName + '_MapAnimationDiv_' + c + '_' + r);
                    if (div!=null) {
                        div.style.width = map.tileWidth + "px";
                        div.style.height = map.tileHeight + "px"; 
                    }  
                } 
            } 
        }
        var rc = this.ResourceCollection;
        var ri = rc.getPosition(this.baseResourceId);
        if (ri>=0) {            ///// Added for dynamic resource addition/deletion
            var rcBaseIndex = ri;
            if (!rc[ri].visible) 
                ri = rc.getBottomVisiblePosition();
            var forcePng = false;
            //for (var ri=rc.length-1;ri>=0;ri++) {
            //if (rc[ri].visible) {
                for (var r=0;r<th;r++) {
                    for (var c=0;c<tw;c++) {
                        tileName = "MapTile_" + this.controlName + "_" + cc + "_" + rr;
                        imageName = "MapTileImage_" + this.controlName + "_" + cc + "_" + rr + "_" + this.baseResourceId;
                        imageName2 = "MapTileImage2_" + this.controlName + "_" + c + "_" + r + "_" + this.baseResourceId;
                        imgObj = document.getElementById(imageName);
                        imgObj2 = document.getElementById(imageName2);
                        if (imgObj!=null) { 
                            if (imgObj.src!=rc[ri].displayedTiles[tileName])
                                imgObj2.src = rc[ri].displayedTiles[tileName];
                            else  
                                imgObj2.src = imgObj.src;
                            if (rcBaseIndex!=ri || this.forcePngAlphaOnBase) 
                                alphaBlend(imgObj2, forcePng); 
                        } else 
                            imgObj2.src = this.blankImageObject.src
                        cc++;
                    }
                    rr++;
                    cc=startCol;
                }
            //}
            //}
        }              ///// Added for dynamic resource addition/deletion
    // Debug stuff that will be displayed in form element, if it exists
    if (checkForFormElement(document, 0, "MapDebugBox")) document.forms[0].MapDebugBox.value += ("Checked MapDiv2\n"); 
    
    }
    
    this.swapMode = function(e) {
        if (shiftPressed) {
            this.mode = this.shiftMode;
            this.actionType = this.shiftAction;
            this.cursor = this.shiftCursor;
            this.divObject.style.cursor = this.cursor;
            
        } else if (ctrlPressed) {
            this.mode = this.ctrlMode;
            this.actionType = this.ctrlAction;
            this.cursor = this.ctrlCursor;
            this.divObject.style.cursor = this.cursor;
            eval(this.ctrlFunction);
        
        } else if (altPressed) {
            this.mode = this.altMode;
            this.actionType = this.altAction;
            this.cursor = this.altCursor;
            this.divObject.style.cursor = this.cursor;
        
        }
    }
    
    this.enableScrollWheel = function(useScrollWheel) {
        this.useScrollWheel = (useScrollWheel!=null) ? useScrollWheel : false;
        var eventName = isIE ? "onmousewheel" : "DOMMouseScroll";
        if (this.useScrollWheel) {          
            if (isIE) 
                this.divObject.detachEvent(eventName, funct);
            else
                this.divObject.removeEventListener(eventName,onWheelScroll, false);
        } else {
            if (this.useZoomAnimation) this.updateMapDiv2;
            if (isIE) 
                this.divObject.attachEvent(eventName, funct);
            else
                this.divObject.addEventListener(eventName,onWheelScroll, false);
        }
    }
    
    // convert decimal delimiter, if necessary
    this.setDecimalDelimiter = function(theNumber, delimiter) {
        if (delimiter==null) delimiter = this.decimalDelimiter;
        var comma = ",";
        var dot = ".";
        var charOut = comma;
        var charIn = dot;
        var numberString = new String(theNumber);
        if (delimiter==",") {
            charOut = dot;
            charIn = comma;
        }
        var pos = numberString.indexOf(charOut);
        if (pos!=-1) {
            var begin = numberString.substring(0,pos);
            var ending = numberString.substring(pos+1, numberString.length);
            numberString = begin + charIn + ending;
        }
        return numberString;
    }

    this.ResourceCollection = new Array();
    this.ResourceCollection.add = esriResourceCollectionAdd;  // map.ResourceCollection.add(resource);
    this.ResourceCollection.contains = esriResourceCollectionContains;  // hasIt =  map.ResourceCollection.contains(resourceId);
    this.ResourceCollection.find = esriResourceCollectionFind;  // resource = map.ResourceCollection.find(resourceId);
    this.ResourceCollection.insert = esriResourceCollectionInsert;    // map.ResourceCollection.insert(resource, position);
    this.ResourceCollection.remove = esriResourceCollectionRemove;  // map.ResourceCollection.remove(resourceId);
    this.ResourceCollection.removeAt = esriResourceCollectionRemoveAt;  // map.ResourceCollection.removeAt(position);
    this.ResourceCollection.getPosition = esriResourceCollectionPosition; // position = map.ResourceCollection.getPosition(resourceId);
    this.ResourceCollection.replace = esriResourceCollectionReplace;    // map.ResourceCollection.replace(newResource, oldResourceId); 
    this.ResourceCollection.replaceAt = esriResourceCollectionReplaceAt;    // map.ResourceCollection.replace(newResource, position); 
    this.ResourceCollection.setObjects = esriResourceCollectionSetObjects;     // map.ResourceCollection.setObjects(); 
    this.ResourceCollection.redraw = esriResourceCollectionRedraw;   //map.ResourceCollection.redraw(resourceId);
    this.ResourceCollection.getBottomVisiblePosition = esriResourceCollectionBottomVisiblePosition;  // position = map.ResourceCollection.getBottomVisiblePosition();
    this.ResourceCollection.mapObject = this; 
    this.baseResourceId = mapDefaultResourceId; 
   
  ///// Added for returned tiles check 
    this.pendingTiles = new Array();
    this.pendingTiles.add = esriPendingTilesAdd;
    this.pendingTiles.find = esriPendingTilesFind;
    this.pendingTiles.remove = esriPendingTilesRemove;  
    this.pendingTiles.mapObject = this; 
    this.pendingTiles.add_onRequestsPending = esriAddOnRequestsPending;
    this.pendingTiles.add_onRequestsRemove = esriAddOnRequestsRemove;
    this.pendingTiles.add_onRequestsCompleted = esriAddOnRequestsCompleted;   
    this.pendingTiles.onRequestsPending = null;   
    this.pendingTiles.onRequestsRemove  = null;
    this.pendingTiles.onRequestsCompleted = null; 
 ///// Added for returned tiles check
   
    this.setSnapCircleSize = function(radius) {
        this.snapCircleObject.style.width = (radius * 2) + "px";
        this.snapCircleObject.style.height = (radius * 2) + "px"; 
        if (isNav && nav8) {
            //var svo = this.snapCircleObject.vectorObject;
            var svo = new VectorObject(this.snapCircleId); 
            svo.clear();
            svo.divColor = "Red";  
            svo.circle(radius, radius, radius);
            svo.draw();
        }
    }  

    this.snapCircleVisible = function(visible) {
        if (visible)
            this.snapCircleObject.style.visibility = "visible";  
        else
            this.snapCircleObject.style.visibility = "hidden";         
    }   
    
} // Map Object

//function createMapObject(controlName, mapContainerName, mapWidth, mapHeight, pageID, backColor, continuousCallback, enableTileCaching, tileServerUrl, navigationEnabled, callBackFunctionString, tileCallbackFunctionString, startResourceList) // debug to test against older build expecting tileServerUrl
function createMapObject(controlName, mapContainerName, mapWidth, mapHeight, pageID, backColor, continuousCallback, navigationEnabled, callBackFunctionString, tileCallbackFunctionString, startResourceList, enableTileCaching, ToolsSupportingClientPostBack)
{
    var percentageBased=false;
    if ((String(mapWidth).indexOf("%")!=-1)||(String(mapHeight).indexOf("%")!=-1)) percentageBased=true;
    
    var width = null;
    var height = null;
    
    if (!percentageBased)
    {
        width=String(mapWidth).replace("px","");
        height=String(mapHeight).replace("px","");
    }
    else
    {
        width=mapWidth;
        height=mapHeight;
    }
    Maps[controlName] = new MapObject(controlName, width, height, 0, 0, -1, 1, 1);
    map = Maps[controlName]; 
    if (pageID!=null) map.pageID = pageID;
    if (backColor!=null) map.backColor = backColor;
    if (navigationEnabled!=null) map.navigationEnabled = navigationEnabled;
    if (startResourceList==null)  
        startResourceList = mapDefaultResourceId + "||true|";
    map.startResourceList = startResourceList; 
    map.createDivs(mapContainerName, startResourceList);
    if (continuousCallback!=null) map.continuousCallback = continuousCallback;
    if (enableTileCaching!=null) map.enableTileCaching = enableTileCaching;
    if (ToolsSupportingClientPostBack!=null) map.forcePostBackEvent = ToolsSupportingClientPostBack;
    map.callBackFunctionString = callBackFunctionString;
    map.tileCallbackFunctionString = tileCallbackFunctionString;
    map.identifyCallbackFunctionString = identifyCallbackFunctionString;
    map.vectorCallbackFunctionString = vectorCallbackFunctionString;
    if (percentageBased) map.resize(map.viewWidth, map.viewHeight);
}

function updateTiles(tileString, context) {

//      // Debug stuff that will be displayed in form element, if it exists
//      if (checkForFormElement(document, 0, "MapDebugBox")) document.forms[0].MapDebugBox.value += ("Tile Response: " + context + ": " + tileString + "\n"); 

    var contextArray = context.split(",");
    var update = false;
    var resourceId = mapDefaultResourceId; 
    var imageType = ""; 
    if (contextArray.length>1 && contextArray[1]=="UpdateDiv2")  update = true;
    if (contextArray.length>2) resourceId = contextArray[2]; 
    //alert(tileString);
    if (tileString==null) {
        alert("No response");
    } else {  
        var tileStrings = tileString.split("^^^");
        var t;
        for (var i=0;i<tileStrings.length;i++) {
            t = tileStrings[i].split(",");
            if (t.length>3)
            {
                  if (t[3]=="null")
                    resourceId = null;
                  else
                    resourceId = t[3];
            }
            if (t.length>4) {
                if (t[4].length>0) 
                    imageType = t[4].toLowerCase(); 
            }           
            Maps[contextArray[0]].updateTileImage(t[0],t[1],t[2], update, resourceId, imageType);
        }
        lastResponseReceivedTime = new Date();  
   } 
 
}

// function for handling server response for scale change
function changeLevel(levelString, context) {
    commonCallbackFree = true;
    lastResponseReceivedTime = new Date();
    var levelArray = levelString.split(":::");
    var contextArray = context.split(",");
    window.setTimeout("Maps['" + levelArray[1] + "'].setUpLevelGrid(" + levelArray[2] + "," + levelArray[3] + "," + levelArray[4] + "," + levelArray[5] + "," + levelArray[6] + "," + levelArray[7] + "," + levelArray[8] + "," + levelArray[9] + "," + levelArray[10] + ");", 1);
}


function TileObject(column, row) {
    this.column = column;
    this.row = row;
}   


// function for setting map control settings    
function addMapControlSettings(mapObj, pageID, toolsForcingPostBack, useScrollWheel, defaultShiftTool, defaultAltTool, useZoomAnimation) {
    mapObj.pageID = pageID;
    //mapObj.toolsForcingPostBack = toolsForcingPostBack;
    if (useScrollWheel!=null) mapObj.useScrollWheel = useScrollWheel;
    if (useZoomAnimation==null) useZoomAnimation = true;
    mapObj.useZoomAnimation = useZoomAnimation;
    if (mapObj.useScrollWheel) {
        var eventName = isIE ? "mousewheel" : "DOMMouseScroll";
        var eventHandler = isIE ? mousewheelhandlepiv : onWheelScroll;
        addEvent(mapObj.divObject, eventName, eventHandler);
        if (mapObj.snapCircleObject!=null) addEvent(mapObj.snapCircleObject, eventName, eventHandler);
    }
    if (defaultShiftTool!=null) mapObj.shiftMode = defaultShiftTool;
    if (defaultAltTool!=null) mapObj.altMode = defaultAltTool;
}

// function for getting map object assoicated with div event
function getSelectedMapObject(e) {
    var m = null;

        m = getMapObjectByXY(mouseX, mouseY);
        var box = calcElementPosition(m.divId);
        m.pageLeft = box.left;
        m.pageTop = box.top;
        box = calcElementPosition(m.containerDivId);
        m.containerLeft = box.left;
        m.containerTop = box.top;
        if (isIE) {
            m.containerLeft+=2;
            m.containerTop+=2;
        }
        m.width = box.width;
        m.height = box.height;
        divObj = document.getElementById(m.divId);
        lastmap = m;
        box=null;

    return m;
}

// function for getting map object by cursor location
function getMapObjectByXY(x,y) {
    var mm = null;
    for (var i=0;i<MapNames.length;i++) {
        var m = Maps[MapNames[i]];
        var box = calcElementPosition(m.containerDivId);
        var right = box.left + box.width;
        var bottom = box.top + box.height;
        if ((x>=box.left) && (x<=right) && (y>=box.top) && (y<=bottom)) {
            mm = m;
            //break;
        }
        box=null;
    }
    return mm;
}

function getMapObjectByDivId(divid) {
    var lastpos = divid.lastIndexOf("_");
    var pos = divid.indexOf("LineDiv_");
    if (pos!=-1) 
        divid = "MapDiv_" + divid.substring(8);
    else {
        pos = divid.indexOf("SnapCircle_");
        if (pos!=-1) divid = "MapDiv_" + divid.substring(11);
    }
    pos = divid.indexOf("MapDiv_");
//  if (pos==-1) pos = divid.indexOf
    var m = null;
    if (pos!=-1) {
        // add logic for testing if the id has an underscore in the name
        var control = divid.substring(7);
        m = Maps[control];
        var box = calcElementPosition(m.divId);
        m.pageLeft = box.left;
        m.pageTop = box.top;
        box = calcElementPosition(m.containerDivId);
        m.containerLeft = box.left;
        m.containerTop = box.top;
        if (isIE) {
            m.containerLeft+=2;
            m.containerTop+=2;
        }

        box=null;
    }
    return m;
}


///////////////////////////////////// Set Tool Functions /////////////////////////////////////
// Drag actions - pan
function MapDragImage(divid, mode, showLoading, cursor) {
    var thisCursor = "move";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "DragImage", thisCursor, -1, "hidden", "");
    }
}
    
// Rectangular actions - zooms, select
function MapDragRectangle(divid, mode, showLoading, cursor) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "DragRectangle", thisCursor, -1, "hidden", "");
    }
}
    
// Point actions - identify, CenterAt, ZoomToPoint, etc.
function MapPoint(divid, mode, showLoading, cursor) {
    var thisCursor = "pointer";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "Point", thisCursor, -1,"hidden", "");
    }
}
    
// Line actions - measure, sketch, select, etc.
function MapLine(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 0, vectorToolbarState, 
        "Line - Click to start line. Move cursor to change line and angle. Click again to finish line.");
    }
}

// Polyline action - measure, sketch, select, etc.
function MapPolyline(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 1, vectorToolbarState, 
        "Polyline - Click to start line. Click again to add vectors. Double-click to add last vector and complete polyline.");
    }
}

// Polygon action - sketch, select, etc.
function MapPolygon(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 2, vectorToolbarState, 
        "Polygon - Click to start line. Click again to add vectors. Double-click to add last vector and complete polygon.");
    }
}

// Circle action - sketch, select, etc.  - click/move/click
//function MapCircleClick(divid, mode, showLoading) {
function MapCircle(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 3, vectorToolbarState, 
        "Circle - Click for center of circle. Move cursor to resize circle. Click again to complete circle.");
    }
}

// Circle action - sketch, select, etc. - mousedown/drag/mouseup
function MapDragCircle(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "DragShape", thisCursor, 3, vectorToolbarState, "");
    }
}

// Oval action - sketch, select, etc. - click/move/click
function MapOval(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 4, "hidden", 
            "Oval - Click for start of oval. Move cursor to resize oval. Click again to complete oval.");
    }
}

// Oval action - sketch, select, etc. - mousedown/drag/mouseup
function MapDragOval(divid, mode, showLoading, cursor) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "DragShape", thisCursor, 4, vectorToolbarState, "");
    }
}

// Box vector action - sketch, select, etc. - click/move/click
function MapBox(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "ClickShape", thisCursor, 5, vectorToolbarState, "Box - Click for start of box. Move cursor to resize box. Click again to complete box.");
    }
}

// Box vector action - sketch, select, etc. - mousedown/drag/mouseup
function MapDragBox(divid, mode, showLoading, cursor, vectorToolbarState) {
    var thisCursor = "crosshair";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    if (vectorToolbarState==null) vectorToolbarState = "hidden";
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "DragShape", thisCursor, 5, vectorToolbarState, "");
    }
}

// Point actions - identify, CenterAt, ZoomToPoint, etc.
function MapTips(divid, mode, showLoading, cursor) {
    var thisCursor = "pointer";
    if ((cursor!=null) && (cursor!="")) thisCursor = cursor;
    map = Maps[divid];
    if (map!=null) {
        map.setTool(mode, showLoading, "MapTips", thisCursor, -1,"hidden", "");
    }
}

///////////////////////////////////// Set Tool Functions /////////////////////////////////////


////////////////////////////////////// Event Handlers ///////////////////////////////////////

// function for handling mousedown event for a map object
function MapMouseDown(e, controlName) {
    if (getSessionLapse() < maximumLapseTime) {
        if (isLeftButton(e)) {
        
        getXY(e);
        map = getMapObjectByDivId(this.id);
        
        checkShiftCtrlAltKeys(e);
        if (shiftPressed || ctrlPressed || altPressed)
            map.swapMode();
        //alert(map.controlName);
        switch (map.actionType) {
            case "DragImage":
                    map.drawBox = false;
                    map.drawShape = false;
                    if (!map.dragImage) {
                        map.dragImage = true;
                        x1=mouseX;
                        y1=mouseY
                        x2=x1;
                        y2=y1;
                        x3 = x2;
                        y3 = y2;
                        document.onmouseup = map.MapMouseUp;
                            map.tempMoveFunction = document.onmousemove;
                        document.onmousemove = map.MapMouseMove;
                        var box = calcElementPosition(map.divId);
                        var box2 = calcElementPosition(map.containerDivId); 
                        panStartLeft = box.left - box2.left;
                        panStartTop = box.top - box2.top;
                    }
                break;
            case "DragRectangle":
                    map.dragImage = false;
                    map.drawShape = false;
                    if (!map.drawBox) {
                        map.drawBox = true;
                        x1=mouseX;
                        y1=mouseY;
                        x2=x1+1;
                        y2=y1+1;
                        
                        if (dragbox!=null) {
                            dragbox.divObject.onmousemove = map.MapMouseMove;
                            dragbox.divObject.onmouseup = map.MapMouseUp;
//                          dragbox.update(x1,y1,x2,y2, map.dragBoxColor);
//                          dragbox.show();
                            dragbox.clip(map.dragLineWidth);
                        }
                        document.onmouseup = map.MapMouseUp;
                            map.tempMoveFunction = document.onmousemove;
                        document.onmousemove = map.MapMouseMove;
                    }
                break;
            case "Point":
                if (!ctrlPressed) {
                    map.divObject.style.cursor = "wait";
                    var box = calcElementPosition(map.containerDivId); 
                    zleft = mouseX - box.left;
                    ztop = mouseY - box.top;

                    map.xMin=zleft;
                    map.yMin=ztop;
                
                    if (map.preModeExecFunction != null)
                        eval(map.preModeExecFunction);
                
                    postBack(map.controlName, 'Point');
                }
                break;
            case "DragShape":
                iframeHideWorkaroundForVML(); 
                map.dragImage = false;
                map.drawShape = true;
                map.drawBox = false;
                map.divObject.onclick = null;
                map.divObject.ondblclick = null;
                map.divObject.onmouseup = map.MapMouseUp;
                map.vectorObject.vectordiv.onclick = null;
                map.vectorObject.vectordiv.ondblclick = null;
                map.vectorObject.vectordiv.onmousemove = map.MapMouseMove;
                map.vectorObject.vectordiv.onmouseup = map.MapMouseUp;
                    map.tempMoveFunction = map.divObject.onmousemove;
                map.divObject.onmousemove = MapMouseMove;
            
                controlType = "map";
                
                var box = calcElementPosition(map.containerDivId);
                map.vectorObject.pixelObject.x1 = mouseX - box.left;
                map.vectorObject.pixelObject.y1 = mouseY - box.top;

                map.vectorObject.vectorCount = 1;
                map.vectorObject.pixelObject.lastX = map.vectorObject.pixelObject.x1;
                map.vectorObject.pixelObject.lastY = map.vectorObject.pixelObject.y1;
                
                break;
            }
        }
    } else
        showLapseAlert();
    return false;
}

// function for handling mousemove event for a map object
function MapMouseMove(e) {
    getXY(e);
    switch (map.actionType) {
        case "DragImage":
            if (map.dragImage) {
                x2 = mouseX;
                y2 = mouseY;
                var xOffset = x2 - lastX;
                var yOffset = y2 - lastY;
                mouseDirection = getMouseDirection(xOffset, yOffset);
                x3 = x2;
                y3 = y2;
                nx = x2-x1;
                ny = y2-y1;
                lastX = x2;
                lastY = y2;
                var panMoveX = nx + panStartLeft;
                var panMoveY = ny + panStartTop;
                
                var currentX = panStartLeft + nx;
                var currentY = panStartTop + ny;
                map.moveTiles(currentX, currentY, mouseDirection);
            }
            break;
        case "DragRectangle":
            if (map.drawBox) {
                // stretch ZoomBox
                x2=mouseX;
                y2=mouseY;
                // adjustments to keep box within view... vital for zooms
                var box = calcElementPosition(map.containerDivId);
                var mapLeft = box.left;
                var mapTop = box.top;
                var vWidth = parseInt(map.viewWidth);
                var vHeight = parseInt(map.viewHeight);
                if (x2 < mapLeft) x2 = mapLeft;
                if (y2 < mapTop) y2 = mapTop;
                if (x2 > mapLeft + vWidth) x2 = mapLeft + vWidth;
                if (y2 > mapTop + vHeight) y2 = mapTop + vHeight;
                //window.status = x1 + ", " + y1 + ", " + x2 + ", " + y2;
                if (dragbox!=null) {
                    dragbox.clip(map.dragLineWidth);
                    dragbox.show();
                }  
            }
            break;
        case "ClickShape":
        case "DragShape":
            if (map.drawShape) {
                var vo = map.vectorObject;
                var pix = vo.pixelObject;
                var xycoord = vo.xyCoord;
                var box = calcElementPosition(map.containerDivId);
                pix.x2 = mouseX - box.left;
                pix.y2 = mouseY - box.top;
                switch (vo.mode) {
                    case 0:
                        vo.clear();
                        vo.line(pix.x1, pix.y1, pix.x2, pix.y2);
                        vo.draw();
                        break;
                    case 1:
                        var n = xycoord.x.length - 1;
                        vo.clear(); 
                        if (vo.vectorCount>1) {
                            vo.polyline(xycoord.x,xycoord.y);
                            vo.line(pix.x2, pix.y2, xycoord.x[n], xycoord.y[n]);
                        } else if (vo.vectorCount>0){
                            vo.line(pix.x1, pix.y1, pix.x2, pix.y2);
                        }
                        vo.draw();
                        break;
                    case 2:
                        var n = vo.vectorCount;
                        if (vo.vectorCount>0) {
                            if (vo.vectorCount==1) {
                                vo.clear();
                                vo.line(xycoord.x[0],xycoord.y[0],pix.x2,pix.y2);
                                vo.draw();
                            } else if (vo.vectorCount>0){
                                var tempx = new Array();
                                var tempy = new Array();
                                tempx = xycoord.x;
                                tempy = xycoord.y;
                                tempx[n] = pix.x2;
                                tempy[n] = pix.y2;
                                vo.clear();
                                vo.polygon(tempx, tempy);
                                vo.draw();
                            }
                        }
                        vo.draw();
                        break;
                    case 3:
                        var dwidth = Math.abs(pix.x2 - pix.x1);
                        var dheight = Math.abs(pix.y2 - pix.y1);
                        var dradius;
                        if ((dwidth == 0) || (dheight == 0))  {
                            dradius = (dwidth == 0) ? dheight : dwidth;
                        } else {
                            dradius = Math.sqrt((dwidth * dwidth) + (dheight * dheight));
                        }
                        
                        vo.clear();
                        vo.circle(pix.x1, pix.y1, dradius, true);
                        vo.draw();
                        break;
                    case 4:
                        var dwidth = Math.abs(pix.x2 - pix.x1);
                        var dheight = Math.abs(pix.y2 - pix.y1);
                        var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                        var dtop = (pix.y1 < pix.y2) ? pix.y1 : pix.y2;
                        vo.clear();
                        vo.oval(dleft, dtop, dwidth, dheight);
                        vo.draw();
                        break;
                    case 5:
                        // box
                        var dwidth = Math.abs(pix.x2 - pix.x1);
                        var dheight = Math.abs(pix.y2 - pix.y1);
                        var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                        var dtop = (pix.y2 < pix.y1) ? pix.y2 : pix.y1;
                        vo.clear();
                        vo.box(dleft, dtop,(dleft + dwidth), (dtop + dheight));
                        vo.draw();
                        break;
                    
                }
                break;
        }
        case "Point":
            //return false;
            break; 
    }
    if (map.moveFunction!=null) {
        map.moveFunction(e);
     }
    return false;
}

// function for handling mouseup event for a map object
function MapMouseUp(e) {
    //alert("MouseUp");
    var mapBox = calcElementPosition(map.containerDivId);
    switch (map.actionType) {
        case "DragImage":
            if (map.dragImage) {
                getXY(e);
                document.onmouseup = null;
                document.onmousemove = map.tempMoveFunction;
                
                finishDragImage(map);
                map.dragImage = false;
            }
            break;
        case "DragRectangle":
            
            if (map.drawBox) {
                map.drawBox = false;
                
                map.divObject.style.cursor = "wait";
                
                getXY(e);
                document.onmouseup = null;
                document.onmousemove = map.tempMoveFunction;
                if (dragbox!=null) {
                    dragbox.hide();
                    dragbox.clip(map.dragLineWidth);
                    dragbox.divObject.onmousemove = null;
                    dragbox.divObject.onmouseup = null;
                }
                // adjust for offsets
                zleft -= mapBox.left;
                zright -= mapBox.left;
                zbottom -= mapBox.top;
                ztop -= mapBox.top;
                map.xMin=zleft;
                map.yMin=ztop;
                map.xMax=zright;
                map.yMax=zbottom;
                if (map.preModeExecFunction != null)
                    eval(map.preModeExecFunction);                          
                map.maptipObject.innerHTML = "";
                postBack(map.controlName, 'DragRectangle');
                map.divObject.style.cursor = map.cursor;
            }
            break;
        case "DragShape": 
            iframeShowWorkaroundForVML();
            map.divObject.style.cursor = "wait";
            map.drawShape = false;
            var restart = false;
            var clientAction = "Line";
            var pix = map.vectorObject.pixelObject;
            switch (map.vectorObject.mode) {
                case 3:
                    var dwidth = Math.abs(pix.x2 - pix.x1);
                    var dheight = Math.abs(pix.y2 - pix.y1);
                    var dradius;
                    if ((dwidth == 0) || (dheight == 0))  {
                        dradius = (dwidth == 0) ? dheight : dwidth;
                    } else {
                        dradius = Math.sqrt((dwidth * dwidth) + (dheight * dheight));
                    }
                    coordString = pix.x1 + ":" + pix.y1 + ":" + dradius;
                    clientAction = "Circle";
                    break;
                case 4:
                    var dwidth = Math.abs(pix.x2 - pix.x1);
                    var dheight = Math.abs(pix.y2 - pix.y1);
                    var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                    var dtop = (pix.y1 < pix.y2) ? pix.y1 : pix.y2;
                    var centerX = dleft + (dwidth / 2);
                    var centerY = dtop + (dheight / 2);
                    coordString = centerX+ ":" + centerY + ":" + dwidth + ":" + dheight;
                    clientAction = "Oval";
                    break;
                case 5:
        
                    // box
                    var dwidth = Math.abs(pix.x2 - pix.x1);
                    var dheight = Math.abs(pix.y2 - pix.y1);
                    var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                    var dtop = (pix.y2 < pix.y1) ? pix.y2 : pix.y1;
                    coordString = dleft + ":" + dtop + "|" + (dleft + dwidth) + ":" + (dtop + dheight);
                    clientAction = "Rectangle";         
                    break;
                    
            }
            map.vectorObject.vectorCount = 0;
            map.vectorObject.xyCoord.x = new Array();
            map.vectorObject.xyCoord.y = new Array();
        
            map.divObject.ondblclick = null;
            map.vectorObject.vectordiv.onmousemove = null;
            map.vectorObject.vectordiv.ondblclick = null;
            map.divObject.onmousemove = map.tempMoveFunction;
            map.divObject.onmouseup = null;
            
            pix.lastX = -9999;
            pix.lastY = -9999;
            
            var m = map.controlName + "_mode";
            if (checkForFormElement(map.document, docFormID, "PostBackMode")) map.document.forms[docFormID].PostBackMode.value = map.document.forms[docFormID].elements[m].value;
            map.coords = coordString;
            
            postBack( map.controlName, map.document.forms[docFormID].elements[m].value);
            map.divObject.style.cursor = map.cursor;
            
            break;
        case "ClickShape":
            iframeHideWorkaroundForVML();
            map = getMapObjectByDivId(this.id);
            map.dragImage = false;
            map.drawShape = true;
            map.drawBox = false;
            var vo = map.vectorObject;
            var pix = vo.pixelObject;
            var xycoord = vo.xyCoord;
            getXY(e);
            var tb = document.getElementById(vectortoolbar);
            if (tb!=null) tb.style.visibility = map.currentVectorToolbarState;
            if (vo.vectorCount==0) {
                map.tempMoveFunction = map.divObject.onmousemove;
                map.divObject.onmousemove = MapMouseMove;
                vo.vectordiv.onmousemove = MapMouseMove;
                controlType = "map";
            }

            pix.x2 = mouseX - mapBox.left;
            pix.y2 = mouseY - mapBox.top;
            //alert((map.width) + ", " + (map.height));
            if (pix.lastX==pix.x2 && pix.lastY==pix.y2) {
                //if this is a double click(second click)
                //  then send it on to finish up
                MapDoubleClick(e);
            } else {
                if (vo.vectorCount==0) {
                    // starting vector
                    pix.x1 = mouseX - mapBox.left;
                    pix.y1 = mouseY - mapBox.top;
                    xycoord.x = new Array();
                    xycoord.y = new Array();
                    xycoord.x[0] = pix.x1;
                    xycoord.y[0] = pix.y1;  
                    switch (vo.mode) {
                        case 0:
                            clientAction = "Line";
                            break;
                        case 1:
                            clientAction = "Polyline";
                            break; 
                        case 2:
                            clientAction = "Polygon";   
                            break;
                        case 3:
                            clientAction = "Circle";
                            break;
                        case 4:
                            clientAction = "Oval";
                            break; 
                        case 5:
                            clientAction = "Rectangle";   
                            break;
                          
                    }
                
                } else {
                    switch (vo.mode) {
                        case 0:
                            // line
                            clientAction = "Line";
                            vo.clear();
                            vo.line(pix.x1, pix.y1, pix.x2, pix.y2);
                            vo.draw();
                            jumpToFinish = true;
                            break;
                        case 1:
                            // polyline
                            clientAction = "Polyline";
                            var n = xycoord.x.length;
                            xycoord.x[n] = pix.x2;
                            xycoord.y[n] = pix.y2;  
                            vo.clear(); 
                            vo.polyline(xycoord.x,xycoord.y);
                            vo.draw();
                            break;
                        case 2:
                            // polygon
                            clientAction = "Polygon";
                            var n = xycoord.x.length;
                            xycoord.x[n] = pix.x2;
                            xycoord.y[n] = pix.y2;  
                            var tempx = new Array();
                            var tempy = new Array();
                            var s="";
                            tempx = xycoord.x;
                            tempy = xycoord.y;
                            vo.clear(); 
                            if (vo.vectorCount>2) vo.polygon(tempx,tempy)
                                else vo.polyline(tempx,tempy);
                            vo.draw();
                            break;
                        case 3:
                            // click circle
                            clientAction = "Circle";
                            var dwidth = Math.abs(pix.x2 - pix.x1);
                            var dheight = Math.abs(pix.y2 - pix.y1);
                            var dradius;
                            if ((dwidth == 0) || (dheight == 0))  {
                                dradius = (dwidth == 0) ? dheight : dwidth;
                            } else {
                                dradius = Math.sqrt((dwidth * dwidth) + (dheight * dheight));
                            }
                            vo.clear();
                            vo.circle(pix.x1, pix.y1, dradius, true);
                            vo.draw();
                            jumpToFinish = true;
                            break;
                        case 4:
                            // click oval
                            clientAction = "Oval";
                            var dwidth = Math.abs(pix.x2 - pix.x1);
                            var dheight = Math.abs(pix.y2 - pix.y1);
                            var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                            var dtop = (pix.y2 < pix.y1) ? pix.y2 : pix.y1;
                            vo.clear();
                            vo.oval(dleft, dtop, dwidth, dheight);
                            vo.draw();
                            jumpToFinish = true;
                            break;
                        case 5:
                            // click box
                            clientAction = "Rectangle";
                            var dwidth = Math.abs(pix.x2 - pix.x1);
                            var dheight = Math.abs(pix.y2 - pix.y1);
                            var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
                            var dtop = (pix.y2 < pix.y1) ? pix.y2 : pix.y1;
                            vo.clear();
                            vo.box(dleft, dtop,(dleft + dwidth), (dtop + dheight));
                            vo.draw();
                            jumpToFinish = true;
                            break;
                    }
                }
                vo.vectorCount++;
                pix.lastX = pix.x2;
                pix.lastY = pix.y2;
            
                if (jumpToFinish) 
                    MapDoubleClick(e);
                else {
                    if (map.vectorCallbackFunctionString!=null && map.vectorCallbackFunctionString.length>0) {
                        // pass back the coords of the current shape
                        coordString ="";
                        if (xycoord.x.length>0) {
                            var n = xycoord.x.length - 1;
                            var m = n - 1;
                            if ((xycoord.x[m]==xycoord.x[n]) && (xycoord.y[m]==xycoord.y[n])) {
                                xycoord.x.length = n;
                                xycoord.y.length = n;
                            }
                            for (var i=0;i<xycoord.x.length;i++) {
                                if (i > 0) coordString += "|";
                                coordString += xycoord.x[i] + ":" + xycoord.y[i];
                            }
                        }
                        var argument = "ControlID=" + map.controlName + "&EventArg=" + clientAction + "&ControlType=Map&coords=" + coordString + "&VectorMode=" + map.mode + "&VectorAction=AddPoint";
                        if (checkForFormElement(document, 0, "MeasureUnits")) argument += "&MeasureUnits=" + document.forms[0].MeasureUnits.value;
                        if (checkForFormElement(document, 0, "AreaUnits")) argument += "&AreaUnits=" + document.forms[0].AreaUnits.value;
                        if (checkForFormElement(document, 0, "MapUnits")) argument += "&MapUnits=" + document.forms[0].MapUnits.options[document.forms[0].MapUnits.selectedIndex].value;
                        
                        var context = map.controlName + "," + clientAction;

        // Debug stuff that will be displayed in form element, if it exists
    if (checkForFormElement(document, 0, "MapDebugBox")) document.forms[0].MapDebugBox.value += ("Vector Request: " + context + ": " + coordString + "\n"); 
                        
                        eval(map.vectorCallbackFunctionString);
                    }
                }               
            }
            break;
        case "Point":
            return false;
            break; 
    }
    return false;
}

function MapDoubleClick(e) {
    iframeShowWorkaroundForVML();
    var vo = map.vectorObject;
    var pix = vo.pixelObject;
    var xycoord = vo.xyCoord;
    map.divObject.style.cursor = "wait";
    var restart = false;
    var clientAction = "Line";
    switch (vo.mode) {
        case 0:
            coordString = pix.x1 + ":" + pix.y1 + "|" + pix.x2 + ":" + pix.y2;
            restart = true;
            break;
        case 1:
            var blurb = "PolyLine:\n";
            coordString ="";
            for (var i=0;i<xycoord.x.length;i++) {
                blurb += "[" + (i+1) + "] " + xycoord.x[i]+ ", "  + xycoord.y[i] + "\n";
                if (i > 0) coordString += "|";
                coordString += xycoord.x[i] + ":" + xycoord.y[i];
            }
            restart = true;
            clientAction = "Polyline";
            break;
        case 2:
            var n = xycoord.x.length - 1;
            var m = n - 1;
            if ((xycoord.x[m]==xycoord.x[n]) && (xycoord.y[m]==xycoord.y[n])) {
                xycoord.x.length = n;
                xycoord.y.length = n;
            }
                
            if (vo.vectorCount>2) {
                var blurb = "Polygon:\n";
                coordString ="";
                for (var i=0;i<xycoord.x.length;i++) {
                    blurb += "[" + (i+1) + "] " + xycoord.x[i] + ", "  + xycoord.y[i] + "\n";
                    if (i > 0) coordString += "|";
                    coordString += xycoord.x[i] + ":" + xycoord.y[i];
                }
                coordString += "|" + xycoord.x[0] + ":" + xycoord.y[0];
                restart = true;
                clientAction = "Polygon";
            } else {
                alert("A Polygon needs at least three vectors.");
            }
            
            break;
        case 3:
            var dwidth = Math.abs(pix.x2 - pix.x1);
            var dheight = Math.abs(pix.y2 - pix.y1);
            var dradius;
            if ((dwidth == 0) || (dheight == 0))  {
                dradius = (dwidth == 0) ? dheight : dwidth;
            } else {
                dradius = Math.sqrt((dwidth * dwidth) + (dheight * dheight));
            }
            coordString = pix.x1 + ":" + pix.y1 + ":" + dradius;
            restart = true;
            clientAction = "Circle";
            break;
        case 4:
            var dwidth = Math.abs(pix.x2 - pix.x1);
            var dheight = Math.abs(pix.y2 - pix.y1);
            var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
            var dtop = (pix.y1 < pix.y2) ? pix.y1 : pix.y2;
            var centerX = dleft + (dwidth / 2);
            var centerY = dtop + (dheight / 2);
            coordString = centerX+ ":" + centerY + ":" + dwidth + ":" + dheight;
            restart = true;
            clientAction = "Oval";
            break;
        case 5:

            // box
            var dwidth = Math.abs(pix.x2 - pix.x1);
            var dheight = Math.abs(pix.y2 - pix.y1);
            var dleft = (pix.x1 < pix.x2) ? pix.x1 : pix.x2;
            var dtop = (pix.y2 < pix.y1) ? pix.y2 : pix.y1;
            coordString = dleft + ":" + dtop + "|" + (dleft + dwidth) + ":" + (dtop + dheight);
            restart = true;
            clientAction = "Rectangle";         
            break;
    }
    if (restart) {
        vo.vectorCount = 0;
        xycoord.x = new Array();
        xycoord.y = new Array();

        map.divObject.ondblclick = null;
        vo.vectordiv.onmousemove = null;
        vo.vectordiv.ondblclick = null;
        pix.lastX = -9999;
        pix.lastY = -9999;
        
        map.coords = coordString;
        
        if (map.vectorCallbackFunctionString!=null && map.vectorCallbackFunctionString.length>0) {
            //
            var argument = "ControlID=" + map.controlName + "&EventArg=" + clientAction + "&ControlType=Map&coords=" + coordString + "&VectorMode=" + map.mode + "&VectorAction=Finish";
            var context = map.controlName + "," + clientAction;
            eval(map.vectorCallbackFunctionString);
        } else
        {
            if (map.preModeExecFunction != null)
                eval(map.preModeExecFunction);
        
            postBack( map.controlName, clientAction);
        }
        
        //vo.clear();
        vo.restart(map.clearDrawnVectors);
        map.divObject.style.cursor = map.cursor;
    }
    jumpToFinish = false;
    map.drawShape = false;
    return false;
}


function getMouseDirection(xOffset, yOffset) {
    var dir = "";
    if (xOffset>0 && yOffset>0) {
        // nw
        dir = "ul";
        
    } else if (xOffset<0 && yOffset>0) {
        // ne
        dir = "ur"
    } else if (xOffset>0 && yOffset<0) {
        // sw
        dir = "ll";
    } else if (xOffset<0 && yOffset<0) {
        // se
        dir = "lr";
    } else if (yOffset>0) {
        // north
        dir = "up";
    } else if (yOffset<0) {
        // south
        dir = "down";
    } else if (xOffset>0) {
        // west
        dir = "left";
    } else if (yOffset<0) {
        // east
        dir = "right";
    }
    return dir;
        
}

// common function for finishing up a drag image type movement... 
    // used by DragImage, keyboard movement, Nav Control, and overview AOI movement
    // uses global temps nx and ny, calculated by the above actions
function finishDragImage(mapObj) {
    var centerX = Math.round(mapObj.viewWidth/2);
    var centerY = Math.round(mapObj.viewHeight/2);
    var newX = centerX - nx;
    var newY = centerY - ny;
    mapObj.xMin=newX;
    mapObj.yMin=newY;
    if (!mapObj.continuousCallback && mapObj.enableTileCaching) {
        mapObj.getTopLeftTile();
        mapObj.updateView(true);
    }
    if (nx==0 && ny==0) {
        // no action currently
    } else { 
        mapObj.maptipObject.innerHTML = "";  
        postBack(mapObj.controlName, 'DragImage');  
    }
    if (mapObj.useZoomAnimation) mapObj.updateMapDiv2();        
    nx = 0;
    ny = 0;

}

function zoomToBox(controlName, left, top, right, bottom) {
    //alert(controlName);
    map = Maps[controlName];
    if (map!=null) {
        map.xMin=left;
        map.yMin=ztop;
        map.xMax=right;
        map.yMax=bottom;
        postBack(controlName, 'DragRectangle');
    } else
        alert(controlName + " not found.");

}
///////////////////////////// IE MouseWheel functions ... zoom ////////////////////////

    // Note: enable by adding these lines after the complete setup of the map object and divs:
        // map.divObject.onmousewheel = mousewheelhandlepiv;
        // setWheelParams(map);
        
        var m_zoomFactor = 1.0;
        // these are hard-coded for testing
        var m_imageWidth = 1800;
        var m_imageHeight = 1200;
        var m_imageLeft = -600;
        var m_imageTop = -400;
        var m_imageXOffset = 0;
        var m_imageYOffset = 0;
        var m_centerX = 300;
        var m_centerY = 200;
        var m_zoomIncre = 0.1;
        var m_zoomEnd = 2.0;
        
        var m_lastZoomFactor = 0;
        var m_moveWheel = false;
        var m_wheelCheckInterval;
        var slideXoffset = 0;
        var slideYoffset = 0;
        var m_canSlide = false;
        var m_sliderId = "";
        var keepZooming = false;
        var zoomAnimationDelay = false;
        var m_mouseWheelForceDelay = 1000; // force delay so multiple zooms will not be triggered on single wheel movement 
        var m_mouseWheelLastUseTime = new Date();
        var m_mouseWheelUseTime = null;
        
        function mousewheelhandlepiv(evt){
            m_mouseWheelUseTime = new Date();
            if (m_mouseWheelUseTime - m_mouseWheelLastUseTime > m_mouseWheelForceDelay) {
                if (getSessionLapse() < maximumLapseTime) {
                    if (!keepZooming) {
                        setWheelParams();
                        if (mouseWheelAwayZoomIn) {
                            if (event.wheelDelta >= 120 && canWheelZoom("in")) 
                                zoomIn(evt);
                            else if (event.wheelDelta <= -120 && canWheelZoom("out")) 
                                zoomOut(evt);
                        } else { 
                            if (event.wheelDelta >= 120 && canWheelZoom("out")) 
                                zoomOut(evt);
                            else if (event.wheelDelta <= -120 && canWheelZoom("in")) 
                                zoomIn(evt);
                        } 
                    }
                } else 
                    showLapseAlert();
                m_mouseWheelLastUseTime = m_mouseWheelUseTime;
            }
        }
        
        function onWheelScroll(evt) {
            m_mouseWheelUseTime = new Date();
            if (m_mouseWheelUseTime - m_mouseWheelLastUseTime > m_mouseWheelForceDelay) {
                if (getSessionLapse() < maximumLapseTime) {
                    if (!keepZooming) {
                        setWheelParams();
                        if (mouseWheelAwayZoomIn) { 
                            if (evt.detail < 0 && canWheelZoom("in"))
                                zoomIn(evt);
                            else if (evt.detail > 0 && canWheelZoom("out")) 
                                zoomOut(evt);
                        } else {
                            if (evt.detail < 0 && canWheelZoom("out"))
                                zoomOut(evt);
                            else if (evt.detail > 0 && canWheelZoom("in")) 
                                zoomIn(evt);
                        }  
                    }       
                } else 
                        showLapseAlert();
                m_mouseWheelLastUseTime = m_mouseWheelUseTime;
            }
        }
        
        function canWheelZoom(dir) {
            var goAhead = false;
            if (map.totalLevels<1)
                goAhead = true;
            else {
                if (dir=="in" && map.level<map.totalLevels-1) 
                    goAhead = true;
                else if (dir=="out" && map.level>0)
                    goAhead = true;
            }
            return goAhead;
        }
        
        function setZoom(which) {
                // update zoom factor
                m_zoomFactor += m_zoomIncre;
                // use zoom factor to set params for scale div
                var iw = m_imageWidth * m_zoomFactor;
                var ih = m_imageHeight * m_zoomFactor;
                var ixw = m_imageXOffset * m_zoomFactor;
                var iyw = m_imageYOffset * m_zoomFactor;
                var il = m_centerX - ixw;
                var it = m_centerY - iyw;   
                // make sure it's visible
                map.divObject2.style.visibility = "visible";
                // update size and position of scale div
                if (isIE) {
                    map.divScaleObject2.style.zoom = m_zoomFactor;
                } else {
                    var div;
                    var tw = (map.columnsPerView + 1);
                    var th = (map.rowsPerView + 1);
                    for (var r=0; r<th; r++) {
                        for (var c=0; c< tw; c++) {
                            div = document.getElementById(map.controlName + '_MapAnimationDiv_' + c + '_' + r);
                            if (div!=null) {
                                div.style.width = Math.round(map.tileWidth * m_zoomFactor) + "px";
                                div.style.height = Math.round(map.tileHeight * m_zoomFactor) + "px"; 
                            }  
                        } 
                    } 
                    map.divScaleObject2.style.width = Math.floor(iw) + "px";
                    map.divScaleObject2.style.height = Math.floor(ih) + "px";
                }
                map.divObject2.style.left = Math.floor(il) + "px";
                map.divObject2.style.top = Math.floor(it) + "px";
        }


        
        function zoomOut(evt) {
            m_zoomFactor = 1;
            m_zoomIncre = -0.05;
            m_zoomEnd = 0.5;
            keepZooming = true;
            if (map.useZoomAnimation) 
                map.showMapDiv2();
            window.setTimeout("navZoomOut(null, '" + map.controlName + "'); zoomAnimationDelay = true;", 0);
            map.maptipObject.innerHTML = "";
            if (map.useZoomAnimation) {
                var speed = 25;
                var timer = 0;
                var start = m_zoomFactor
                for (var i = start; i >= m_zoomEnd; i+=m_zoomIncre) {
                    window.setTimeout("setZoom();", (timer * speed));
                    timer++;
                }  
                 keepZooming = false;
            }
            else
                keepZooming = false;
            var rc = map.ResourceCollection;
            for (var i=0;i<rc.length;i++) {
                rc[i].divObject.innerHTML = "";
            }
        }

        function zoomIn(evt) {
            m_zoomFactor = 1;
            m_zoomIncre = 0.1;
            m_zoomEnd = 2.0;
            keepZooming = true;
            if (map.useZoomAnimation) 
                map.showMapDiv2();
            window.setTimeout("navZoomIn(null, '" + map.controlName + "'); zoomAnimationDelay = true;", 0);
            map.maptipObject.innerHTML = ""; 
            //alert("zoomIn"); 
            if (map.useZoomAnimation) {
                var speed = 25;
                var timer = 0;
                var start = m_zoomFactor
                for (var i = start; i <= m_zoomEnd; i+=m_zoomIncre) {
                    window.setTimeout("setZoom();", (timer * speed));
                    timer++;
                }  
                 keepZooming = false;
            }
            else
                 keepZooming = false;
            var rc = map.ResourceCollection;
            for (var i=0;i<rc.length;i++) {
                rc[i].divObject.innerHTML = "";
            }
        }
        
        function setWheelParams(map2) {
            if (map2!=null) map = map2;
            if (map.useZoomAnimation) map.checkMapDiv2();
            m_centerX = Math.floor(map.viewWidth / 2);
            m_centerY = Math.floor(map.viewHeight / 2);
            m_imageLeft = parseInt(map.divObject2.style.left);
            m_imageTop = parseInt(map.divObject2.style.top);
            m_imageXOffset = m_centerX + (0 - m_imageLeft);
            m_imageYOffset = m_centerY + (0 - m_imageTop);

        }
        
function checkNavDirection(type) {
    var xDir = 0;
    var yDir = 0;
    if (nav_active) {
        switch (type) {
            case "up":
                ny+=map.mapMoveIncrement;
                yDir = 1;
                break;
            case "ur":
                nx-=map.mapMoveIncrement;
                ny+=map.mapMoveIncrement;
                xDir = -1;
                yDir = 1;
                break;
            case "right":
                nx-=map.mapMoveIncrement;
                xDir = -1;
                break;
            case "lr":
                nx-=map.mapMoveIncrement;
                ny-=map.mapMoveIncrement;
                xDir = -1;
                yDir = -1;
                break;
            case "down":
                ny-=map.mapMoveIncrement;
                yDir = -1;
                break;
            case "ll":
                nx+=map.mapMoveIncrement;
                ny-=map.mapMoveIncrement;
                xDir = 1;
                yDir = -1;
                break;
            case "left":
                nx+=map.mapMoveIncrement;
                xDir = 1;
                break;
            case "ul":
                nx+=map.mapMoveIncrement;
                ny+=map.mapMoveIncrement;
                xDir = 1;
                yDir = 1;
                break;
        }
    } else {
        nx=0;
        ny=0;   
    }
    var panMoveX = nx + panStartLeft;
    var panMoveY = ny + panStartTop;
    navDir = type;
    
    var currentX =0;
    var currentY = 0;
    var tLeft = 0-(map.tileWidth * map.columns);
    var tTop = 0-(map.tileHeight * map.rows);
    currentX = panStartLeft + nx;
    currentY = panStartTop + ny;
    
    map.moveTiles(currentX, currentY, navDir);
    return false;
}

        function keyDown(e) {
            if (map.keyFocus) {
                var theKey;
                var dir = "";
                if (isIE) 
                    theKey = event.keyCode;
                else
                    theKey = e.which;
                checkShiftCtrlAltKeys(e);
                if (shiftPressed)
                    map.divObject.style.cursor = map.shiftCursor;
                else if (ctrlPressed)
                    map.divObject.style.cursor = map.ctrlCursor;
                else if (altPressed)
                    map.divObject.style.cursor = map.altCursor;
                switch (theKey)
                {
                case 37:
                    // left
                    dir = "left";
                    break;
                case 38:
                    // up
                    dir = "up";
                    break;
                case 39:
                    // right
                    dir = "right";
                    break;
                case 40:
                    // down
                    dir = "down";
                    break;
                case 33:
                    // PgUp... ur
                    dir = "ur";
                    break;
                case 34:
                    // PgDn... lr
                    dir = "lr";
                    break;
                case 35:
                    // End... ll
                    dir = "ll";
                    break;
                case 36:
                    // Home... ul
                    dir = "ul";
                    break;
                case 107:
                    // shift-plus ... zoom in
                    if (shiftPressed) {
                        dir ="";
                        if (getSessionLapse() < maximumLapseTime) {
                            nav_active = false;
                           setWheelParams(); 
                           if (canWheelZoom("in"))
                            zoomIn(e); 
                        } else
                            showLapseAlert();
                    }
                    break;
                case 109:
                    // shift-minus ... zoom out
                    if (shiftPressed) {
                        dir ="";
                        if (getSessionLapse() < maximumLapseTime) {
                            nav_active = false;
                           setWheelParams(); 
                           if (canWheelZoom("out"))
                            zoomOut(e); 
                        } else
                            showLapseAlert();
                    }
                    break;
                default:
                    // no direction
                    nav_active = false;
                }
                
                if (dir!="") {
                    if (getSessionLapse() < maximumLapseTime) {
                        if (!nav_active) {
                            var box = calcElementPosition(map.divId);
                            var box2 = calcElementPosition(map.containerDivId); 
                            panStartLeft = box.left - box2.left;
                            panStartTop = box.top - box2.top;
                            map.dragImage = true;
                            nav_active = true;
                        }
                        var tempIncre = map.mapMoveIncrement;
                        map.mapMoveIncrement *= 2;
                        checkNavDirection(dir);
                        map.mapMoveIncrement = tempIncre;
                        if (map.vectorObject!=null) map.vectorObject.restart();
                    } else
                        showLapseAlert();
                }
                else if (theKey == 27) { // Escape
                    if (map.vectorObject!=null) map.vectorObject.restart();
                }
            }
        }
        
        function keyUp(e) {
            map.dragImage = false;
            if (nav_active) {
                nav_active = false;
                finishDragImage(map);
                nx = 0;
                ny = 0;
            }
            dir=""; 
            map.divObject.style.cursor = map.tempCursor;
            
        }
        
        function setMapFocus(control) {
            //alert(control);
            map = Maps[control];
            map.keyFocus = true;
        }
        function setMapBlur(control) {
            //
            map.keyFocus = false;
        }
        
function navZoomIn(e, controlName)
{
    if (getSessionLapse() < maximumLapseTime) {
        map = Maps[controlName];
        if (map!=null) {
            if (map.totalLevels<1) {
                // dynamic tiles
                map.coords = "2";
                postBack(map.controlName, "ScrollWheelZoom");
            } else {
                // static tiles
                var level = map.level;
                if (level<map.totalLevels-1) {
                    level++;
                    map.switchToLevel(level);
                }
            }
        }
    } else
        showLapseAlert();
    return false;
}

function navZoomOut(e, controlName)
{
    if (getSessionLapse() < maximumLapseTime) {
        map = Maps[controlName];
        if (map!=null) {
            if (map.totalLevels<1) {
                // dynamic tiles
                map.coords = map.setDecimalDelimiter(1 / 2);
                postBack(map.controlName, "ScrollWheelZoom");
            } else {
                var level = map.level;
                if (level>0) {
                    level--;
                    map.switchToLevel(level);
                }
            }
        }
    } else
        showLapseAlert();
    return false;
}

 function fixedZoomIn(e, controlName) 
{
    if (getSessionLapse() < maximumLapseTime) {
        map = Maps[controlName];
        if (map!=null) { 
            nav_active = false;
           setWheelParams(); 
           if (canWheelZoom("in"))
                zoomIn(e); 
      } 
    } else
        showLapseAlert();
}

function fixedZoomOut(e, controlName)
{
    if (getSessionLapse() < maximumLapseTime) {
        map = Maps[controlName];
        if (map!=null) { 
            nav_active = false;
           setWheelParams();
           if (canWheelZoom("out")) 
                zoomOut(e); 
        }
    } else
        showLapseAlert();

}
  

function AutoResizeMap(event, controlName) {
    window.clearTimeout(reloadTimer);
    if (controlName==null) {
        // call the function that will check the maps
        reloadTimer = window.setTimeout("AutoResizeMapToParent();",1000);
    } else {    
        // a map controlname passed in... resize that one
        reloadTimer = window.setTimeout("if (Maps['" + controlName + "'].enableResizeEvent) Maps['" + controlName + "'].resizeToParent();",1000);
    }
}

function AutoResizeMapToWindow(event, controlName) {
    window.clearTimeout(reloadTimer);
        // a map controlname passed in... resize that one
    reloadTimer = window.setTimeout("if (Maps['" + controlName + "'].enableResizeEvent) Maps['" + controlName + "'].resizeToWindow();",1000);
}

function AutoResizeMapToParent() {
    var m;
    if (MapNames.length==1 && map!=null) {
        // only one map... resize that one if permitted
        if (map.enableResizeEvent)
            map.resizeToParent();
    } else {
        // loop through all maps and resize those that are permitted
        for (var i=0;i<MapNames.length;i++) {
            m = Maps[MapNames[i]];
            if (m.enableResizeEvent)
                m.resizeToParent();
        }
    }
}

function moveSnapCircle(e) {
        var snap = map.snapCircleObject;
        getXY(e);
        var mx = mouseX;
        var my = mouseY;
        if (isIE) {
            // undo adjustment for ie... not necessary for snap circle;
            mx+=3;
            my+=3;
        }  
        if (snap!=null) {
            var box = calcElementPosition(map.containerObject.id);
            snap.style.left = (mx - Math.round(parseFloat(snap.clientWidth) / 2) - box.left) + "px";
            snap.style.top = (my - Math.round(parseFloat(snap.clientHeight) / 2)- box.top) + "px";
        } 
}
    
/* Resource related properties
*/

function ResourceObject(id, index, visible, mapId, tileServerUrl, tileServerUrlGenerator, tileServerImageFormat, gridLimits, mappedLevel) {
    this.id = id;
    this.index = (index!=null) ? index : 0;
    this.visible = (visible!=null) ? eval(visible) : true;  
    this.mapId = (mapId!=null) ? mapId : "Map1";
    this.tileServerUrl = (tileServerUrl!=null) ? tileServerUrl : ""; 
    this.tileServerUrlGenerator = (tileServerUrlGenerator!=null) ? tileServerUrlGenerator : ""; 
    this.mapObject = null; 
    this.divObject = null;
    this.divId = "MapResourceDiv_" +  this.mapId + "_ " + this.id ;  
    this.displayedTiles = new Array();
    this.pngTiles = new Array();
    this.imageFormat = (tileServerImageFormat!=null) ? tileServerImageFormat : ""; 
    this.checkCallbackCount = 0;
    ///// Added for resource limit check 
    this.minColumn = 0;
    this.maxColumn = 0;  
    this.minRow = 0;
    this.maxRow = 0;      
    this.gridLimits = (gridLimits==null) ? "" : gridLimits;
    var limits = this.gridLimits.split(",");
    if (limits.length==4) {
        this.minColumn = parseInt(limits[0]);
        this.minRow = parseInt(limits[1]);
        this.maxColumn = parseInt(limits[2]);
        this.maxRow = parseInt(limits[3]);
    }   
   ///// Added for resource limit check
    this.mappedLevel = (mappedLevel==null) ? 0 : mappedLevel; ///// Added for resource mapping check
     
    this.redraw = function() {
        // clear resource grid and redraw resource tiles displayed in view  
        this.mapObject.clearLevelGrid(this.id, this.gridLimits);
    }  
   
    this.show = function() {
        this.visible = true;
        this.redraw();
    }     

    this.hide = function() {
        this.visible = false;
        this.redraw();
    }     

    this.toggle = function() {
        this.visible = !this.visible;
        this.redraw();
    }    
   
    ///// Added for resource limit check 
    this.isWithinLimits = function(column, row) {
        // do not set limits if .gridLimits is nothing or all limits equal -99 
        if (this.gridLimits==null || this.gridLimits=="" || (this.minColumn==-99 && this.minRow==-99 && this.maxColumn==-99 && this.maxRow==-99))
            return true;
        else  
            return (column>= this.minColumn && column<=this.maxColumn && row>=this.minRow && row<=this.maxRow);
    }
   
    this.setLimits = function(minColumn, minRow, maxColumn, maxRow) {    
        this.minColumn = minColumn;
        this.minRow = minRow;
        this.maxColumn = maxColumn;
        this.maxRow = maxRow;
        this.gridLimits = minColumn + "," + minRow + "," + maxColumn + "," + maxRow;
        if (this.gridLimits="-99,-99,-99,-99") {
            this.gridLimits = ""; 
        }
    } 
    ///// Added for resource limit check 
}

function esriResourceCollectionAdd(resource, draw) { 
        var position = this.length;
        this[this.length] = resource;  
        this[position].index = position;
        if (draw==null) draw = false;
        var resourceHtml =  '<div id="' + resource.divId + '" style="position:absolute; left:0px; top:0px;  width:' + this.mapObject.viewWidth + '; height:' + this.mapObject.viewHeight + '; "  ></div>\n';
        this.mapObject.divObject.insertAdjacentHTML("AfterBegin", resourceHtml);           ///// Added for dynamic resource addition/deletion
        this.setObjects();
        if (draw) this.redraw(resource.id);
}

function esriResourceCollectionContains(id) {
    for (var i=0; i<this.length; i++ ) {
        if (this[i].id == id)
            return true;
    }
    return false;
}

function esriResourceCollectionFind(id) {
    for (var i=0; i<this.length;i++) {
        if (this[i].id == id)
            return this[i];
    }
    return null;    
}
        
function esriResourceCollectionInsert(resource, position, draw) {
    //var length = this.length - 1;
    if (draw==null) draw = false; 
    ///// Added for dynamic resource addition/deletion 
    var node = null;
    var resourceHtml =  '<div id="' + resource.divId + '" style="position:absolute; left:0px; top:0px;  width:' + this.mapObject.viewWidth + '; height:' + this.mapObject.viewHeight + '; "  ></div>\n';
    if (position>this.length) position = this.length;
    if (position==this.length) {
        this.add(resource, draw);
    } else  {
        node = document.getElementById(this[position].divId);
        if (node!=null) {
            node.insertAdjacentHTML("AfterEnd", resourceHtml);  
            for (var i=this.length; i>position;i--) {
                this[i] = this[i-1];
                this[i].index = i;
//                this[i].displayedTiles = new Array();
//                this[i].pngTiles = new Array();
            }
    ///// Added for dynamic resource addition/deletion 
            this[position] = resource;
            this[position].index = position;
        } else {
            alert("Cannot insert new resource. Unable to find " + this[position].divId + ".");
        }
    }
    this.setObjects();
    if (draw) this.redraw(resource.id);
    
}
        
function esriResourceCollectionRemove(id) {
    var position = this.getPosition(id);
    if (position>-1) {
         this.removeAt(position, false);
    }  
}

function esriResourceCollectionRemoveAt(position) {
///// Added for dynamic resource addition/deletion
//    if (this.length>1) {
        var length = this.length - 1;
        var node = null;
        if (position>-1 && position<this.length) 
            node = document.getElementById(this[position].divId);
        if (node!=null) {
            var id = this[position].id; 
            node.removeNode(true);
                for (var i=position; i<this.length;i++) {
                    if (i<length) this[i] = this[i+1];
                    this[i].index = i; 
                    //this[i].displayedTiles = new Array();
                    //this[i].pngTiles = new Array();
                }
                this.length = length;
            if (id==this.mapObject.baseResourceId && this.length>0) {
                this.mapObject.baseResourceId = this[this.length - 1].id; 
                this.mapObject.createMapDiv2();
            }
            
        } else {
            alert("Cannot remove resource. Unable to find resource at position " + position + "."); 
        }
//    } else {
//        alert("Cannot remove resource if it is the only resource.");
//    }
///// Added for dynamic resource addition/deletion
}

function esriResourceCollectionPosition(id) {
    var position = -1;
    for (var i=0; i<this.length;i++) {
        if (this[i].id == id)
            return i;
    }
    return position;    
}   


function esriResourceCollectionReplace(newResource, oldResourceId, draw) {
    var position = this.getPosition(oldResourceId);
    if (draw==null) draw = false; 
    if (position>-1) 
        this.replaceAt(newResource, position, draw); 

}

function esriResourceCollectionReplaceAt(newResource, position, draw) {
    if (position==null || isNaN(position)) position = 0;
    if (draw==null) draw = false; 
    var length = this.length - 1; 
    this[position] = resource; 
    this[position].index = position;
    if (draw) this.redraw(newResource.id);  
}

function esriResourceCollectionSetObjects() {
    for (var i=0;i<this.length;i++) {
        this[i].divObject = document.getElementById(this[i].divId);
        this[i].mapObject = Maps[this[i].mapId];
    }  
}

function esriResourceCollectionRedraw(id) {
    var resourceIndex = this.getPosition(id);
    var resource = this[resourceIndex];
    var gridLimits = resource.gridLimits;
    this.mapObject.clearLevelGrid(id, gridLimits);
}

function esriResourceCollectionBottomVisiblePosition() {
    var position = 0;
    for (var i=0; i<this.length;i++) {
        if (this[i].visible)
            position = i;
    }
    return position;    
}

///// Added for returned tiles check
function esriPendingTilesAdd(tileString) {
    this.push(tileString);
    this.mapObject.divObject.style.cursor = "progress";
    if (this.onRequestsPending!=null) this.onRequestsPending(this.mapObject);
}

function esriPendingTilesFind(tileString) {
    var found = new Array();
    for (var i=0;i<this.length; i++) {
        if (this[i]==tileString) found.push(i);
    }  
    return found; 
}

function esriPendingTilesRemove(tileString) {
    var found = this.find(tileString);
    if (found.length>0) {
        for (var i=found.length-1;i>=0; i--) {
            this.splice(found[i],1);
        }
    }
    if (this.onRequestsRemove!=null) this.onRequestsRemove(this.mapObject); 
    if (this.length==0) {
        this.mapObject.divObject.style.cursor = this.mapObject.cursor;
        if (this.onRequestsComplete!=null) this.onRequestsComplete(this.mapObject);  
    }  
}

function esriAddOnRequestsPending(theHandler) {
    this.onRequestsPending = theHandler;
}

function esriAddOnRequestsRemove(theHandler) {
    this.onRequestsRemove = theHandler;
}

function esriAddOnRequestsCompleted(theHandler) {
    this.onRequestsComplete = theHandler;
}


///// Added for returned tiles check
    
//alert("map.js loaded");