function IeFix(url) {
	if (document.namespaces && document.namespaces.add) {
		try { 
			document.execCommand('BackgroundImageCache', false, true); 
		} catch(e) {};
		var cssStr = "img, body { behavior: url(" + url + "iepngfix.htc); }";
		var style = document.createElement("style");
		style.setAttribute("type", "text/css");
		
		if(style.styleSheet){
			style.styleSheet.cssText = cssStr;
		} else {
			var cssText = doc.createTextNode(cssStr);
			style.appendChild(cssText);
		}		
		document.getElementsByTagName("head")[0].appendChild(style);
	}
};

function DrawingCanvasSVGT(parent, width, height)
{
  if (!parent) {
  	throw new Error("No canvas parent!");
  }

  if (!width) {
    width  = parent.clientWidth;
  }
  if (!height) {
  	height = parent.clientHeight;
  }

  this.parent        = parent;
  this.width         = width;
  this.height        = height;
  this._bgColor      = "none";
  this._lineWidth    = 2;
  this._lineColor    = "#000";
  this._dotColor 	 = "#000";
  this._dotMode 	 = false;
  this._isDrawing    = false;
  this._currentShape = null;
  this._points       = "";
  this._dummyDot     = null;
  this._stack        = [];
  this._stackSize    = 0;
  this._opacity 	 = 0.45;

  var svg = document.createElementNS(this._XMLNS_SVG, "svg");
  svg.setAttribute("width", width);
  svg.setAttribute("height", height);
  svg.setAttribute("overflow", "visible");

  var rect = document.createElementNS(this._XMLNS_SVG, "rect");
  rect.setAttribute("width", width);
  rect.setAttribute("height", height);
  rect.setAttribute("fill", this._bgColor);
  svg.appendChild(rect);

  var container = document.createElementNS("http://www.w3.org/1999/xhtml",
                                          "div");
  container.setAttribute("style", "width: "  + width  + "px; " +
                                  "height: " + height + "px; ");
  container.appendChild(svg);

  parent.appendChild(container);

  this.container = container;
  this._svgRoot  = svg;
  this._bg       = rect;
};

DrawingCanvasSVGT.prototype = {
  _XMLNS_SVG: "http://www.w3.org/2000/svg",
  
  setPosX: function(left) {
  	this._svgRoot.style.position = "absolute";
  	this._svgRoot.style.zIndex = 1000;
  	this._svgRoot.style.left = left + "px";
  },
  
  setPosY: function(top) {
  	this._svgRoot.style.position = "absolute";
  	this._svgRoot.style.zIndex = 1000;
  	this._svgRoot.style.top = top + "px";  	
  },
  
  setViewBox: function(left, top, width, height) {
  	var vb = left + " " + top + " " + width + " " + height; 
  	this._svgRoot.setAttribute("viewBox", vb);
  },
  
  setSize: function(width, height) {
  	this._svgRoot.setAttribute("width", width);
  	this._svgRoot.setAttribute("height", height);
	this._bg.setAttribute("width", width);
  	this._bg.setAttribute("height", height);  	
  	this.width = width;
  	this.height = height;
  },

  setBgColor: function (color) {
    this._bgColor = (color == "transparent") ? "none" : color;
    this._refresh();
  },

  setLineColor: function (color) {
  	if (color == undefined) {
  		return;
  	}
    this._lineColor = color;
  },
  
  setOpacity: function(opacity) {
  	this._opacity = opacity;
  },

  setLineWidth: function (width) {
    this._lineWidth = Number(width) || 0;
  },
  
  createGeofence: function(x, y, r, lbl) {
  	this.createCircle(x, y, r, true);
    this.createArrow(x, y, r);
    this.createText(x, y, r, lbl);
  },
  
  createCircle: function(x, y, r, geofence) {
    var dotColor = this._lineColor;
    if (this._dotMode == true || geofence == true) {
    	dotColor = this._dotColor;
	    var dot = document.createElementNS(this._XMLNS_SVG, "circle");
	    dot.setAttribute("cx", x);
	    dot.setAttribute("cy", y);
	    dot.setAttribute("r", r);
	    if (geofence == true) {
	    	dot.setAttribute("stroke", "black");
    		dot.setAttribute("stroke-width", 2);
    		dot.setAttribute("fill", "none");	    	
	    } else {
	    	dot.setAttribute("fill", dotColor);
	    }       
	  	this._svgRoot.appendChild(dot);
	    this._pushStack(dot);    	
    } 	
  },
  
  createArrow: function(x, y, r) {
    var arr = document.createElementNS(this._XMLNS_SVG, "polyline");
    var points = (x+r-5)+","+(y-5)+" "+(x+r)+","+y+" "
    	+x+","+y+" "+(x+r)+","+y+" "+(x+r-5)+","+(y+5);
    arr.setAttribute("fill", "none");
    arr.setAttribute("stroke", "black");
    arr.setAttribute("stroke-width", 2);
    arr.setAttribute("stroke-linecap", "round");
    arr.setAttribute("stroke-linejoin", "round");
    arr.setAttribute("points", points);
    this._svgRoot.appendChild(arr);
    this._pushStack(arr);
  },
  
  createText: function(x, y, r, l) {
  	var tex = document.createElementNS(this._XMLNS_SVG, "text");
  	tex.setAttribute("x", x);
  	tex.setAttribute("y", y-5);
  	tex.setAttribute("fill", "red");
  	tex.setAttribute("stroke-linejoin", "bevel");
  	tex.setAttribute("font-size", 18);
  	tex.appendChild(document.createTextNode((l/1000)+" km"));
    this._svgRoot.appendChild(tex);
    this._pushStack(tex);  	
  },

  startLine: function (x, y) {
    if (this._isDrawing) {
      this.endLine();
    }
    this._isDrawing = true;
	this.createCircle(x, y, this._lineWidth / 2);
    this._points   = x + "," + y;

    var polyline = document.createElementNS(this._XMLNS_SVG, "polyline");
    polyline.setAttribute("fill", "none");
    polyline.setAttribute("stroke", this._lineColor);
    polyline.setAttribute("stroke-width", this._lineWidth);
    polyline.setAttribute("stroke-linecap", "round");
    polyline.setAttribute("stroke-linejoin", "round");
    polyline.setAttribute("opacity", this._opacity);
    polyline.setAttribute("points", this._points);
    this._svgRoot.appendChild(polyline);
    this._currentShape = polyline;
  },

  endLine: function () {
    if (!this._isDrawing) {
    	return;
    }

    if (this._dummyDot) {
      this._svgRoot.removeChild(this._currentShape);
      this._pushStack(this._dummyDot);
      this._dummyDot = null;
    } else {
      this._pushStack(this._currentShape);
    }
    this._isDrawing    = false;
    this._currentShape = null;
    this._points       = "";
  },

  lineTo: function (x, y) {
    if (!this._isDrawing) {
    	return;
    }
    if (this._dummyDot) {
      this._svgRoot.removeChild(this._dummyDot);
      this._dummyDot = null;
    }

	this.createCircle(x, y, this._lineWidth / 2);

    this._points += " " + x + "," + y;
    this._currentShape.setAttribute("points", this._points);
  },

  undo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize <= 0) {
      return false;
	}
    this._svgRoot.removeChild(this._stack[--this._stackSize]);
    this._refresh();
    return true;
  },

  redo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize >= this._stack.length) {
      return false;
	}
    this._svgRoot.appendChild(this._stack[this._stackSize++]);
    this._refresh();
    return true;
  },

  clearShape: function () {
    if (this._isDrawing){
    	this.endLine();
    }
    if (this._stack.length > 1) {
	   	this._svgRoot.removeChild(this._stack[this._stack.length-1]);
	    this._refresh();
	   	this._stack.length = this._stack.length - 1;
	   	this._stackSize    = this._stackSize - 1;   	
    }
  },

  clear: function () {
    if (this._isDrawing) {
      this.endLine();
	}
    for (var i = this._stackSize; i--;) {
      if (this._stack[i]!=undefined) this._svgRoot.removeChild(this._stack[i]);
    }
    this._refresh();
    this._stack.length = 0;
    this._stackSize    = 0;
  },

  getX: function () {
    var box = this.container;
    var x   = box.offsetLeft;
    while ((box = box.offsetParent)) {
      x += box.offsetLeft;
	}
    return x;
  },

  getY: function () {
    var box = this.container;
    var y   = box.offsetTop;
    while ((box = box.offsetParent)) {
      y += box.offsetTop;
	}
    return y;
  },

  _pushStack: function (shape) {
    if (this._stackSize + 1 < this._stack.length) {
      this._stack.length = this._stackSize + 1;
    }
    this._stack[this._stackSize++] = shape;
  },

  _refresh: function () {
    this._bg.setAttribute("fill", this._bgColor);
  }
};

function DrawingCanvasCanvas(parent, width, height)
{
  if (!parent) {
  	throw new Error("No canvas parent!");
  }

  if (!width) {
  	width  = parent.clientWidth;
  }
  if (!height) {
  	height = parent.clientHeight;
  }

  this.parent        = parent;
  this.width         = width;
  this.height        = height;
  this._bgColor      = "transparent";
  this._lineWidth    = 2;
  this._lineColor    = "#000";
  this._dotColor 	 = "#000";
  this._dotMode 	 = false;
  this._isDrawing    = false;
  this._opacity 	 = 0.45;

  this._points       = null;
  this._stack        = [];
  this._stackSize    = 0;

  var canvas = document.createElement("canvas");
  canvas.setAttribute("id", "DCCanvas" + (new Date()).getTime() +
                            ++arguments.callee._count);
  canvas.setAttribute("width", width);
  canvas.setAttribute("height", height);

  var container = document.createElement("div");
  container.setAttribute("style", "width: "  + width  + "px; " +
                                  "height: " + height + "px; ");
  container.appendChild(canvas);
  parent.appendChild(container);

  var context = canvas.getContext("2d");
  context.lineCap  = "round";
  context.lineJoin = "round";

  this.container = container;
  this._context  = context;
  this._canvas   = canvas;
};

DrawingCanvasCanvas._count = 0;

DrawingCanvasCanvas.prototype = {
  setBgColor: function (color) {
    this._bgColor = color;
    this._refresh();
  },
  
  setPos:function(left, top) {
  	this.container.style.left = left + "px";
  	this.container.style.top = top + "px";
  },
  
  setSize: function(width, height) {
  	this.container.style.width = width + "px";
  	this.container.style.height = height + "px";
	this._canvas.setAttribute("width", width);
  	this._canvas.setAttribute("height", height);
  	this.width = width;
  	this.height = height;  	
  },  

  setLineColor: function (color) {
  	if (color == undefined) {
  		return;
  	} 	
    this._lineColor = color;
  },

  setLineWidth: function (width) {
    this._lineWidth = Number(width) || 0;
  },
  
  setOpacity: function (opacity) {
  	this._opacity = opacity;
  },

  startLine: function (x, y) {
    if (this._isDrawing) {
      this.endLine();
    }
    this._isDrawing = true;

    this._context.strokeStyle = this._lineColor;
    this._context.fillStyle   = this._lineColor;
    this._context.lineWidth   = this._lineWidth;

    this._context.arc(x, y, this._lineWidth / 2, 0, 2 * Math.PI, true);
    this._context.fill();

    this._points           = [x, y];
    this._currentX         = x;
    this._currentY         = y;
    this._currentLineColor = this._lineColor;
    this._currentLineWidth = this._lineWidth;
  },

  endLine: function () {
    if (!this._isDrawing) {
    	return;
    }

    this._isDrawing = false;
    this._pushStack(this._points,
                    this._currentLineColor, this._currentLineWidth);
    this._points    = null;
  },

  lineTo: function (x, y) {
    if (!this._isDrawing) {
    	return;
    }

    this._context.moveTo(this._currentX, this._currentY);
    this._context.lineTo(x, y);
    this._context.stroke();

    this._points.push(x, y);
    this._currentX = x;
    this._currentY = y;
  },

  undo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize <= 0) {
      return false;
    }

    --this._stackSize;
    this._refresh();
    return true;
  },

  redo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize >= this._stack.length) {
      return false;
    }

    ++this._stackSize;
    this._refresh();
    return true;
  },
  
  clearShape: function () {
    if (this._isDrawing) {
      this.endLine();
	}
	if (this._stack.length > 1) {
		this._stack[this._stack.length-1] = undefined;
   		this._refresh();
	}		
  },
  
  clear: function () {
    if (this._isDrawing) {
      this.endLine();
    }

    this._stack.length = 0;
    this._stackSize    = 0;
    this._refresh();
  },

  getX: function () {
    var box = this.container;
    var x   = box.offsetLeft;
    while ((box = box.offsetParent)) {
      x += box.offsetLeft;
	};
    return x;
  },

  getY: function () {
    var box = this.container;
    var y   = box.offsetTop;
    while ((box = box.offsetParent)) {
      y += box.offsetTop;
	};
    return y;
  },

  _pushStack: function (points, lineColor, lineWidth) {
    if (this._stackSize + 1 < this._stack.length) {
      this._stack.length = this._stackSize + 1;
    }
    this._stack[this._stackSize++] = {
      type:      (points.length == 2) ? "dot" : "polyline",
      points:    points,
      lineColor: lineColor,
      lineWidth: lineWidth
    }
  },

  _refresh: function () {
    if (this._bgColor == "transparent") {
      this._context.clearRect(0, 0, this.width, this.height);
    } else {
      this._context.fillStyle = this._bgColor;
      this._context.fillRect(0, 0, this.width, this.height);
    }

    for (var i = 0; i < this._stackSize; i++) {
      var shape = this._stack[i];
      if (shape.type == "dot") {
        this._context.fillStyle = shape.lineColor;
        this._context.arc(shape.points[0], shape.points[1],
                          shape.lineWidth / 2, 0, this._MATH_2PI, true);
        this._context.fill();
      } else {
        this._context.strokeStyle = shape.lineColor;
        this._context.lineWidth   = shape.lineWidth;
        this._context.moveTo(shape.points[0], shape.points[1]);
        for (var j = 2, n = shape.points.length; j < n; j += 2)
          this._context.lineTo(shape.points[j], shape.points[j + 1]);
        this._context.stroke();
      }
    }
  }
};


function DrawingCanvasCSSP(parent, width, height)
{
  if (!parent) {
  	throw new Error("No canvas parent!");
  }

  if (!width) {
    width  = parent.clientWidth;
  }
  if (!height) {
  	height = parent.clientHeight;
  }

  this.parent         = parent;
  this.width          = width;
  this.height         = height;
  this._bgColor       = "transparent";
  this._lineWidth     = 2;
  this._lineColor     = "#000";
  this._dotColor 	 = "#000";
  this._dotMode 	 = false;
  this._isDrawing     = false;
  this._currentLayer  = null;
  this._stack         = [];
  this._stackSize     = 0;
  this._opacity 	  = 0.45;

  this._dotStyle         = "";
  this._currentLineWidth = 0;
  this._dotOffset        = 0;
  this._dotX             = 0;
  this._dotY             = 0;

  var container = document.createElement("div");
  var containerStyle = "background-color: " + this._bgColor + "; " +
                       "position: relative; " +
                       "width: "  + width  + "px; " +
                       "height: " + height + "px; " +
                       "overflow: hidden; ";
  if (this._useCssText) {
    container.style.cssText = containerStyle;
  } else {
    container.setAttribute("style", containerStyle);
  }

  parent.appendChild(container);
  this.container = container;
};

DrawingCanvasCSSP.prototype = {
  _useCssText: document.documentElement.getAttribute("style") ==
               document.documentElement.style,

  setPos:function(left, top) {
  	this.container.style.left = left + "px";
  	this.container.style.top = top + "px";
  },

  setSize: function(width, height) {
  	this.container.style.width = width + "px";
  	this.container.style.height = height + "px";
  	this.width = width;
  	this.height = height;  	  	
  },

  setBgColor: function (color) {
    this.container.style.backgroundColor = this._bgColor = color;
  },

  setLineColor: function (color) {
  	if (color == undefined) {
  		return;
  	}  	
    this._lineColor = color;
  },

  setLineWidth: function (width) {
    this._lineWidth = Number(width) || 0;
  },

  startLine: function (x, y) {
    if (this._isDrawing) {
      this.endLine();
    }
    this._isDrawing = true;

    x = Math.round(x);
    y = Math.round(y);

    var currentLineWidth = this._lineWidth;
    this._dotStyle       = "background-color: " + this._lineColor + "; " +
                           "position: absolute; " +
                           "overflow: hidden; ";
    this._dotOffset      = Math.floor(currentLineWidth / 2);
    this._dotX           = x - this._dotOffset;
    this._dotY           = y - this._dotOffset;

    var layer    = document.createElement("div");
    var dot      = document.createElement("div");
    var dotStyle = this._dotStyle +
                   "width: "  + currentLineWidth + "px; " +
                   "height: " + currentLineWidth + "px; " +
                   "left: "   + this._dotX       + "px; " +
                   "top: "    + this._dotY       + "px; ";
    if (this._useCssText) {
      dot.style.cssText   = dotStyle;
    } else {
      dot.setAttribute("style", dotStyle);
    }
    layer.appendChild(dot);
    this.container.appendChild(layer);
    this._currentLineWidth = currentLineWidth;
    this._currentLayer     = layer;
  },

  endLine: function () {
    if (!this._isDrawing) {
    	return;
    }

    this._isDrawing        = false;
    this._pushStack(this._currentLayer);
    this._currentLineWidth = 0;
    this._currentLayer     = null;
  },

  lineTo: function (x, y) {
    if (!this._isDrawing) {
    	return;
    }

    x = Math.round(x);
    y = Math.round(y);

    var currentX = this._dotX;
    var currentY = this._dotY;
    var endX     = x - this._dotOffset;
    var endY     = y - this._dotOffset;
    var dirX     = (currentX < endX) ? 1 : -1;
    var dirY     = (currentY < endY) ? 1 : -1;
    var dx       = (dirX == 1) ? endX - currentX : currentX - endX;
    var dy       = (dirY == 1) ? endY - currentY : currentY - endY;
    var error, errorIncrement, errorCorrection;

    if (dx == 0 && dy == 0) {
      return;
    }
    var fragment       = document.createDocumentFragment();
    var dotStyleCommon = this._dotStyle;
    var useCssText     = this._useCssText;
    var lineWidth      = this._currentLineWidth;
    var lineLength     = lineWidth;

    if (dx >= dy) {
      var left, dot, dotStyle;
      var isPositiveDir = (dirX == 1);
      error             = -dx;
      errorIncrement    = dy << 1;
      errorCorrection   = dx << 1;
      for (var i = 0; i < dx; ++i) {
        error += errorIncrement;
        if (error >= 0) {
          left     = isPositiveDir ? currentX - lineLength + lineWidth
                                   : currentX;
          dot      = document.createElement("div");
          dotStyle = dotStyleCommon +
                     "width: "  + lineLength + "px; " +
                     "height: " + lineWidth  + "px; " +
                     "left: "   + left       + "px; " +
                     "top: "    + currentY   + "px; ";
          if (useCssText) {
            dot.style.cssText = dotStyle;
          } else {
            dot.setAttribute("style", dotStyle);
          }
          fragment.appendChild(dot);

          currentY   += dirY;
          error      -= errorCorrection;
          lineLength = lineWidth;
        } else {
          ++lineLength;
        }
        currentX += dirX;
      }
      left     = isPositiveDir ? endX - lineLength + lineWidth : endX;
      dot      = document.createElement("div");
      dotStyle = dotStyleCommon +
                 "width: "  + lineLength + "px; " +
                 "height: " + lineWidth  + "px; " +
                 "left: "   + left       + "px; " +
                 "top: "    + endY       + "px; ";
      if (useCssText) {
        dot.style.cssText = dotStyle;
      } else {
        dot.setAttribute("style", dotStyle);
      }
      fragment.appendChild(dot);
    } else { 
      var top, dot, dotStyle;
      var isPositiveDir = (dirY == 1);
      error             = -dy;
      errorIncrement    = dx << 1;
      errorCorrection   = dy << 1;
      for (var i = 0; i < dy; ++i) {
        error += errorIncrement;
        if (error >= 0) {
          top      = isPositiveDir ? currentY - lineLength + lineWidth
                                   : currentY;
          dot      = document.createElement("div");
          dotStyle = dotStyleCommon +
                     "width: "  + lineWidth  + "px; " +
                     "height: " + lineLength + "px; " +
                     "left: "   + currentX   + "px; " +
                     "top: "    + top        + "px; ";
          if (useCssText) {
            dot.style.cssText = dotStyle;
          } else {
            dot.setAttribute("style", dotStyle);
          }
          fragment.appendChild(dot);

          currentX   += dirX;
          error      -= errorCorrection;
          lineLength = lineWidth;
        } else {
          ++lineLength;
        }
        currentY += dirY;
      }
      top      = isPositiveDir ? endY - lineLength + lineWidth : endY;
      dot      = document.createElement("div");
      dotStyle = dotStyleCommon +
                 "width: "  + lineWidth  + "px; " +
                 "height: " + lineLength + "px; " +
                 "left: "   + endX       + "px; " +
                 "top: "    + top        + "px; ";
      if (useCssText) {
        dot.style.cssText = dotStyle;
      } else {
        dot.setAttribute("style", dotStyle);
      }
      fragment.appendChild(dot);
    }

    this._currentLayer.appendChild(fragment);
    this._dotX = endX;
    this._dotY = endY;
  },

  undo: function () {
    if (this._isDrawing){
      this.endLine();
    }
    if (this._stackSize <= 0) {
      return false;
    }

    this.container.removeChild(this._stack[--this._stackSize]);
    return true;
  },

  redo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize >= this._stack.length) {
      return false;
    }

    this.container.appendChild(this._stack[this._stackSize++]);
    return true;
  },

  clearShape: function () {
    if (this._isDrawing){
      this.endLine();
    }
    
    if (this._stack.length > 1) {
	   	this.container.removeChild(this._stack[this._stack.length-1]);
	    this._stack.length = this._stack.length - 1;
	   	this._stackSize    = this._stackSize - 1;
    }
  },

  clear: function () {
    if (this._isDrawing) {
      this.endLine();
    };

    for (var i = this._stackSize; i--;) {
      this.container.removeChild(this._stack[i]);
    };
    this._stack.length = 0;
    this._stackSize    = 0;
  },

  _htmlIsRoot: (typeof document.compatMode == "string") &&
               (document.compatMode == "CSS1Compat"),

  getX: function () {
    var box = this.container;
    var x = box.offsetLeft;
    while ((box = box.offsetParent)){
      x += box.offsetLeft;
    }

    if (this._useCssText){
      x += (this._htmlIsRoot ? document.documentElement
                             : document.body).clientLeft;
	}
    return x;
  },

  getY: function () {
    var box = this.container;
    var y = box.offsetTop;
    while ((box = box.offsetParent)) {
      y += box.offsetTop;
    }

    if (this._useCssText) {
      y += (this._htmlIsRoot ? document.documentElement
                             : document.body).clientTop;
	}
    return y;
  },

  _pushStack: function (layer) {
    if (this._stackSize + 1 < this._stack.length) {
      this._stack.length = this._stackSize + 1;
    }
    this._stack[this._stackSize++] = layer;
  }
};


function DrawingCanvasVML(parent, width, height)
{
  if (!document.namespaces) {
  	throw new Error("Not supported!");
  }
  if (!document.namespaces.v) {
    document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
    document.createStyleSheet().addRule("v\\:*",
                                        "behavior: url(#default#VML);");
  }
  if (!parent) {
  	throw new Error("No canvas parent!");
  }
  if (!width)  {
  	width  = parent.clientWidth;
  }
  if (!height) {
  	height = parent.clientHeight;
  }

  this.parent        = parent;
  this.width         = width;
  this.height        = height;
  this._bgColor      = "none";
  this._lineWidth    = 2;
  this._lineColor    = "#000";
  this._dotColor 	 = "#000";
  this._dotMode 	 = false;
  this._isDrawing    = false;
  this._currentShape = null;
  this._dummyDot     = null;
  this._points       = "";
  this._stack        = [];
  this._stackSize    = 0;
  this._opacity 	 = 0.45;
  
  var container = document.createElement("div");
  container.style.cssText = "position: relative;" +
                            "width: "  + width  + "px; " +
                            "height: " + height + "px; " +
                            "overflow: hidden;";                           	                           
  var vmlRoot = document.createElement("v:group");
  vmlRoot.style.cssText = "width: "  + width  + "px; " +
  						"height: " + height + "px; ";					  					
  container.appendChild(vmlRoot);
  parent.appendChild(container);  
  this.container = container;
  this._vmlRoot = vmlRoot;
};

DrawingCanvasVML.prototype = {
  setBgColor: function (color) {
    this.container.style.backgroundColor = this._bgColor = color;
  },
  
  setViewBox: function(left, top, width, height) {
  	this._vmlRoot.setAttribute("coordorigin", left + " " + top);
  	this._vmlRoot.setAttribute("coordsize", parseInt(width + this._lineWidth * 2) 
  	+ "," + parseInt(height + this._lineWidth * 2));
  },  
  
  setPosX: function(left) {
  	this.container.style.left = left + "px";  	
  },  
  
  setPosY: function(top) {
	this.container.style.top = top + "px";  	
  },

  setSize: function(width, height) {
  	this.container.style.width = width + "px";
  	this.container.style.height = height + "px";
  	this._vmlRoot.style.width = width + "px";
  	this._vmlRoot.style.height = height + "px";
  	this.width = width;
  	this.height = height;  	  	
  },

  setLineColor: function (color) {
  	if (color == undefined) {
  		return;
  	} 	
    this._lineColor = color;
  },
  
  setOpacity: function (opacity) {
  	this._opacity = opacity;
  },

  setLineWidth: function (width) {
    this._lineWidth = Number(width) || 0;
  },
  
  createGeofence: function(x, y, r, l) {
  	this.setViewBox(0,0,this.width,this.height);
  	this.createCircle(x, y, r, true);
  	this.createArrow(x, y, r);
  	this.createText(x, y, r, l);
  },
  
  createCircle: function(x, y, r, geofence) {
    var dotColor = this._lineColor;
    if (this._dotMode == true || geofence == true) {
    	dotColor = this._dotColor;
	  	r = Math.round(r);
	    var dot  = document.createElement("v:oval");
	    dot.strokeweight = 2;
	    var w = r*2; 
	    dot.style.cssText = "position: absolute; width: "  + w + "px; " +
	                        "height: " + w + "px; left: " + (x-r) + "px; " +
	                        "top: " + (y-r) + "px; ";
		if (geofence == true) {
			dot.innerHTML = "<v:fill on='false' />";
		} else {
			dot.innerHTML = "<v:fill on='true' color='" + dotColor + "' />";
		}
	    this._vmlRoot.appendChild(dot);
	    this._pushStack(dot);    	
    }   
  },
  
  createArrow: function(x, y, r) {
    var arr = document.createElement("v:polyline");
    arr.filled       = false;
    arr.strokecolor  = "black";
    arr.strokeweight = 2;
    arr.points       = (x+r-5)+","+(y-5)+" "+(x+r)+","+y+" "
    	+x+","+y+" "+(x+r)+","+y+" "+(x+r-5)+","+(y+5);
    this._vmlRoot.appendChild(arr);    
    this._pushStack(arr);
  },
  
  createText: function(x, y, r, l) {   
    var lin = document.createElement("v:line");
    lin.from = x+" "+(y-10); lin.to = (x+r)+" "+(y-11);
    lin.innerHTML = "<v:fill on='True' color='red'/>"
    	+ "<v:path textpathok='True'/>"
    	+ "<v:textpath on='True' string='"+(l/1000)+" km"
    	+ "' style='font:normal normal normal 12pt Arial'/>";
	this._vmlRoot.appendChild(lin);
    this._pushStack(lin);    	
  },
	
  startLine: function (x, y) {
    if (this._isDrawing){
      this.endLine();
    }
    this._isDrawing = true;
	this.createCircle(x, y, this._lineWidth/2);

    this._points   = x + "," + y;

    var polyline = document.createElement("v:polyline");
    polyline.filled       = false;
    polyline.strokecolor  = this._lineColor;
    polyline.strokeweight = this._lineWidth;
    polyline.points       = this._points;  	
    
    var stroke = document.createElement("v:stroke");
    stroke.endcap = "round";
    stroke.opacity = this._opacity;
    polyline.appendChild(stroke);
    this._vmlRoot.appendChild(polyline);
    this._currentShape = polyline;
  },

  endLine: function () {
    if (!this._isDrawing) {
    	return;
    }

    if (this._dummyDot) {
      this.container.removeChild(this._currentShape);
      this._pushStack(this._dummyDot);
      this._dummyDot = null;
    } else {
      this._pushStack(this._currentShape);
    }
    this._isDrawing    = false;
    this._currentShape = null;
    this._points       = "";
  },

  lineTo: function (x, y) {
    if (!this._isDrawing) {
      return;
    }
    if (this._dummyDot) {
      this._vmlRoot.removeChild(this._dummyDot);
      this._dummyDot = null;
    }
	this.createCircle(x, y, this._lineWidth/2);

    this._points +=  " " + x + "," + y;
    this._currentShape.points.value = this._points;
  },

  undo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize <= 0) {
      return false;
    }

    this._stack[--this._stackSize].style.visibility = "hidden";
    return true;
  },

  redo: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    if (this._stackSize >= this._stack.length) {
      return false;
    }

    this._stack[this._stackSize++].style.visibility = "visible";
    return true;
  },

  clearShape: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    
    if (this._stack.length > 1) {
	   	this._vmlRoot.removeChild(this._stack[this._stack.length-1]);
	    this._stack.length = this._stack.length - 1;
	    this._stackSize    = this._stackSize - 1;
    }
  },

  clear: function () {
    if (this._isDrawing) {
      this.endLine();
    }
    for (var i = this._stack.length; i--;) {
      if (this._stack[i]!=undefined) this._vmlRoot.removeChild(this._stack[i]);
    }
    this._stack.length = 0;
    this._stackSize    = 0;
  },

  _htmlIsRoot: (typeof document.compatMode == "string") &&
               (document.compatMode == "CSS1Compat"),

  getX: function () {
    var box = this.container;
    var x   = box.offsetLeft;
    while ((box = box.offsetParent)) {
      x += box.offsetLeft;
    };

    x += (this._htmlIsRoot ? document.documentElement
                           : document.body).clientLeft;
    return x;
  },

  getY: function () {
    var box = this.container;
    var y   = box.offsetTop;
    while ((box = box.offsetParent)){
      y += box.offsetTop;
    };

    y += (this._htmlIsRoot ? document.documentElement
                           : document.body).clientTop;
    return y;
  },

  _pushStack: function (shape) {
    var stackLength = this._stack.length;
    if (this._stackSize < stackLength) {
      for (var i = this._stackSize; i < stackLength; i++) {
        this._vmlRoot.removeChild(this._stack[i]);
      }
      this._stack.length = this._stackSize + 1;
    }
    this._stack[this._stackSize++] = shape;
  }
};


function DrawingCanvas()
{
  var backend = "CSSP";
  if (document.namespaces && document.namespaces.add) {
    backend = "VML";
  }
  try {
    if (document.createElement("canvas").getContext) {
      backend = "Canvas";
    };
  } catch (e) {}
  if (document.createElementNS) {
	var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
    if (document.implementation && 
		(document.implementation.hasFeature("org.w3c.svg", "1.0") ||
        document.implementation.hasFeature(svgFeature + "SVG", "1.1") ||
        document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") )) {
    	backend = "SVGT";
    }
    if (window.opera) {
      var ua    = navigator.userAgent;
      var index = ua.indexOf("Opera");
      if (index >= 0 && parseInt(ua.substring(index + 6)) >= 8) {
        backend = "SVGT";
      };
    };    
  };

  switch (backend) {
    case "SVGT":   DrawingCanvas = DrawingCanvasSVGT;   break;
    case "Canvas": DrawingCanvas = DrawingCanvasCanvas; break;
    case "CSSP":   DrawingCanvas = DrawingCanvasCSSP;   break;
    case "VML":    DrawingCanvas = DrawingCanvasVML;    break;
  };
  DrawingCanvas.backend = backend;
  DrawingCanvas.prototype.constructor = DrawingCanvas;
};

DrawingCanvas();

function Point(x, y) {
    this.x = x;
    this.y = y;
};

function Vertex(x, y) {
    this.x = x;
    this.y = y;
};

function GLatLng(x,y) {
	this.x = x;
	this.y = y;
};

function getHttpObject() {
	var xmlHttp;
	try {
		xmlHttp = new XMLHttpRequest();		
	} catch (e) {
		try {
			xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');				
		} catch (e) {
			try {
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");	
			} catch (e) {
				alert("Your browser does not support AJAX!");
				return false;
			};
		};
	};
	return xmlHttp;
};

function Ajax(url, callback) {

    var req = getHttpObject();
    req.onreadystatechange = processRequest;
        
    function processRequest () {
    	if (req.readyState == 4) {
    		if (req.status == 200) {
    			if (callback) {
    				callback(req);
    			}
    		}
    	}
    };

    this.doGet = function() {
    	req.open("GET", url, true);
    	req.send(null);
    };
    
    this.doPost = function(body, xmlMode) {
    	req.open("POST", url, true);
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-length", body.length);    	
    	if (xmlMode == true || xmlMode != undefined) {
    		req.setRequestHeader("Content-Type", "text/xml");
		}   	
    	req.send(body);
    };
};


function Rectangle(left, top_, right, bottom) {
    this.left = left;
    this.top = top_;
    this.right = right;
    this.bottom = bottom;
    
    this.setWidth = function(value) {
    	this.right = this.left + value;
    };
    
    this.setHeight = function(value) {
    	this.bottom = this.top + value;
    };
    
    this.offset = function(x, y) {
    	this.left = this.left + x;
    	this.top = this.top + y;
    	this.right = this.right + x;
    	this.bottom = this.bottom + y;
    };
    
    this.width = function() {
    	return Math.abs(this.right - this.left);	    	
    };
    
    this.height = function() {
    	return Math.abs(this.bottom - this.top);
    };
};

function DElement(el, id, _left, _top, _w, _h, _pos, _zIndex, _src, _color, overflow) {
	var cons = document.createElement(el);
	if (id != undefined && id != '') { cons.id = id; };
	if (_left != undefined && _left != '') { cons.style.left = _left; };
	if (_top != undefined && _top != '') { cons.style.top = _top; };
	if (_w != undefined && _w != '') { cons.style.width = _w; };
	if (_h != undefined && _h != '') { cons.style.height = _h; };
	if (_pos != undefined && _pos != '') { cons.style.position = _pos; };
	if (_src != undefined && _src != '') { cons.src = _src; };
	if (_zIndex != undefined && _zIndex != '') { cons.style.zIndex = _zIndex; };	
	if (_color != undefined && _color != '') { cons.style.backgroundColor = _color; };
	if (overflow != undefined && overflow == true) { cons.style.overflow = "hidden"; };
	return cons;
};

function MDiv(id, _left, _top, _w, _h, _pos, _zIndex, _color, overflow) {
	return new DElement("div", id, _left, _top, _w, _h, _pos, _zIndex, '', _color, overflow);
};

function MImg(id, _src, _left, _top, _w, _h, _pos, _zIndex, overflow) {
	return new DElement("img", id, _left, _top, _w, _h, _pos, _zIndex, _src, overflow);
};

function MSpan(value) {
	var span = new DElement("span");
	span.innerHTML = value;
	return span;
};

function MapTile(row, col, img, div) {
	this.row = row;
	this.col = col;
	this.img = img;
	this.div = div;
};
function OffsetPoint(pt, x, y) {
    var result = new Point();
    result.x = pt.x + x;
    result.y = pt.y + y;
    return result;
};

function getTopLeft(obj) {
	if (obj == undefined) {
		return {x:0, y:0};
	}
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		};
	};
	return {x: curleft, y: curtop};
};

function getCursorPos(e, obj) {
	var _alt = getTopLeft(obj);
	var currX, currY, _x, _y;
	currX = (!document.all) ? e.pageX : (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
	currX -= _alt.x;
	currY = (!document.all) ? e.pageY : (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
	currY -= _alt.y;
	if(document.all) {		
		_x = event.clientX;
		_y = event.clientY;
	}else {
		_x = e.clientX;
		_y = e.clientY;
	};
	return {x: currX, y: currY, vx: _x, vy: _y};
};

function ViewportInfo() {
    this.width = 0;
    this.height = 0;
    this.centerVertex = new Vertex(0, 0);
    this.imgUrl = '';
    this.currentLvToHighLvPercentage = 0;    
};

function Quadtree(mapClient) {
	this.mapClient = mapClient;	
};


function MapSource(pathUrl, mapName) {
    this.mapTitle = '';
    this.mapCode = '';
    this.mapYear = '';
    this.mapZone = '';
    this.isSouth = '';
    this.isCassini = '';
    this.mapScales = [];
    this.pathUrl = pathUrl;
    this.name = mapName;

    this.loadFromXml = function(xmlDom) {
    	this.mapTitle = xmlDom.getElementsByTagName('TITLE').item(0).firstChild.nodeValue;
    	this.mapCode = xmlDom.getElementsByTagName('MAPCODE').item(0).firstChild.nodeValue;
    	this.mapYear = xmlDom.getElementsByTagName('YEAR').item(0).firstChild.nodeValue;
    	this.mapZone = xmlDom.getElementsByTagName('MAPZONE').item(0).firstChild.nodeValue;
    	this.mapScales = [];
    	
    	var scales = xmlDom.getElementsByTagName('SCALE');

		for (i=0;i<scales.length;i++)
		{
		  	
		  	var attlist = scales.item(i).attributes;
		  	var scale = new MapScale();
		  
	  		if (attlist.getNamedItem("DISABLED").nodeValue != "True") 
	  		{		  		
		  		scale.mapWidth = parseInt(attlist.getNamedItem("WIDTH").nodeValue); 
		  		scale.mapHeight = parseInt(attlist.getNamedItem("HEIGHT").nodeValue);
		  		scale.maxCol = parseInt(attlist.getNamedItem("MAXCOL").nodeValue);
		  		scale.maxRow = parseInt(attlist.getNamedItem("MAXROW").nodeValue);
		  		scale.minLon = parseFloat(attlist.getNamedItem("MINLONG").nodeValue);  
		  		scale.maxLon = parseFloat(attlist.getNamedItem("MAXLONG").nodeValue);
		  		scale.maxLat = parseFloat(attlist.getNamedItem("MAXLAT").nodeValue);
		  		scale._name = attlist.getNamedItem("LEVELCODE").nodeValue;
		  		if (attlist.getNamedItem("USERSCALING").nodeValue == "True") {
					scale._scaleValue = parseFloat(attlist.getNamedItem("USERSCALE").nodeValue);		  			
		  		}
		  		this.mapScales.push(scale);
	  		};
		};		
    };

    this.getMapTileUrl = function(col, row, mapScale) {
  	     return this.pathUrl + 'param.php?cd=map&s='+escape(this.name)+'&r='+row+'&c='+col+'&l='+mapScale._name;
    };

    this.getFirstScaleLevel = function(val) {
  	     if (this.mapScales[val] != undefined){  
  	     	return this.mapScales[val];
  	     };
    };
};

function MapScale(mapWidth, mapHeight, maxCol, maxRow, minLon, maxLon, minLat, maxLat,
    name_, desc, userScale, gridArray) {    
    this.mapWidth = mapWidth;
    this.mapHeight = mapHeight;
    this.maxCol = maxCol;
    this.maxRow = maxRow;
    this.minLon = minLon;
    this.maxLon = maxLon;
    this.minLat = minLat;
    this.maxLat = maxLat;
    this._name = name_;
    this.desc = desc;
    this.userScale = userScale;
    this._scaleValue = 0;

    this.scaleValue = function() {
    	if (this._scaleValue == 0) {
        	this._scaleValue = (this.maxLon - this.minLon) / (this.maxCol * this.mapWidth);
    	}
        return this._scaleValue;
    };
        
    this.pixelToUtm = function(x, y) {
        var _scaleValue = this.scaleValue();
        return new Vertex((this.minLon) + (x * _scaleValue), (this.maxLat) - (y * _scaleValue));
    }; 

    this.utmToPixel = function(vertX, vertY) {
        var result = new Point();
        var _scaleValue = this.scaleValue();                 
        result.x = Math.round((vertX - this.minLon) / _scaleValue);
        result.y = Math.round((this.maxLat - vertY) / _scaleValue);
        return result;
    };
    
    this.inflateVert = function(vert, x, y) {
        var ptPixel = this.utmToPixel(vert.x, vert.y);
        ptPixel = OffsetPoint(ptPixel, x, y);
        return this.pixelToUtm(ptPixel.x, ptPixel.y);
    };
    
    this.getDistance = function(vert0, vert1) {
    	if (isNaN(vert0.x) || isNaN(vert0.y)
    		|| isNaN(vert1.x) || isNaN(vert1.y)) {
    		return;
    	};
    	return Math.sqrt((vert0.x-vert1.x)*(vert0.x-vert1.x)
    		+(vert1.y-vert0.y)*(vert1.y-vert0.y));
    };

    this.getCenterVertex = function() {
        return this.pixelToUtm((this.maxCol * this.mapWidth) / 2, 
        	(this.maxRow * this.mapHeight) / 2);
    };
       
    this.getTopLeftPoint = function(vertX, vertY, displayWidth, displayHeight) {
        var pt = this.utmToPixel(vertX, vertY);
        pt = OffsetPoint(pt, -(displayWidth / 2), -(displayHeight / 2));
        return pt;
    };
};

function MapUtil(mapClient) {
	this.mapClient = mapClient;
	
	this.getCenterLevel = function(points) {
		var _x = new Array(), _y = new Array();
		var _min, _max, _main, _delta, _level, _scale, _resLevel, 
			_iconBounds;
		for (var b=0; b<points.length; b++) {
			if (points[b][0] != undefined) {				
				for (var c=0; c<points[b][0].length; c++) {
					if (points[b][0][c] != null 
						&& points[b][0][c].x != undefined 
						&& points[b][0][c].y != undefined) {
						_x.push(points[b][0][c].x);
						_y.push(points[b][0][c].y);
					}
				}			
			} else if (points[b] != undefined){
				if (points[b].x != undefined 
					&& points[b].y != undefined) {				
					_x.push(points[b].x);
					_y.push(points[b].y);
				}	
			}
		}
		
		_x.push(this.mapClient.centerVertex.x);
		_y.push(this.mapClient.centerVertex.y);		
		
		_min = new Point(this.findMin(_x), this.findMin(_y));
		_max = new Point(this.findMax(_x), this.findMax(_y));
		_iconBounds = new Rectangle(_min.x, _max.y, _max.x, _min.y);
		_main = new Point(parseInt((_min.x + _max.x)/2), parseInt((_min.y + _max.y)/2));

		var srcScales = this.mapClient.mapSource.mapScales;
		var prevDeltaScale = 10000;
		var ee = 0, cs = 0, currentScale = 0, deltaScale = 0, 
			iconTotalScale = 0, radian = null, mapBound = new Rectangle();
		for (var e=srcScales.length-1; e>=0; e--) {
			currentScale = this.mapClient.mapSource.mapScales[e];
			cs = currentScale.scaleValue();
			
			radian = new Point(this.mapClient.mapWidth / 2 * cs,
				this.mapClient.mapHeight / 2 * cs);
			mapBound.left = this.mapClient.centerVertex.x - radian.x;
			mapBound.right = this.mapClient.centerVertex.x + radian.x;
			mapBound.top = this.mapClient.centerVertex.y + radian.y;
			mapBound.bottom = this.mapClient.centerVertex.y - radian.y;
			
			if (_iconBounds.left > mapBound.left && _iconBounds.left < mapBound.right
				&& _iconBounds.right > mapBound.left && _iconBounds.right < mapBound.right
				&& _iconBounds.bottom > mapBound.bottom && _iconBounds.bottom < mapBound.top
				&& _iconBounds.top > mapBound.bottom && _iconBounds.top < mapBound.top				
			) {
				ee = e;
				break;
			}
		}
		_resLevel=ee;
		return { x : _main.x, y : _main.y, level : _resLevel };
	};	

	this.findMin = function(intA) {     
	     if ( intA.length == 0 ) { 
	         return 0;
	     }
	     if ( intA.length == 1 ) { 
	         return 1;
	     }
	     var o_intMin = intA[0];
	     for (var p_intI = 1; p_intI < intA.length; p_intI += 1) {
	         if ( intA[p_intI] < o_intMin ) {
	            o_intMin = intA[p_intI];
	         } 
	  	 } 
	  	 return parseInt(o_intMin);     
	};

	this.findMax = function(intA) {
	    for ( var i_intI = 0; i_intI < intA.length;i_intI += 1 ) {
	        intA[i_intI] = intA[i_intI] * -1;
	    };
	    var o_intMax = this.findMin(intA);
	    o_intMax = o_intMax * -1;
	    return parseInt(o_intMax);
	};
};

function MapScaleList(listSize) {
    this.listSize = listSize;
    this.listitems = new Array(listSize);
    
    this.getItem = function(idx){
        return listItems(idx);
    };
        
    this.setItem = function(idx, mapScale) {
        listItems[idx] = mapScale;
    };
};

function MapClient() {
    
    this.viewportInfo = new ViewportInfo();
    this.mapWidth = 0;
    this.mapHeight = 0;
    this.mapScale = new MapScale();
    this.centerVertex = new Vertex(0, 0);
    this.levelIndex = 0;
    this.mapName = 'Singapore';    
    this.mapSource = new MapSource();
    
    this.setLevelIndex = function (lvl) {	
    	if (this.mapSource.mapScales[lvl] != undefined) {
    		this.levelIndex = lvl;
    	};    	
    };
    
    this.setCenterVertex = function(vertex) {
    	this.centerVertex.x = vertex.x;
    	this.centerVertex.y = vertex.y; 
    };
    
    this.setMapSource = function(mapName, autoLevel) {
    	this.mapName = mapName;  	
    	this.mapConfig = this.baseUrl + 'param.php?cd=mc&s=' + escape(mapName);
    	var xmlHttp = getHttpObject();    	
    	var _mapClient = this;
    	var _autoLevel = autoLevel;
    	if (!xmlHttp){
            alert ('Your browser does not support AJAX!');
            return;
        };
        xmlHttp.onreadystatechange = function xmlHttpStateChanged()
		    {		      
		        if(xmlHttp.readyState == 4)
		        {		            
		            if (xmlHttp.status==200)
		            {
		            	var xmlDom = xmlHttp.responseXML;
		                if (xmlDom == null) {
		                	return;		     
		                };
		               
		               _mapClient.mapSource.name = _mapClient.mapName; 
		               _mapClient.mapSource.loadFromXml(xmlDom);
		               _mapClient.mapScale = _mapClient.mapSource.getFirstScaleLevel(_mapClient.levelIndex);
		               if (_mapClient.centerVertex.x == 0 && _mapClient.centerVertex.y == 0){
		               		_mapClient.centerVertex = _mapClient.mapScale.getCenterVertex();
		               };
		               if (_autoLevel && _mapClient.mapDraw != null) {
		               		var center = _mapClient.mapDraw.getCenterLevel(2);
		               		_mapClient.levelIndex = center.level;
		               		if (_mapClient.mapSource.mapScales[_mapClient.levelIndex] != undefined) {
		               			_mapClient.mapScale = _mapClient.mapSource.mapScales[_mapClient.levelIndex];
		               		}
		               }
		               _mapClient.drawMap();               
		            };
		        };
		    };        
        xmlHttp.open('GET', this.mapConfig, true);
        xmlHttp.send(null);	
        
    };
        
    this.setContainerTopLeft = function(topleftPt, topLeftCell, bottomRightCell) {
    	this.mapContainer.bound.top = (topLeftCell.y - 1) * this.mapScale.mapHeight;
    	this.mapContainer.bound.left = (topLeftCell.x - 1) * this.mapScale.mapWidth;
    	this.mapContainer.bound.right = (bottomRightCell.x) * this.mapScale.mapWidth;  
    	this.mapContainer.bound.bottom = (bottomRightCell.y) * this.mapScale.mapHeight;
    	
    	this.mapContainer.rect.x = this.mapContainer.bound.left - topleftPt.x;
    	this.mapContainer.rect.y = this.mapContainer.bound.top - topleftPt.y;
    	this.mapContainer.style.left = this.mapContainer.rect.x+"px";
		this.mapContainer.style.top = this.mapContainer.rect.y+"px";
		this.mapContainer.style.width = ((bottomRightCell.x - topLeftCell.x + 1) * this.mapScale.mapWidth)+  "px"; 
		this.mapContainer.style.height = ((bottomRightCell.y - topLeftCell.y + 1) * this.mapScale.mapHeight)+  "px";
    };
    
    this.clearTilesContainer = function() {
    	var tileItems = this.mapContainer.Items; 
        for (i=0; i < tileItems.length; i++) {
        	this.tilesContainer.removeChild(tileItems[i].div);
        	tileItems[i].div = undefined;
			tileItems[i] = undefined;
        };	
        this.mapContainer.Items = [];
    };
    
    
    this.drawMap = function() {    	    	
    	this.generateMap(this.getviewportInfo());   	
		if (this.mapDraw != undefined) {
			this.mapDraw.updatePanel();
		}
    };
    
    this.moveViewportPosition = function(offsetX, offsetY) {
    	this.closeInfoWindow();
    	this.centerVertex = this.mapScale.inflateVert(this.centerVertex, -offsetX, -offsetY);
    	this.mapContainer.rect.x += offsetX;
	    this.mapContainer.rect.y += offsetY;
	    this.mapContainer.style.left = this.mapContainer.rect.x + "px";
	 	this.mapContainer.style.top = this.mapContainer.rect.y + "px";
    };
    
    this.vertexToScreen = function(vertX, vertY) {
    	if (this.mapScale == null) {
    		return new Vertex(0,0);
    	}
		var pt = this.mapScale.utmToPixel(vertX, vertY);
		var topLeft = this.mapScale.getTopLeftPoint(this.centerVertex.x,
			this.centerVertex.y, this.mapWidth, this.mapHeight);
		pt.x -= topLeft.x;
		pt.y -= topLeft.y;
		return pt;
    };
    
	this.screenToVertex = function(pos) {
		var pt = this.mapScale.inflateVert(this.centerVertex, 
			pos.x-this.mapWidth/2, pos.y-this.mapHeight/2);
		return pt;
	};
    
    this.getVertexTopLeft = function(x, y) {
    	var pt = this.mapScale.pixelToUtm(x, y);
    	var topLeft = this.mapScale.getTopLeftPoint(this.centerVertex.x, this.centerVertex.y, this.mapWidth, this.mapHeight);
    	pt.x -= topLeft.x;
    	pt.y -= topLeft.y;
    	return pt;
    };
    
    this.panMapByOffset = function(offsetX, offsetY) {   	 	
    	this.centerVertex = this.mapScale.inflateVert(this.centerVertex, -offsetX, -offsetY);
    	this.drawMap();
    	this.updateInfo();
    };
    
    this.zoomIn = function() {
    	var _chZoom = this.levelIndex + 1;
    	this.changeLevel(_chZoom);
    };
    
    this.changeLevel = function(level) {
    	this.closeInfoWindow();
    	this.setLevelIndex(level);   	
   		this.mapScale = this.mapSource.mapScales[this.levelIndex];
   		this.drawMap();
    };
    
    this.zoomOut = function() {
    	var _chZoom = this.levelIndex - 1;
    	this.changeLevel(_chZoom);
    };
    
    this.generateMap = function(viewportInfo) {
    	if (this.mapScale == null 
    		|| this.mapScale.mapWidth == null) {
    		return;
    	};
		var vi = viewportInfo;		    	
        var topLeft = this.mapScale.getTopLeftPoint(
        	this.centerVertex.x, this.centerVertex.y, this.mapWidth, this.mapHeight);
        var colStart = Math.ceil(topLeft.x / this.mapScale.mapWidth);
        var rowStart = Math.ceil(topLeft.y / this.mapScale.mapHeight);
        var colEnd = Math.ceil((topLeft.x + this.mapWidth) /
            this.mapScale.mapWidth);
        var rowEnd = Math.ceil((topLeft.y + this.mapHeight) /
            this.mapScale.mapHeight);

        var r = new Rectangle(0, 0, 0, 0);
        
        var topLeftCell = new Point(colStart, rowStart);
        var bottomRightCell = new Point(colEnd, rowEnd);
        
        this.clearTilesContainer();
        this.setContainerTopLeft(topLeft, topLeftCell, bottomRightCell);
        for (iRow = rowStart; iRow <= rowEnd; iRow++)          
        {
            for (iCol = colStart; iCol <= colEnd; iCol++)
            {
				if (iRow < 0 || iCol < 0 || iCol > this.mapScale.maxCol 
					|| iRow > this.mapScale.maxRow)
                	continue;
                	            	
            	r.left = (iCol - colStart) * this.mapScale.mapWidth;
                r.top = (iRow - rowStart) * this.mapScale.mapHeight;
                r.Width = this.mapScale.mapWidth;
                r.Height = this.mapScale.mapHeight;
                                                             
                var divImage = new MDiv('', r.left + 'px', r.top + 'px',
                	this.mapScale.mapWidth + 'px', this.mapScale.mapHeight + 'px', 
                	"absolute");
                //divImage.style.backgroundImage = "url(" + this.baseUrl + 'img/loading_text.gif' + ")";                
                var tile = new MapTile(iRow, iCol, new MImg(), divImage);
                var tileURL = this.mapSource.getMapTileUrl(iCol, iRow, this.mapScale);        		        		
                divImage.appendChild(tile.img);
        		this.tilesContainer.appendChild(divImage);
        		this.mapContainer.Items.push(tile);        		
        		tile.img.src = tileURL;
        		tile.img.style.width = this.mapScale.mapWidth+'px';
        		tile.img.style.height = this.mapScale.mapHeight+'px';        		   		   
           };
        };
    };
    
    this.createDefaultMapSource = function(baseUrl) {    	
    	this.baseUrl = baseUrl;
    	this.mapSource = new MapSource('default', 'sq', 2000, '',
    		false, true, this.baseUrl, '');
    	this.mapSource.mapScales.push(new MapScale(5076, 2476, 1, 1, 1976, 57959, 0, 51191, '3', '3', 0, 0));
    	this.mapSource.mapScales.push(new MapScale(270, 372, 46, 17, 3072, 56897.75, 0, 51191, '4', '4', 0, 0));
    	this.mapSource.mapScales.push(new MapScale(540, 744, 46, 17, 3072, 56897.75, 0, 51191, '5', '5', 0, 0));
    	this.mapSource.mapScales.push(new MapScale(1080, 1488, 46, 17, 3072, 56897.75, 0, 51191, '6', '6', 0, 0));
    	
    	this.levelIndex = 4;
    	this.mapScale = this.mapSource.mapScales[this.levelIndex];
    	this.centerVertex.x = 44907;
    	this.centerVertex.y = 37804;    	
    };
    
    this.initWithDefaultMapSource = function(viewport_id, baseUrl) {
    	this.createDefaultMapSource(baseUrl);
    	this.init(viewport_id, baseUrl);    
    };
    
    this.init = function(mapApi) {
    	this.mapSource = new MapSource(mapApi.baseUrl);
    	this.mapDraw = mapApi.mapDraw;
   		this.viewport = mapApi.viewportLayer;
    	this.mapWidth = mapApi.granParentLayer.clientWidth == 0 ? parseInt(mapApi.granParentLayer.style.width) : mapApi.granParentLayer.clientWidth;
    	this.mapHeight = mapApi.granParentLayer.clientHeight == 0 ? parseInt(mapApi.granParentLayer.style.height) : mapApi.granParentLayer.clientHeight;
    	this.baseUrl = mapApi.baseUrl;
    	this.loadingImgUrl = this.baseUrl+'1.jpg';
    	
    	this.mapContainer = new MDiv('', "0px", "0px", 
    		"100%", "100%", "absolute", 0, ''); 
    	this.mapContainer.style.backgroundImage = "url(" + this.baseUrl + 'img/brown.gif' + ")";
		this.mapContainer.rect = {x: 0, y: 0};
		this.mapContainer.Items = [];
		this.mapContainer.bound = new Rectangle(0, 0, 0, 0);		
		    	
		this.tilesContainer = new MDiv('', "0px", "0px",
			'', '', "absolute", 0, ''); 
		this.mapContainer.appendChild(this.tilesContainer);
		this.viewport.appendChild(this.mapContainer);	
    };
    
    this.getviewportInfo = function() {
        var result = new ViewportInfo();
        result.width = this.mapWidth;
        result.height = this.mapHeight;
        result.centerVertex = this.centerVertex;
        return result;
    };
    
	this.openInfoWindowHtml = function(point, html, iconSize) {
		if (this.popup == null) {
			this.popup = new MapBubble(200, 100);
			this.popup.init(this);
			this.viewport.appendChild(this.popup.obj);
		};
		if (iconSize != undefined) {
			this.popup.iconSize = iconSize;
		}
		this.popup.setDisplay(2);
		this.popup.enableOpacity(true);
		this.popup.initContent(html, point);	
		this.popup.obj.style.display = "";	
	};
	
	this.updateInfo = function() {
		if (this.popup != undefined) {
			this.popup.updatePosition(true);
		}
	};
	
	this.updateInfoWindowHtml = function(point, html, iconSize) {
		if (this.popup != undefined) {
			if (iconSize != undefined) {
				this.popup.iconSize = iconSize;
			}			
			this.popup.setContent(html, point);
		} else {
			this.openInfoWindowHtml(point, html);
		}
	};
	
	this.closeInfoWindow = function() {
		if (this.popup != undefined) {
			this.popup.obj.style.display = "none";
		};
	};  
    
    this.getScalePercentageCurrentLevelToHighLevel = function() {
        var lastScale  = mapSource.getLastLevel();
        if (lastScale == null) {
        	return 100;
        } else if (lastScale.totalWidth == 0) {
        	return 100;
        };
        return scale.totalWidth / lastScale.totalWidth;
    };
};

function MapDrawingController() {
	this.lines = new Array();
	this.icons = new Array();
	this.plots = new Array();
	this.color = "Black";
	this.dotColor = "Black";
	this.panelIcon = new MapIconController();
	this.panelLine = new MapLineController();
	this.panelDraw = new MapLineController();
	this.panelGeo = new MapGeofenceController();
	
	this.init = function (mapClient) {
		this.client = mapClient;
		this.panelIcon.init(mapClient);
		this.panelLine.init(mapClient);
		this.panelDraw.init(mapClient);
		this.panelGeo.init(mapClient);
		this.panelDraw.panel.setLineWidth(2);
		this.panelDraw.setColor("red");		
		this.panelLine.setColor("blue");
		this.util = new MapUtil(mapClient);
	};
	
	this.panPanelByOffset = function(x, y) {
		this.panelIcon.panByOffset(x, y);
		this.panelLine.panByOffset(x, y);
		this.panelDraw.panByOffset(x, y);
		this.panelGeo.panByOffset(x, y);
	};
	
	this.stopDrawing = function() {		
		this.panelDraw.panel.endLine();
		this.getDistanceState();
		this.panelDraw.enableLiveDraw(false);
	};
	
	this.enableDot = function(values) {
		this.panelLine.dotMode = values;
	};
	
	this.clearDrawing = function() {
		this.panelDraw.panel.clear();
		this.getDistanceState();
		this.plots = new Array();		
	};

	this.enableOpacity = function(state) {
		if (state == true) {
			this.client.viewport.style.backgroundColor = "#FFFFFF";
			this.client.viewport.style.filter = "alpha(opacity=20)";
			this.client.viewport.style.MozOpacity = 2.0;
			this.client.viewport.style.opacity = .20;
		} else {
			this.client.viewport.style.backgroundColor = "";
			this.client.viewport.style.filter = "";
			this.client.viewport.style.MozOpacity = null;
			this.client.viewport.style.opacity = null;
		};
	};

	this.getCurrentPos = function(pos) {
		var _x = pos.x-this.client.mapWidth/2;
		var _y = pos.y-this.client.mapHeight/2;
		return {x : pos.x, y : pos.y, rx : _x, ry : _y};		
	};
	
	this.savePosition = function(pos) {
		var utm = this.client.mapScale.inflateVert(
			this.client.centerVertex, pos.rx, pos.ry);
		this.plots.push(utm);
	};
	
	this.addIcon = function(x, y, isCenter, showAllLevel) {
		if (isCenter == undefined) {
			isCenter = false;
		}
		if (showAllLevel == undefined) {
			showAllLevel = true;
		}
		return this.panelIcon.addIcon(x, y, isCenter, showAllLevel);
	};
	
	this.addGeofence = function(x, y, r) {
		this.panelGeo.addGeofence(x, y, r);
	};
	
	this.addLine = function(point, color) {
		this.panelLine.addLine(point, color);
	};
	
	this.renderLine = function(point, color) {
		this.panelLine.render(point, color);
	};
	
	this.stopRenderLine = function() {
		this.panelLine.stopRender();
	};	
	
	this.addPoint = function(point, color) {
		this.panelLine.addPoint(point, color);
	};
	
	this.updatePanel = function () {
		this.panelIcon.updatePosition();
		this.panelLine.updatePosition();
		this.panelDraw.updatePosition();
		this.panelGeo.updatePosition();
	};
	
	this.setPosition = function(icon, x, y) {
		this.panelIcon.setPosition(icon, x, y);
	};
	
	this.getCenterLevel = function(mode) {
		if (mode == 2) {
			return this.util.getCenterLevel(this.panelIcon.icons);
		} else {
			return this.util.getCenterLevel(this.panelLine.points);
		}
	};
	
	this.draw = function(pos, buffer) {
		this.panelDraw.panel.setSize(this.client.mapWidth, this.client.mapHeight);
		this.panelDraw.panel.setViewBox(0, 0, this.client.mapWidth, this.client.mapHeight);		

		this.panelDraw.enableLiveDraw(true);
		var plot = this.getCurrentPos(pos);
		if (buffer == false) {
			this.savePosition(plot);
			this.panelDraw.points = new Array();
			this.panelDraw.addLine(this.plots);
			this.panelDraw.updatePosition();
			this.getDistanceState();
		} else {
			if (this.plots.length > 0) {			
				var tmp = this.client.vertexToScreen(this.plots[this.plots.length-1].x, 
					this.plots[this.plots.length-1].y);
				this.panelDraw.panel.clearShape();
				this.panelDraw.panel.startLine(tmp.x, tmp.y);
				this.panelDraw.panel.lineTo(plot.x, plot.y);
				this.panelDraw.panel.endLine();
				this.getDistanceState(plot);
			};
		};
	};
	
	this.getDistanceState = function(latestPos) {
		var dist = 0;
		for (var i=0,s=this.plots.length;i<s;i++) {
			if ((i+1) <= s-1) {
				dist += this.client.mapScale.getDistance(this.plots[i], 
					this.plots[i+1]);				
			};
		};
		if (latestPos != undefined) {
			var tmp = this.client.mapScale.inflateVert(
				this.client.centerVertex, latestPos.rx, latestPos.ry);
			dist += this.client.mapScale.getDistance(
				this.plots[this.plots.length-1], tmp);		
		};
		if (dist > 0) {
			if (this.divOutput != undefined || this.divOutput != null) {
				this.divOutput.innerHTML = "Distance&nbsp;:&nbsp;"+(dist/1000)+"&nbsp;km";
			} else {
				window.status = "Distance : "+(dist/1000)+" km";
			}					
		};
	};
	
	this.clear = function() {
		this.panelDraw.clear();
		this.panelIcon.clear();
		this.panelGeo.clear();
	};
	
	this.deleteAll = function() {
		this.panelDraw.deleteLines();
		this.panelLine.deleteLines();
		this.panelIcon.deleteIcons();		
		this.panelGeo.deleteGeos();
	};	
	
	this.deleteGeofences = function() {
		this.panelGeo.deleteGeos();
	};
	
	this.showStatusAt = function(div) {
		if (div == undefined || div == null) {
			return;
		}
		this.divOutput = div;
	};
};

function MapGeofenceController() {
	this.items = new Array();
	this.panel = null;
	this.mapClient = null;

	this.init = function(mapClient) {
		this.mapClient = mapClient;
		this.panel = new DrawingCanvas(mapClient.viewport);
		this.panel.setLineWidth("4");
		this.panel.container.style.zIndex = 7;
		this.panel.setLineColor("black");
		this.reset();
	};	
	
	this.clear = function() {
		this.reset();
		this.panel.clear();
		this.panel.setSize(this.mapClient.mapWidth, this.mapClient.mapHeight)
	};
	
	this.deleteGeos = function() {
		this.clear();
		this.items = new Array();		
	};

	this.reset = function() {
		this.panel.container.style.left = "0px";
		this.panel.container.style.top = "0px";
		this.panel.container.style.position = "absolute";		
	};	
	
	this.addGeofence = function(x, y, r) {
		this.items.push(new Array(x,y,r));
	};
	
	this.updatePosition = function() {
		this.clear();
		for (var j=0, csum=this.items.length; j<csum; j++) {
			var pt = this.mapClient.vertexToScreen(this.items[j][0], this.items[j][1]);
			var r= Math.abs(this.items[j][2]/this.mapClient.mapScale.scaleValue());
			r = Math.round(r);
			this.panel.createGeofence(parseInt(pt.x), parseInt(pt.y), r, this.items[j][2]);
		};
	};
	
	this.panByOffset = function(pX, pY) {
		var _x = parseInt(this.panel.container.style.left);
		var _y = parseInt(this.panel.container.style.top);
		if (!isNaN(_x) && !isNaN(_y)) {
		    this.panel.container.style.left = (_x + pX) + 'px';
		    this.panel.container.style.top = (_y + pY) + 'px';
		};
	};	
};

function MapLineController() {
	this.color = "blue";
	this.points = new Array();
	this.colors = new Array();
	this.dotMode = false;
	this.panel = null;
	this.width = "4";	
	this.zIndex = 7;
	this.mapLevel = 0;
	this.mapClient = null;
	
	this.nSize = new Point(0,0);
	this.nPos = new Point(0,0);
	this.nTopLeft = new Vertex(0,0);
	this.liveDraw = false;
	this.running = true;
	
	this.init = function(mapClient) {
		this.mapClient = mapClient;
		this.mapLevel = mapClient.levelIndex;
		this.panel = new DrawingCanvas(mapClient.viewport);
		this.panel.setLineWidth(this.width);
		this.panel.container.style.zIndex = this.zIndex;
		this.reset();
	};
	
	this.enableLiveDraw = function(cond) {
		if (cond != undefined) {
			this.liveDraw = cond;
		}
	};
	
	this.setColor = function(color) {
		if (color != undefined) {
			this.color = color;
		}
	};
	
	this.deleteLines = function() {
		this.clear();
		this.points = new Array();
	};
	
	this.clear = function() {
		this.reset();
		this.panel.clear();
	};
	
	this.reset = function() {
		this.panel.container.style.left = "0px";
		this.panel.container.style.top = "0px";
		this.panel.container.style.position = "absolute";		
	};
	
	this.stopRender = function() {
		this.running = false;
		this.deleteLines();		
	};
	
	this.addLine = function(points, _color) {
		this.points.push(new Array(points, _color));
	};
	
	this.inViewPort = function(point) {
	    var pt = this.mapClient.mapScale.utmToPixel(point.x, point.y);
	    var w0 = this.mapClient.mapWidth / 2;
	    var h0 = this.mapClient.mapHeight / 2;
	    if ((this.mapClient.mapWidth+w0 > pt.x && pt.x > -w0)
	    	&& (this.mapClient.mapHeight+h0 > pt.y && pt.y > -h0)
	    	&& !isNaN(pt.x) && !isNaN(pt.y)) {
	    	return true;
	    }
	    return false;
	};
	
	this.draw = function(points) {
		this.nSize = new Vertex(0,0);
		this.nPos = new Vertex(0,0);
		var pt = "", r =0, idx = 0, lastPos = new Vertex(0,0), i = 0, sum=points.length;
		
		while (this.running && i<sum) {
			if (points[i][1] == undefined) {
				points[i][1] = this.color; 
			}
			this.panel.setLineColor(points[i][1]);	
			if (points[i][0] != undefined && points[i][0].length != undefined) {
				for (var j=0, jsum=points[i][0].length; j<jsum; j++) {
					if (points[i][0][j].x == undefined 
						|| points[i][0][j].y == undefined) {
						continue;
					}
						pt = this.mapClient.vertexToScreen(points[i][0][j].x, points[i][0][j].y);
						if (!isNaN(pt.x) && !isNaN(pt.y)) {
							if (j == 0) {
								this.panel.startLine(pt.x, pt.y);
							} else if (lastPos.x != pt.x && lastPos.y != pt.y) {
								this.panel.lineTo(pt.x, pt.y);
							};
							if (pt.x > this.nSize.x) this.nSize.x = pt.x;
							if (pt.y > this.nSize.y) this.nSize.y= pt.y;
							if (parseInt(pt.x) < this.nPos.x) this.nPos.x = pt.x;
							if (parseInt(pt.y) < this.nPos.y) this.nPos.y = pt.y;												
							lastPos = pt;
						}
				};				
				this.panel.endLine();
			};
			i++;			
		}
		
		if (this.liveDraw == false) {
			if (!isNaN(this.nPos.x) && this.nPos.x < 0) {
				this.panel.setPosX(this.nPos.x);
			}
			if (!isNaN(this.nPos.y) && this.nPos.y < 0) {
				this.panel.setPosY(this.nPos.y);
			}
			this.nSize = OffsetPoint(this.nSize, -this.nPos.x, -this.nPos.y);
			this.nTopLeft = this.mapClient.screenToVertex(this.nPos);
			if (this.nSize.x > 0 && this.nSize.y > 0) {			
				this.panel.setSize(this.nSize.x, this.nSize.y);
				this.panel.setViewBox(this.nPos.x, this.nPos.y, this.nSize.x, this.nSize.y);
			} else {
				this.panel.setSize(this.mapClient.mapWidth, this.mapClient.mapHeight);
			}			
		}
	};
	
	this.render = function(point, color) {
		var tmp = new Array(point, color);
		this.draw(new Array(tmp));
		this.points.push(tmp);
		this.mapLevel = this.mapClient.levelIndex;
		if (this.nTopLeft.x != 0 && this.nTopLeft.y != 0) {
			this.reset();
			var pos = this.mapClient.vertexToScreen(this.nTopLeft.x, this.nTopLeft.y);
			if (!isNaN(pos.x)) this.panel.setPosX(pos.x);
			if (!isNaN(pos.y)) this.panel.setPosY(pos.y);
		}		
	};
	
	this.updatePosition = function() {		
		if (this.mapClient.levelIndex < 4) {
			this.panel._dotMode = false;
		} else {
			this.panel._dotMode = this.dotMode; 
		}	
		if ((this.mapLevel != this.mapClient.levelIndex || this.liveDraw == true) 
			&& (this.mapClient.mapScale != null 
			&& this.points.length > 0)) {
			this.clear();
			this.draw(this.points);
			this.mapLevel = this.mapClient.levelIndex;
		}
		if (this.nTopLeft.x != 0 && this.nTopLeft.y != 0) {
			this.reset();
			var pos = this.mapClient.vertexToScreen(this.nTopLeft.x, this.nTopLeft.y);
			if (!isNaN(pos.x)) this.panel.setPosX(pos.x);
			if (!isNaN(pos.y)) this.panel.setPosY(pos.y);
		}
	};
	
	this.panByOffset = function(pX, pY) {
		var _x = parseInt(this.panel.container.style.left);
		var _y = parseInt(this.panel.container.style.top);
		if (!isNaN(_x) && !isNaN(_y)) {
		    this.panel.container.style.left = (_x + pX) + 'px';
		    this.panel.container.style.top = (_y + pY) + 'px';
		};
	};
};

function MapIconController() {
	this.icons = new Array();
	this.mapClient = null;
	this.zIndex = 9;
	
	this.init = function(mapClient) {
		this.mapClient = mapClient;
	};
	
	this.addIcon = function(x, y, isCenter, showAllLevel) {		
		var ico = new MapIcon(x, y, this.zIndex, this.mapClient, isCenter, showAllLevel);
		this.icons.push(ico);
		return ico;
	};
	
	this.updatePosition = function() {
		if (this.icons.length > 0) {
			this.clear();
		};
		if ((this.mapClient.levelIndex > -1 && this.mapClient.mapDraw.panelLine.points.length > 0)
			|| this.mapClient.mapDraw.panelLine.points.length == 0) {
			for (var i=0, sum=this.icons.length; i<sum; i++) {
				this.icons[i].updatePosition();
			};
		};
	};
	
	this.setPosition = function (icon, x, y) {
		icon.x = x;
		icon.y = y;
		icon.updatePosition();
	};
	
	this.panByOffset = function (x, y) {
		for (var i=0, sum=this.icons.length; i<sum; i++) {
			this.icons[i].offsetPosition(x, y);	
		};
	};

	this.clear = function() {
		for (var i=0, sico=this.icons.length; i<sico; i++) {
			for (var j=0; j<this.mapClient.viewport.childNodes.length; j++) {
				if (this.icons[i].obj == this.mapClient.viewport.childNodes[j]) {
					this.mapClient.viewport.removeChild(this.icons[i].obj);
					break;	
				}			
			}
		}		
	};
	
	this.deleteIcons = function() {
		this.clear();
		this.icons = new Array();		
	};
};

function MapIcon(x, y, zIndex, mapClient, isCenter, hideLevel) {
	this.x = x;
	this.y = y;
	this.popupContent = "";
	this.mapClient = mapClient;
    this.obj = new MImg('',
    	this.mapClient.baseUrl + "icon.php", x + 'px', y + 'px',
    	"19px", "32px", "absolute", zIndex); 
    this.size = new Point(19, 32);
    this.obj.mapIcon = this;        
    this.obj.style.cursor = "pointer";
    this.popup = null;
    this.isCenter = isCenter;
    this.hideLevel = hideLevel;
    this.gMarkerBound = new Rectangle(350, 250, 
    	this.mapClient.mapWidth-350, this.mapClient.mapHeight-250);		    	
    this.isDisplayed = true;
	
	this.setUrl = function(url, w, h) {
		this.obj.src = url;
		w = w % 2 == 0 ? w : w + 1;
		h = h % 2 == 0 ? h : h + 1;
		this.size = new Point(w, h);
		if (w > 0 && h > 0) {
    		this.obj.style.width = w + "px";
    		this.obj.style.height = h + "px";
		};		
	};
	
	this.setDisplay = function(cond) {
		this.isDisplayed = cond;
		this.updatePosition();
	};
	
	this.setPosition = function (x, y, updateCenterMap) {
		this.x = x;
		this.y = y;
		this.updatePosition(updateCenterMap);
	};	
		
	this.updatePosition = function(updateCenterMap) {
		if (this.hideLevel != undefined) {
			for (var j=0, d=this.hideLevel.length; j<d; j++) {
				if (this.mapClient.levelIndex == hideLevel[j]) {
					return;
					//this.isDisplayed = false;
				}
			}
		}
		var pos = new Point(0,0);
	    var pt = this.mapClient.vertexToScreen(this.x, this.y);
	    if ((this.mapClient.mapWidth > pt.x && pt.x > -10)
	    	&& (this.mapClient.mapHeight > pt.y && pt.y > -10)
	    	&& !isNaN(pt.x) && !isNaN(pt.y)) {
	    	if (this.isCenter) {
	    		pos.x = parseInt(this.obj.style.width)/2;
	    		pos.y = parseInt(this.obj.style.height)/2;
	    	} else {
	    		pos.x = parseInt(this.obj.style.width)/2 - 2;
	    		pos.y = parseInt(this.obj.style.height);	    		
	    	}
		    this.obj.style.left = (pt.x - pos.x) + "px";
		    this.obj.style.top  = (pt.y - pos.y) + "px";
		    var _isExist = this.isExist();
		    if (!_isExist && this.isDisplayed) {
		    	this.mapClient.viewport.appendChild(this.obj);
		    } else if (_isExist && !this.isDisplayed) {
		    	this.mapClient.viewport.removeChild(this.obj);
		    }
	    	return true;
	    };
	    if (updateCenterMap == true) {
	    	var x = this.gMarkerBound.right < pt.x ? -(pt.x - this.gMarkerBound.right) :
	    		this.gMarkerBound.left > pt.x ? -(pt.x - this.gMarkerBound.left) : 0;
	    	var y = this.gMarkerBound.top > pt.y ? -(pt.y - this.gMarkerBound.top) :
	    		this.gMarkerBound.bottom < pt.y ? -(pt.y - this.gMarkerBound.bottom) : 0;
	    	this.mapClient.panMapByOffset(x, y); 
	    }
	    
	    return false;
	};
	
	this.isExist = function() {
		var child = this.mapClient.viewport.childNodes;
		for (var j=0; j<child.length; j++) {
			if (this.obj == child[j]) {
				return true;
			}
		}	
		return false;	
	};
	
	this.offsetPosition = function(pX, pY) {
		var _x = parseFloat(this.obj.style.left);
		var _y = parseFloat(this.obj.style.top);
		if (!isNaN(_x) && !isNaN(_y)) {
		    this.obj.style.left = (_x + pX) + 'px';
		    this.obj.style.top = (_y + pY) + 'px';
		};
	};
	
	this.openInfoWindowHtml = function(html) {
		this.mapClient.openInfoWindowHtml(new Vertex(this.x, this.y), html, this.size);
	};
	
	this.updateInfoWindowHtml = function(html) {
		this.mapClient.updateInfoWindowHtml(new Vertex(this.x, this.y), html, this.size);
	};
	
	this.closeInfoWindow = function() {
		this.mapClient.closeInfoWindow();
	};
};

function MapBubble(w, h) {
	this.obj = null;
	this.content = null;
	this.mapClient = null;
	this.point = null;
	this.w = w; 
	this.h = h;	
	this.pos = 1;
	this.useStick = false;
	this.iconSize = new Point(19, 32);
	
	this.initContent = function(info, pt) {
		this.setContentHTML(info, pt);
		this.updatePosition(false);
	};
	
	this.setContent = function(info, pt) {
		this.setContentHTML(info, pt);
		this.updatePosition(true);
	};
	
	this.setContentHTML = function(info, pt) {
		this.point = pt;
		this.content.innerHTML = info;
		this.obj.style.display = "";
		this.obj.style.position = "absolute";		
	};
	
	this.setPosition = function(pt) {
		this.point = pt;
		this.updatePosition(false);
	};
	
	this.enableOpacity = function(cond) {
		if (cond == true) {
			this.obj.style.backgroundColor = "#FFFFFF";
			this.obj.style.filter = "alpha(opacity=75)";
			this.obj.style.MozOpacity = 7.5;
			this.obj.style.opacity = .75;
		} else {
			this.obj.style.backgroundColor = "";
			this.obj.style.filter = "";
			this.obj.style.MozOpacity = null;
			this.obj.style.opacity = null;
		};		
	};
	
	this.setDisplay = function(pos) {
		this.pos = pos;
	};
	
	this.enableStick = function(pos) {
		this.useStick = pos;
	};
	
	this.init = function(mapClient) {
		this.mapClient = mapClient;
		this.obj = new MDiv();
		this.obj.style.zIndex = 10;
		this.obj.style.width = this.w + 'px';
		this.obj.style.height = this.h + 'px';
		
		this.stick = new Point(34, 32);
		var sizeB = new Point(8,8); 
		var topLeft = new Point(0, 0);
		var dwnRight = new Point(this.w-sizeB.x, this.h-sizeB.y);
		var tl = this.coreBnd(sizeB, topLeft, topLeft, "small_top_left.png");
		var tr = this.coreBnd(sizeB, new Point(dwnRight.x, topLeft.y), topLeft, "small_top_right.png");
		var bl = this.coreBnd(sizeB, new Point(topLeft.x, dwnRight.y), topLeft, "small_btm_left.png");
		var br = this.coreBnd(sizeB, dwnRight, topLeft, "small_btm_right.png");
		var c0 = this.coreBnd(this.stick, new Point(this.w/3+this.stick.x/1.7, dwnRight.y), topLeft, "small_arr.gif");
		this.exBtn = this.coreBnd(new Point(14,13), new Point(dwnRight.x-13, 10), topLeft, "cl_grey.png");
        
		this.exBtn.style.cursor = "pointer";
		this.exBtn.o = this;
		this.exBtn.onclick = function() {
			if (this.o.obj.style.display == "") {
				this.o.obj.style.display = "none";
			} else {
				this.o.obj.style.display = "";
			}
		};
		
		var w_ = document.namespaces && document.namespaces.add ? 0 : 2;
		var h_ = document.namespaces && document.namespaces.add ? 25 : 24;
		var y_ = document.namespaces && document.namespaces.add ? 6 : 1;
		 
		var tb = new MDiv();
        tb.style.cssText = "border-top: 1px solid rgb(171, 171, 171); " +
        	"position: absolute; left: " + sizeB.x + "px; top: 0px; width: " + (this.w-sizeB.x*2) +"px;" +
            "height: " + sizeB.y + "px; background-color: white;";
        var mb = new MDiv();
        mb.style.cssText = "border-left: 1px solid rgb(171, 171, 171); " +
        	"border-right: 1px solid rgb(171, 171, 171); " +
            "position: absolute; left: "+ topLeft.x +"px; top: " + topLeft.y+sizeB.y + "px; width: " 
            + (this.w-w_) + "px;" + "height: " + (dwnRight.y-sizeB.y) 
            + "px; background-color: white;";
        var bb = new MDiv();
        bb.style.cssText = "border-bottom: 1px solid rgb(171, 171, 171); " +
        	"position: absolute; left: " + sizeB.x + "px; top: " + parseInt(dwnRight.y-y_) + "px;" +
            "width: " + (this.w-sizeB.x*2) + "px; height: " + sizeB.y + "px; background-color: white;";
        this.content = new MDiv();
        this.content.style.cssText = "position: absolute; left: " + sizeB.x + "px; top: " + sizeB.y + "px; " +
        	"width: " + (this.w-sizeB.x*2-14) + "px; height: " + (this.h-sizeB.y*2) + "px; z-index: 10;";
				
		this.obj.appendChild(tl); this.obj.appendChild(tr);
		this.obj.appendChild(bl); this.obj.appendChild(br);
		this.obj.appendChild(tb); this.obj.appendChild(mb); 
		this.obj.appendChild(bb); 
		this.obj.appendChild(this.exBtn);
		this.obj.appendChild(this.content);
		if (this.useStick) {
			this.obj.appendChild(c0);
		};	
	};
	this.coreBnd = function(size, posDiv, posImg, url) {
		var d = new MDiv('', posDiv.x + "px", posDiv.y + "px", 
			size.x + "px", size.y + "px", "absolute", 0, '', true); 
		var i = new MImg('', 
			this.mapClient.baseUrl + "img/" + url, posImg.x + 'px',
			posImg.y + 'px', '', '', "absolute"); 
		i.style.border = '0px';
		d.appendChild(i);
		return d;
	};	
	
	this.panByOffset = function(pX, pY) {
		var _x = parseInt(this.obj.style.left);
		var _y = parseInt(this.obj.style.top);
		if (!isNaN(_x) && !isNaN(_y)) {
		    this.obj.style.left = (_x + pX) + 'px';
		    this.obj.style.top = (_y + pY) + 'px';
		};
	};
	
	this.updatePosition = function(fromDrawer) {
		var diff = new Vertex(0,0), _ptx, _pty;
		var pt = this.mapClient.vertexToScreen(this.point.x, this.point.y);
		if (pt.x == null || pt.y == null) {
			return;
		};
		var left = pt;
		var right = left;
		var h = (this.useStick ? this.h + this.stick.y : this.h);
		_pty = new Point(this.w, h);
		switch(this.pos) {
			case 4:
				_ptx = new Point(-(this.w/2), -(h/2)+this.iconSize.y);
				break;			
			case 3:
				_ptx = new Point(-this.w-this.iconSize.x/2, -(h)+(h-this.iconSize.y));
				break;
			case 2:
				_ptx = new Point(-(this.w/2), -(h)-this.iconSize.y);
				break;
			case 1:
			default:
				_ptx = new Point(this.iconSize.x/2, -(h)+(h-this.iconSize.y));
				break;
		};
		left = OffsetPoint(left, _ptx.x, _ptx.y);
		right = OffsetPoint(right, _pty.x, _pty.y);
		this.obj.style.left = left.x + "px";
		this.obj.style.top = left.y + "px";
		
		if (fromDrawer == false) {
		    if (this.mapClient.mapWidth < right.x) {
		    	diff.x = -(right.x - this.mapClient.mapWidth + 10);
		    };
			if (this.mapClient.mapHeight < right.y) {
				diff.y = -(right.y - this.mapClient.mapHeight - 10);
			};
			if (left.x < 25) {
				diff.x = Math.abs(left.x) + 25;
			};
			if (left.y < 10) {
				diff.y = Math.abs(left.y) + 20;
			};
			this.mapClient.panMapByOffset(diff.x, diff.y);
		};
	};
};

function MapThumbnail(w, h, viewportLayer) {
	this.width = w;
	this.height = h;
	this.baseUrl = "";
	this.mapApi = null;
	this.tmpSize = new Point(0, 0);
	
	this.init = function(w, h, mapApi) {
		this.width = w;
		this.height = h;		
		this.mapApi = mapApi;
		this.baseUrl = mapApi.baseUrl;
		this.wFac = w / 20;
		this.hFac = h / 20;
		
		this.thumbNailPanel = new MDiv();
		this.thumbNailPanel.style.cssText = "border-top: 1px solid " +
			"rgb(151, 151, 151); border-left: 1px solid " +
			"rgb(151, 151, 151); overflow: hidden; width: 0px; " +
			"height: 0px; background-color: white; z-index:11;" +
			"position: absolute; right: -1px; bottom: -1px;";
		this.mapPanel = new MDiv();
		this.mapPanel.style.cssText = "position:absolute; left:5px; top:5px;" +
			"border-top:1px solid rgb(151, 151, 151); border-left:" +
			"1px solid rgb(151, 151, 151); z-index:1;";
		this.btnShow = new MImg();
		this.btnShow.style.cssText = "position: absolute; right: 0px; " +
			"bottom: 0px; cursor:pointer; z-index:11;";
		this.btnShow.src = this.baseUrl + "img/thumb_max.gif";
		this.btnShow.o = this;
		this.btnShow.onclick = function() {
			var me = this;
			if (this.o.tmpSize.x >= this.o.width 
				&& this.o.tmpSize.y >= this.o.height) {
				this.o.display(false);
			} else {
				this.o.display(true);
			};
		};		
		
		this.thumbNailControl = new MDiv();
		var map = new MImg();
		map.src = this.baseUrl + "img/thumbnail.gif";
		this.mapPanel.appendChild(map);
		this.thumbNailPanel.appendChild(this.mapPanel);
		this.thumbNailPanel.appendChild(this.thumbNailControl);
		mapApi.parentLayer.appendChild(this.thumbNailPanel);
		mapApi.parentLayer.appendChild(this.btnShow);		
	};
		
	this.display = function(vars) {
		if (vars == true) {
			this.tmpSize.x += this.wFac; this.tmpSize.y += this.hFac;
		} else {
			this.tmpSize.x -= this.wFac; this.tmpSize.y -= this.hFac;
		};
		this.thumbNailPanel.style.width = this.tmpSize.x +'px';
		this.thumbNailPanel.style.height = this.tmpSize.y +'px';
		if ((this.tmpSize.x > 0 && this.tmpSize.y > 0 && vars == false) 
			|| (this.width+5 >= this.tmpSize.x 
				&& this.height+5 >= this.tmpSize.y && vars == true)) {
			var me = this;
			setTimeout(function() {
				me.display(vars);
			}, 5);
		} else {
			if (vars == true) {
				this.btnShow.src = this.baseUrl + 'img/thumb_min.gif';
			} else {
				this.btnShow.src = this.baseUrl + 'img/thumb_max.gif';
			};
		};
	};	
	
	this.updateThumbNailControl = function() {
		if (this.thumbNailPanel == null || this.mapApi.mapClient == undefined) {
			return;
		}		
		var scale = new MapScale(this.width, this.height, 1, 1, 
			341963.83, 398341.80, 0, 162948.46);
		
		var pt = scale.utmToPixel(this.mapApi.mapClient.centerVertex.x, 
			this.mapApi.mapClient.centerVertex.y);

		var l = pt.x - 7.5, t = pt.y, w = 15, h = 15;
		this.thumbNailControl.style.cssText = "width: " + w + "px; " +
				"height: " + h + "px; left:" + l + "px; top: " + t + "px; " +
				"z-index:2; border-style: solid; border-color: rgb(136, 136, 255); " +
				"border-width: 2px; position: absolute; cursor: move; background-image:url(" + this.baseUrl + 'img/x.gif' + ")";
		this.thumbNailPanel._api = this.mapApi;
		this.thumbNailPanel._scale = scale;
		this.thumbNailPanel._parent = this;
		this.thumbNailPanel.onmousedown = this.onPanelMouseDown;		
		this.thumbNailPanel.onmousemove = this.onPanelMouseMove;
		this.thumbNailPanel.onmouseup = this.onPanelMouseClick;
		this.thumbNailPanel.onmouseout = this.onPanelMouseClick;		
	};
	
	this.onPanelMouseClick = function(e) {
		if (this.panelDrag == true) { 
			var pos = getCursorPos(e, this._parent.mapPanel);
			var p = this._scale.pixelToUtm(pos.x - 5 + 7.5, pos.y - 5);
			this._api.setCenterVertex(p);
			this._parent.updateThumbNailControl();
			this.panelDrag = false;
		}
	};
	
	this.onPanelMouseDown = function(e) {
		this.panelDrag = true;
	};
			
	this.onPanelMouseMove = function(e) {
		if (!this.panelDrag) {
			return;
		}
		var pos = getCursorPos(e, this._parent.mapPanel);
		this._parent.thumbNailControl.style.left = (pos.x - 5) + 'px';
		this._parent.thumbNailControl.style.top = (pos.y - 5) + 'px';
	};	
			
};

function MapApiController() {
	this.mapClient = new MapClient();
	this.mapDraw = new MapDrawingController();	
	this.mapThumb = new MapThumbnail();
	this.drawMode = false;
	this.dragging = true;
	this.autoLevel = false;
	
	function onMouseDblClick(e)	{
		if (this._p.drawMode == true){
			this._p.enableDrawCursor(false);
			this._p.setCursor(false);
			this._p.mapDraw.stopDrawing();
		};
		this._p.drawMode = false;
	};
	
	function onMouseDown(e)	{
		/*var pos = getCursorPos(e, this._p.granParentLayer);
		var vertex = this._mapClient.screenToVertex(pos);
		this._mapClient.centerVertex = vertex; 
		this._mapClient.drawMap();
		return ;*/
		var pos = getCursorPos(e, this._p.granParentLayer);		
		this.startX = pos.x;
		this.startY = pos.y;
		this.firstX = pos.x;
		this.firstY = pos.y;
		if (window.Event) {
			if (e.which == 2 || e.which == 3) {
				return;
			};
		} else if (event.button == 2 || event.button == 3) {
		    return;
		};
		this.dragging = this._p.dragging ? true : false;
		if (this.dragging == true) {
			this._p.setCursor(false);
		};
		if (this._p.drawMode == true) {
			this._p.enableDrawCursor(true);
			this._p.mapDraw.draw(pos, false);
			this.dragging = false;
		};
	};
	
	function onMouseMove(e)	{
		if (!this._p.drawMode && !this.dragging) {
			return;
		};
		var pos = getCursorPos(e, this._p.granParentLayer);
		var moveX = pos.x;
		var moveY = pos.y;
		if (this._p.drawMode == true) {
			this.dragging = false;
			this._p.enableDrawCursor(true);
			this._p.mapDraw.draw(pos, true);						
		};
		if (this.dragging == true) {			
			this._mapClient.moveViewportPosition(moveX-this.startX, moveY-this.startY);
			if (this._p.mapDraw != undefined) {
				this._p.mapDraw.panPanelByOffset(moveX-this.startX, moveY-this.startY);
			};			
			this.startX = pos.x;
			this.startY = pos.y;					
		};
	};
	
	function onMouseUp(e) {
		if (this.dragging == true) {
			var pos = getCursorPos(e, this._p.granParentLayer);
			if (pos.x == this.firstX && pos.y == this.firstY) {
				this.dragging = false;
				return;
			};
			this._p.setCursor(true);
			this.dragging = false;
	  		this._mapClient.panMapByOffset(pos.x-this.startX, pos.y-this.startY);
			if(this._p.mapDraw!=undefined){
				this._p.mapDraw.panPanelByOffset(pos.x-this.startX, pos.y-this.startY);
			}	  			  		
	  		this._p.mapThumb.updateThumbNailControl();
		};
		this._p.revertContainer();
	};

	this.initController = function() {
		this.dragImgUrl = this.baseUrl + 'img/x.gif';
		this.dragArea = new MDiv('', '', '', "100%", "100%", "relative", 8, '');
		this.dragArea.style.backgroundImage = "url(" +this.dragImgUrl + ")";
		this.dragArea._p = this;
		this.dragArea._mapClient = this.mapClient;
		this.dragArea.onmousedown = onMouseDown;		
		this.dragArea.onmousemove = onMouseMove;
		this.dragArea.onmouseup = onMouseUp;
		this.dragArea.onmouseout = onMouseUp;	
		this.dragArea.ondblclick = onMouseDblClick;
		this.viewportLayer.appendChild(this.dragArea);
		//this.setCursor(true);
		this.loadingLayer = new MDiv('', '0px', '0px', '100%', '100%', 'absolute', 12, '');
		this.loadingLayer.style.backgroundImage = "url(" + this.baseUrl + 'img/brown.gif' + ")";
		//this.loadingLayer.innerHTML = "Loading ...";
		this.loaderImg = new MImg('', this.baseUrl + "img/loading.gif", 
			(this.mapClient.mapWidth/2) - 50 + "px", 
			(this.mapClient.mapHeight/2) - 50 + "px", '', '', "absolute");
		this.loaderImg.style.display = "none";	
		this.parentLayer.appendChild(this.loaderImg);
	};
	
	this.revertContainer = function() {
		this.viewportLayer.style.height = "100%";
		this.parentLayer.style.height = "100%";
	};
	
	this.initContainer = function(parent_id) {
		this.granParentLayer = document.getElementById(parent_id);
		this.granParentLayer.setAttribute("onselectstart", "return false");
		this.granParentLayer.setAttribute("onmousedown", "if (typeof event.preventDefault != 'undefined') {" +
				"event.preventDefault();}");
		this.parentLayer = new MDiv();
		this.viewportLayer = new MDiv('', "0px", "0px", "100%", "100%", "absolute", '', '', true);
		this.parentLayer.appendChild(this.viewportLayer);
		this.granParentLayer.appendChild(this.parentLayer);		
	};

	this.setMapSize = function(width, height) {		
		this.granParentLayer.style.width = width +"px";
		this.granParentLayer.style.height = height +"px";
		this.mapClient.mapWidth = width;
		this.mapClient.mapHeight = height;
		this.mapClient.drawMap();
	};
	
	this.setAutoLevel = function(value) {
		if (value == true || value == false) {
			this.autoLevel = value;
		}
	};
	
	this.setCursor = function(openx) {				
		if (openx == true) {
			if (document.namespaces && document.namespaces.add) {
				this.dragArea.style.cursor = "url('" + this.baseUrl + "img/openhand.cur'), default";			
			} else {
				this.dragArea.style.cursor = "-moz-grab";	
			};
		} else if (openx == false) {
			if (document.namespaces && document.namespaces.add) {
				this.dragArea.style.cursor = "url('" + this.baseUrl + "img/closedhand.cur'), default";
			} else {
				this.dragArea.style.cursor = "-moz-grabbing";	
			};
		};
	};
	
	this.enableDrawCursor = function(openx) {
		if (openx == true) {
			this.dragArea.style.cursor = "move";
		} 
	};	
	
	this.setMapSource = function(mapName){
		this.mapClient.setMapSource(mapName, this.autoLevel);		
	};
	
	this.enableDragging = function(cond) {
		this.dragging = cond;
	};
	
	this.setCenterVertex = function(vertex) {
		if (vertex.x == 0 && vertex.y == 0) {
			return;
		}
		this.mapClient.setCenterVertex(vertex);
		this.mapClient.drawMap();
	};
	
	this.setLevelIndex = function(level) {
		this.mapClient.changeLevel(level);
		if (this.navigation != undefined 
			|| this.navigation != null) {
			this.navigation.getSelectedController(this.navigation.btnLevel, this.mapClient.levelIndex);
		}
	};
	
	this.addControl = function(control) {
		if (control == null || control == undefined
			|| control.navigation == undefined) {
			return;
		};
		control.navigation.init(this.mapClient, this);
		this.parentLayer.appendChild(control.getNavigation());
		this.navigation = control.navigation;
	};
	
	this.showThumbnail = function(cond) {
		if (cond) {
			this.mapThumb.init(187, 107, this);
		}
	};
	
	this.showLoadingImg = function(cond) {
		if (cond) {
			this.loaderImg.style.left = (this.mapClient.mapWidth/2) - 50 + "px";
			this.loaderImg.style.top = (this.mapClient.mapHeight/2) - 50 + "px";			
			this.loaderImg.style.display = "";
			this.mapDraw.enableOpacity(true);
		} else {
			this.loaderImg.style.display = "none";
			this.mapDraw.enableOpacity(false);
		}
	};	
	
	this.init = function(viewport_id, url) {
		IeFix(url);		
		this.initContainer(viewport_id);
		this.baseUrl = url;
		this.mapClient.init(this, url);
		this.mapClient.levelIndex = 4;	
		this.mapClient.setCenterVertex(new Vertex(365292.630777,144934.832246));
		this.mapDraw.init(this.mapClient);
		this.initController();
	};
};

function SmallMapControl(showIndicator) {
	if (showIndicator == undefined) {
		showIndicator = true;
	}	
	this.navigation = new MapNavigation();
	this.getNavigation = function() {
		var panel = new MDiv('', "0px", "40px",
			"50px", "80px", "absolute", 11);
		panel.appendChild(this.navigation.getDirectionControl());
		panel.appendChild(this.navigation.getZoomControl(showIndicator));
		return panel;
	};
};

function MediumMapControl() {
	this.navigation = new MapNavigation();
	this.getNavigation = function() {
		var panel = new MDiv('', "0px", "40px",
			"50px", "100px", "absolute", 11);
		panel.appendChild(this.navigation.getDirectionControl());
		panel.appendChild(this.navigation.getLevelControl());
		return panel;
	};
};

function CompleteMapControl() {
	this.navigation = new MapNavigation();
	this.getNavigation = function() {
		var panel = new MDiv('', "0px", "40px",
			"50px", "150px", "absolute", 11);
		panel.appendChild(this.navigation.getDirectionControl());
		panel.appendChild(this.navigation.getZoomControl());
		panel.appendChild(this.navigation.getDrawControl());
		panel.appendChild(this.navigation.getLevelControl());
		return panel;
	};
};

function MapLogo() {
	this.init = function(mapClient, mapApi) {
		if (mapClient == null || mapApi == null) {
			return false;
		}		
		var logo = new MImg('', mapApi.baseUrl + "img/logo.gif", 
			"0px", "0px", '76px', '30px', "absolute");
		var cpright = new MImg('', mapApi.baseUrl + "img/copyright.gif", 
			"0px", (mapClient.mapHeight - 12) + "px", '125px', '12px', "absolute");
		var north = new MImg('', mapApi.baseUrl + "img/north.gif", 
			(mapClient.mapWidth - 28) + "px", (mapClient.mapHeight - 16) + "px", '28px', '16px', "absolute");

		cpright.style.cssText = "position: absolute; left:0px; bottom: 0px;"; 
		north.style.cssText = "position: absolute; right: 0px; bottom: 0px;"; 

		mapApi.parentLayer.appendChild(logo);
		mapApi.parentLayer.appendChild(cpright);
		mapApi.parentLayer.appendChild(north);
	};	
};

function MapNavigation() {
	this.mapClient = null;
	this.mapApi = null;
	
	this.init = function(mapClient, mapApi) {
		this.mapClient = mapClient;
		this.mapApi = mapApi;
	};
	
	this.createNavigationContainer = function(_left, _top, _w, _h, index, color) {
		return new MDiv('', _left, _top, _w, _h, "absolute", index, color);
	};
	
	this.checkValidity = function() {
		if (this.mapClient == null || this.mapApi == null) {
			return false;
		}
		return true;
	};
	
	this.createNavigationControl = function(url, left, topx)	{
		var img = new MImg('', url, left + "px", topx + "px",
			'', '', "absolute");
		img.style.cursor = "pointer";
		img._mapClient = this.mapClient;		
		img._mapApi = this.mapApi;
		img._p = this;
		return img;
	};
	
	this.getDirectionControl = function() {
		if (!this.checkValidity()) {
			return;
		}
        var moveX = this.mapClient.mapWidth / 2; 
        var moveY = this.mapClient.mapHeight / 2; 
        
        var directionPanel = new MDiv('', "0px", "0px", "50px", "70px", "relative", "11"); 
	    var img1 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_up.gif", 16, 0);
	    img1.onclick = function() { this._mapClient.panMapByOffset(0, moveY); };
	    
	    var img2 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_left.gif", 6, 22);
	    img2.onclick = function() { this._mapClient.panMapByOffset(moveX, 0); };
	    
	    var img3 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_right.gif", 27, 22);
	    img3.onclick = function() { this._mapClient.panMapByOffset(-moveX, 0); };
	    
	    var img4 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_btm.gif", 15, 44);
	    img4.onclick = function() { this._mapClient.panMapByOffset(0, -moveY); };

		directionPanel.appendChild(img1);
		directionPanel.appendChild(img2);
		directionPanel.appendChild(img3);
		directionPanel.appendChild(img4);
		return directionPanel;
	};
	
	this.getZoomControl = function(showIndicator) {	
		if (!this.checkValidity()) {
			return;
		}		    
		var zoomPanel = new MDiv('', "0px", "0px", "50px", "40px", "relative", "11");
		if (showIndicator) {
			var indicatorImg = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_" + (this.mapClient.levelIndex+1) + ".gif", 15, 20);
			indicatorImg.style.cursor = "";
			zoomPanel.appendChild(indicatorImg);
		}				

	    var img5 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_in.gif", 15, 0);
	    img5.indicator = {status:showIndicator, image:indicatorImg};
	    img5.onclick = function() {
	    	var newLevel = this._mapClient.levelIndex + 1;
	    	if ((this._p.btnLevel != undefined 
	    		&& this._p.btnLevel.length != undefined)
	    		&& newLevel > -1 && newLevel < 6) {
	    		this._p.getSelectedController(this._p.btnLevel, newLevel);	
	    	};
    		if (this.indicator.status) {
    			var nl = newLevel < 0 ? 1 : (newLevel > 2 ? 3 : newLevel+1);       			
    			this.indicator.image.src = this._mapApi.baseUrl + "img/nav_" + (nl) + ".gif";
    		}    	
	    	this._mapClient.zoomIn();
	    };
	    
	    var img6 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_out.gif", 15, 40);
	    img6.indicator = {status:showIndicator, image:indicatorImg};
	    img6.onclick = function() {
	    	var newLevel = this._mapClient.levelIndex - 1;
	    	if ((this._p.btnLevel != undefined 
	    		&& this._p.btnLevel.length != undefined)
	    		&& newLevel > -1 && newLevel < 6) {	    		
	    		this._p.getSelectedController(this._p.btnLevel, newLevel);	
	    	};
    		if (this.indicator.status) {
    			var nl = newLevel < 0 ? 1 : (newLevel > 2 ? 3 : newLevel+1);       			
    			this.indicator.image.src = this._mapApi.baseUrl + "img/nav_" + (nl) + ".gif";
    		}    	
	    	this._mapClient.zoomOut();
	    };
        zoomPanel.appendChild(img5);
		zoomPanel.appendChild(img6);
		return zoomPanel;
	};
	
	this.getDrawControl = function() {
		if (!this.checkValidity()) {
			return;
		}		
		var drawPanel = new MDiv('', "0px", "0px", "50px", "20px", "relative", 11);		
	    var img7 = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_dist.gif", 15, 0);
	    img7.onclick = function() {
	    	if (this._mapApi.drawMode == false) {
	    		this._mapApi.mapDraw.clearDrawing(); 
	    	}
	    	this._mapApi.drawMode = !this._mapApi.drawMode;	    	
	    };
	    drawPanel.appendChild(img7);
	    return drawPanel;
	};
	
	this.getLevelControl = function() {
		if (!this.checkValidity()) {
			return;
		}		
		var levelPanel = new MDiv('', "0px", "0px", "50px", "120px", "relative", 11);
		btnLevel = new Array();
		
		btnLevel[0] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_1.gif", 15, 0);
		btnLevel[1] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_2.gif", 15, 22);
		btnLevel[2] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_3.gif", 15, 44);
		btnLevel[3] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_4.gif", 15, 66);
		btnLevel[4] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_5.gif", 15, 88);
		btnLevel[5] = this.createNavigationControl(this.mapApi.baseUrl + "img/nav_6.gif", 15, 111);
		for (var i=0; i<btnLevel.length; i++) {
			levelPanel.appendChild(btnLevel[i]);			
			btnLevel[i].idx = i;
			btnLevel[i].my = this;
			btnLevel[i]._parent = btnLevel;
			btnLevel[i].onclick = function() {
				this._mapClient.changeLevel(this.idx);				
				this.my.getSelectedController(this._parent, this.idx);
			};
		};
		this.getSelectedController(btnLevel, this.mapClient.levelIndex);
		this.btnLevel = btnLevel;
		return levelPanel;
	};
	
	this.getSelectedController = function(controller, idx) {
		if (controller == undefined) {
			return false;
		}
		for (var i=0; i<controller.length; i++) {
			if (i == idx) {
				controller[i].style.border = "1px solid #000";
			} else {
				controller[i].style.border = "";
			};
		};
	};	
};
var VEvent = {
	addListener : function(object, method, refs) {
		var obj = object.obj == undefined ? object : object.obj;
		if(window.addEventListener){ 
			obj.addEventListener(method, refs, false);
		} else { 
			obj.attachEvent('on' + method, refs);
		}
	}
};


