//MapImage.js
//displays and handles navigation for a map object

MapImage = function(newID, parentElement, newXPosition, newYPosition, newZIndex, newWidth, newHeight, newVisibility, newMapObject, newMapType)
{
  var $_this = this;
  this.drawplanes = [];
  this.id = newID;
  this.map = newMapObject;
  this.mapType = newMapType;  //valid types are 'MASTER','SLAVE'
  this.dragEnabled = false;
  this.currentCursor = 'MapImageWait';
  this.loadImage = null;
  this.waiting = false;
  var zoomBoxPending = false;
  this.mouseDownPosition = Array(0,0);  
  this.dragPending = false;
  this.cursorPos = [-1,-1];
  this.eventCallbacks = {
    resize:Array(),
    click:Array(),
    mouseOver:Array(),
    mouseOut:Array(),
    mouseUp:Array(),
    mouseDown:Array(),
    mouseMove:Array(),
    dragStart:Array(),
    drag:Array(),
    dragEnd:Array()
  };
  var zoomBox = {
    element: document.createElement('DIV'),
    xstart: 0,ystart: 0,xend: 0,yend: 0,xdelta:0,ydelta:0,
    setActive: function(x1,y1){
      this.xstart=x1;this.ystart=y1;
      xResizeTo(this.element,1,1);
      xMoveTo(this.element,x1,y1);
      xShow(this.element);
    },
    update: function (x2,y2){
      this.xend = x2;
      this.yend = y2;
      if ((this.xend > 0) && (this.xend < $_this.width()) && (this.yend > 0) && (this.yend < $_this.height()))
      {
        xMoveTo(this.element,(this.xstart<this.xend)?this.xstart:this.xend,(this.ystart<this.yend)?this.ystart:this.yend);
        xResizeTo(this.element,Math.abs(this.xstart - this.xend), Math.abs(this.ystart - this.yend));
      }
      else
        this.setInactive();
    },
    setInactive: function(){xHide(this.element);}
  };
  setClass(zoomBox.element,'zoomBox');
  xHide(zoomBox.element);
/*******************************************/
this.registerEventCallback = function(eventType,callback)
{
  if (this.eventCallbacks[eventType]!=null)  //empty array can eval to false
    this.eventCallbacks[eventType].push(callback);
  return this.eventCallbacks[eventType].length-1;
};
this.unregisterEventCallback = function(eventType,index)
{
  if (this.eventCallbacks[eventType]!=null)  //empty array can eval to false
    this.eventCallbacks[eventType][index]=null;
};
/*******************************************/
this.setMapObject = function(newMapObject){this.map = newMapObject;};
this.setMapImage = function(newImagePath)
{
  //parameter is the url for the new map image.
  this.imageNode.src = newImagePath;
  this.dragTiles[4].src = newImagePath;
  this.positionDragTiles();  
};
  this.addDrawplane=function(){
    //create a new drawplane layer and return the index
    //optional parameter, htmlelement
    var retval=this.drawplanes.length;
    var drawplane=(arguments.length>0)?arguments[0]:document.createElement('DIV');
    //drawplane.style.zIndex=eventHandlerNode.style.zIndex;
    drawplane.style.position='absolute';
    drawplane.style.left=0;
    drawplane.style.top=0;
    drawplane.style.display='block';
    drawplane.width=this.eventHandlerNode.width;
    drawplane.height=this.eventHandlerNode.height;
    //eventHandlerNode.style.zIndex++;
    this.customDrawPlaneNode.appendChild(drawplane);
    this.drawplanes.push(drawplane);
    return retval;
  };
  this.getDrawplane=function(idx){return this.drawplanes[idx];};
  this.removeDrawplane=function(idx){
    var drawplane=this.drawplanes[idx];
    this.customDrawPlaneNode.removeChild(drawplane);
    this.drawplanes[idx]=null;
    return drawplane;
  };

/*******************************************/
this.setMouseMode = function(newMode)
{
  //valid modes are:  select, zoomIn, zoomOut, center,
  this.mouseMode = newMode;
  switch (newMode)
  {
    case 'DragMap':
      this.currentCursor = 'MapImageDrag';
      this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),'MapImageDrag');
      break;
    case 'ZoomIn':
    case 'ZoomOut':
    case 'ZoomWindow':
    case 'CoordConvSP2LatLon':
    case 'MeasureDistance':
    case 'Markup':
      this.currentCursor = 'MapImageZoom';
      this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),'MapImageZoom');
      this.dragEnabled = false;
      break;
    case 'Center':
      this.currentCursor = 'MapImageCenter';
      this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),'MapImageCenter');
      break;
    case 'Select':
    case 'SelectWindow':
    case 'BufferXY':
      this.currentCursor = 'MapImageSelect';
      this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),'MapImageSelect');
      break;
    default:
      this.dragEnabled = false;
      break;
  }
  if(arguments.length>1)
    this.eventHandlerNode.style.cursor = arguments[1];
};

this.setWaiting = function (newState)
{
  //shows or hides the loading image.
  if (newState)
  {
    if (this.mapType == 'MASTER')
      xShow(this.loadImage);
  }
  else
  {
    if (this.mapType == 'MASTER')
      xHide(this.loadImage);
    xMoveTo(this.imageNode,0,0);
    xShow(this.imageNode);
  }
  this.waiting = newState;
  this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),((newState)?('MapImageWait'):(this.currentCursor)));
};

/*******************************************/
this.show = function(){xShow(this.element);};
this.hide = function(){xHide(this.element);};
/*******************************************/
this.left = function(){return ((arguments.length > 0)?(xLeft(this.element, arguments[0])):(xLeft(this.element)));};
this.top = function(){return ((arguments.length > 0)?(xTop(this.element, arguments[0])):(xTop(this.imageNode)));};
this.moveTo = function(newXPosition, newYPosition){xMoveTo(this.element,newXPosition, newYPosition);};
/*******************************************/
this.width = function()
{
  if (arguments.length > 0)
  {
    var width = arguments[0];
    var height = this.height();
    this.resizeTo(width,height);
  }
  return xWidth(this.imageNode);
};
this.height = function()
{
  if (arguments.length > 0)
  {
    var width = this.width();
    var height = arguments[0];
    this.resizeTo(width,height);
  }
  return xHeight(this.imageNode);
};
this.resizeTo = function(newWidth, newHeight)
{
  var centerX = Math.floor(0.5*newWidth);
  var centerY = Math.floor(0.5*newHeight);
  
  xResizeTo(this.element, newWidth, newHeight);
  xResizeTo(this.drawPlaneNode, newWidth, newHeight);
  if (this.measureCanvas)
  {
    xResizeTo(this.measureCanvas, newWidth, newHeight);
    this.measureCanvas.width = newWidth;
    this.measureCanvas.height = newHeight;
  }
  xResizeTo(this.rasterDrawPlaneNode, newWidth, newHeight);
  xResizeTo(this.customDrawPlaneNode, newWidth, newHeight);
  xResizeTo(this.eventHandlerNode, newWidth, newHeight);
  xResizeTo(this.imageNode, newWidth, newHeight);
  xMoveTo(this.bufferTargetNode,centerX-25,centerY-25);    
  xMoveTo(this.zoomInTargetNode,centerX-25,centerY-25);    
  xMoveTo(this.zoomOutTargetNode,centerX-25,centerY-25);    
  if ((this.mapType == 'MASTER')&&(this.loadImage != null))
    xMoveTo(this.loadImage,centerX,centerY);
  this.positionDragTiles(newWidth,newHeight);
  for (var i=0;i<this.eventCallbacks['resize'].length;i++)
    if (this.eventCallbacks['resize'][i])
      this.eventCallbacks['resize'][i](newWidth,newHeight);
};

/****************************************************************/
/* Event Callback Functions                                     */
/****************************************************************/
this.clickCallback = function(e)
{
  //pass x position, yposition, width, height and click mode to the map object
  var X = e.offsetX;
  var Y = e.offsetY;
  this.cursorPos = [X,Y];
  this.dragPending = false;
  if ((X == this.mouseDownPosition[0]) && (Y == this.mouseDownPosition[1]))
  {
    if (this.mapType == 'SLAVE'){
      //newX,newY are the local coordinates on the image that were clicked.
      //can calculate the new position based on this and the map extent... 
      return this.map.centerOnPoint(((X / this.width()) * (this.map.vmapExtent[3]-this.map.vmapExtent[2])) + this.map.vmapExtent[2],((1.0 - (Y / this.height())) * (this.map.vmapExtent[1]-this.map.vmapExtent[0])) + this.map.vmapExtent[0]);
    }
    else
    {
      var MapWidth = this.width();
      var MapHeight = this.height();
      var XPercent = X / MapWidth;
      var YPercent = 1.0 -(Y / MapHeight);
      switch (this.mouseMode)
      {
        case 'SelectWindow':
          this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'Select');
          break;
        case 'ZoomWindow':
          this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'ZoomIn');
          break;
        case 'DragMap':
          this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'Center');
          break;
        default:
          this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,this.mouseMode);
          break;
      }
    }
  }
  for (var i=0;i<this.eventCallbacks['click'].length;i++)
    if (this.eventCallbacks['click'][i])
      this.eventCallbacks['click'][i](e);
};

this.mouseMoveCallback = function(e)
{
  //pass x position, yposition, width, height and click mode to the map object
  var X = e.offsetX;
  var Y = e.offsetY;
  if ((X==this.cursorPos[0])&&(Y==this.cursorPos[1])){return false;};
  this.cursorPos = [X,Y];
  if (this.mapType != 'SLAVE')
  {
    var MapWidth = this.width();
    var MapHeight = this.height();
    this.map.mouseMove(X,Y,MapWidth,MapHeight,X / MapWidth,1.0 -(Y / MapHeight),this.mouseMode);
  }
  for (var i=0;i<this.eventCallbacks['mouseMove'].length;i++)
    if (this.eventCallbacks['mouseMove'][i])
      this.eventCallbacks['mouseMove'][i](e);
};


this.processMapDrag = function (dX,dY)
{
  //newX,newY are the local coordinates on the image that were clicked.
  //can calculate the new position based on this and the map extent... 
  this.dragEnabled = false;
  var MapWidth = this.width();
  var MapHeight = this.height();
  var X = (MapWidth*0.5-dX);
  var Y = (MapHeight*0.5-dY);
  if(dX == 0 && dY == 0){
	return false;
  }
  else{
	return this.map.click(X,Y,MapWidth,MapHeight,X / MapWidth,1.0 -(Y / MapHeight),'Center');
  }
};

/*******************************************/
this.mouseOverCallback = function(e)
{
  this.cursorPos = [-1,-1];
  for (var i=0;i<this.eventCallbacks['mouseOver'].length;i++)
    if (this.eventCallbacks['mouseOver'][i])
      this.eventCallbacks['mouseOver'][i](e);
};

this.mouseOutCallback = function(e)
{
   this.cursorPos = [-1,-1];
   //the cursor has moved out of the active map surface.  Abort zoom windows and drag-pans.
   if ((this.mouseMode == 'DragMap')&&this.dragEnabled)
   {
     this.imageNode.src = this.dragTiles[4].src;
     this.positionDragTiles();
     for (i=0;i<this.drawplanes.length;i++){
       if(this.drawplanes[i]){
         if(this.drawplanes[i]["freeance_drag"])
           xMoveTo(this.drawplanes[i],0,0);
       }
     }
   };
   this.dragEnabled = false;
   var pagex=xPageX(this.imageNode),pagey=xPageY(this.imageNode);
   if (!((e.pageX > pagex) &&
        (e.pageX < (pagex+xWidth(this.imageNode))) &&
        (e.pageY > pagey &&
        (e.pageY < (pagey+xHeight(this.imageNode))))
       ))
      zoomBox.setInactive();
  for (var i=0;i<this.eventCallbacks['mouseOut'].length;i++)
    if (this.eventCallbacks['mouseOut'][i])
      this.eventCallbacks['mouseOut'][i](e);
};
/*******************************************/
this.mouseUpCallback = function(e){
  this.cursorPos = [e.offsetX,e.offsetY];
  for (var i=0;i<this.eventCallbacks['mouseUp'].length;i++)
    if (this.eventCallbacks['mouseUp'][i])
      this.eventCallbacks['mouseUp'][i](e);
};
/*******************************************/
this.mouseDownCallback = function(e){
  this.cursorPos = [e.offsetX,e.offsetY];
  this.mouseDownPosition = Array(e.offsetX,e.offsetY);
  for (var i=0;i<this.eventCallbacks['mouseDown'].length;i++)
    if (this.eventCallbacks['mouseDown'][i])
      this.eventCallbacks['mouseDown'][i](e);
};
/*******************************************/
$_this.mouseWheelCallback = function(e){
  var xe = new xEvent(e);
  var X = xe.offsetX;
  var Y = xe.offsetY;
  $_this.cursorPos = [X,Y];
  $_this.dragPending = false;
  var MapWidth = $_this.width();
  var MapHeight = $_this.height();
  var XPercent = X / MapWidth;
  var YPercent = 1.0 -(Y / MapHeight);
  if(e.wheelDelta < 0){
    $_this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'ZoomOut');
  }
  else{
    $_this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'ZoomIn');
  }
  if(e.stopPropagation)
    e.stopPropagation();
  if(e.preventDefault)
    e.preventDefault();
  e.cancelBubble = true;
  e.cancel = true;
  e.returnValue = false;
  return false;
};
/*******************************************/
$_this.keyDownCallback = function(e){
  var xe = new xEvent(e);
  if(xe.target.tagName != 'INPUT' && xe.target.tagName != 'TEXTAREA'){
    var X = xe.offsetX;
    var Y = xe.offsetY;
    $_this.cursorPos = [X,Y];
    $_this.dragPending = false;
    var MapWidth = $_this.width();
    var MapHeight = $_this.height();
    var XPercent = X / MapWidth;
    var YPercent = 1.0 -(Y / MapHeight);

    switch(e.keyCode){
      case 33: //page up
      case 105: //9
        $_this.map.click(X,Y,MapWidth,MapHeight,0.75,0.75,'Center');
        break;
      case 34: //page down
      case 99: //3
        $_this.map.click(X,Y,MapWidth,MapHeight,0.75,0.25,'Center');
        break;
      case 35: //end
      case 97: //1
        $_this.map.click(X,Y,MapWidth,MapHeight,0.25,0.25,'Center');
        break;
      case 36: //home
      case 103: //7
        $_this.map.click(X,Y,MapWidth,MapHeight,0.25,0.75,'Center');
        break;
      case 37: //left
      case 100: //4
        $_this.map.click(X,Y,MapWidth,MapHeight,0.25,0.5,'Center');
        break;
      case 38: //up
      case 104: //8
        $_this.map.click(X,Y,MapWidth,MapHeight,0.5,0.75,'Center');
        break;
      case 39: //right
      case 102: //6
        $_this.map.click(X,Y,MapWidth,MapHeight,0.75,0.5,'Center');
        break;
      case 40: //down
      case 98: //2
        $_this.map.click(X,Y,MapWidth,MapHeight,0.5,0.25,'Center');
        break;
      case 45: //insert
      case 96: //0
        $_this.map.click(X,Y,MapWidth,MapHeight,0.5,0.5,'ZoomOut');
        break;
      case 46: //delete
      case 101: //5
      case 110: //.
        $_this.map.click(X,Y,MapWidth,MapHeight,0.5,0.5,'ZoomIn');
        break;
    }
  }
};
/*******************************************/
$_this.mouseScrollCallback = function(e){
  var xe = new xEvent(e);
  var X = xe.offsetX;
  var Y = xe.offsetY;
  $_this.cursorPos = [X,Y];
  $_this.dragPending = false;
  var MapWidth = $_this.width();
  var MapHeight = $_this.height();
  var XPercent = X / MapWidth;
  var YPercent = 1.0 -(Y / MapHeight);
  if(e.detail > 0){
    $_this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'ZoomOut');
  }
  else{
    $_this.map.click(X,Y,MapWidth,MapHeight,XPercent,YPercent,'ZoomIn');
  }
  if(e.stopPropagation)
    e.stopPropagation();
  if(e.preventDefault)
    e.preventDefault();
  e.cancelBubble = true;
  e.cancel = true;
  e.returnValue = false;
  return false;
};
/*******************************************/
this.dragStartCallback = function(element,xPos,yPos)
{
  switch (this.mouseMode)
  {
    case 'ZoomWindow':
    case 'SelectWindow':
      zoomBoxPending = true;
      zoomBox.xdelta = zoomBox.ydelta = 0;
      break;
    case 'DragMap':
      this.dragPending = true;
      this.element.appendChild(this.dragPlaneNode);
      this.positionDragTiles();
      this.dragDelta = Array(0,0);
      this.dragTiles[4].src = this.imageNode.src;
      this.imageNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
      break;
    default:
      break;
  }
  this.dragEnabled = true;
  document.mouseUpCallbackObject = this;
  for (var i=0;i<this.eventCallbacks['dragStart'].length;i++)
    if (this.eventCallbacks['dragStart'][i])
      this.eventCallbacks['dragStart'][i](xPos,yPos);
};

/*******************************************/
this.dragCallback = function(dx,dy)
{
  //if either the zoom window or map drag functions are active, 
  //update the coordinates of either the zoom window or the map image.
  if (zoomBoxPending)
  {
    zoomBox.setActive(this.mouseDownPosition[0], this.mouseDownPosition[1]);
    zoomBoxPending = false;
  }
  if (((this.mouseMode == 'ZoomWindow') || (this.mouseMode == 'SelectWindow')) && (this.dragEnabled))
  {
    zoomBox.xdelta += dx;zoomBox.ydelta += dy;
    zoomBox.update(this.mouseDownPosition[0]+zoomBox.xdelta, this.mouseDownPosition[1]+zoomBox.ydelta);
  }
  if (this.dragPending)
  {
    this.dragPending = false;
  }
  if ((this.mouseMode == 'DragMap') && this.dragEnabled)
  {
    this.dragDelta[0]+=dx;
    this.dragDelta[1]+=dy;
    xMoveTo(this.dragPlaneNode,this.dragDelta[0]-this.width(),this.dragDelta[1]-this.height());

    for (i=0;i<this.drawplanes.length;i++){
      if(this.drawplanes[i]){
        if(this.drawplanes[i]["freeance_drag"]){
          xMoveTo(this.drawplanes[i],this.dragDelta[0],this.dragDelta[1]);
        }
      }
    }
  }
  for (var i=0;i<this.eventCallbacks['drag'].length;i++)
    if (this.eventCallbacks['drag'][i])
      this.eventCallbacks['drag'][i](dx,dy);
};

/*******************************************/
this.dragEndCallback = function(evt, xPos, yPos)
{
  //execute the appropriate functions based on the current map mode.
  if (((this.mouseMode == 'ZoomWindow')||(this.mouseMode == 'SelectWindow'))&&(this.dragEnabled) &&(Math.abs(zoomBox.xdelta)>0) &&(Math.abs(zoomBox.ydelta)>0))
  {
    zoomBox.setInactive();
    this.dragEnabled = false;
    this.submitZoomWindow();
  }
  else
    if ((this.mouseMode == 'DragMap')&&(this.dragEnabled))
    {
      this.processMapDrag(this.dragDelta[0],this.dragDelta[1]);
    }
  for (var i=0;i<this.eventCallbacks['dragEnd'].length;i++)
    if (this.eventCallbacks['dragEnd'][i])
      this.eventCallbacks['dragEnd'][i](xPos,yPos);
    
};

this.submitZoomWindow = function()
{
  var MapWidth = this.width();
  var MapHeight = this.height();
  var x1 = this.mouseDownPosition[0];
  var y1 = this.mouseDownPosition[1];
  var x2 = this.mouseDownPosition[0]+zoomBox.xdelta;
  var y2 = this.mouseDownPosition[1]+zoomBox.ydelta;
  if(x1 < x2)
  {
    var left=x1,right=x2;
  }
  else
  {
    var left=x2,right=x1;
  } 
  if(y1 < y2)  // use reverse direction since web is flipped from gis
  {
    var top=y1,bottom=y2;
  }
  else
  {
    var top=y2,bottom=y1;
  }
  switch (this.mapType)
  {
    case 'MASTER':
      var the_bottom = 1.0 -(bottom / MapHeight);
      var the_top    = 1.0 -(top / MapHeight);
      var the_left   = left / MapWidth;
      var the_right  = right / MapWidth;
      switch (this.mouseMode)
      {
        case 'SelectWindow':
          if(this.map.selectionControl)
            this.map.selectionControl.selectByWindow(the_bottom,the_top,the_left,the_right);
          break;
        case 'ZoomWindow':
          this.map.zoomToWindow(the_bottom,the_top,the_left,the_right);
          break;
      }
      break;
    case 'SLAVE':
      var extent = this.map.vmapExtent;
      this.map.zoomToExtent([
          ((1.0 - (bottom / MapHeight)) * (extent[1]-extent[0])) + extent[0],
          ((1.0-(top / MapHeight)) * (extent[1]-extent[0])) + extent[0],
          ((left / MapWidth) * (extent[3]-extent[2])) + extent[2],
          ((right / MapWidth) * (extent[3]-extent[2])) + extent[2]
        ]);    
      break;
  }
};

this.showBufferTarget = function(){this.bufferTargetNode.style.display = 'block';};
this.hideBufferTarget = function(){this.bufferTargetNode.style.display = 'none';};
this.showZoomInTarget = function(){this.zoomInTargetNode.style.display = 'block';};
this.hideZoomInTarget = function(){this.zoomInTargetNode.style.display = 'none';};
this.showZoomOutTarget = function(){this.zoomOutTargetNode.style.display = 'block';};
this.hideZoomOutTarget = function(){this.zoomOutTargetNode.style.display = 'none';};
this.showCompass = function(){this.compassNode.style.display = 'block';};
this.hideCompass = function(){this.compassNode.style.display = 'none';};  

this.clearDragTiles = function()
{
  for (var i=0;i<this.dragTiles.length;i++)
    this.dragTiles[i].src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
};

this.positionDragTiles = function()
{
  var width = (arguments.length>0)?arguments[0]:this.width();
  var height = (arguments.length>1)?arguments[1]:this.height();
  xLeft(this.dragPlaneNode,-width);
  xTop(this.dragPlaneNode,-height);
  xWidth(this.dragPlaneNode,width*3);
  xHeight(this.dragPlaneNode,height*3);
  var currentTile = null;
  for (var x=0;x<3;x++)
  {
    for (var y=0;y<3;y++)
    {
      currentTile = this.dragTiles[x+y*3];
      xLeft(currentTile,x*width);
      xTop(currentTile,y*height);
      xWidth(currentTile,width);
      xHeight(currentTile,height);
    }
  }
};

/*******************************************************************************
**  INITIALIZATION CODE
*********************************/
  this.element = document.createElement("DIV");
  this.element.id = this.id;
  this.element.objectManagerId = OBJECT_MANAGER.registerObject(this.id, this);
  if (parentElement == null)
    parentElement = document.getElementsByTagName("body").item(0); 
	parentElement.appendChild(this.element);
  xLeft(this.element,newXPosition);
  xTop(this.element, newYPosition);
  xZIndex(this.element,newZIndex);
  xWidth(this.element,newWidth);
  xHeight(this.element,newHeight);
  if (newVisibility)
    xShow(this.element);
  else
    xHide(this.element);
  this.imageNode = document.createElement("IMG");
  this.dragPlaneNode = document.createElement("DIV");
  this.dragPlaneNode.setAttribute('id','dragPlaneNode');
  this.dragTiles = Array();
  for (var i=0;i<9;i++){
    var tile=document.createElement("IMG");
    tile.setAttribute((xIE4Up?("className"):("class")),'MapImage');
    tile.setAttribute('id','MapImage.dragTiles['+i+']');
    tile.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
    this.dragPlaneNode.appendChild(tile);
    this.dragTiles.push(tile);
  }
  this.clearDragTiles();  
  this.drawPlaneNode = document.createElement("DIV");
  this.drawPlaneNode.setAttribute('id',this.id+'.drawPlaneNode');
  this.drawPlaneNode.appendChild(zoomBox.element);
  try{
    var canvasElement = document.createElement("CANVAS");
    this.element.appendChild(canvasElement);
    if (typeof(G_vmlCanvasManager) != "undefined") {
      canvasElement = G_vmlCanvasManager.initElement(canvasElement);
    }
    this.measureCanvas = canvasElement;
    this.measureCanvas.getContext("2d");
  }catch(e)
  {
    //alert('canvas could not be initialized\n'+describeObject('',e,'\n'));
    this.measureCanvas = null;
  }
  this.customDrawPlaneNode = document.createElement("DIV");
  this.rasterDrawPlaneNode = document.createElement("DIV");
  this.eventHandlerNode = document.createElement("IMG");
  
  this.bufferTargetNode = document.createElement('DIV');
  this.bufferTargetIMG = document.createElement("IMG");
  this.bufferTargetNode.appendChild(this.bufferTargetIMG);
  
  this.zoomInTargetNode = document.createElement('DIV');
  this.zoomInTargetIMG = document.createElement("IMG");
  this.zoomInTargetNode.appendChild(this.zoomInTargetIMG);
  
  this.zoomOutTargetNode = document.createElement('DIV');
  this.zoomOutTargetIMG = document.createElement("IMG");
  this.zoomOutTargetNode.appendChild(this.zoomOutTargetIMG);
  
  this.compassNode = document.createElement(((xIE4Up)?('DIV'):('IMG')));
  this.productLogoNode = document.createElement(((xIE4Up)?('DIV'):('IMG')));
  this.loadImage = document.createElement('IMG'); //animated gif

  //assemble the main object
  this.element.appendChild(this.imageNode);
  this.element.appendChild(this.drawPlaneNode);
  this.element.appendChild(this.customDrawPlaneNode);
  this.element.appendChild(this.rasterDrawPlaneNode);
	this.element.appendChild(this.eventHandlerNode);
  
  //Assemble map overlay images
  this.rasterDrawPlaneNode.appendChild(this.loadImage);
  this.rasterDrawPlaneNode.appendChild(this.bufferTargetNode);
  this.rasterDrawPlaneNode.appendChild(this.zoomInTargetNode);
  this.rasterDrawPlaneNode.appendChild(this.zoomOutTargetNode);
  this.rasterDrawPlaneNode.appendChild(this.compassNode);
  this.rasterDrawPlaneNode.appendChild(this.productLogoNode);
  this.rasterDrawPlaneNode.style.overflow = 'hidden';
  this.rasterDrawPlaneNode.style.width = 50;
  this.rasterDrawPlaneNode.style.height = 50;
  
  this.eventHandlerNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
  this.resizeTo(newWidth, newHeight);
  
  //set load image attributes
  var centerX = Math.floor(0.5*newWidth);
  var centerY = Math.floor(0.5*newHeight);
  this.loadImage.id = this.id+'.loadImage';
  this.loadImage.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/mapLoad.gif';
  this.loadImage.style.position = 'absolute';
  this.loadImage.style.width = _MapLoadImageWidth;
  this.loadImage.style.height = _MapLoadImageHeight;
  xMoveTo(this.loadImage,centerX-0.5*_MapLoadImageWidth,centerY-0.5*_MapLoadImageHeight);
  this.loadImage.style.display = ((this.mapType == 'MASTER')?('block'):('none'));
  
  //set map overlay attributes
  this.bufferTargetNode.style.position = this.zoomInTargetNode.style.position = this.zoomOutTargetNode.style.position = this.compassNode.style.position = 'absolute';
  this.zoomInTargetIMG.style.width = this.bufferTargetIMG.style.width = this.zoomOutTargetIMG.style.width = 50;
  this.zoomInTargetIMG.style.height = this.bufferTargetIMG.style.height = this.zoomOutTargetIMG.style.height = 200;
  this.zoomInTargetNode.style.overflow = this.bufferTargetNode.style.overflow = this.zoomOutTargetNode.style.overflow  = 'hidden';
  this.bufferTargetNode.style.display=this.zoomInTargetNode.style.display=this.zoomOutTargetNode.style.display = 'none';
  this.compassNode.style.display = 'none';
  this.compassNode.style.width = 50;
  this.compassNode.style.height = 200;
  this.compassNode.style.top = -145;
  this.compassNode.style.right = 5;
  this.productLogoNode.style.position = 'absolute';
  this.productLogoNode.style.display = ((this.mapType=='MASTER')?('block'):('none'));
  if (xIE4Up)
  {
    this.productLogoNode.style.width = _MapProductLogoWidth;
    this.productLogoNode.style.height = _MapProductLogoHeight;
  }
  this.productLogoNode.style.right = 5;
  this.productLogoNode.style.bottom = 5;


  //fix internet explorer 6 problem with 24-bit png map overlays
  if (xIE4Up) //fix png
  {
    this.bufferTargetIMG.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png'+'\', sizingMethod=\'image\')';
    this.zoomInTargetIMG.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png'+'\', sizingMethod=\'image\')';
    this.zoomOutTargetIMG.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png'+'\', sizingMethod=\'image\')';
    this.compassNode.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png'+'\', sizingMethod=\'image\')';
    this.productLogoNode.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/mapProductLogo.png'+'\', sizingMethod=\'image\')';
    this.bufferTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
    this.zoomInTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
    this.zoomOutTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
    this.compassNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/blank.gif';
    this.productLogoNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/mapProductLogo.png';
  }
  else
  {
    this.bufferTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png';
    this.zoomInTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png';
    this.zoomOutTargetIMG.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png';
    this.compassNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/target.png';
    this.productLogoNode.src = GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/mapProductLogo.png';
  }
  this.eventHandlerNode.mapImageObject = this;
  
  this.imageNode.style.position = this.dragPlaneNode.style.position = this.drawPlaneNode.style.position = this.rasterDrawPlaneNode.style.position = this.customDrawPlaneNode.style.position = 'absolute';
  this.zoomInTargetIMG.style.top = -100;
  this.zoomOutTargetIMG.style.top = -50;
  this.bufferTargetIMG.style.top = 0;
  this.zoomInTargetIMG.style.position = this.bufferTargetIMG.style.position = this.zoomOutTargetIMG.style.position = 'relative';
  this.zoomInTargetNode.style.overflow = this.bufferTargetNode.style.overflow = this.zoomOutTargetNode.style.overflow  = 'hidden';
  this.zoomInTargetNode.style.height = this.bufferTargetNode.style.height = this.zoomOutTargetNode.style.height = 50;
  
  if (this.measureCanvas)
    this.measureCanvas.style.position = 'absolute';
  this.eventHandlerNode.setAttribute((xIE4Up?("className"):("class")),'MapImage');
  xZIndex(this.dragPlaneNode,0);
  xZIndex(this.imageNode,1);
  xZIndex(this.drawPlaneNode,2); 
  xZIndex(this.customDrawPlaneNode,3); 
  xZIndex(this.rasterDrawPlaneNode,4); 
  //xZIndex(this.zoomWindowNode,5); 
  if (this.measureCanvas)
    xZIndex(this.measureCanvas,6); 
  xZIndex(this.eventHandlerNode,7);
  
  xMoveTo(this.imageNode, 0,0);
  xMoveTo(this.drawPlaneNode, 0,0);
  xMoveTo(this.rasterDrawPlaneNode, 0,0);
  if (this.measureCanvas)
    xMoveTo(this.measureCanvas, 0,0);
  xMoveTo(this.eventHandlerNode, 0,0);
  var targetX = centerX-25; 
  var targetY = centerY-25;
  xMoveTo(this.bufferTargetNode,targetX,targetY);
  xMoveTo(this.zoomInTargetNode,targetX,targetY);
  xMoveTo(this.zoomOutTargetNode,targetX,targetY);
  
  //set up event listeners
  this.eventHandlerNode.mapImage = this;
  xAddEventListener(this.eventHandlerNode, 'click', function(e){$_this.clickCallback(new xEvent(e));}, false);
  xAddEventListener(this.eventHandlerNode, 'mouseover', function(e){$_this.mouseOverCallback(new xEvent(e));}, false);
  xAddEventListener(this.eventHandlerNode, 'mouseout', function(e){$_this.mouseOutCallback(new xEvent(e));}, false);
  xAddEventListener(this.eventHandlerNode, 'mouseup', function(e){$_this.mouseUpCallback(new xEvent(e));}, false);
  xAddEventListener(this.eventHandlerNode, 'mousedown', function(e){$_this.mouseDownCallback(new xEvent(e));}, false);
  xAddEventListener(this.eventHandlerNode, 'mousemove', function(e){$_this.mouseMoveCallback(new xEvent(e));}, false);
  if(this.mapType == 'MASTER'){
    xAddEventListener(this.eventHandlerNode, 'mousewheel', $_this.mouseWheelCallback, false);
    xAddEventListener(this.eventHandlerNode, 'DOMMouseScroll', $_this.mouseScrollCallback, false);
    xAddEventListener(document, 'keydown', $_this.keyDownCallback, true);
  }
  xEnableDrag(this.eventHandlerNode,
    function(element,dx,dy){$_this.dragStartCallback(dx,dy);},
    function(element,dx,dy){$_this.dragCallback(dx,dy);},
    function(element,dx,dy){$_this.dragEndCallback(dx,dy);}
  );
  setClass(this.element,'MapImageContainer');
  //force set vicinity maps to zoom window mode.  if the user clicks the map, will recenter at current zoom extent
  if (this.mapType == 'SLAVE')
    this.setMouseMode('ZoomWindow');
};

