//controls position and display of map controls
//requires mapCustom.js, mapNav.js, mapGraphics.js
//update history:
//2007_06_20 -  J.S. enhanced TOC to take advantage of 9.2 xml for group layers,
//        changed the following funcitons: buildLayerDivs(),toggleLayer()
//        added function: toggleGroupLayer()
//      -   J.S. fixed IE bug in getMouseX() and getMouseY()
//2007_07_27  changed createPrintPage() - no longer calls loadPrintMap() - print page now calls it
//2007_09_26 -  J.S. bug fix: layers in the mxd can now have characters like "&" in them

//current extents of the map
var g_fMaxX = g_fInitMaxX;
var g_fMaxY = g_fInitMaxY;
var g_fMinX = g_fInitMinX;
var g_fMinY = g_fInitMinY;

//current extents of the OV map
var g_fOVMaxX = g_fOVInitMaxX;
var g_fOVMaxY = g_fOVInitMaxY;
var g_fOVMinX = g_fOVInitMinX;
var g_fOVMinY = g_fOVInitMinY;

//current extents for print page
var g_fPrintMaxX = 0;
var g_fPrintMaxY = 0;
var g_fPrintMinX = 0;
var g_fPrintMinY = 0;

var g_fMapAspectRatio = 0.00;   //used for adjusting zoom boxes = mapWidth / mapHeight
var g_nMapSizeFactor = 0;       //used when resizing map

var g_sMapScale = "";         //string used to show scale in status bar
var g_fMapUnitsPerPixel = 0;    //map units per pixel

var g_sCurrentTool = "zoomInBox"; //default tool
var g_sPreviousTool = "zoomInBox";

var g_sSelectableLayer = g_sDefaultSelectableLayer;
var g_sSearchCriteria = "beginsWith";

var g_sSearchLayer = g_sDefaultSearchLayer;
var g_sSearchField = g_sDefaultSearchField;
var g_sSearchValue = g_sDefaultSearchValue;

var g_nPanOffsetX = 0;        //used for moving position of map image when panning realtime
var g_nPanOffsetY = 0;
var g_nPanStartX = 0;
var g_nPanStartY = 0;

//selected features variables
var g_sSelectedFeaturesSpatialQuery = "";
var g_nSelectedFeaturesLayerIdx = 0;
var g_nSelectCount = 0;

//print page variables
var g_bIncludeComments = false;
var g_bIncludeLegend = false;
var g_bIncludeResultsTable = false;
var g_bPreserveMapExtent = false;
var g_bPreserveMapScale = false;
var g_nPrintMapWidth = 0;
var g_nPrintMapHeight = 0;
var g_sPrintPageComments = "";
var g_sPrintPageTitle = "";

//legend vars
var g_bLegendVisible = false;
var g_sLegendBackColorRGB = "";

//measure arrays
var g_aXPoints = new Array();
var g_aYPoints = new Array();
var g_fTotalDistance = 0;
var g_fSegmentDistance = 0;
var g_nStretchPointIdx = 0;


String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); };

function bufferSelectedFeatures(){
  if ((g_bOkToGetFeatures == false) || (g_bOkToGetMap == false)){
    return;
  }

  var buffTargetElem = document.getElementById("lstBufferLayer");
  var sBufferTargetLayer = buffTargetElem.options[buffTargetElem.selectedIndex].value;
  var nBufferDistance = document.getElementById("txtBufferDistance").value;

  if(sBufferTargetLayer == g_sSelectableLayer){
    alert("Unable to perform a buffer select from the same layer.");
    return;
  }

  if (isNaN(nBufferDistance)){
    alert("Invalid buffer distance");
    return;
  }

  if (g_nSelectCount == 0){
    if(g_sDrawBufferQuery != ""){
      alert("Unable to buffer the results of a buffer.\nClear buffer and create a new selection.");
    } else {
      alert("There are no features selected to buffer.");
    }
    return;
  }

  //splice buffer into existing spatial query
  var nPos = 0;
  nPos = g_sSelectedFeaturesSpatialQuery.indexOf("</SPATIALQUERY>");

  var nTargetLayerIdx = getLayerID(sBufferTargetLayer);

  var sBufferXML = "";

  //craeate buffer graphic
  sBufferXML = '<LAYER type="featureclass" name="theBufferGraphic" id="theBufferGraphic">\n';
  sBufferXML += '<DATASET fromlayer="' + g_nSelectedFeaturesLayerIdx + '" />\n';
  sBufferXML += g_sSelectedFeaturesSpatialQuery.substring(0,nPos);
  sBufferXML += '<BUFFER distance="' + nBufferDistance + '" bufferunits="' + g_aProperties["mapUnits"] + '">\n';
  sBufferXML += '</BUFFER>';
  sBufferXML += '</SPATIALQUERY>';
  sBufferXML += '<SIMPLERENDERER>\n';
  sBufferXML += '<SIMPLEPOLYGONSYMBOL fillcolor="255,255,0" filltransparency=".3" boundarycolor="255,255,0" boundarywidth="2" />\n';
  sBufferXML += '</SIMPLERENDERER>\n';
  sBufferXML += '</LAYER>\n';

  //show selected features query if needed
  if (sBufferTargetLayer != "No Layer"){
    sBufferXML += '<LAYER type="featureclass" name="theBufferSelected" id="theBufferSelected">\n';
    sBufferXML += '<DATASET fromlayer="' + g_nSelectedFeaturesLayerIdx + '" />\n';
    sBufferXML += g_sSelectedFeaturesSpatialQuery.substring(0,nPos);
    sBufferXML += '<BUFFER distance="' + nBufferDistance + '" bufferunits="' + g_aProperties["mapUnits"] + '">\n';
    sBufferXML += '<TARGETLAYER id="' + nTargetLayerIdx + '" />';
    sBufferXML += '<SPATIALQUERY subfields="' + buildSelectFieldString(sBufferTargetLayer) + '" />';
    sBufferXML += '</BUFFER>';
    sBufferXML += '</SPATIALQUERY>';
    sBufferXML += '<SIMPLERENDERER>\n';
    sBufferXML += '<SIMPLEPOLYGONSYMBOL fillcolor="255,255,0" filltransparency=".3" boundarycolor="255,255,0" boundarywidth="2" />\n';
    sBufferXML += '</SIMPLERENDERER>\n';
    sBufferXML += '</LAYER>\n';
  }

  g_sDrawBufferQuery = sBufferXML;

  sBufferXML = '<LAYER id="' + g_nSelectedFeaturesLayerIdx + '" />\n';
  sBufferXML += g_sSelectedFeaturesSpatialQuery.substring(0,nPos);
  sBufferXML += '<BUFFER distance="' + nBufferDistance + '" bufferunits="' + g_aProperties["mapUnits"] + '">\n';
  sBufferXML += '<TARGETLAYER id="' + nTargetLayerIdx + '" />\n';
  sBufferXML += '<SPATIALQUERY subfields="' + buildSelectFieldString(sBufferTargetLayer) + '" />\n';
  sBufferXML += '</BUFFER>\n';
  sBufferXML += '</SPATIALQUERY>\n';

  //perform query if needed
  if (sBufferTargetLayer != "No Layer"){
    g_nSelectCount = 0;
    g_sSelectedFeaturesSpatialQuery = sBufferXML;
    g_sSelectableLayer = sBufferTargetLayer;
    g_nSelectedFeaturesLayerIdx = nTargetLayerIdx;
    changeSelectableLayer(sBufferTargetLayer);
    getFeatures(sBufferXML,0,false,true);
  }
  loadMap();
}

function buildCirclePoints(startX, startY, radius, angle0, angle1, steps) {
  var dangle = angle1 - angle0;
  var sangle = dangle / steps;
  var x = parseFloat(startX);
  var y = parseFloat(startY);
  var cx = x - radius * Math.cos(angle0 * Math.PI / 180);
  var cy = y + radius * Math.sin(angle0 * Math.PI / 180);
  var ar = new Array();
  ar[0] = new Array();
  ar[0][0] = x;
  ar[0][1] = y;

  for (var i = 0; i < steps; i++) {
    angle0 += sangle;
    x = cx + radius * Math.cos(angle0 * Math.PI / 180);
    y = cy - radius * Math.sin(angle0 * Math.PI / 180);
    ar[i+1] = new Array();
    ar[i+1][0] = String(x);
    ar[i+1][1] = String(y);
  }

  return ar;
}

function buildLayerDivs(){
  var aGroupLayers = new Array();

  var bSkipLayer = false;
  var bHasSwatch = false;
  var bIsParent = false;
  var bParentExpanded = false;

  var nLoopCounter = 0;
  var nLoopCounter2 = 0;
  var nLoopCounter3 = 0;
  var nLoopCounter4 = 0;
  var nLoopCounter5 = 0;

  var nMaxScale = 0;
  var nMinScale = 0;

  var sLayerName = "";
  var sLayerId = "";
  var sParentLayerId = "";
  var sLayersDiv = "";
  var sExpandGroupHtml = "";
  var sSwatchImg = "";
  var sSwatchHtml = "";
  var sVisible = "";

  //loop through all layers in layers array
  for (nLoopCounter = 0;nLoopCounter < g_aLayersArray.length;nLoopCounter++){
    bSkipLayer = false;
    bParentExpanded = false;
    sParentLayerId = g_aLayersArray[nLoopCounter]["parentLayerId"];
    sLayerId = g_aLayersArray[nLoopCounter]["id"];
    sLayerName = g_aLayersArray[nLoopCounter]["layerName"];
    sVisible = g_aLayersArray[nLoopCounter]["visible"];
    nMinScale = g_aLayersArray[nLoopCounter]["minScale"];
    nMaxScale = g_aLayersArray[nLoopCounter]["maxScale"];
    bIsParent = g_aLayersArray[nLoopCounter]["isParent"];

    //check to see if layer should be excluded

    for (nLoopCounter2 = 0;nLoopCounter2 < g_aExcludeFromTocLayers.length;nLoopCounter2++){
      if (sLayerName.indexOf(g_aExcludeFromTocLayers[nLoopCounter2],0) != -1){
        bSkipLayer = true;
      }
    }

    if(!bSkipLayer){
      bShowSwatch = false;
      bHasSwatch = false;

      //check to see if there will be a legend swatch - if so create html for plus or minus image
      for (nLoopCounter4 = 0;nLoopCounter4 < g_aLegendLayers.length;nLoopCounter4++){
        if (g_aLegendLayers[nLoopCounter4]["layerName"] == sLayerName){
          bHasSwatch = true;

          if(g_aLegendLayers[nLoopCounter4]["expanded"] == "true"){
            sSwatchHtml = '<img id="expandImg' + sLayerName + '" onclick="toggleLegendSwatch(\'' + sLayerName + '\');" style="width:9px;height:9px;margin-right:3px;margin-bottom:2px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_collapse.png" alt="Collapse Legend Image" title="Collapse Legend Image" />';
            sSwatchImg = '<img id="swatch' + sLayerName + '" style="margin-left:25px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/' + g_aLegendLayers[nLoopCounter4]["swatchImage"] + '" alt="Legend Image for ' + sLayerName + '" title="Legend Image for ' + sLayerName + '" />';
          } else {
            sSwatchHtml = '<img id="expandImg' + sLayerName + '" onclick="toggleLegendSwatch(\'' + sLayerName + '\');" style="width:9px;height:9px;margin-right:3px;margin-bottom:2px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_expand.png" alt="Expand Legend Image" title="Expand Legend Image" />';
            sSwatchImg = '<img id="swatch' + sLayerName + '" style="margin-left:25px;display:none;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/' + g_aLegendLayers[nLoopCounter4]["swatchImage"] + '" alt="Legend Image for ' + sLayerName + '" title="Legend Image for ' + sLayerName + '" />';
          }

        }
      }

      //if layer has a parent, then check to see if it's parent is expanded
      //and set display property appropriately
      if(sParentLayerId == ""){
        if(bIsParent){
          sLayersDiv += '<div id="layer' + sLayerName + '">';
        } else {
          sLayersDiv += '<div id="layer' + sLayerName + '" style="margin-left:15px;">';
        }
      }else{
        //loop through expanded layer array to see if display should be none or block
        for (nLoopCounter5 = 0;nLoopCounter5 < g_aLayersArray.length;nLoopCounter5++){
          if(g_aLayersArray[nLoopCounter5]["id"] == sParentLayerId){
            bParentExpanded = g_aLayersArray[nLoopCounter5]["expanded"];
          }
        }

        if(bParentExpanded){
          sLayersDiv += '<div style="display:block;margin-left:20px;" id="layer' + sLayerName + '">';
        } else {
          sLayersDiv += '<div style="display:none;margin-left:20px;" id="layer' + sLayerName + '">';
        }
      }


      //if it is a parent layer, then display expand or collapse image with toggleGroupLayer function
      if(bIsParent){
        if(g_aLayersArray[nLoopCounter]["expanded"]){
          sLayersDiv += '<img id="expandGroup' + sLayerName + '" onclick="toggleGroupLayer(\'' + sLayerId + '\',\'' + sLayerName + '\');" style="width:9px;height:9px;margin-left:3px;margin-right:3px;margin-bottom:2px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_collapse.png" alt="Collapse Group Layer" title="Collapse Group Layer" />';
        }else {
          sLayersDiv += '<img id="expandGroup' + sLayerName + '" onclick="toggleGroupLayer(\'' + sLayerId + '\',\'' + sLayerName + '\');" style="width:9px;height:9px;margin-left:3px;margin-right:3px;margin-bottom:2px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_expand.png" alt="Expand Group Layer" title="Expand Group Layer" />';
        }
      }

      if (sVisible == "true"){
        sLayersDiv += '<input onclick="toggleLayer(this.value,true)" type="checkbox" id="' + sLayerName + '" value="' +  sLayerName + '" checked="checked" />';

        if (bHasSwatch == true){ sLayersDiv += sSwatchHtml; }

        //if layer is visible, but not at current scale say why
        if (nMaxScale < g_fMapUnitsPerPixel && nMaxScale != 0){
          sLayersDiv += '<img style="width:16px;height:16px" src="http://cdn.sidwellco.com/shared_images/ajaxgis/zoom_in.gif" alt="Zoom in to see layer" title="Zoom in to see layer" />';
          sLayersDiv += '<span style="background-color:' + g_sLayerNotVisibleAtScaleColor + '" id="' + sLayerName + '">' + sLayerName + '</span></div>';
        } else if (nMinScale > g_fMapUnitsPerPixel){
          sLayersDiv += '<img style="width:16px;height:16px" src="http://cdn.sidwellco.com/shared_images/ajaxgis/zoom_out.gif" alt="Zoom out to see layer" title="Zoom out to see layer" />';
          sLayersDiv += '<span style="background-color:' + g_sLayerNotVisibleAtScaleColor + '" id="' + sLayerName + '">' + sLayerName + '</span></div>';
        } else {
          sLayersDiv += '<span style="background-color:#ffffff" id="' + sLayerName + '">' + sLayerName + '</span></div>';
        }

      } else {
          sLayersDiv += '<input onclick="toggleLayer(this.value,true)" type="checkbox" id="' + sLayerName + '" value="' +  sLayerName + '" />';
          if (bHasSwatch == true){ sLayersDiv += sSwatchHtml; }
          sLayersDiv += '<span id="' + sLayerName + '">' + sLayerName + '</span></div>';
      }

      if (bHasSwatch == true){
        sLayersDiv += sSwatchImg;
      }
    }
  }
  document.getElementById("tocDiv").innerHTML = sLayersDiv;
}


function buildSearchFieldList(){
  var aField = new Array();
  var searchElem = document.getElementById("searchField");

  var nLoopCounter = 0;
  var nLoopCounter2 = 0;

  var sField = "";
  var sFieldAlias = "";
  var sFieldName = "";

  var nListCount = searchElem.options.length;

  //clear out options
  for (nLoopCounter = 0;nLoopCounter < nListCount;nLoopCounter++){
    //as the list gets cleared out, the next index to delete will always be 0
    searchElem.options[0] = null;
  }

  //loop through all layers in selectable layers array
  for (nLoopCounter = 0;nLoopCounter < g_aSelectableLayers.length;nLoopCounter++){
    if(g_aSelectableLayers[nLoopCounter][0] == g_sSearchLayer){
      //loop through all fields in array and populate field list
      for (nLoopCounter2 = 1;nLoopCounter2 < g_aSelectableLayers[nLoopCounter].length;nLoopCounter2++){
        //check for field alias
        sField = g_aSelectableLayers[nLoopCounter][nLoopCounter2];
        aField = sField.split("|");
        sFieldName = aField[0];

        //if there is a field alias value use it if not use fieldname
        if(aField.length == 2){
          sFieldAlias = aField[1];
        } else {
          sFieldAlias = sFieldName;
        }

        if (nLoopCounter2 == 1){
          g_sSearchField = sFieldName;
        }

        //use [nLoopCounter2 - 1] b/c loop starts at 1
        searchElem.options[nLoopCounter2 - 1] = new Option(sFieldAlias,sFieldName,false,false);
      }
    }
  }

}

function buildSearchLayerList(){
  var searchElem = document.getElementById("searchLayer");
  var bufferElem = document.getElementById("lstBufferLayer");
  var radiusElem = document.getElementById("lstRadiusLayer");

  var nLoopCounter = 0;

  //loop through all layers in selectable layers array
  for (nLoopCounter = 0;nLoopCounter < g_aSelectableLayers.length;nLoopCounter++){
    searchElem.options[nLoopCounter] = new Option(g_aSelectableLayers[nLoopCounter][0],g_aSelectableLayers[nLoopCounter][0]);
    //buffer and radius layer lists start at 1 b/c first option is 'no layer'
    bufferElem.options[nLoopCounter + 1] = new Option(g_aSelectableLayers[nLoopCounter][0],g_aSelectableLayers[nLoopCounter][0]);
    radiusElem.options[nLoopCounter + 1] = new Option(g_aSelectableLayers[nLoopCounter][0],g_aSelectableLayers[nLoopCounter][0]);
  }

  for (nLoopCounter = 0;nLoopCounter < searchElem.length;nLoopCounter++){
    if(searchElem.options[nLoopCounter].value == g_sDefaultSearchLayer){
      searchElem.selectedIndex = nLoopCounter;
    }
  }

  buildSearchFieldList();

  //set search field list selected index to default selected item
  var searchFieldElem = document.getElementById("searchField");

  for (nLoopCounter = 0;nLoopCounter < searchFieldElem.length;nLoopCounter++){
    if(searchFieldElem.options[nLoopCounter].value == g_sDefaultSearchField){
      searchFieldElem.selectedIndex = nLoopCounter;
    }
  }

  buildSearchValue();
}

function buildSearchValue(){
  var searchElem = document.getElementById("searchValue");
  searchElem.value = g_sDefaultSearchValue;

  var pinSearchElem = document.getElementById("searchPin");
  pinSearchElem.value = g_sSamplePin;

}

function buildSelectableLayerList(){
  var selElem = document.getElementById("selectableLayer");
  var nLoopCounter = 0;

  //loop through all layers in selectable layers array
  for (nLoopCounter = 0;nLoopCounter < g_aSelectableLayers.length;nLoopCounter++){
    if(g_aSelectableLayers[nLoopCounter][0] == g_sDefaultSelectableLayer){
      selElem.options[nLoopCounter] = new Option(g_aSelectableLayers[nLoopCounter][0],g_aSelectableLayers[nLoopCounter][0],true,true);
    } else {
      selElem.options[nLoopCounter] = new Option(g_aSelectableLayers[nLoopCounter][0],g_aSelectableLayers[nLoopCounter][0]);
    }
  }

}


function bumpZoomSlide(nBump){
  if (g_bOkToGetMap == true){
    var slideZoomElem = document.getElementById("zoomSliderValue");
    var nValue = parseInt(slideZoomElem.value) + parseInt(nBump);
    A_SLIDERS[1].f_setValue(nValue.toString());
    slideZoomMap();
  }
}

function calcAspectRatio(){
  g_fMapAspectRatio = g_nMapWidth / g_nMapHeight;
}


function calcScale(){
  var fPixelSize = 0;
  var fRelativeScale = 0;
  var fScaleBarDist = 0;

  //get pixel size in meters - .0254 is number of meters in an inch
  fPixelSize = .0254 / g_aProperties["dpi"];

  //convert pixel size to desired units
  switch(g_aProperties["mapUnits"]){
  case "feet":
  case "us_survey_feet":
    //pixel size in feet
    fPixelSize = fPixelSize * 3.28;
    break;
  case "decimal_degrees":
    //pixel size in degrees
    //one degree = 111.195 km
    fPixelSize = fPixelSize / 111195;
    break;
  case "meters":
    break;
  }
  fRelativeScale = (g_fMaxX - g_fMinX) / (fPixelSize * g_nMapWidth);
  g_sMapScale = "1:" + Math.round(fRelativeScale * 100)/100; //multiply and dive by 100 so round is to 2 dec. places
  window.status = "Map Scale: " + g_sMapScale;

  //calculate the map units per pixel factor
  g_fMapUnitsPerPixel = (g_fMaxX - g_fMinX) / (g_nMapWidth);

  //calulate distance of scale bar for scale bar text
  fScaleBarDist = g_fMapUnitsPerPixel * g_nScaleBarImgWidth;
  document.getElementById("scaleBarEndValue").innerHTML = Math.round(fScaleBarDist);
  document.getElementById("scaleBarMapUnits").innerHTML = "Map Units: " + g_aProperties["mapUnitsDisplay"];

}

function calcSegmentDistance(){
  if(g_aXPoints.length > 1){
    var fSegmentPixelLength = 0;
    var fSegmentX1 = g_aXPoints[g_aXPoints.length - 2];
    var fSegmentY1 = g_aYPoints[g_aYPoints.length - 2];
    var fSegmentX2 = g_aXPoints[g_aXPoints.length - 1];
    var fSegmentY2 = g_aYPoints[g_aYPoints.length - 1];
    var fXDist = Math.abs(fSegmentX1 - fSegmentX2);
    var fYDist = Math.abs(fSegmentY1 - fSegmentY2);

    fSegmentPixelLength = Math.sqrt(Math.pow(fXDist,2) + Math.pow(fYDist,2));
    g_fSegmentDistance = g_fMapUnitsPerPixel * fSegmentPixelLength;
    var resultsElem = document.getElementById("measureResults");
    resultsElem.innerHTML = "Distance - Total: " + (Math.round((g_fTotalDistance + g_fSegmentDistance) * 100) / 100) + " Segment: " + (Math.round(g_fSegmentDistance * 100) / 100);
    //resultsElem.innerHTML = "points.length:" + g_aXPoints.length + " - seg1x: " + fSegmentX1 + " seg2x: " + fSegmentX2;
  }
}

function calcTotalDistance(){
  g_fTotalDistance += g_fSegmentDistance;
  var resultsElem = document.getElementById("measureResults");
  resultsElem.innerHTML = "Distance - Total: " + (Math.round(g_fTotalDistance * 100) / 100) + " Segment: " + (Math.round(g_fSegmentDistance * 100) / 100);
  calcSegmentDistance();
}

function changeSelectableLayer(sLayerName){
  var selElem = document.getElementById("selectableLayer");

  for (nLoopCounter = 0;nLoopCounter < selElem.length;nLoopCounter++){
    var myOption = selElem.options[nLoopCounter];

    if (myOption.value == sLayerName){
      myOption.selected = true;
    }
  }

  makeLayerVisible(sLayerName);
}

function clearMeasurePoints(){
  g_aXPoints = new Array();
  g_aYPoints = new Array();
  g_jg.clear();
  g_fTotalDistance = 0;
  g_fSegmentDistance = 0;
  g_nStretchPointIdx = 0;
  //document.getElementById("measureResults").innerHTML = "Distance - Total:...  Segment:..." ;
}

function convertOVScreenXToMapX(nXPos){
  var fXPosPct = nXPos / g_nOVMapWidth;
  var fXMapPos = g_fOVMinX  + ((g_fOVMaxX - g_fOVMinX) * fXPosPct);
  return fXMapPos;
}

function convertOVScreenYToMapY(nYPos){
  var fYPosPct = (g_nOVMapHeight - nYPos) / g_nOVMapHeight;
  var fYMapPos = g_fOVMinY  + ((g_fOVMaxY - g_fOVMinY) * fYPosPct);
  return fYMapPos;
}

function convertScreenXToMapX(nXPos){
  var fXPosPct = nXPos / g_nMapWidth;
  var fXMapPos = g_fMinX  + ((g_fMaxX - g_fMinX) * fXPosPct);
  return fXMapPos;
}

function convertScreenYToMapY(nYPos){
  var fYPosPct = (g_nMapHeight - nYPos) / g_nMapHeight;
  var fYMapPos = g_fMinY  + ((g_fMaxY - g_fMinY) * fYPosPct);
  return fYMapPos;
}

function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}

function createLegend(){
  if(g_bOkToGetLegend == true){
    g_sLegendTitle = document.getElementById("txtLegendTitle").value;
    g_nLegendTitleFontSize = document.getElementById("txtLegendTitleFontSize").value;
    g_sLegendBackColor = document.getElementById("txtLegendBackColor").value;
    g_sLegendBackColorRGB = HexToR(g_sLegendBackColor) + "," + HexToG(g_sLegendBackColor) + "," + HexToB(g_sLegendBackColor);
    g_nLegendLayerFontSize = document.getElementById("txtLegendLayerFontSize").value;
    g_nLegendSwatchHeight = document.getElementById("txtLegendSwatchHeight").value;
    g_nLegendSwatchWidth = document.getElementById("txtLegendSwatchWidth").value;
    g_nLegendValueFontSize = document.getElementById("txtLegendValueFontSize").value;
    document.getElementById("legendImg").src = "http://cdn.sidwellco.com/shared_images/ajaxgis/loading_spinner.gif";
    document.getElementById("legendImg").style.display = "block";
    getLegend();
  }
}


function createPrintPage(){
  var pageSizeElem = document.getElementById("printPageSize");
  var pageOrientElem = document.getElementById("printPageOrientation");
  g_bPreserveMapExtent = false;
  g_bPreserveMapScale = false;
  g_bIncludeResultsTable = false;
  g_bIncludeLegend = false;


  g_bPreserveMapExtent = document.getElementById("preserveMapExtent").checked;
  g_bPreserveMapScale = document.getElementById("preserveMapScale").checked;
  g_bIncludeResultsTable = document.getElementById("includeResults").checked;
  g_bIncludeComments = document.getElementById("includeComments").checked;
  g_bIncludeLegend = document.getElementById("includeLegend").checked;
  g_sPrintPageComments = document.getElementById("printPageComments").value;
  g_sPrintPageTitle = document.getElementById("printPageTitleValue").value;

  var sPageSize = pageSizeElem.options[pageSizeElem.selectedIndex].value;
  var sPageOrient = pageOrientElem.options[pageOrientElem.selectedIndex].value;

  switch(sPageSize){
    case "85x11":
      if (sPageOrient == "portrait"){
        g_nPrintMapWidth = 600;
        g_nPrintMapHeight = 800;
      } else {
        g_nPrintMapWidth = 800;
        g_nPrintMapHeight = 600;
      }
      break;
    case "11x17":
      if (sPageOrient == "portrait"){
        g_nPrintMapWidth = 800;
        g_nPrintMapHeight = 1200;
      } else {
        g_nPrintMapWidth = 1200;
        g_nPrintMapHeight = 780;
      }
      break;
  }

  //load new legend if needed
  if (g_bLegendVisible == false && g_bIncludeLegend == true){
    createLegend();
  }

  if (g_bOkToGetMap){
    popUpPrintPage();
    //loadPrintMap();
  }
}

function displayCoords(e){
  var nXPos = getMouseX(e) - g_nMapDivLeft;
  var nYPos = getMouseY(e) - g_nMapDivTop;
  var fXMapPos = convertScreenXToMapX(nXPos);
  var fYMapPos = convertScreenYToMapY(nYPos);

  window.status = "Map Scale: " + g_sMapScale + " -- x:" + (Math.round(fXMapPos * 100) / 100) + "  y:" + (Math.round(fYMapPos * 100) / 100);
}


function displayOVExtentBox(){
  if (g_fMinX < g_fOVMinX) g_fMinX = g_fOVMinX;
  if (g_fMaxX > g_fOVMaxX) g_fMaxX = g_fOVMaxX;
  if (g_fMinY < g_fOVMinY) g_fMinY = g_fOVMinY;
  if (g_fMaxY > g_fOVMaxY) g_fMaxY = g_fOVMaxY;

  var elemOvExtent = document.getElementById("ovExtentDiv");

  //remove extent if max extents
  /*if ((g_fMinX = g_fOVMinX) && (g_fMaxX = g_fOVMaxX) && (g_fMinY = g_fOVMinY) && (g_fMaxY = g_fOVMaxY)){
    //elemOvExtent.style.display = "none";
  } else {
    alert("setting extent div to block");
    elemOvExtent.style.display = "block";
  }*/

  var fLeftPct = (g_fMinX - g_fOVMinX) / (g_fOVMaxX - g_fOVMinX);
  var fTopPct = (g_fOVMaxY - g_fMaxY) / (g_fOVMaxY -  g_fOVMinY);
  elemOvExtent.style.top = parseInt(g_nOVMapHeight * fTopPct) + "px";
  elemOvExtent.style.left = parseInt(g_nOVMapWidth * fLeftPct) + "px";

  var fXDistPct = (g_fMaxX - g_fMinX) / (g_fOVMaxX - g_fOVMinX);
  var fYDistPct = (g_fMaxY - g_fMinY) / (g_fOVMaxY - g_fOVMinY);
  elemOvExtent.style.width = parseInt(g_nOVMapWidth * fXDistPct) + "px";
  elemOvExtent.style.height = parseInt(g_nOVMapHeight * fYDistPct) + "px";
}

function doCurrentTool(e){
  var nXPos = getMouseX(e) - g_nMapDivLeft;
  var nYPos = getMouseY(e) - g_nMapDivTop;
  //make ypos from bottom of image up, not from top down
  //nYPos = g_nMapHeight - nYPos;
  var fXMapPos = convertScreenXToMapX(nXPos);
  var fYMapPos = convertScreenYToMapY(nYPos);

  if (g_bOkToGetMap == true){
    switch (g_sCurrentTool){
    case "placeText":
      var bOkToPlaceText = true;
      document.getElementById("txtLabelCoords").value = Math.round(fXMapPos) + "," + Math.round(fYMapPos);

      var sText = document.getElementById("txtLabelText").value;

      var sBlockout = document.getElementById("txtBackgroundColor").value;
      if (sBlockout != ""){
        sBlockout = HexToR(sBlockout) + "," + HexToG(sBlockout) + "," + HexToB(sBlockout);
      }

      var fontElem = document.getElementById("lstFont");
      var sFont = fontElem.options[fontElem.selectedIndex].value;

      var sFontColor = document.getElementById("txtFontColor").value;
      sFontColor = HexToR(sFontColor) + "," + HexToG(sFontColor) + "," + HexToB(sFontColor);

      var nFontSize = document.getElementById("txtFontSize").value;

      var fontStyleElem = document.getElementById("lstFontStyle");
      var sFontStyle = fontStyleElem.options[fontStyleElem.selectedIndex].value;

      var hAlignElem = document.getElementById("lstHAlign");
      var sHAlign = hAlignElem.options[hAlignElem.selectedIndex].value;

      var sOutline = document.getElementById("txtOutlineColor").value;
      if(sOutline != ""){
        sOutline = HexToR(sOutline) + "," + HexToG(sOutline) + "," + HexToB(sOutline);
      }

      var vAlignElem = document.getElementById("lstVAlign");
      var sVAlign = vAlignElem.options[vAlignElem.selectedIndex].value;


      if (isNaN(nFontSize)){
        alert("Font size invalid");
        bOkToPlaceText = false;
      }

      if (bOkToPlaceText == true){
        var aLabel = new Array();
        aLabel["layerId"] = "acetateLayer" + g_aAcetateLabels.length;
        aLabel["xpos"] = Math.round(fXMapPos);
        aLabel["ypos"] = Math.round(fYMapPos);
        aLabel["labelText"] = sText;
        aLabel["blockout"] = sBlockout;
        aLabel["font"] = sFont;
        aLabel["fontColor"] = sFontColor;
        aLabel["fontSize"] = nFontSize;
        aLabel["fontStyle"] = sFontStyle;
        aLabel["halign"] = sHAlign;
        aLabel["outline"] = sOutline;
        aLabel["valign"] = sVAlign;


        g_aAcetateLabels[g_aAcetateLabels.length] = aLabel;
        loadMap();
      }

      break;

    case "placeMarker":
      var bOkToPlaceMarker = true;
      var markerTypeElem = document.getElementById("lstMarker");
      var sMarkerType = markerTypeElem.options[markerTypeElem.selectedIndex].value;
      var nWidth = document.getElementById("txtMarkerWidth").value;

      var sColor = document.getElementById("txtMarkerColor").value;
      if (sColor != ""){
        sColor = HexToR(sColor) + "," + HexToG(sColor) + "," + HexToB(sColor);
      }

      var sOutline = document.getElementById("txtMarkerOutline").value;
      if (sOutline != ""){
        sOutline = HexToR(sOutline) + "," + HexToG(sOutline) + "," + HexToB(sOutline);
      }

      if (isNaN(nWidth)){
        bOkToPlaceMarker = false;
        alert("Invalid marker width");
      }

      if (bOkToPlaceMarker == true){
        var aMarker = new Array();
        aMarker["type"] = sMarkerType;
        aMarker["width"] = nWidth;
        aMarker["outline"] = sOutline;
        aMarker["color"] = sColor;
        aMarker["layerId"] = "acetateMarker" + g_aAcetateMarkers.length;
        aMarker["xpos"] = Math.round(fXMapPos);
        aMarker["ypos"] = Math.round(fYMapPos);

        g_aAcetateMarkers[g_aAcetateMarkers.length] = aMarker;
        loadMap();
      }
      break;

    case "zoomInBox":
      //the Y values for image are a distance from the top, need to be from bottom
      var fBoxMinX = g_MapWindow.getMinX();
      var fBoxMinY = g_MapWindow.getMaxY(); //must use maxY because event y is from top down
      var fBoxMaxX = g_MapWindow.getMaxX();
      var fBoxMaxY = g_MapWindow.getMinY(); //must use minY because event y is from top down

      //check for single click zoom if so then perform a fixed zoom in
      if (fBoxMinX == fBoxMaxX && fBoxMinY == fBoxMaxY){
        var fNewXDist = ((g_fMaxX - g_fMinX) * g_fZoomFactor);
        var fNewYDist = fNewXDist / g_fMapAspectRatio;
        g_fMinX = fXMapPos - (fNewXDist / 2);
        g_fMinY = fYMapPos - (fNewYDist / 2);
        g_fMaxX = fXMapPos + (fNewXDist / 2);
        g_fMaxY = fYMapPos + (fNewYDist / 2);
      } else {
        var fBoxXDist = (fBoxMaxX - fBoxMinX);
        var fBoxYDist = (fBoxMaxY - fBoxMinY);
        var fBoxCenterX = fBoxMinX + ((fBoxMaxX - fBoxMinX) / 2);
        var fBoxCenterY = fBoxMinY + ((fBoxMaxY - fBoxMinY) / 2);

        /* 2007_03_27 - updated this to use compare aspect ratio of zoom box and map aspect ratio
        //if xdist is greater than ydist, use xdist and calc ydist based on aspect ratio
        //else -  use ydist and calc xdist based on aspect ratio
        if(Math.abs(fBoxXDist) >= Math.abs(fBoxYDist)){
          fBoxMinY = fBoxCenterY - ((fBoxXDist / g_fMapAspectRatio) / 2);
          fBoxMaxY = fBoxCenterY + ((fBoxXDist / g_fMapAspectRatio) / 2);
        } else {
          fBoxMinX = fBoxCenterX - ((fBoxYDist * g_fMapAspectRatio) / 2);
          fBoxMaxX = fBoxCenterX + ((fBoxYDist * g_fMapAspectRatio) / 2);
        }*/

        //compare aspect ration of map (R) to aspect ratio of zoom box (Z)
        //if Z < R => newWidth = R * H
        //if Z > R => newHeight = W / R
        var R = g_fMapAspectRatio;
        var Z = Math.abs(fBoxXDist / fBoxYDist);

        if (Z >= R){
          fNewYDist = Math.abs(fBoxXDist / R);
          fBoxMinY = fBoxCenterY - (fNewYDist / 2);
          fBoxMaxY = fBoxCenterY + (fNewYDist / 2);
        } else {
          fNewXDist = Math.abs(R * fBoxYDist);
          fBoxMinX = fBoxCenterX - (fNewXDist / 2);
          fBoxMaxX = fBoxCenterX + (fNewXDist / 2);
        }

        var fNewMinX = convertScreenXToMapX(fBoxMinX);
        var fNewMaxX = convertScreenXToMapX(fBoxMaxX);
        var fNewMinY = convertScreenYToMapY(fBoxMinY);
        var fNewMaxY = convertScreenYToMapY(fBoxMaxY);
        g_fMinX = fNewMinX;
        g_fMaxX = fNewMaxX;
        g_fMinY = fNewMinY;
        g_fMaxY = fNewMaxY;
      }

      loadMap();
      break;

    case "zoomInFixed":
      var fNewXDist = ((g_fMaxX - g_fMinX) * g_fZoomFactor);
      var fNewYDist = fNewXDist / g_fMapAspectRatio;
      var fCenterPointX = g_fMinX + ((g_fMaxX - g_fMinX) / 2);
      var fCenterPointY = g_fMinY + ((g_fMaxY - g_fMinY) / 2);
      g_fMinX = fCenterPointX - (fNewXDist / 2);
      g_fMinY = fCenterPointY - (fNewYDist / 2);
      g_fMaxX = fCenterPointX + (fNewXDist / 2);
      g_fMaxY = fCenterPointY + (fNewYDist / 2);
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "zoomOutFixed":
      var fNewXDist = ((g_fMaxX - g_fMinX) / g_fZoomFactor);
      var fNewYDist = fNewXDist / g_fMapAspectRatio;
      var fCenterPointX = g_fMinX + ((g_fMaxX - g_fMinX) / 2);
      var fCenterPointY = g_fMinY + ((g_fMaxY - g_fMinY) / 2);
      g_fMinX = fCenterPointX - (fNewXDist / 2);
      g_fMinY = fCenterPointY - (fNewYDist / 2);
      g_fMaxX = fCenterPointX + (fNewXDist / 2);
      g_fMaxY = fCenterPointY + (fNewYDist / 2);
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;


    case "clearSelection":
      g_nSelectCount = 0;
      g_sSelectedFeaturesSpatialQuery = "";
      var resultsElem = document.getElementById("resultsContentsDiv");
      resultsElem.innerHTML = "";
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "zoomFullExtent":
      g_fMinX = g_fActualStartMinX;
      g_fMinY = g_fActualStartMinY;
      g_fMaxX = g_fActualStartMaxX;
      g_fMaxY = g_fActualStartMaxY;
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "refreshMap":
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "panNorth":
      var bumpDist = (g_fMaxY - g_fMinY) * g_fBumpPanPct;
      g_fMinY = g_fMinY + bumpDist;
      g_fMaxY = g_fMaxY + bumpDist;
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "panSouth":
      var bumpDist = (g_fMaxY - g_fMinY) * g_fBumpPanPct;
      g_fMinY = g_fMinY - bumpDist;
      g_fMaxY = g_fMaxY - bumpDist;
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "panEast":
      var bumpDist = (g_fMaxX - g_fMinX) * g_fBumpPanPct;
      g_fMinX = g_fMinX + bumpDist;
      g_fMaxX = g_fMaxX + bumpDist;
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "panWest":
      var bumpDist = (g_fMaxX - g_fMinX) * g_fBumpPanPct;
      g_fMinX = g_fMinX - bumpDist;
      g_fMaxX = g_fMaxX - bumpDist;
      setActiveTool(g_sPreviousTool);
      loadMap();
      break;

    case "slideZoom":
      slideZoomMap();
      break;

    case "selectFeatures":

      //verify that thet selectable layer is visible
      var bIsVis = isSelectableLayerVisibleAtCurrentScale();

      if (bIsVis == false){
        alert("Selectable layer (" + g_sSelectableLayer + ") is not visible at current scale.\nZoom to a scale where layer is visible.");
        break;
      }

      //build get features string based on selectable layer
      //the Y values for image are a distance from the top, need to be from bottom
      var fBoxMinX = g_MapWindow.getMinX();
      var fBoxMinY = g_MapWindow.getMaxY(); //must use maxY because event y is from top down
      var fBoxMaxX = g_MapWindow.getMaxX();
      var fBoxMaxY = g_MapWindow.getMinY(); //must use minY because event y is from top down

      var sSpatialQuery = "";

      sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '">\n' +
                '<SPATIALFILTER relation="area_intersection">\n';

      var fSelectMinX = convertScreenXToMapX(fBoxMinX);
      var fSelectMaxX = convertScreenXToMapX(fBoxMaxX);
      var fSelectMinY = convertScreenYToMapY(fBoxMinY);
      var fSelectMaxY = convertScreenYToMapY(fBoxMaxY);

      //verify that the maxX and minX are different - if not make them different
      if (fSelectMinX == fSelectMaxX){
        fSelectMinX = fSelectMinX - 1;
        fSelectMaxX = fSelectMaxX + 1;
      }
      //verify that the maxY and minY are different - if not make them different
      if (fSelectMinY == fSelectMaxY){
        fSelectMinY = fSelectMinY - 1;
        fSelectMaxY = fSelectMaxY + 1;
      }

      sSpatialQuery += '<ENVELOPE minx="' + parseFloat(fSelectMinX) + '" miny="' + parseFloat(fSelectMinY) + '" maxx="' + parseFloat(fSelectMaxX) + '" maxy="' + parseFloat(fSelectMaxY) + '" />\n';


      sSpatialQuery += '</SPATIALFILTER>\n' +
            '</SPATIALQUERY>\n';
      g_sSelectedFeaturesSpatialQuery = sSpatialQuery;
      g_nSelectedFeaturesLayerIdx = getSelectableLayerID();
      getFeatures(sSpatialQuery,0,false,false);
      break;

    case "radiusSelect":
      var fXMapPos = convertScreenXToMapX(nXPos);
      var fYMapPos = convertScreenYToMapY(nYPos);
      var nRadius = document.getElementById("txtRadiusDistance").value;
      var sPoints = "";
      var sReq = "";

      var radiusElem = document.getElementById("lstRadiusLayer");
      var sRadiusTargetLayer = radiusElem.options[radiusElem.selectedIndex].value;
      g_sRadiusColor = document.getElementById("txtRadiusColor").value;
      var sRadiusColorRGB = HexToR(g_sRadiusColor) + "," + HexToG(g_sRadiusColor) + "," + HexToB(g_sRadiusColor);
      var nRadiusThickness = document.getElementById("txtRadiusThickness").value;

      if (isNaN(nRadius)){
        alert("Invalid radius distance.");
        return;
      }

      if (isNaN(nRadiusThickness)){
        alert("Invalid radius thickness.");
        return;
      }

      //add radius to x to get start point in center
      fXMapPos = parseFloat(fXMapPos + parseFloat(nRadius));
      var aPoints = buildCirclePoints(fXMapPos,fYMapPos,nRadius,0,360,360);

      //build point string from array of circle points
      for (var i = 0; i < aPoints.length; i++) {
        sPoints +=  '<POINT x="' + parseFloat(aPoints[i][0]) + nRadius + '" y="' + aPoints[i][1] + '" />\n';
      }
      // draw the circle
      sReq = '<LAYER type="acetate" name="radiusPoint1">\n';
      sReq += '<OBJECT units="database">\n';
      sReq += '<SIMPLELINESYMBOL color="' + sRadiusColorRGB + '" width="' + nRadiusThickness + '" />\n';
      sReq += '<POLYLINE>\n<PATH>\n';

      //this code creates a diamond around point as alternate to circle
      /*sReq += '<POINT x="' + parseFloat(geocodeX) + nRadius + '" y="' + geocodeY + '" />\n';
      sReq += '<POINT x="' + parseFloat(geocodeX) + '" y="' + parseFloat(geocodeY) - nRadius) + '" />\n';
      sReq += '<POINT x="' + parseFloat(geocodeX) - nRadius + '" y="' + forceComma(geocodeY) + '" />\n';
      sReq += '<POINT x="' + geocodeX + '" y="' + parseFloat(geocodeY) + nRadius + '" />\n';
      sReq += '<POINT x="' + parseFloat(geocodeX) + nRadius + '" y="' + geocodeY + '" />\n';
      */

      sReq += sPoints;
      sReq += '</PATH>\n</POLYLINE>\n</OBJECT>/n</LAYER>';
      g_sDrawRadiusXML = sReq;

      //perform query using circle if needed
      if (sRadiusTargetLayer.indexOf('No Layer') == -1){
        g_sSelectableLayer = sRadiusTargetLayer;
        g_nSelectedFeaturesLayerIdx = getLayerID(sRadiusTargetLayer);
        changeSelectableLayer(sRadiusTargetLayer);
        sReq = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '">\n';
        sReq += '<SPATIALFILTER relation="area_intersection">\n';
        sReq += '<POLYGON>\n';
        sReq += '<RING>\n';
        sReq += sPoints;
        sReq += '</RING>\n';
        sReq += '</POLYGON>\n';
        sReq += '</SPATIALFILTER>\n';
        sReq += '</SPATIALQUERY>\n';
        g_sSelectedFeaturesSpatialQuery = sReq;
        getFeatures(sReq,0,false,false);
      } else {
        loadMap();
      }

      break;
    }

  }

}

function getMouseX(e) {
    if(navigator.userAgent.search("Opera(\ |\/)6") != -1 ){   //o6
        return e.clientX;
  }else if(document.all){
        //e4,e5,e6
        return document.documentElement.scrollLeft+e.clientX;
    }else if(document.layers || document.getElementById){
    //n4,n6,n7,m1,o7,s1
        return e.pageX;
  }
}

function getMouseY(e) {
    if(navigator.userAgent.search("Opera(\ |\/)6") != -1 ){
    //o6
    return e.clientY;
    }else if(document.all){
    //e4,e5,e6
        return document.documentElement.scrollTop+e.clientY;
  } else if(document.layers || document.getElementById){
    //n4,n6,n7,m1,o7,s1
        return e.pageY;
  }
}

function HexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
function HexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
function HexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}

function hideDiv(sDiv){
  //Effect.Fade(sDiv);
  var elemDiv = document.getElementById(sDiv);
  elemDiv.style.display = "none";
}

function hideMsg(){
  new Effect.Fade("msgDiv")

}

function makeDivTop(sDiv){
  for(i=0; i<document.elements.length; i++){
     alert(document.elements[i].name)
  }
}

function makeLayerVisible(sLayer){
  var nLoopCounter = 0;

  for (nLoopCounter = 0;nLoopCounter < g_aLayersArray.length;nLoopCounter++){
    //when a match is found and layer vis is false then toggle the layer visiblity
    if (g_aLayersArray[nLoopCounter]["layerName"] == sLayer){
      if(g_aLayersArray[nLoopCounter]["visible"] == "false"){
        toggleLayer(sLayer,false);
      }
    }
  }

}

function mapDblClick(){
  var resultsElem = document.getElementById("measureResults");
  resultsElem.innerHTML = "Distance - Total: " + (Math.round((g_fTotalDistance) * 100) / 100);
  clearMeasurePoints();
}

function mapMouseDown(e){
  g_bMouseDown = true;
  var nXPos = getMouseX(e) - g_nMapDivLeft;
  var nYPos = getMouseY(e) - g_nMapDivTop;

  g_MapWindow.X1 = nXPos;
  g_MapWindow.Y1 = nYPos;
  g_MapWindow.X2 = nXPos;
  g_MapWindow.Y2 = nYPos;

  //reset pan offset variables
  g_nPanOffsetX = 0;
  g_nPanOffsetY = 0;
  g_nPanStartX = nXPos;
  g_nPanStartY = nYPos;

  switch(g_sCurrentTool){
  case "measureDistance":
    g_aXPoints[g_aXPoints.length] = nXPos;
    g_aYPoints[g_aYPoints.length] = nYPos;
    g_nStretchPointIdx = g_aXPoints.length - 1;
    calcTotalDistance();
    break;
  }
}

function mapMouseMove(e){
  displayCoords(e);


  var nXPos = getMouseX(e) - g_nMapDivLeft;
  var nYPos = getMouseY(e) - g_nMapDivTop;


  g_MapWindow.X2 = nXPos;
  g_MapWindow.Y2 = nYPos;

  var nZoomwinLeft = g_MapWindow.getMinX();
  var nZoomwinTop = g_MapWindow.getMinY();
  var nZoomwinWidth = g_MapWindow.getWidth();
  var nZoomwinHeight = g_MapWindow.getHeight();


  //check to see if current tool needs graphics made on mouse move
  switch (g_sCurrentTool){
  case "zoomInBox":
  case "selectFeatures":
    if (g_bOkToGetMap == true){
      if (g_bMouseDown == true){
        g_jg.clear();
        g_jg.setColor(g_sZoomBoxColor);
        g_jg.setStroke(3);
        g_jg.drawRect(nZoomwinLeft-1, nZoomwinTop-1, nZoomwinWidth-1, nZoomwinHeight-1);
        g_jg.paint();
      }
    }
    break;
  case "panRealtime":
    if (g_bOkToGetMap == true){
      if (g_bMouseDown == true){
        g_nPanOffsetX = (nXPos - g_nPanStartX);
        g_nPanOffsetY = (nYPos - g_nPanStartY);

        var mapImgElem = document.getElementById("mapDivImg");
        mapImgElem.style.left = g_nPanOffsetX + "px";
        mapImgElem.style.top = g_nPanOffsetY + "px";
      }
    }
    break;
  case "measureDistance":
    g_aXPoints[g_nStretchPointIdx] = nXPos;
    g_aYPoints[g_nStretchPointIdx] = nYPos;
    g_jg.clear();
    g_jg.setColor(g_sMeasureColor);
    g_jg.setStroke(2);
    g_jg.drawPolyline(g_aXPoints,g_aYPoints);
    g_jg.paint();
    calcSegmentDistance();
    break;
  }

}

function mapMouseUp(e){
  g_bMouseDown = false;

  if(g_sCurrentTool != "measureDistance"){
    g_jg.clear();
  }

  if (g_sCurrentTool == "panRealtime"){
    if (g_bOkToGetMap == true){
      var nXPos = getMouseX(e) - g_nMapDivLeft;
      var nYPos = getMouseY(e) - g_nMapDivTop;
      var fXMapPos = convertScreenXToMapX(nXPos);
      var fYMapPos = convertScreenYToMapY(nYPos);
      var fMapStartPanX = convertScreenXToMapX(g_nPanStartX);
      var fMapStartPanY = convertScreenYToMapY(g_nPanStartY);

      g_fMinX = g_fMinX - (fXMapPos - fMapStartPanX);
      g_fMinY = g_fMinY - (fYMapPos - fMapStartPanY);
      g_fMaxX = g_fMaxX - (fXMapPos - fMapStartPanX);
      g_fMaxY = g_fMaxY - (fYMapPos - fMapStartPanY);

      loadMap();
    }
  } else {
    doCurrentTool(e);
  }
  hideMsg();
}

function ovMapMouseDown(e){
  //pan map to center on point selected on ov map
  if (g_bOkToGetMap == true){
    var nXPos = getMouseX(e) - g_nMapDivLeft;
    var nYPos = getMouseY(e) - g_nMapDivTop;
    var fXOVMapPos = convertOVScreenXToMapX(nXPos);
    var fYOVMapPos = convertOVScreenYToMapY(nYPos);
    var fXDist = (g_fMaxX - g_fMinX);
    var fYDist = (g_fMaxY - g_fMinY);

    g_fMinX = fXOVMapPos - (fXDist / 2);
    g_fMaxX = fXOVMapPos + (fXDist / 2);
    g_fMinY = fYOVMapPos - (fYDist / 2);
    g_fMaxY = fYOVMapPos + (fYDist / 2);
    loadMap();
  }

}

function openHelpWindow(){
  var myWin = window.open("../help/index.php","_blank","width=900,height=600,location=yes,menubar=yes,resizable=yes,scrollbars=yes,status=yes,toolbar=yes");

}

function parseEntity(oldString) {
  //alert(oldString);
  oldString = oldString.replace(/&apos;/g, "'");
  oldString = oldString.replace(/&gt;/g, ">");
  oldString = oldString.replace(/&lt;/g, "<");
  oldString = oldString.replace(/&quot;/g, '"');
  oldString = oldString.replace(/&amp;/g, "&");
  //alert(oldString);
  /*
  oldString = swapStuff(oldString,"&apos;","'");
  oldString = swapStuff(oldString,"&divide;","/");
  oldString = swapStuff(oldString,"&ge;",">=");
  oldString = swapStuff(oldString,"&gt;",">");
  oldString = swapStuff(oldString,"&le;","<=");
  oldString = swapStuff(oldString,"&lt;","<");
  oldString = swapStuff(oldString,"&ne;","<>");
  oldString = swapStuff(oldString,"&quot;",'"');
  oldString = swapStuff(oldString,"&amp;","&");
  */

  return oldString;
}

function populateBufferForm(){
  document.getElementById("txtMapUnits").innerHTML = g_aProperties["mapUnitsDisplay"];
  document.getElementById("txtBufferTargetText").innerHTML = "<b>" + g_sSelectableLayer + "</b>  features.";
}

function populateLegendSettings(){
  document.getElementById("txtLegendTitle").value = g_sLegendTitle;
  document.getElementById("txtLegendTitleFontSize").value = g_nLegendTitleFontSize;
  document.getElementById("txtLegendBackColor").value = g_sLegendBackColor;
  document.getElementById("backgroundSwatch").style.background = g_sLegendBackColor;
  document.getElementById("txtLegendLayerFontSize").value = g_nLegendLayerFontSize;
  document.getElementById("txtLegendSwatchHeight").value = g_nLegendSwatchHeight;
  document.getElementById("txtLegendSwatchWidth").value = g_nLegendSwatchWidth;
  document.getElementById("txtLegendValueFontSize").value = g_nLegendValueFontSize;
}

function populateRadiusSelectForm(){
  document.getElementById("txtRadiusMapUnits").innerHTML = g_aProperties["mapUnitsDisplay"];
  document.getElementById("txtRadiusColor").value = g_sRadiusColor;
  document.getElementById("radiusColorSwatch").style.background = g_sRadiusColor;
}


function populateZoomToScaleBox(){
  document.getElementById("zoomToScaleValue").value = g_sMapScale.substr(2,(g_sMapScale.length - 2));
}


function resizeMap(){

  var factorElem = document.getElementById("sliderValue");
  var nFactor = factorElem.value;

  if (nFactor != g_nMapSizeFactor){
    g_nMapSizeFactor = nFactor;
    nFactor = 1 + (nFactor / 10);
    var mapElem = document.getElementById("mapDiv");

    g_nMapWidth = g_nStartingMapWidth * nFactor;
    g_nMapHeight = g_nStartingMapHeight * nFactor;
    mapElem.style.width = g_nMapWidth + "px";
    mapElem.style.height = g_nMapHeight + "px";

    //reposition scalebar
    var scaleBarDivElem = document.getElementById("scaleBarImgDiv");
    scaleBarDivElem.style.top = (g_nMapHeight + 80) + "px";

    //reposition msgdiv
    var msgElem = document.getElementById("msgDiv");
    msgElem.style.top = (g_nMapHeight + 80) + "px";

    loadMap();
  }

}

function replaceChars(sString){
  sString = sString.replace("&","&amp;");
  sString = sString.replace("\"","&quot;");
  sString = sString.replace("'","''");
  sString = sString.replace(">","&gt;");
  sString = sString.replace("<","&lt;");
  return sString;
}

function searchOtherPinLayers(){

  g_sSearchLayer = g_aPINLayers[g_nPINLayerIdx]["layerName"];
  g_sSelectableLayer = g_sSearchLayer;
  changeSelectableLayer(g_sSearchLayer);
  g_sSearchField = g_aPINLayers[g_nPINLayerIdx]["pinField"];
  g_nPINLayerIdx = g_nPINLayerIdx + 1;

  sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' LIKE \'' + g_sSearchValue + '%\'"></SPATIALQUERY>\n';
  g_sSelectedFeaturesSpatialQuery = sSpatialQuery;
  g_nSelectedFeaturesLayerIdx = getSelectableLayerID();
  getFeatures(sSpatialQuery,0,false,false);
}

function searchParcels(){
  var sSpatialQuery = "";
  g_sSearchLayer = g_sParcelLayerName;
  g_sSearchField = g_sParcelPinField;
  g_sSearchValue = document.getElementById("searchPin").value;
  g_sSearchValue = g_sSearchValue.trim();

  if ((g_sSearchLayer != "") && (g_sSearchField != "")&& (g_sSearchValue != "")){
    g_sSelectableLayer = g_sSearchLayer;
    changeSelectableLayer(g_sSearchLayer);
    sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' LIKE \'' + g_sSearchValue + '%\'"></SPATIALQUERY>\n';
    g_sSelectedFeaturesSpatialQuery = sSpatialQuery;
    g_nSelectedFeaturesLayerIdx = getSelectableLayerID();
    g_bSearchingPinLayers = true;
    getFeatures(sSpatialQuery,0,false,false);
  } else {
    alert("Missing search criteria.\nMake sure a search layer, search field, and search value are specified.");
  }

}

function searchLayers(){
  var sSpatialQuery = "";
  var searchLayerElem = document.getElementById("searchLayer");
  var searchFieldElem = document.getElementById("searchField");
  var searchValueElem = document.getElementById("searchValue");

  g_sSearchLayer = searchLayerElem.options[searchLayerElem.selectedIndex].value;
  g_sSearchField = searchFieldElem.options[searchFieldElem.selectedIndex].value;
  g_sSearchValue = searchValueElem.value;
  g_sSearchValue = g_sSearchValue.trim();
  g_sSearchValue = replaceChars(g_sSearchValue);

  if (g_bUseCaseInsensitiveTweak) {
    //Case-insensitive tweak [Eric - 2008-03-14]
    g_sSearchField = "UPPER(" + g_sSearchField + ")";
    g_sSearchValue = g_sSearchValue.toUpperCase();
  }

  if ((g_sSearchLayer != "") && (g_sSearchField != "")&& (g_sSearchValue != "")){
    g_sSelectableLayer = g_sSearchLayer;
    changeSelectableLayer(g_sSearchLayer);

    switch(g_sSearchCriteria){
      case "beginsWith":
        sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' LIKE \'' + g_sSearchValue + '%\'"></SPATIALQUERY>\n';
        break;
      case "endsWith":
        sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' LIKE \'%' + g_sSearchValue + '\'"></SPATIALQUERY>\n';
        break;
      case "contains":
        sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' LIKE \'%' + g_sSearchValue + '%\'"></SPATIALQUERY>\n';
        break;
      case "exactMatch":
        sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sSearchField + ' = \'' + g_sSearchValue + '\'"></SPATIALQUERY>\n';
        break;
    }

    g_sSelectedFeaturesSpatialQuery = sSpatialQuery;
    g_nSelectedFeaturesLayerIdx = getSelectableLayerID();
    getFeatures(sSpatialQuery,0,false,false);
  } else {
    alert("Missing search criteria.\nMake sure a search layer, search field, and search value are specified.");
  }
}


function setSearchCriteria(){
  var criteriaElem = document.getElementById("searchCriteria");
  g_sSearchCriteria = criteriaElem.options[criteriaElem.selectedIndex].value;
}

function setSearchValue(){
  var searchElem = document.getElementById("searchValue");
  g_sSearchValue = searchElem.value;
}

function setSearchField(){
  var searchElem = document.getElementById("searchField");
  g_sSearchField = searchElem.options[searchElem.selectedIndex].value;
}

function setSearchLayer(){
  var searchElem = document.getElementById("searchLayer");
  g_sSearchLayer = searchElem.options[searchElem.selectedIndex].value;
  buildSearchFieldList();
}

function setSelectableLayer(){
  var selElem = document.getElementById("selectableLayer");
  g_sSelectableLayer = selElem.options[selElem.selectedIndex].value;
  document.getElementById("txtBufferTargetText").innerHTML = "<b>" + g_sSelectableLayer + "</b>  features.";
  makeLayerVisible(g_sSelectableLayer);

}

function setActiveTool(sTool){
  //set border of all tools to nothing
  document.getElementById("zoomInBox").style.border = "1px solid #ffffff";
  document.getElementById("zoomInFixed").style.border = "1px solid #ffffff";
  document.getElementById("zoomOutFixed").style.border = "1px solid #ffffff";
  document.getElementById("zoomFullExtent").style.border = "1px solid #ffffff";
  document.getElementById("clearSelection").style.border = "1px solid #ffffff";
  document.getElementById("refreshMap").style.border = "1px solid #ffffff";
  document.getElementById("selectFeatures").style.border = "1px solid #ffffff";
  document.getElementById("panNorth").style.border = "1px solid #ffffff";
  document.getElementById("panSouth").style.border = "1px solid #ffffff";
  document.getElementById("panEast").style.border = "1px solid #ffffff";
  document.getElementById("panWest").style.border = "1px solid #ffffff";
  document.getElementById("panRealtime").style.border = "1px solid #ffffff";
  document.getElementById("measureDistance").style.border = "1px solid #ffffff";

  setMouseCursor(sTool);
  //make sure measure results div is not visible
  document.getElementById("measureResultsDiv").style.display = "none";

  if (sTool == "measureDistance"){
    toggleDiv("measureResultsDiv");
  }

  //set border to active tool color if needed
  if (sTool != "slideZoom" && sTool != "placeText" && sTool != "placeMarker" && sTool != "selectBufferPoint" && sTool != "radiusSelect"){
    document.getElementById(sTool).style.border = "1px solid " + g_sActiveToolColor;
  }

  g_sCurrentTool = sTool;

  //remember previous tool only if it is a tool that requires repetitive map interaction
  if (g_sCurrentTool == "zoomInBox" || g_sCurrentTool == "panRealtime" || g_sCurrentTool == "selectFeatures" || g_sCurrentTool == "measureDistance"){
    g_sPreviousTool = g_sCurrentTool;
  }


}
function setMouseCursor(sTool){
  var mapElem = document.getElementById("mapDiv");

  switch(sTool){
    case "selectFeatures":
      mapElem.style.cursor = "help";
      break;
    case "panRealtime":
      mapElem.style.cursor = "move";
      break;
    default:
      mapElem.style.cursor = "crossHair";
  }

}
function showMsg(sMsg){
  var msgElem = document.getElementById("msgDiv");
  var msgTxtElem = document.getElementById("msgTxt");
  msgTxtElem.innerHTML = sMsg;
  msgElem.style.display = "block";
  msgElem.style.opacity = "1.0";
  new Effect.Pulsate("msgDiv",{duration:2.0, pulses:2});

}


function slideZoomMap(){
  if (g_bOkToGetMap == true){
    var slideZoomElem = document.getElementById("zoomSliderValue");
    var nFactor = 100 - parseInt(slideZoomElem.value);
    var fZoomPct = parseFloat(nFactor / 100);

    //factor range 1 - 100; 100 = full extent 1 = fully zoomed in
    var xDistRange = (g_fActualStartMaxX - g_fActualStartMinX);
    var yDistRange = (g_fActualStartMaxY - g_fActualStartMinY);

    if(fZoomPct == 0){
      var fNewXDist = g_nSmallestXDist;
      var fNewYDist = fNewXDist / g_fMapAspectRatio;
    } else {
      var fNewXDist = xDistRange * fZoomPct;
      var fNewYDist = yDistRange * fZoomPct;
    }

    //var fNewYDist = fNewXDist / g_fMapAspectRatio;
    var fCenterPointX = g_fMinX + ((g_fMaxX - g_fMinX) / 2);
    var fCenterPointY = g_fMinY + ((g_fMaxY - g_fMinY) / 2);
    g_fMinX = fCenterPointX - parseFloat(fNewXDist / 2);
    g_fMinY = fCenterPointY - parseFloat(fNewYDist / 2);
    g_fMaxX = fCenterPointX + parseFloat(fNewXDist / 2);
    g_fMaxY = fCenterPointY + parseFloat(fNewYDist / 2);
    loadMap();
    setActiveTool(g_sPreviousTool);
  }
}

function toggleCloseButton(buttonElem){
  //alert (buttonElem.src);
  if (buttonElem.src.indexOf("close_off.png") != -1){
    buttonElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/close_on.png";
  } else {
    buttonElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/close_off.png";
  }
}

function toggleDiv(sDiv){
  var elemDiv = document.getElementById(sDiv);
  if(!(elemDiv == undefined)){
    if (elemDiv.style.display == "none"){
      elemDiv.style.display = "block";
      //Effect.Appear(sDiv);

      if (sDiv == "advTextSettings"){
        var settingsElem = document.getElementById("addTextDiv");
        settingsElem.style.height = "390px";
      }

      if (sDiv == "legendDiv"){
        populateLegendSettings();
        createLegend();
        g_bLegendVisible = true;
      }

    } else {
      elemDiv.style.display = "none";
      //Effect.Fade(sDiv);

      if (sDiv = "advTextSettings"){
        var settingsElem = document.getElementById("addTextDiv");
        settingsElem.style.height = "250px";
      }

      if (sDiv == "legendDiv"){
        g_bLegendVisible = false;
      }
    }
  }
}

function toggleGroupLayer(sGroupLayerId,sGroupLayerName){
  //loop through global layer array
  //for each layer with parentid that matches sGroupLayerId
  //toggle it's display
  //N.B. - does not change the layer's visibility on map, just simulates the expanding of layer
  //toggle expanded property of group layer

  var nLoopCounter = 0;
  var sLayerName = "";

  for (nLoopCounter = 0;nLoopCounter < g_aLayersArray.length;nLoopCounter++){
    if(g_aLayersArray[nLoopCounter]["parentLayerId"] == sGroupLayerId){
      sLayerName = "layer" + g_aLayersArray[nLoopCounter]["layerName"];
      var elemLayer = document.getElementById(sLayerName);
      if(!(elemLayer == undefined)){
        if (elemLayer.style.display == "none"){
          elemLayer.style.display = "block";
        } else {
          elemLayer.style.display = "none";
        }
      }
    }

    if(g_aLayersArray[nLoopCounter]["layerName"] == sGroupLayerName){
      g_aLayersArray[nLoopCounter]["expanded"] = !g_aLayersArray[nLoopCounter]["expanded"]
    }
  }

  //for the group layer, toggle the expand/collapse button
  var expandImgElem = document.getElementById("expandGroup" + sGroupLayerName);
  if (expandImgElem.src.indexOf("button_expand.png") != -1){
    expandImgElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_collapse.png";
    expandImgElem.alt = "Collapse Group Layer";
    expandImgElem.title = "Collapse Group Layer";
  } else {
    expandImgElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_expand.png";
    expandImgElem.alt = "Expand Group Layer";
    expandImgElem.title = "Expand Group Layer";
  }

}

function toggleLayer(sLayerName,bRedraw){
  var aGrouplayers = new Array();
  var aLayer = new Array();

  var bIsGroupLayer = false;

  var nLoopCounter = 0;
  var nLoopCounter2 = 0;
  var nLoopCounter3 = 0;

  var sGroupedLayerName = "";
  var sCompareName = "";

  //if layer to be toggled is a sublayer, then set layer = group layer the group layer so all
  //sublayers are toggled
  //2007_09_26 the next section of code is no longer needed after arcims 9.2
  /*
  for(nLoopCounter = 0;nLoopCounter < g_aGroupedLayers.length;nLoopCounter++){
    aGroupLayers = g_aGroupedLayers[nLoopCounter];
    for(nLoopCounter2 = 1;nLoopCounter2 < aGroupLayers.length;nLoopCounter2++){
      if(aGroupLayers[nLoopCounter2] == sLayerName){
        sLayerName = aGroupLayers[0];
      }
    }
  }


  //loop through grouped layers to see if layer to be toggled is a group layer
  for(nLoopCounter = 0;nLoopCounter < g_aGroupedLayers.length;nLoopCounter++){
    aGroupLayers = g_aGroupedLayers[nLoopCounter];
    //if layer to be toggled is a grouped layer, then toggle all sub layers
    if (aGroupLayers[0] == sLayerName){
      bIsGroupLayer = true;
      for(nLoopCounter2 = 0; nLoopCounter2 < aGroupLayers.length; nLoopCounter2++){
        sGroupedLayerName = aGroupLayers[nLoopCounter2];
        for (nLoopCounter3 = 0;nLoopCounter3 < g_aLayersArray.length;nLoopCounter3++){
          //when a match is found toggle the layer visiblity
          if (g_aLayersArray[nLoopCounter3]["layerName"] == sGroupedLayerName){
            if (g_aLayersArray[nLoopCounter3]["visible"] == "false"){
              g_aLayersArray[nLoopCounter3]["visible"] = "true";
            } else {
              g_aLayersArray[nLoopCounter3]["visible"] = "false";
            }
          }
        }
      }
    }
  }
  */

  if (!bIsGroupLayer){
    //loop through all layers in layers array
    for (nLoopCounter = 0;nLoopCounter < g_aLayersArray.length;nLoopCounter++){
      //when a match is found toggle the layer visiblity
      sCompareName = parseEntity(g_aLayersArray[nLoopCounter]["layerName"]);
      if (sCompareName == sLayerName){
        if (g_aLayersArray[nLoopCounter]["visible"] == "false"){
          g_aLayersArray[nLoopCounter]["visible"] = "true";
        } else {
          g_aLayersArray[nLoopCounter]["visible"] = "false";
        }
      }
    }
  }


  //refresh map if autorefresh is true
  var autoRefreshElem = document.getElementById("chkAutoRefresh");
  if(autoRefreshElem.checked && bRedraw){
    loadMap();
  }
}

function toggleLegendSwatch(sLayerName){
  var nLayerIdx = 0;
  var nLoopCounter = 0;

  var swatchImgElem = document.getElementById("swatch" + sLayerName);
  var expandImgElem = document.getElementById("expandImg" + sLayerName);

  //loop through g_aLegendLayers and get index for layer
  for (nLoopCounter = 0;nLoopCounter < g_aLegendLayers.length;nLoopCounter++){
    if (g_aLegendLayers[nLoopCounter]["layerName"] == sLayerName){
      nLayerIdx = nLoopCounter;
    }
  }

  if (swatchImgElem.style.display == "none"){
    swatchImgElem.style.display = "block";
    expandImgElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_collapse.png";
    expandImgElem.alt = "Collapse Legend Image";
    expandImgElem.title = "Collapse Legend Image";
    g_aLegendLayers[nLayerIdx]["expanded"] = "true";
  } else {
    swatchImgElem.style.display = "none";
    expandImgElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/legend/button_expand.png";
    expandImgElem.alt = "Expand Legend Image";
    expandImgElem.title = "Expand Legend Image";
    g_aLegendLayers[nLayerIdx]["expanded"] = "false";
  }

}

function showSpinner() {
  var spinElem = document.getElementById("loadingDiv");
  spinElem.style.display = "block";
}

function hideSpinner() {
  var spinElem = document.getElementById("loadingDiv");
  spinElem.style.display = "none";
}

function showQuerySpinner() {
  var spinElem = document.getElementById("queryingDiv");
  spinElem.style.display = "block";
}

function hideQuerySpinner() {
  var spinElem = document.getElementById("queryingDiv");
  spinElem.style.display = "none";
}

function updateExtentBufferButtons(){
  var zoomPreviousElem = document.getElementById("viewPreviousImg");
  var zoomNextElem = document.getElementById("viewNextImg");

  if (g_aExtentBuffer.length > 0){

    if (g_nExtentBufferIdx > 0){
      zoomPreviousElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/button_view_previous.gif";
      zoomPreviousElem.onclick = function(){ zoomToPreviousExtent(); };
    } else {
      zoomPreviousElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/button_view_previous_off.gif";
      zoomPreviousElem.onclick = null;
    }

    if (g_nExtentBufferIdx == g_aExtentBuffer.length - 1){
      zoomNextElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/button_view_next_off.gif";
      zoomNextElem.onclick = null;
    } else {
      zoomNextElem.src = "http://cdn.sidwellco.com/shared_images/ajaxgis/button_view_next.gif";
      zoomNextElem.onclick = function(){ zoomToNextExtent(); };
    }

  }


}

function updateSlideBar(){
  var fXDist = g_fMaxX - g_fMinX;
  var fXPct = fXDist / (g_fActualStartMaxX - g_fActualStartMinX);
  var nPct = 100 - parseInt(fXPct * 100);
  A_SLIDERS[1].f_setValue(nPct.toString());
}


function windowLoaded(evt) {
    // prevent IE text selection while dragging unless the select is coming
    // from a text box, then allow it
    document.body.ondrag = function () { return false; };
    document.body.onselectstart = function () {
      if ((event.srcElement.type != "text") && (event.srcElement.type != "textarea")){
        return false;
      }
    };

    //assign behavior for map div and images that need onload events
    var mapDivElem = document.getElementById("mapDiv");
    mapDivElem.ondragstart = function () { return false; };
    mapDivElem.onselectstart = function () { return false; };

    var mapDivImgElem = document.getElementById("mapDivImg");
    mapDivImgElem.onload = function () {
      hideSpinner();
      this.style.left = "0px";
      this.style.top = "0px";
      this.style.width = mapDivElem.style.width;
      this.style.height = mapDivElem.style.height;
      g_bOkToGetMap = true;
    };

    var ovMapDivImgElem = document.getElementById("ovMapDivImg");
    ovMapDivImgElem.onload = function () { ovMapDivImgElem.style.display = 'block'; };

  var legendImgElem = document.getElementById("legendImg");
  legendImgElem.onload = function () { g_bOkToGetLegend = true;};

  //Initialization code for mouse scrolling.
  if (window.addEventListener) window.addEventListener('DOMMouseScroll', wheel, false);
  window.onmousewheel = document.onmousewheel = wheel;
}

/** This is high-level function.
 * It must react to delta being more/less than zero.
 */
function handle(delta) {
  return;

  var mapDivElem = document.getElementById("mapDiv");
  var mapDivImgElem = document.getElementById("mapDivImg");

  var aspect = parseInt(mapDivElem.style.width) / parseInt(mapDivElem.style.height);

  mapDivImgElem.style.width = (parseInt(mapDivImgElem.style.height) * aspect) + ((delta*2) * aspect) + "px";
  mapDivImgElem.style.height = parseInt(mapDivImgElem.style.height) + (delta*2) + "px";
  mapDivImgElem.style.left = (parseInt(mapDivImgElem.style.left) - (delta * aspect)) + "px";
  mapDivImgElem.style.top = (parseInt(mapDivImgElem.style.top) - delta) + "px";
}

/** Event handler for mouse wheel event.
 */
function wheel(event){
  var delta = 0;
  if (!event) /* For IE. */
      event = window.event;
  if (event.wheelDelta) { /* IE/Opera. */
      delta = event.wheelDelta/120;
      /** In Opera 9, delta differs in sign as compared to IE.
       */
      if (window.opera)
          delta = -delta;
  } else if (event.detail) { /** Mozilla case. */
      /** In Mozilla, sign of delta is different than in IE.
       * Also, delta is multiple of 3.
       */
      delta = -event.detail/3;
  }
  /** If delta is nonzero, handle it.
   * Basically, delta is now positive if wheel was scrolled up,
   * and negative, if wheel was scrolled down.
   */
  if (delta)
      handle(parseInt(delta*5));
  /** Prevent default actions caused by mouse wheel.
   * That might be ugly, but we handle scrolls somehow
   * anyway, so don't bother here..
   */
  if (event.preventDefault)
      event.preventDefault();

  event.returnValue = false;
}

//handles all the map graphics for zoomin / zoomout and measure

var g_bMouseDown = false;
var g_MapWindow = new clsExtents();

/* CLASS: clsExtents */
 function clsExtents() {
  this.X1 = 0.0;
  this.Y1 = 0.0;
  this.X2 = 0.0;
  this.Y2 = 0.0;
  this.init = false;
 
  this.reset = function() {
   this.X1 = 0.0;
   this.Y1 = 0.0;
   this.X2 = 0.0;
   this.Y2 = 0.0;
   this.init = false;
  };
 
  this.getMinX = function() { return (this.X1 > this.X2?this.X2:this.X1); };
  this.getMinY = function() { return (this.Y1 > this.Y2?this.Y2:this.Y1); };
  this.getMaxX = function() { return (this.X1 < this.X2?this.X2:this.X1); };
  this.getMaxY = function() { return (this.Y1 < this.Y2?this.Y2:this.Y1); };
  this.getWidth = function() { return (this.getMaxX() - this.getMinX()); };
  this.getHeight = function() { return (this.getMaxY() - this.getMinY()); };
  this.getWidthMid = function() { return ((this.X1 + this.X2) / 2); };
  this.getHeightMid = function() { return ((this.Y1 + this.Y2) / 2); };
 
  this.isValid = function() {
   return ((!isNaN(this.X1))&&(!isNaN(this.Y1))&&(!isNaN(this.X2))&&(!isNaN(this.Y2)));
  };
 
  this.clone = function() {
   var temp = new clsExtents();
   temp.X1 = this.X1;
   temp.Y1 = this.Y1;
   temp.X2 = this.X2;
   temp.Y2 = this.Y2;
   temp.init = this.init;
   return temp;
  };
 }

//requires: mapCustom.js, mapControls.js, scriptaculous.js
//update history:
//2007_06_20  J.S. enhanced TOC to take advantage of 9.2 xml for group layers,
//        changed the following funcitons: parseLayerInfo()
//        added new function: detectParentLayers()
//2007_07_27  J.S. changed how print map page is displayed to avoid popup blocker issues
//        changed function parseGetMapResponse() - no longer calls popup
//        added global variable for g_oPrintPageWindow, replaced win object in popUpPrintPage()
//2007_10_19    J.S. added a parseEntity function to filter out common html entities
//2008_01_10  E.S. add fix to highlight selected features (9.2-SP4 bug)
//2008_11_25  E.S. set the overview off by default
//2008_12_31  E.S. added a getFieldAlias function

var g_oPrintPageWindow;

var g_aLayersArray = new Array();
var g_aProperties = new Array();
var g_aEnvelopes = new Array();
var g_aExtentBuffer = new Array();
var g_aAcetateLabels = new Array();
var g_aAcetateMarkers = new Array();

var g_fActualStartMinX = 0;
var g_fActualStartMaxX = 0;
var g_fActualStartMinY = 0;
var g_fActualStartMaxY = 0;

var g_bIsInitialMap = true;
var g_bIsPrintMap = false;
var g_bOkToGetMap = true;
var g_bOkToGetLegend = true;
var g_bOkToGetFeatures = true;
var g_bAddExtentToBuffer = true;
var g_bIsPrintMap = false;
var g_bSearchingPinLayers = false;
var g_bIsBufferSelect = false;
var g_bIsNextPrevQuery = false;
var g_bHasMore = false;
var g_bLoadedOverviewMap = false; //2008_11_25  E.S.

var g_nExtentBufferIdx = 0;
var g_nPINLayerIdx = 0;
var g_nQueryStartIdx = 1;

var g_sPrintMapUrl = "";
var g_sLegendUrl = "";
var g_sResultsHtml = "";
var g_sAcetateText = "";
var g_sDrawBufferQuery = "";
var g_sDrawRadiusXML = "";

function addExtentToBuffer(){
  if (g_bAddExtentToBuffer == true){
    var aBuffer = new Array();
    aBuffer["minx"] = g_fMinX;
    aBuffer["miny"] = g_fMinY;
    aBuffer["maxx"] = g_fMaxX;
    aBuffer["maxy"] = g_fMaxY;
    g_aExtentBuffer = g_aExtentBuffer.slice(0,g_nExtentBufferIdx + 1);
    g_aExtentBuffer[g_aExtentBuffer.length] = aBuffer;
    g_nExtentBufferIdx = g_aExtentBuffer.length - 1;
  } else {
    //reset boolean to add extent
    g_bAddExtentToBuffer = true;
  }

}

function buildAcetateMarkerXML(){
  var loopCounter = 0;
  var sAXL = "";

  for (loopCounter = 0;loopCounter < g_aAcetateMarkers.length;loopCounter++){
    sAXL += '<LAYER type="acetate" name="' + g_aAcetateMarkers[loopCounter]["layerId"] + '" visible="true" id="' + g_aAcetateMarkers[loopCounter]["layerId"] + '">\n';
    sAXL += '<OBJECT units="database">\n';
    sAXL += '<POINT coords="' + g_aAcetateMarkers[loopCounter]["xpos"] + ' ' + g_aAcetateMarkers[loopCounter]["ypos"] + '">\n';
    sAXL += '<SIMPLEMARKERSYMBOL';
    if(g_aAcetateMarkers[loopCounter]["outline"] != ""){
      sAXL += ' outline="' + g_aAcetateMarkers[loopCounter]["outline"] + '"';
    }
    sAXL += ' type="' + g_aAcetateMarkers[loopCounter]["type"] + '" color="' + g_aAcetateMarkers[loopCounter]["color"] + '" width="' + g_aAcetateMarkers[loopCounter]["width"] + '" />\n';
    sAXL += '</POINT>\n';
    sAXL += '</OBJECT>\n';
    sAXL += '</LAYER>\n';
  }
  return sAXL;
}

function buildAcetateTextXML(){
  var loopCounter = 0;
  var sAXL = "";

  for (loopCounter = 0;loopCounter < g_aAcetateLabels.length;loopCounter++){
    sAXL += '<LAYER type="acetate" name="' + g_aAcetateLabels[loopCounter]["layerId"] + '" visible="true" id="' + g_aAcetateLabels[loopCounter]["layerId"] + '">\n';
    sAXL += '<OBJECT units="database">\n';
    sAXL += '<TEXT coords="' + g_aAcetateLabels[loopCounter]["xpos"] + ' ' + g_aAcetateLabels[loopCounter]["ypos"] + '" label="' + g_aAcetateLabels[loopCounter]["labelText"] + '">\n';
    sAXL += '<TEXTMARKERSYMBOL';
    if(g_aAcetateLabels[loopCounter]["blockout"] != ""){
      sAXL += ' blockout="' + g_aAcetateLabels[loopCounter]["blockout"] + '"';
    }
    if(g_aAcetateLabels[loopCounter]["outline"] != ""){
      sAXL += ' outline="' + g_aAcetateLabels[loopCounter]["outline"] + '"';
    }
    sAXL += ' font="' + g_aAcetateLabels[loopCounter]["font"] + '" fontcolor="' + g_aAcetateLabels[loopCounter]["fontColor"] + '" fontsize="' + g_aAcetateLabels[loopCounter]["fontSize"] + '" fontstyle="' + g_aAcetateLabels[loopCounter]["fontStyle"] + '" halignment="' + g_aAcetateLabels[loopCounter]["halign"] + '" valignment="' + g_aAcetateLabels[loopCounter]["valign"] + '"  />\n';
    sAXL += '</TEXT>\n';
    sAXL += '</OBJECT>\n';
    sAXL += '</LAYER>\n';
  }
  return sAXL;
}


function buildDrawSelectedFeaturesXML(){
  var sAXL = "";
  sAXL += '<LAYER type="featureclass" name="Selected Features" visible="true">\n';
  sAXL += '<DATASET fromlayer="' + g_nSelectedFeaturesLayerIdx + '" />\n';
  sAXL += g_sSelectedFeaturesSpatialQuery;

  //in 9.2-SP4 we need the 3 lines of code below to highlight the selected features (ERIC - 01-10-2008)
  sAXL += '<SIMPLERENDERER>\n';
  sAXL += '<SIMPLEPOLYGONSYMBOL fillcolor="255,255,0" filltype="solid" transparency="0.5" boundarycolor="255,255,255" />\n';
  sAXL += '</SIMPLERENDERER>\n';

  sAXL += '</LAYER>\n';
  return sAXL;
}


function buildLayerString(){
  var aLayer = new Array();
  var sLayers = "";
  var loopCounter = 0;

  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    sLayers += '<LAYERDEF id="' + g_aLayersArray[loopCounter]["id"] + '" visible="' + g_aLayersArray[loopCounter]["visible"] + '" />\n';
  }
  return sLayers;
}

function buildLegendLayerString(){
  var bExclude = false;
  var aLayer = new Array();
  var sLayers = "";
  var sLayerName = "";
  var sExcludedLayerName = "";
  var loopCounter = 0;
  var loopCounter2 = 0;

  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    sLayerName = g_aLayersArray[loopCounter]["layerName"];
    bExclude = false;

    for (loopCounter2 = 0;loopCounter2 < g_aExcludeFromLegendImage.length;loopCounter2++){
      sExcludedLayerName = g_aExcludeFromLegendImage[loopCounter2];

      if (sLayerName.indexOf(sExcludedLayerName,0) != -1){
        bExclude = true;
      }

    }

    if (bExclude == true){
      sLayers += '<LAYERDEF id="' + g_aLayersArray[loopCounter]["id"] + '" visible="false" />\n';
    } else {
      sLayers += '<LAYERDEF id="' + g_aLayersArray[loopCounter]["id"] + '" visible="' + g_aLayersArray[loopCounter]["visible"] + '" />\n';
    }


  }
  return sLayers;
}


function buildFieldValueString(sLayerName,sFieldName,sFieldAlias,sFieldValue){
  //check to see is value should be part of hyperlink
  var nLoopCounter = 0;
  var sReturnVal = sFieldValue;
  var sHref = "";

  for (nLoopCounter = 0;nLoopCounter < g_aHyperLinkFields.length;nLoopCounter++){
    if (g_aHyperLinkFields[nLoopCounter]["layerName"] == sLayerName){

      if ((g_aHyperLinkFields[nLoopCounter]["fieldName"] == sFieldName) || (g_aHyperLinkFields[nLoopCounter]["fieldName"] == sFieldAlias)){
        sHref = g_aHyperLinkFields[nLoopCounter]["linkPrefix"] + sReturnVal + g_aHyperLinkFields[nLoopCounter]["linkSuffix"];
        sReturnVal = '<span class="darkUlineSmall"><a href="javascript:void(0);" onclick="var mapParent = window.open(\'' + sHref + '\', \'' + g_sLinkWindowName + '\');mapParent.focus()">' + sFieldValue + '</a></span>';
      }

    }
  }
  return sReturnVal;

}

function buildFeatureEnvelopeArray(sFeatureList){
  var nEndPos = 0;
  var nLoopCounter = 0;
  var nStartPos = 0;

  var sEnvelope = "";

  g_aEnvelopes = new Array();

  //for each feature selected get the field values
  for (nLoopCounter = 0;nLoopCounter < g_nSelectCount;nLoopCounter++){
    nStartPos = sFeatureList.indexOf('<ENVELOPE',nStartPos);
    if (nStartPos != -1){
      nEndPos = sFeatureList.indexOf('/>',nStartPos);
      nEndPos = nEndPos + 2;
      sEnvelope = sFeatureList.substring(nStartPos,nEndPos);
      g_aEnvelopes[nLoopCounter] = sEnvelope;
    }
    nStartPos = nEndPos;
  }
}

function buildResultsDiv(sFeatureList){
  var aFields = new Array();
  var aField = new Array();

  var nEndPos = 0;
  var nStartPos = 0;
  var nStartPos2 = 0;
  var nLoopCounter = 0;
  var nLoopCounter2 = 0;
  var nLoopCounter3 = 0;

  var sFieldName = "";
  var sFieldAlias = "";
  var sFieldValue = "";
  var sResults = "";

  var sColor1 = "#ffffff";
  var sColor2 = "#cfcfcf";
  var sColor = "";

  sResults = '<div style="text-align:center"><span style="background-color:#ffffff;text-align:center;font-weight:bold;">' +
  g_sSelectableLayer + '</span><br />';

  //if more than one selected feature, add zoom to features link
  if (g_nSelectCount >= 1){
    sResults += '<a class="darkSmall" href="javascript:void(0);" onclick="zoomToSelectedFeatures();return false;">' +
    '<img style="width:16px;height:16px;border:0px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/zoom_in.gif" alt="Zoom to these features" title="Zoom to these features" />' +
    'Zoom to these features</a><br />';
  }

  //check to see if previous records link should be displayed
  if(g_nQueryStartIdx > g_nMaxFeaturesReturned){
    sResults += '<a href="javascript:void(0)" onclick="getPreviousRecords();" style="margin-right:5px;font-size:10px"><< Previous</a>';
  }

  //check to see if next records link should be displayed
  if (g_bHasMore){
    sResults += '<a href="javascript:void(0)" onclick="getNextRecords();" style="font-size:10px">Next >></a>';
  }


  sResults += '</div>\n';
  sResults += '<table class="resultTable">\n';

  //loop through selectable layers array and look for selectable layer array
  for (nLoopCounter = 0;nLoopCounter < g_aSelectableLayers.length;nLoopCounter++){
    if (g_aSelectableLayers[nLoopCounter][0] == g_sSelectableLayer){
      aFields = g_aSelectableLayers[nLoopCounter];
      sColor = sColor1;

      if (g_nSelectCount == 0){
        sResults += '<tr><td class="resultContent" colspan="2" style="border-top:1px dashed black;">No features found</td></tr>';
      }

      //for each feature selected get the field values
      for (nLoopCounter2 = 0;nLoopCounter2 < g_nSelectCount;nLoopCounter2++){

        sResults += '<tr style="background-color:' + sColor + ';">' +
              '<td class="resultContent" style="border-top:1px dashed black;" colspan="2">' +
              '<a class="darkSmall" href="javascript:void(0);" onclick="zoomToEnvelope(' + nLoopCounter2 + ');">' +
              '<img style="width:16px;height:16px;border:0px;" src="http://cdn.sidwellco.com/shared_images/ajaxgis/zoom_in.gif" alt="Zoom to feature" title="Zoom to feature" />' +
              '</a>Feature (' + (nLoopCounter2 + 1) + ')' +
              '</td></tr>\n';

        nStartPos2 = sFeatureList.indexOf('<FIELDS>',nStartPos2) + 8;

        //loop through fields - start at 1 b/c 0 position is layer name
        for (nLoopCounter3 = 1;nLoopCounter3 < aFields.length;nLoopCounter3++){
          sField = aFields[nLoopCounter3];
          aField = sField.split("|");
          sFieldName = aField[0];
          nStartPos = sFeatureList.indexOf('<FIELD name="' + sFieldName + '"',nStartPos2);
          nStartPos = sFeatureList.indexOf('value="',nStartPos);
          nStartPos = nStartPos + 7;
          nEndPos = sFeatureList.indexOf(g_sDQuote,nStartPos);
          sFieldValue = sFeatureList.substring(nStartPos,nEndPos);
          sFieldValue = parseEntity(sFieldValue);

          if (sFieldValue == "") sFieldValue = "n/a";

          //if there is a field alias value use it if not use fieldname
          if(aField.length == 2){
            sFieldAlias = aField[1];
          } else {
            sFieldAlias = "";
          }

          sResults += '<tr style="background-color:' + sColor + '">';

          if (sFieldAlias == ""){
            sResults += '<td style="padding-left:10px;font-weight:bold" class="resultContent">' + sFieldName + '</td>\n';
          } else {
            sResults += '<td style="padding-left:10px;font-weight:bold" class="resultContent">' + sFieldAlias + '</td>\n';
          }

          sResults += '<td class="resultContent">' + buildFieldValueString(g_sSelectableLayer,sFieldName,sFieldAlias,sFieldValue) + '</td>\n';
          sResults += '</tr>';
        }


        if (sColor == sColor1){
          sColor = sColor2;
        } else {
          sColor = sColor1;
        }

      }

    }
  }
  //add one more row for bottom border
  sResults += '<tr><td class="resultContent" colspan="2" style="border-top:1px dashed black;"></td></tr>';
  sResults += '</table>';
  g_sResultsHtml = sResults;
  //set inner html of result content div
  var resultsElem = document.getElementById("resultsContentsDiv");
  resultsElem.innerHTML = sResults;
  resultsElem.style.opacity = "1.0";

  //make result div visible
  var resultsElem = document.getElementById("resultsDiv");
  resultsElem.style.display = "block";

  new Effect.Pulsate("resultsContentsDiv",{duration:1.0, pulses:1});
}

function buildScaleBarXML(){
  var sAXL = "";
  sAXL += '<LAYER type="acetate" name="scalebar" visible="true" id="scalebar">\n';
  sAXL += '<OBJECT units="pixel">\n';
  sAXL += '<SCALEBAR coords="5 5" barcolor="' + g_sScaleBarColor + '" barwidth="' + g_nScaleBarWidth + '" font="' + g_sScaleBarFont + '" fontcolor="' + g_sScaleBarFontColor + '" fontsize="' + g_nScaleBarFontSize + '" fontstyle="' + g_sScaleBarFontStyle + '" mapunits="' + g_sScaleBarMapUnits + '" scaleunits="' + g_sScaleBarScaleUnits + '" screenlength="' + g_nScaleBarScreenLength + '"  />\n';
  sAXL += '</OBJECT>\n';
  sAXL += '</LAYER>\n';
  return sAXL;
}
function buildSelectFieldString(sLayerName){
  var sField = "";
  var aField = new Array();
  var sFieldList = "#SHAPE# ";
  var nLoopCounter = 0;
  var nLoopCounter2 = 0;
  var aFields = new Array();

  //loop through selectable layers array and build list of fields
  for (nLoopCounter = 0;nLoopCounter < g_aSelectableLayers.length;nLoopCounter++){
    if (g_aSelectableLayers[nLoopCounter][0] == sLayerName){
      aFields = g_aSelectableLayers[nLoopCounter];

      //loop through fields - start at 1 b/c 0 position is layer name
      for (nLoopCounter2 = 1;nLoopCounter2 < aFields.length;nLoopCounter2++){
        sField = aFields[nLoopCounter2];
        aField = sField.split("|");
        sField = aField[0];
        if (sField == "#ALL#"){
          sFieldList = sField;
        }else {
          sFieldList += sField + " ";
        }

      }

    }
  }
  return sFieldList;
}

function calcPrintExtents(){
  //can either preserve extents or scale, not both b/c print map image dimensions will be different
  if(g_bPreserveMapExtent){
    //leave map extents as they are
    g_fPrintMinX = g_fMinX;
    g_fPrintMinY = g_fMinY;
    g_fPrintMaxX = g_fMaxX;
    g_fPrintMaxY = g_fMaxY;
  } else {
    //preserve scale
    //1. calc centerpoint x and y
    //2. use current scale in map units per pixel - g_fMapUnitsPerPixel calc new print map width and height map unit distances
    //3. calc minx, maxx, miny, maxy
    var fXDist = (g_fMaxX - g_fMinX);
    var fYDist = (g_fMaxY - g_fMinY);
    var fCenterX = g_fMinX + (fXDist / 2);
    var fCenterY = g_fMinY + (fYDist / 2);
    var fNewXDist =  g_nPrintMapWidth * g_fMapUnitsPerPixel;
    var fNewYDist = g_nPrintMapHeight *  g_fMapUnitsPerPixel;
    g_fPrintMinX = fCenterX - Math.abs((fNewXDist) / 2);
    g_fPrintMaxX = g_fPrintMinX + fNewXDist;
    g_fPrintMinY = fCenterY - Math.abs((fNewYDist) / 2);
    g_fPrintMaxY = g_fPrintMinY + fNewYDist;
  }
}

function checkParams(){
  //build spatial query
  var sSpatialQuery = "";

  if(g_sPin != ""){
    g_sQueryLayer = g_sParcelLayerName;
    g_sQueryField = g_sParcelPinField;
    g_sQueryValue = g_sPin;
  }

  if ((g_sQueryLayer != "") && (g_sQueryField != "")&& (g_sQueryValue != "")){
    g_sSelectableLayer = g_sQueryLayer;
    changeSelectableLayer(g_sQueryLayer);
    sSpatialQuery = '<SPATIALQUERY subfields="' + buildSelectFieldString(g_sSelectableLayer) + '" where="'+ g_sQueryField + ' = \'' + g_sQueryValue + '\'"></SPATIALQUERY>\n';
    g_sSelectedFeaturesSpatialQuery = sSpatialQuery;
    g_nSelectedFeaturesLayerIdx = getSelectableLayerID();
    getFeatures(sSpatialQuery,0,true,false);
  }

}

function detectParentLayers(){
  var loopCounter = 0;
  var loopCounter2 = 0;
  var sParentId = "";

  //loop through each layer, if it has a parent, set the parent layers isParent property to true
  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    if(g_aLayersArray[loopCounter]["parentLayerId"] != ""){
      sParentId = g_aLayersArray[loopCounter]["parentLayerId"];

      //loop through each layer and find layer with parent id, set it's isParent prop to true, and expanded prop to false
      for (loopCounter2 = 0;loopCounter2 < g_aLayersArray.length;loopCounter2++){
        if(g_aLayersArray[loopCounter2]["id"] == sParentId){
          g_aLayersArray[loopCounter2]["isParent"] = true;
          g_aLayersArray[loopCounter2]["expanded"] = false;
        }
      }

    }
  }

}

function getFeatures(sSpatialQuery,nBeginRecord,bIncludeGeometry,bIsBuffer){

  g_bIsBufferSelect = bIsBuffer

  //if starting at record 0, reset global start index
  if (nBeginRecord == 0){
    g_nQueryStartIdx = 1;
  }

  //clear out buffer query if doing a new query
  if(!bIsBuffer){
    g_sDrawBufferQuery = "";
  }

  //get id for selectable layer
  var nId = getSelectableLayerID();
  var sReq =  '<ARCXML version="1.1">\n' +
          '<REQUEST>\n' +
            '<GET_FEATURES dataframe="' + g_sLayersDataFrame + '" featurelimit="' + g_nMaxFeaturesReturned + '" beginrecord="' + nBeginRecord + '" outputmode="newxml" geometry="' + bIncludeGeometry + '" checkesc="true" envelope="true" compact="true">\n';
              if (!bIsBuffer){
                sReq += '<LAYER id="' + nId +  '" />\n';
              }
              sReq += sSpatialQuery +
            '</GET_FEATURES>\n' +
          '</REQUEST>\n' +
        '</ARCXML>\n';
  if ((g_bOkToGetFeatures == true) && (g_bOkToGetMap == true)){
    showQuerySpinner();
    g_bOkToGetFeatures = false;
    //console.log(sReq);
    var myAjax = new Ajax.Request(g_sServiceUrl,{method:'post',postBody:sReq,onComplete:parseGetFeaturesResponse});
  }

}

function getLayerID(sLayerName){
  var nId = 0;
  var loopCounter = 0;

  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    if (g_aLayersArray[loopCounter]["layerName"] == sLayerName){
      nId = g_aLayersArray[loopCounter]["id"];
    }
  }
  return nId;
}

function getLayers(){
  var sReq =  '<ARCXML version="1.1">\n' +
          '<REQUEST>\n' +
            '<GET_SERVICE_INFO fields="false" envelope="false" dataframe="' + g_sLayersDataFrame + '" toc="false" />\n' +
          '</REQUEST>\n' +
        '</ARCXML>';
  var myAjax = new Ajax.Request(g_sServiceUrl,{method:'post',postBody:sReq,onComplete:parseServiceInfoResponse});
}


function getLegend(){
  var sLayers = buildLegendLayerString();
  var sReq =  '<ARCXML version="1.1">\n' +
          '<REQUEST>\n' +
            '<GET_IMAGE>\n' +
              '<PROPERTIES>\n' +
                '<ENVELOPE minx="' + g_fMinX + '" miny="' + g_fMinY +
                '" maxx="' + g_fMaxX + '" maxy="' + g_fMaxY + '" />\n' +
                '<IMAGESIZE height="' + g_nMapHeight + '" width="' + g_nMapWidth + '" />\n' +
                '<LAYERLIST>\n' + sLayers +
                '</LAYERLIST>\n' +
                '<LEGEND autoextend="true" backgroundcolor="' + g_sLegendBackColorRGB + '" ' +
                'font="' + g_sLegendFont + '" layerfontsize="' + g_nLegendLayerFontSize + '" ' +
                'swatchheight="' + g_nLegendSwatchHeight + '" swatchwidth="' + g_nLegendSwatchWidth + '" ' +
                'title="' + g_sLegendTitle + '" titlefontsize="' +  g_nLegendTitleFontSize + '" ' +
                'valuefontsize="' + g_nLegendValueFontSize + '" >\n' +
                '</LEGEND>\n' +
                '<DRAW map="false" />\n' +
              '</PROPERTIES>\n' +
            '</GET_IMAGE>\n' +
          '</REQUEST>\n' +
        '</ARCXML>\n';
  g_bOkToGetLegend = false;
  var myAjax = new Ajax.Request(g_sServiceUrl,{method:'post',postBody:sReq,onComplete:parseGetLegendResponse});

}


function getMap(fMinX,fMinY,fMaxX,fMaxY,nMapHeight,nMapWidth,sLayers,sDataFrame){

  var mapImgElem = document.getElementById("mapDivImg");
  var sReq =  '<ARCXML version="1.1">\n' +
          '<REQUEST>\n' +
            '<GET_IMAGE dataframe="' + sDataFrame + '">\n' +
              '<PROPERTIES>\n' +
                '<ENVELOPE minx="' + fMinX + '" miny="' + fMinY +
                '" maxx="' + fMaxX + '" maxy="' + fMaxY + '" />\n' +
                '<IMAGESIZE height="' + nMapHeight + '" width="' + nMapWidth + '" />\n' +
                '<LAYERLIST>\n' + sLayers +
                '</LAYERLIST>\n' +
              '</PROPERTIES>\n';

            if(g_sDrawBufferQuery != ""){
              sReq += g_sDrawBufferQuery;
            }

            if(g_bIncludeScaleBar == true && sDataFrame != g_sOverViewDataFrame){
              sReq += buildScaleBarXML();
            }

            if (sDataFrame != g_sOverViewDataFrame){
              sReq += buildAcetateTextXML();
              sReq += buildAcetateMarkerXML();
            }

            if (g_sDrawRadiusXML != ""){
              sReq += g_sDrawRadiusXML;
            }

            if(g_nSelectCount > 0){
              sReq += buildDrawSelectedFeaturesXML();
            }


            sReq += '</GET_IMAGE>\n' +
          '</REQUEST>\n' +
        '</ARCXML>';

  if (sDataFrame == g_sOverViewDataFrame){
    var myAjax = new Ajax.Request(g_sServiceUrl,{method:'post',postBody:sReq,onComplete:parseGetOVMapResponse});
  } else {
    g_bOkToGetMap = false;
    var myAjax = new Ajax.Request(g_sServiceUrl,{method:'post',postBody:sReq,onComplete:parseGetMapResponse});
  }
}

function getNextRecords(){
  g_nQueryStartIdx = g_nQueryStartIdx + g_nMaxFeaturesReturned;
  g_bIsNextPrevQuery = true;
  getFeatures(g_sSelectedFeaturesSpatialQuery,g_nQueryStartIdx,false,g_bIsBufferSelect);
}

function getPreviousRecords(){
  g_nQueryStartIdx = g_nQueryStartIdx - g_nMaxFeaturesReturned;
  g_bIsNextPrevQuery = true;
  getFeatures(g_sSelectedFeaturesSpatialQuery,g_nQueryStartIdx,false,g_bIsBufferSelect);
}


function getSelectableLayerID(){
  var nId = 0;
  var loopCounter = 0;

  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    if (g_aLayersArray[loopCounter]["layerName"] == g_sSelectableLayer){
      nId = g_aLayersArray[loopCounter]["id"];
    }
  }
  return nId;
}

function isSelectableLayerVisibleAtCurrentScale(){
  var bIsVisible = false;
  var nId = 0;
  var loopCounter = 0;

  for (loopCounter = 0;loopCounter < g_aLayersArray.length;loopCounter++){
    if (g_aLayersArray[loopCounter]["layerName"] == g_sSelectableLayer){
      var nMaxScale = g_aLayersArray[loopCounter]["maxScale"];
      var nMinScale = g_aLayersArray[loopCounter]["minScale"];

      if ((nMinScale > g_fMapUnitsPerPixel) || (nMaxScale < g_fMapUnitsPerPixel  && nMaxScale != 0)){
        bIsVisible = false;
      } else {
        bIsVisible = true;
      }
    }
  }

  return bIsVisible;
}

function loadInitialMap(){
  showSpinner();
  getLayers();
  buildSelectableLayerList();
  buildSearchLayerList();
  calcAspectRatio();
  getMap(g_fInitMinX,g_fInitMinY,g_fInitMaxX,g_fInitMaxY,g_nMapHeight,g_nMapWidth,"",g_sLayersDataFrame);
}


//2008_11_25  E.S.
function loadOverviewMap(){
  if(!g_bLoadedOverviewMap) {
    getMap(g_fInitMinX,g_fOVInitMinY,g_fOVInitMaxX,g_fOVInitMaxY,g_nOVMapHeight,g_nOVMapWidth,"",g_sOverViewDataFrame);
    g_bLoadedOverviewMap = true;
  }
}


function loadMap(){
  var sLayers = "";
  showSpinner();
  sLayers = buildLayerString();
  getMap(g_fMinX,g_fMinY,g_fMaxX,g_fMaxY,g_nMapHeight,g_nMapWidth,sLayers,g_sLayersDataFrame);

  if(g_bLegendVisible == true){
    createLegend();
  }

  //clear graphic layer and reset measure totals
  clearMeasurePoints();
}

function loadPrintMap(){
  var sLayers = "";
  showSpinner();
  sLayers = buildLayerString();
  g_bIsPrintMap = true;
  calcPrintExtents();
  getMap(g_fPrintMinX,g_fPrintMinY,g_fPrintMaxX,g_fPrintMaxY,g_nPrintMapHeight,g_nPrintMapWidth,sLayers,g_sLayersDataFrame);
}

function parseEntity(oldString) {
  //alert(oldString);
  oldString = oldString.replace(/&apos;/g, "'");
  oldString = oldString.replace(/&gt;/g, ">");
  oldString = oldString.replace(/&lt;/g, "<");
  oldString = oldString.replace(/&quot;/g, '"');
  oldString = oldString.replace(/&amp;/g, "&");
  return oldString;
}


function parseEnvironment(origRequest){
  var gmReply = origRequest.responseText;
  var nDpi = 0;
  var nEndPos = 0;
  var nEndEnvironmentPos = 0;
  var nStartPos = 0;
  var nStartEnvironmentPos = 0;
  var sEnvironment = "";

  nStartEnvironmentPos = gmReply.indexOf('<ENVIRONMENT>',0);
  nEndEnvironmentPos = gmReply.indexOf('</ENVIRONMENT>',nStartEnvironmentPos);
  sEnvironment = gmReply.substring(nStartEnvironmentPos,nEndEnvironmentPos);

  //get the dpi setting
  nStartPos = sEnvironment.indexOf('<SCREEN',0);
  nStartPos = sEnvironment.indexOf('dpi="',nStartPos);
  nStartPos = nStartPos + 5;
  nEndPos = sEnvironment.indexOf(g_sDQuote,nStartPos);
  nDpi = parseInt(sEnvironment.substring(nStartPos,nEndPos));
  g_aProperties["dpi"] = nDpi;
}

function parseGetFeaturesResponse(origRequest){
  var bLoadMap = false;
  var gmReply = origRequest.responseText;
  var nStartPos = 0;
  var nEndPos = 0;

  if (gmReply.indexOf('<ERROR') != -1){
    hideQuerySpinner();
    nStartPos = gmReply.indexOf('<ERROR');
    nStartPos = gmReply.indexOf('>',nStartPos) + 1;
    nEndPos = gmReply.indexOf('<',nStartPos);
    //reinit booleans
    g_bOkToGetFeatures = true;
    var sErrorMsg = gmReply.substring(nStartPos,nEndPos);
    alert("Error requesting map:\n" + sErrorMsg);
    hideSpinner();
    g_bOkToGetMap = true;
    return;
  }

  //get feature count and if it has more
  nStartPos = gmReply.indexOf('<FEATURECOUNT count="');
  nStartPos = nStartPos + 21;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  var nNewSelectCount = parseInt(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('hasmore="',nStartPos);
  nStartPos = nStartPos + 9;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);

  var sHasMore = gmReply.substring(nStartPos,nEndPos);

  if (sHasMore == "true"){
    g_bHasMore = true;
  } else {
    g_bHasMore = false;
  }

  //if there are no features found and the target layer is the parcel layer
  //then check additional PIN layers for matches - this will repeat for as
  //many PIN layers in g_aPINLayers
  if (nNewSelectCount == 0 && g_bSearchingPinLayers == true){
    if (g_nPINLayerIdx < g_aPINLayers.length){
      g_bOkToGetMap = true;
      g_bOkToGetFeatures = true;
      //2007_05_09 - JS - added next line to turn query spinner off
      hideQuerySpinner();
      searchOtherPinLayers();
      return;
    }
  } else {
    g_nPINLayerIdx = 0;
    g_bSearchingPinLayers = false;
  }

  //if there was a selected feature, but now there isn't then redraw map
  //to clear selected feature layer
  if (g_nSelectCount > 0 && nNewSelectCount == 0){
    bLoadMap = true;
  }

  g_nSelectCount = nNewSelectCount;

  if (g_nSelectCount > 1){
    bLoadMap = true;
  }


  //if only one reset global extents and zoom to it
  if (g_nSelectCount == 1 && g_bZoomToSingleSelect == true && g_bIsNextPrevQuery == false){
    nStartPos = gmReply.indexOf('<ENVELOPE minx="');
    nStartPos = nStartPos + 16;
    nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
    g_fMinX = parseFloat(gmReply.substring(nStartPos,nEndPos));

    nStartPos = gmReply.indexOf('miny="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
    g_fMinY = parseFloat(gmReply.substring(nStartPos,nEndPos));

    nStartPos = gmReply.indexOf('maxx="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
    g_fMaxX = parseFloat(gmReply.substring(nStartPos,nEndPos));

    nStartPos = gmReply.indexOf('maxy="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
    g_fMaxY = parseFloat(gmReply.substring(nStartPos,nEndPos));

    //if it is a point, apply zoom out factor
    if (g_fMinX == g_fMaxX && g_fMinY == g_fMaxY){
      g_fMinX = g_fMinX - (g_nZoomToPointDist / 2);
      g_fMaxX = g_fMinX + g_nZoomToPointDist;
      g_fMinY = g_fMinY - (g_nZoomToPointDist / 2);
      g_fMaxY = g_fMinY + g_nZoomToPointDist;
    } else {
      //is not a point, so apply singleselect zoom factor
      var fXDist = g_fMaxX - g_fMinX;
      var fYDist = g_fMaxY - g_fMinY;
      fXDist = (fXDist * g_fSingleSelectZoomFactor);
      fYDist = (fYDist * g_fSingleSelectZoomFactor);

      g_fMinX = g_fMinX - fXDist;
      g_fMaxX = g_fMaxX + fXDist;
      g_fMinY = g_fMinY - fYDist;
      g_fMaxY = g_fMaxY + fYDist;
    }

    bLoadMap = true;
  }

  //extract everything from <FEATURES> TO </FEATURES> and send to buildResultsDiv()
  nStartPos = gmReply.indexOf('<FEATURES>');
  nStartPos = nStartPos + 10;
  nEndPos = gmReply.indexOf('</FEATURES>');
  var sFeatureList = gmReply.substring(nStartPos,nEndPos);

  buildFeatureEnvelopeArray(sFeatureList);
  buildResultsDiv(sFeatureList);

  //don't draw map if results are from a buffer query.  This draw happens before query when it's a buffer
  if (g_sDrawBufferQuery != ""){
    bLoadMap = false;
  }

  //check to see if the query is a result of a get next, or get previous records request if so then don't loadmap
  if (g_bIsNextPrevQuery){
    bLoadMap = false;

    //reinit boolean
    g_bIsNextPrevQuery = false;
  }

  if (bLoadMap == true){
    loadMap();
  }

  //if it's a buffer select, then reset selected features to 0
  if(g_bIsBufferSelect){
    g_nSelectCount = 0;
  }

  g_bOkToGetFeatures = true;
  hideQuerySpinner();
}

function parseGetLegendResponse(origRequest){
  var gmReply = origRequest.responseText;
  var nStartPos = gmReply.indexOf('<LEGEND url="');
  nStartPos = nStartPos + 13;
  var nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  g_sLegendUrl = gmReply.substring(nStartPos,nEndPos);
  document.getElementById("legendImg").src = g_sLegendUrl;
}

function parseGetMapResponse(origRequest){
  //if it's a print map, dont set global extents!
  var fMinX = 0;
  var fMaxX = 0;
  var fMinY = 0;
  var fMaxY = 0;

  var nStartPos = 0;
  var nEndPos = 0;

  var mapImgElem = document.getElementById("mapDivImg");

  var gmReply = origRequest.responseText;
  if (gmReply.indexOf('<ERROR') != -1){
    nStartPos = gmReply.indexOf('<ERROR');
    nStartPos = gmReply.indexOf('>',nStartPos) + 1;
    nEndPos = gmReply.indexOf('<',nStartPos);
    g_bOkToGetMap = true;
    var sErrorMsg = gmReply.substring(nStartPos,nEndPos);
    alert("Error requesting map:\n" + sErrorMsg);
    hideSpinner();
    g_bOkToGetMap = true;
    return;
  }

  nStartPos = gmReply.indexOf('<ENVELOPE minx="');
  nStartPos = nStartPos + 16;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  fMinX = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('miny="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  fMinY = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('maxx="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  fMaxX = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('maxy="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  fMaxY = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('<OUTPUT ="',nEndPos);
  nStartPos = gmReply.indexOf('url="',nStartPos);
  nStartPos = nStartPos + 5;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);

  var sMapImgUrl = gmReply.substring(nStartPos,nEndPos);

  if (g_bIsPrintMap == true){
    hideSpinner();
    g_bOkToGetMap = true;
  } else {
    g_fMinX = fMinX;
    g_fMinY = fMinY;
    g_fMaxX = fMaxX;
    g_fMaxY = fMaxY;
    mapImgElem.src = sMapImgUrl;
    calcScale();
    calcAspectRatio();
    buildLayerDivs();
    displayOVExtentBox();
    updateSlideBar();
    addExtentToBuffer();
    updateExtentBufferButtons();
  }

  if (g_bIsInitialMap == true){
    g_fActualStartMinX = g_fMinX;
    g_fActualStartMaxX = g_fMaxX;
    g_fActualStartMinY = g_fMinY;
    g_fActualStartMaxY = g_fMaxY;
    //check to see if query passed in url params
    g_bOkToGetMap = true;
    checkParams();
  }

  g_bIsInitialMap = false;

  if (g_bIsPrintMap == true){
    g_sPrintMapUrl = sMapImgUrl;
    g_oPrintPageWindow.document.getElementById("printMapImg").src = sMapImgUrl;
    g_bIsPrintMap = false;
  }
}


function parseGetOVMapResponse(origRequest){
  var gmReply = origRequest.responseText;
  var nStartPos = gmReply.indexOf('<ENVELOPE minx="');
  nStartPos = nStartPos + 16;
  var nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  g_fOVMinX = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('miny="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  g_fOVMinY = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('maxx="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  g_fOVMaxX = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('maxy="',nEndPos);
  nStartPos = nStartPos + 6;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  g_fOVMaxY = parseFloat(gmReply.substring(nStartPos,nEndPos));

  nStartPos = gmReply.indexOf('<OUTPUT ="',nEndPos);
  nStartPos = gmReply.indexOf('url="',nStartPos);
  nStartPos = nStartPos + 5;
  nEndPos = gmReply.indexOf(g_sDQuote,nStartPos);
  var sMapImgUrl = gmReply.substring(nStartPos,nEndPos);

  var ovMapImgElem = document.getElementById("ovMapDivImg");
  ovMapImgElem.src = sMapImgUrl;
}


function parseLayerInfo(origRequest){
  var gmReply = origRequest.responseText;

  var bSkipLayer = false;
  var loopCounter = 0;
  var nEndLayerInfoPos = 0;
  var nEndPos = 0;
  var nLayerId = 0;  //starting n for layers
  var nLoopCounter = 0;
  var nLoopCounter2 = 0;
  var nMaxScale = 0;
  var nMinScale = 0;
  var nStartPos = 0;
  var nStartLayerInfoPos = gmReply.indexOf('<LAYERINFO type="');
  var sLayerIdx = "";
  var sLayerInfoString = "";
  var sLayersDiv = "";
  var sLayerName = "";
  var sLayerType = "";
  var sParentLayerId = "";

  var n = 0;

  while (nStartLayerInfoPos != -1){
    //init vars
    sLayerType = "";
    sParentLayerId = "";
    sLayerName = "";
    sLayerIdx = "";
    sVisible = "";
    nMinScale = 0;
    nMaxScale = 0;

    nEndLayerInfoPos = gmReply.indexOf('>',nStartLayerInfoPos);
    sLayerInfoString = gmReply.substring(nStartLayerInfoPos,nEndLayerInfoPos);

    //get layer type
    nStartPos = sLayerInfoString.indexOf('type="',0);
    nStartPos = nStartPos + 6;
    nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
    sLayerType = sLayerInfoString.substring(nStartPos,nEndPos);

    //get parentlayer id (if it has one)
    nStartPos = sLayerInfoString.indexOf('parentlayerid="',0);
    if(nStartPos != -1){
      nStartPos = nStartPos + 15;
      nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
      sParentLayerId = sLayerInfoString.substring(nStartPos,nEndPos);
    }

    //get layer name
    nStartPos = sLayerInfoString.indexOf('name="',0);
    nStartPos = nStartPos + 6;
    nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
    sLayerName = sLayerInfoString.substring(nStartPos,nEndPos);

    //get id
    nStartPos = sLayerInfoString.indexOf(' id="',0);
    nStartPos = nStartPos + 5;
    nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
    sLayerIdx = sLayerInfoString.substring(nStartPos,nEndPos);

    //get visibility
    nStartPos = sLayerInfoString.indexOf('visible="',0);
    nStartPos = nStartPos + 9;
    nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
    sVisible = sLayerInfoString.substring(nStartPos,nEndPos);

    //get minscale - if present
    nStartPos = sLayerInfoString.indexOf('minscale="',0);
    if (nStartPos != -1){
      nStartPos = nStartPos + 10;
      nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
      nMinScale = parseFloat(sLayerInfoString.substring(nStartPos,nEndPos));
    }

    //get minscale - if present
    nStartPos = sLayerInfoString.indexOf('maxscale="',0);
    if (nStartPos != -1){
      nStartPos = nStartPos + 10;
      nEndPos = sLayerInfoString.indexOf(g_sDQuote,nStartPos);
      nMaxScale = parseFloat(sLayerInfoString.substring(nStartPos,nEndPos));
    }

    //build global layer array
    g_aLayersArray[n] = new Array();
    g_aLayersArray[n]["id"] = sLayerIdx;          //id num
    g_aLayersArray[n]["layerName"] = sLayerName;      //layer name
    g_aLayersArray[n]["visible"] = sVisible;        //visibility
    g_aLayersArray[n]["minScale"] = nMinScale;        //minscale
    g_aLayersArray[n]["maxScale"] = nMaxScale;        //maxscale
    g_aLayersArray[n]["parentLayerId"] = sParentLayerId;  //ParentLayer Id
    g_aLayersArray[n]["type"] = sLayerType;         //layer type

    nStartLayerInfoPos = gmReply.indexOf('<LAYERINFO type="',nStartLayerInfoPos + 1);
    bSkipLayer = false;
    n++;
  }

  //check layers to see if they have a parent for the toc
  detectParentLayers();
  g_aLayersArray.reverse(true);
  buildLayerDivs();
}

function parseProperties(origRequest){
  var gmReply = origRequest.responseText;
  var nEndPos = 0;
  var nEndPropertiesPos = 0;
  var nStartPos = 0;
  var nStartPropertiesPos = 0;
  var sProperties = "";
  var sMapUnits = "";
  var sFeatureCoordSys = "";
  var sFilterCoordSys = "";

  nStartPropertiesPos = gmReply.indexOf('<PROPERTIES>',0);
  nEndPropertiesPos = gmReply.indexOf('</PROPERTIES>',nStartPropertiesPos);
  sProperties = gmReply.substring(nStartPropertiesPos,nEndPropertiesPos);

  //get the feature coordsys
  nStartPos = sProperties.indexOf('<FEATURECOORDSYS',0);
  nStartPos = sProperties.indexOf('id="',nStartPos);
  nStartPos = nStartPos + 4;
  nEndPos = sProperties.indexOf(g_sDQuote,nStartPos);
  sFeatureCoordSys = sProperties.substring(nStartPos,nEndPos);
  g_aProperties["featureCoordSys"] = sFeatureCoordSys;

  //get the filter coordsys
  nStartPos = sProperties.indexOf('<FILTERCOORDSYS',0);
  nStartPos = sProperties.indexOf('id="',nStartPos);
  nStartPos = nStartPos + 4;
  nEndPos = sProperties.indexOf(g_sDQuote,nStartPos);
  sFilterCoordSys = sProperties.substring(nStartPos,nEndPos);
  g_aProperties["filterCoordSys"] = sFilterCoordSys;

  //get the mapunits property
  nStartPos = sProperties.indexOf('<MAPUNITS',0);
  nStartPos = sProperties.indexOf('units="',nStartPos);
  nStartPos = nStartPos + 7;
  nEndPos = sProperties.indexOf(g_sDQuote,nStartPos);
  sMapUnits = sProperties.substring(nStartPos,nEndPos);
  g_aProperties["mapUnits"] = sMapUnits;
  switch(sMapUnits){
  case "feet":
  case "us_survey_feet":
    g_aProperties["mapUnitsDisplay"] = "feet";
    break;
  }

}

function parseServiceInfoResponse(origRequest){
  parseProperties(origRequest);
  parseEnvironment(origRequest);
  calcScale();
  parseLayerInfo(origRequest);
}

function popUpPrintPage(){
  var sPopUpUrl = 'printPage.php?printMapHeight=' + g_nPrintMapHeight + '&printMapWidth=' + g_nPrintMapWidth + "&showresults=" + g_bIncludeResultsTable;
  g_oPrintPageWindow = window.open(sPopUpUrl, "PrintPage", "height=" + (g_nPrintMapHeight + 100) + ",width=" + (g_nPrintMapWidth + 100) + ",scrollbars=1,resizable=1,menubar=1,toolbar=1,status=1,location=1");
}

function zoomToEnvelope(nEnvelopeId){
  var nStartPos = 0;
  var nEndPos = 0;
  var sEnvelope = "";

  if (g_bOkToGetMap){
    sEnvelope = g_aEnvelopes[nEnvelopeId];


    nStartPos = sEnvelope.indexOf('<ENVELOPE minx="');
    nStartPos = nStartPos + 16;
    nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
    g_fMinX = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

    nStartPos = sEnvelope.indexOf('miny="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
    g_fMinY = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

    nStartPos = sEnvelope.indexOf('maxx="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
    g_fMaxX = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

    nStartPos = sEnvelope.indexOf('maxy="',nStartPos);
    nStartPos = nStartPos + 6;
    nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
    g_fMaxY = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

    //if it is a point, apply zoom out factor
    if (g_fMinX == g_fMaxX && g_fMinY == g_fMaxY){
      g_fMinX = g_fMinX - (g_nZoomToPointDist / 2);
      g_fMaxX = g_fMinX + g_nZoomToPointDist;
      g_fMinY = g_fMinY - (g_nZoomToPointDist / 2);
      g_fMaxY = g_fMinY + g_nZoomToPointDist;
    } else {
      //is not a point, so apply singleselect zoom factor
      var fXDist = g_fMaxX - g_fMinX;
      var fYDist = g_fMaxY - g_fMinY;
      fXDist = (fXDist * g_fSingleSelectZoomFactor);
      fYDist = (fYDist * g_fSingleSelectZoomFactor);

      g_fMinX = g_fMinX - fXDist;
      g_fMaxX = g_fMaxX + fXDist;
      g_fMinY = g_fMinY - fYDist;
      g_fMaxY = g_fMaxY + fYDist;
    }

    loadMap();
  }

}

function zoomToRelativeScale(){

  var fNewXDist = 0;
  var fNewYDist = 0;
  var fXDist = (g_fMaxX - g_fMinX);
  var fYDist = (g_fMaxY - g_fMinY);
  var fCenterX = g_fMinX + (fXDist / 2);
  var fCenterY = g_fMinY + (fYDist / 2);

  var nScale = 0;
  var nInches = 0;

  //get pixel size in meters - .0254 is number of meters in an inch
  var fPixelSize = .0254 / g_aProperties["dpi"];

  //convert pixel size to desired units
  switch(g_aProperties["mapUnits"]){
    case "feet":
    case "us_survey_feet":
      //pixel size in feet
      fPixelSize = fPixelSize * 3.28;
      break;
    case "decimal_degrees":
      //pixel size in degrees
      //one degree = 111.195 km
      fPixelSize = fPixelSize / 111195;
      break;
    case "meters":
    break;
  }

  if (g_bOkToGetMap){
    nScale = document.getElementById("zoomToScaleValue").value;
    if (isNaN(nScale)){
      alert(nScale + " is not a valid number");
    } else {
      //calculate what xdist should be based on new scale
      //calculate ydist based on aspect ratio
      //loadmap with new extents
      fNewXDist = nScale * (fPixelSize * g_nMapWidth);
      fNewYDist = fNewXDist / g_fMapAspectRatio;
      g_fMinX = fCenterX - Math.abs((fNewXDist) / 2);
      g_fMaxX = g_fMinX + fNewXDist;
      g_fMinY = fCenterY - Math.abs((fNewYDist) / 2);
      g_fMaxY = g_fMinY + fNewYDist;
      loadMap();
    }
  }
}

function zoomToSelectedFeatures(){
  //loop through selected features array and look for the minx and miny with
  //the lowest value and the maxx maxy with highest value
  var nStartPos = 0;
  var nEndPos = 0;
  var nLoopCounter = 0;

  var fCenterX = 0;
  var fCenterY = 0;
  var fMinX = 0;
  var fMinY = 0;
  var fMaxX = 0;
  var fMaxY = 0;
  var fXDist = 0;
  var fYDist = 0;


  var sEnvelope = "";

  if (g_bOkToGetMap){
    for (nLoopCounter = 0;nLoopCounter < g_aEnvelopes.length;nLoopCounter++){
      sEnvelope = g_aEnvelopes[nLoopCounter];
      nStartPos = sEnvelope.indexOf('<ENVELOPE minx="');
      nStartPos = nStartPos + 16;
      nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
      fMinX = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

      nStartPos = sEnvelope.indexOf('miny="',nStartPos);
      nStartPos = nStartPos + 6;
      nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
      fMinY = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

      nStartPos = sEnvelope.indexOf('maxx="',nStartPos);
      nStartPos = nStartPos + 6;
      nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
      fMaxX = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

      nStartPos = sEnvelope.indexOf('maxy="',nStartPos);
      nStartPos = nStartPos + 6;
      nEndPos = sEnvelope.indexOf(g_sDQuote,nStartPos);
      fMaxY = parseFloat(sEnvelope.substring(nStartPos,nEndPos));

      if (nLoopCounter > 0){
        if (fMinX < g_fMinX) g_fMinX = fMinX;
        if (fMaxX > g_fMaxX) g_fMaxX = fMaxX;
        if (fMinY < g_fMinY) g_fMinY = fMinY;
        if (fMaxY > g_fMaxY) g_fMaxY = fMaxY;
      } else {
        g_fMinX = fMinX;
        g_fMaxX = fMaxX;
        g_fMinY = fMinY;
        g_fMaxY = fMaxY;
      }
    }

    fXDist = g_fMaxX - g_fMinX;
    fYDist = g_fMaxY - g_fMinY;

    //get the center point then calculate box based on aspect ratio
    fCenterX = g_fMinX + (fXDist / 2);
    fCenterY = g_fMinY + (fYDist / 2);

    /* 2007_03_27 - updated this to use compare aspect ratio of zoom box and map aspect ratio
    //if xdist is greater than ydist, use xdist and calc ydist based on aspect ratio
    //else -  use ydist and calc xdist based on aspect ratio
    if(Math.abs(fXDist) >= Math.abs(fYDist)){
      g_fMinY = fCenterY - ((fXDist / g_fMapAspectRatio) / 2);
      g_fMaxY = fCenterY + ((fXDist / g_fMapAspectRatio) / 2);
    } else {
      g_fMinX = fCenterX - ((fYDist * g_fMapAspectRatio) / 2);
      g_fMaxX = fCenterX + ((fYDist * g_fMapAspectRatio) / 2);
    }*/

    //compare aspect ration of map (R) to aspect ratio of zoom box (Z)
    //if Z < R => newWidth = R * H
    //if Z > R => newHeight = W / R
    var R = g_fMapAspectRatio;
    var Z = Math.abs(fXDist / fYDist);

    if (Z >= R){
      var fNewYDist = Math.abs(fXDist / R);
      g_fMinY = fCenterY - (fNewYDist / 2);
      g_fMaxY = fCenterY + (fNewYDist / 2);
    } else {
      var fNewXDist = Math.abs(R * fYDist);
      g_fMinX = fCenterX - (fNewXDist / 2);
      g_fMaxX = fCenterX + (fNewXDist / 2);
    }


    //zoom out by single select zoom factor
    fXDist = g_fMaxX - g_fMinX;
    fYDist = g_fMaxY - g_fMinY;
    fXDist = (fXDist * g_fSingleSelectZoomFactor);
    fYDist = (fYDist * g_fSingleSelectZoomFactor);

    g_fMinX = g_fMinX - fXDist;
    g_fMaxX = g_fMaxX + fXDist;
    g_fMinY = g_fMinY - fYDist;
    g_fMaxY = g_fMaxY + fYDist;

    loadMap();
  }
}

function zoomToNextExtent(){
  if (g_bOkToGetMap){
    g_bAddExtentToBuffer = false;
    g_nExtentBufferIdx = g_nExtentBufferIdx + 1;

    g_fMinX = g_aExtentBuffer[g_nExtentBufferIdx]["minx"];
    g_fMinY = g_aExtentBuffer[g_nExtentBufferIdx]["miny"];
    g_fMaxX = g_aExtentBuffer[g_nExtentBufferIdx]["maxx"];
    g_fMaxY = g_aExtentBuffer[g_nExtentBufferIdx]["maxy"];
    loadMap();
  }
}

function zoomToPreviousExtent(){
  if (g_bOkToGetMap){
    g_bAddExtentToBuffer = false;
    g_nExtentBufferIdx = g_nExtentBufferIdx - 1;

    g_fMinX = g_aExtentBuffer[g_nExtentBufferIdx]["minx"];
    g_fMinY = g_aExtentBuffer[g_nExtentBufferIdx]["miny"];
    g_fMaxX = g_aExtentBuffer[g_nExtentBufferIdx]["maxx"];
    g_fMaxY = g_aExtentBuffer[g_nExtentBufferIdx]["maxy"];
    loadMap();
  }
}

/* This notice must be untouched at all times.

wz_jsgraphics.js    v. 2.33
The latest version is available at
http://www.walterzorn.com
or http://www.devira.com
or http://www.walterzorn.de

Copyright (c) 2002-2004 Walter Zorn. All rights reserved.
Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )
Last modified: 24. 10. 2005

Performance optimizations for Internet Explorer
by Thomas Frank and John Holdsworth.
fillPolygon method implemented by Matthieu Haller.

High Performance JavaScript Graphics Library.
Provides methods
- to draw lines, rectangles, ellipses, polygons
  with specifiable line thickness,
- to fill rectangles and ellipses
- to draw text.
NOTE: Operations, functions and branching have rather been optimized
to efficiency and speed than to shortness of source code.

LICENSE: LGPL

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
or see http://www.gnu.org/copyleft/lesser.html
*/


var jg_ihtm, jg_ie, jg_fast, jg_dom, jg_moz,
jg_n4 = (document.layers && typeof document.classes != "undefined");


function chkDHTM(x, i)
{
  x = document.body || null;
  jg_ie = x && typeof x.insertAdjacentHTML != "undefined";
  jg_dom = (x && !jg_ie &&
    typeof x.appendChild != "undefined" &&
    typeof document.createRange != "undefined" &&
    typeof (i = document.createRange()).setStartBefore != "undefined" &&
    typeof i.createContextualFragment != "undefined");
  jg_ihtm = !jg_ie && !jg_dom && x && typeof x.innerHTML != "undefined";
  jg_fast = jg_ie && document.all && !window.opera;
  jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";
}


function pntDoc()
{
  this.wnd.document.write(jg_fast? this.htmRpc() : this.htm);
  this.htm = '';
}


function pntCnvDom()
{
  var x = document.createRange();
  x.setStartBefore(this.cnv);
  x = x.createContextualFragment(jg_fast? this.htmRpc() : this.htm);
  this.cnv.appendChild(x);
  this.htm = '';
}


function pntCnvIe()
{
  this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this.htmRpc() : this.htm);
  this.htm = '';
}


function pntCnvIhtm()
{
  this.cnv.innerHTML += this.htm;
  this.htm = '';
}


function pntCnv()
{
  this.htm = '';
}


function mkDiv(x, y, w, h)
{
  this.htm += '<div style="position:absolute;'+
    'left:' + x + 'px;'+
    'top:' + y + 'px;'+
    'width:' + w + 'px;'+
    'height:' + h + 'px;'+
    'clip:rect(0,'+w+'px,'+h+'px,0);'+
    'background-color:' + this.color +
    (!jg_moz? ';overflow:hidden' : '')+
    ';"><\/div>';
}


function mkDivIe(x, y, w, h)
{
  this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';
}


function mkDivPrt(x, y, w, h)
{
  this.htm += '<div style="position:absolute;'+
    'border-left:' + w + 'px solid ' + this.color + ';'+
    'left:' + x + 'px;'+
    'top:' + y + 'px;'+
    'width:0px;'+
    'height:' + h + 'px;'+
    'clip:rect(0,'+w+'px,'+h+'px,0);'+
    'background-color:' + this.color +
    (!jg_moz? ';overflow:hidden' : '')+
    ';"><\/div>';
}


function mkLyr(x, y, w, h)
{
  this.htm += '<layer '+
    'left="' + x + '" '+
    'top="' + y + '" '+
    'width="' + w + '" '+
    'height="' + h + '" '+
    'bgcolor="' + this.color + '"><\/layer>\n';
}


var regex =  /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;
function htmRpc()
{
  return this.htm.replace(
    regex,
    '<div style="overflow:hidden;position:absolute;background-color:'+
    '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');
}


function htmPrtRpc()
{
  return this.htm.replace(
    regex,
    '<div style="overflow:hidden;position:absolute;background-color:'+
    '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');
}


function mkLin(x1, y1, x2, y2)
{
  if (x1 > x2)
  {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2-x1, dy = Math.abs(y2-y1),
  x = x1, y = y1,
  yIncr = (y1 > y2)? -1 : 1;

  if (dx >= dy)
  {
    var pr = dy<<1,
    pru = pr - (dx<<1),
    p = pr-dx,
    ox = x;
    while ((dx--) > 0)
    {
      ++x;
      if (p > 0)
      {
        this.mkDiv(ox, y, x-ox, 1);
        y += yIncr;
        p += pru;
        ox = x;
      }
      else p += pr;
    }
    this.mkDiv(ox, y, x2-ox+1, 1);
  }

  else
  {
    var pr = dx<<1,
    pru = pr - (dy<<1),
    p = pr-dy,
    oy = y;
    if (y2 <= y1)
    {
      while ((dy--) > 0)
      {
        if (p > 0)
        {
          this.mkDiv(x++, y, 1, oy-y+1);
          y += yIncr;
          p += pru;
          oy = y;
        }
        else
        {
          y += yIncr;
          p += pr;
        }
      }
      this.mkDiv(x2, y2, 1, oy-y2+1);
    }
    else
    {
      while ((dy--) > 0)
      {
        y += yIncr;
        if (p > 0)
        {
          this.mkDiv(x++, oy, 1, y-oy);
          p += pru;
          oy = y;
        }
        else p += pr;
      }
      this.mkDiv(x2, oy, 1, y2-oy+1);
    }
  }
}


function mkLin2D(x1, y1, x2, y2)
{
  if (x1 > x2)
  {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2-x1, dy = Math.abs(y2-y1),
  x = x1, y = y1,
  yIncr = (y1 > y2)? -1 : 1;

  var s = this.stroke;
  if (dx >= dy)
  {
    if (dx > 0 && s-3 > 0)
    {
      var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;
      _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
    }
    else var _s = s;
    var ad = Math.ceil(s/2);

    var pr = dy<<1,
    pru = pr - (dx<<1),
    p = pr-dx,
    ox = x;
    while ((dx--) > 0)
    {
      ++x;
      if (p > 0)
      {
        this.mkDiv(ox, y, x-ox+ad, _s);
        y += yIncr;
        p += pru;
        ox = x;
      }
      else p += pr;
    }
    this.mkDiv(ox, y, x2-ox+ad+1, _s);
  }

  else
  {
    if (s-3 > 0)
    {
      var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;
      _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
    }
    else var _s = s;
    var ad = Math.round(s/2);

    var pr = dx<<1,
    pru = pr - (dy<<1),
    p = pr-dy,
    oy = y;
    if (y2 <= y1)
    {
      ++ad;
      while ((dy--) > 0)
      {
        if (p > 0)
        {
          this.mkDiv(x++, y, _s, oy-y+ad);
          y += yIncr;
          p += pru;
          oy = y;
        }
        else
        {
          y += yIncr;
          p += pr;
        }
      }
      this.mkDiv(x2, y2, _s, oy-y2+ad);
    }
    else
    {
      while ((dy--) > 0)
      {
        y += yIncr;
        if (p > 0)
        {
          this.mkDiv(x++, oy, _s, y-oy+ad);
          p += pru;
          oy = y;
        }
        else p += pr;
      }
      this.mkDiv(x2, oy, _s, y2-oy+ad+1);
    }
  }
}


function mkLinDott(x1, y1, x2, y2)
{
  if (x1 > x2)
  {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2-x1, dy = Math.abs(y2-y1),
  x = x1, y = y1,
  yIncr = (y1 > y2)? -1 : 1,
  drw = true;
  if (dx >= dy)
  {
    var pr = dy<<1,
    pru = pr - (dx<<1),
    p = pr-dx;
    while ((dx--) > 0)
    {
      if (drw) this.mkDiv(x, y, 1, 1);
      drw = !drw;
      if (p > 0)
      {
        y += yIncr;
        p += pru;
      }
      else p += pr;
      ++x;
    }
    if (drw) this.mkDiv(x, y, 1, 1);
  }

  else
  {
    var pr = dx<<1,
    pru = pr - (dy<<1),
    p = pr-dy;
    while ((dy--) > 0)
    {
      if (drw) this.mkDiv(x, y, 1, 1);
      drw = !drw;
      y += yIncr;
      if (p > 0)
      {
        ++x;
        p += pru;
      }
      else p += pr;
    }
    if (drw) this.mkDiv(x, y, 1, 1);
  }
}


function mkOv(left, top, width, height)
{
  var a = width>>1, b = height>>1,
  wod = width&1, hod = (height&1)+1,
  cx = left+a, cy = top+b,
  x = 0, y = b,
  ox = 0, oy = b,
  aa = (a*a)<<1, bb = (b*b)<<1,
  st = (aa>>1)*(1-(b<<1)) + bb,
  tt = (bb>>1) - aa*((b<<1)-1),
  w, h;
  while (y > 0)
  {
    if (st < 0)
    {
      st += bb*((x<<1)+3);
      tt += (bb<<1)*(++x);
    }
    else if (tt < 0)
    {
      st += bb*((x<<1)+3) - (aa<<1)*(y-1);
      tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
      w = x-ox;
      h = oy-y;
      if (w&2 && h&2)
      {
        this.mkOvQds(cx, cy, -x+2, ox+wod, -oy, oy-1+hod, 1, 1);
        this.mkOvQds(cx, cy, -x+1, x-1+wod, -y-1, y+hod, 1, 1);
      }
      else this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, oy-h+hod, w, h);
      ox = x;
      oy = y;
    }
    else
    {
      tt -= aa*((y<<1)-3);
      st -= (aa<<1)*(--y);
    }
  }
  this.mkDiv(cx-a, cy-oy, a-ox+1, (oy<<1)+hod);
  this.mkDiv(cx+ox+wod, cy-oy, a-ox+1, (oy<<1)+hod);
}


function mkOv2D(left, top, width, height)
{
  var s = this.stroke;
  width += s-1;
  height += s-1;
  var a = width>>1, b = height>>1,
  wod = width&1, hod = (height&1)+1,
  cx = left+a, cy = top+b,
  x = 0, y = b,
  aa = (a*a)<<1, bb = (b*b)<<1,
  st = (aa>>1)*(1-(b<<1)) + bb,
  tt = (bb>>1) - aa*((b<<1)-1);

  if (s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))
  {
    var ox = 0, oy = b,
    w, h,
    pxl, pxr, pxt, pxb, pxw;
    while (y > 0)
    {
      if (st < 0)
      {
        st += bb*((x<<1)+3);
        tt += (bb<<1)*(++x);
      }
      else if (tt < 0)
      {
        st += bb*((x<<1)+3) - (aa<<1)*(y-1);
        tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
        w = x-ox;
        h = oy-y;

        if (w-1)
        {
          pxw = w+1+(s&1);
          h = s;
        }
        else if (h-1)
        {
          pxw = s;
          h += 1+(s&1);
        }
        else pxw = h = s;
        this.mkOvQds(cx, cy, -x+1, ox-pxw+w+wod, -oy, -h+oy+hod, pxw, h);
        ox = x;
        oy = y;
      }
      else
      {
        tt -= aa*((y<<1)-3);
        st -= (aa<<1)*(--y);
      }
    }
    this.mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);
    this.mkDiv(cx+a+wod-s+1, cy-oy, s, (oy<<1)+hod);
  }

  else
  {
    var _a = (width-((s-1)<<1))>>1,
    _b = (height-((s-1)<<1))>>1,
    _x = 0, _y = _b,
    _aa = (_a*_a)<<1, _bb = (_b*_b)<<1,
    _st = (_aa>>1)*(1-(_b<<1)) + _bb,
    _tt = (_bb>>1) - _aa*((_b<<1)-1),

    pxl = new Array(),
    pxt = new Array(),
    _pxb = new Array();
    pxl[0] = 0;
    pxt[0] = b;
    _pxb[0] = _b-1;
    while (y > 0)
    {
      if (st < 0)
      {
        st += bb*((x<<1)+3);
        tt += (bb<<1)*(++x);
        pxl[pxl.length] = x;
        pxt[pxt.length] = y;
      }
      else if (tt < 0)
      {
        st += bb*((x<<1)+3) - (aa<<1)*(y-1);
        tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
        pxl[pxl.length] = x;
        pxt[pxt.length] = y;
      }
      else
      {
        tt -= aa*((y<<1)-3);
        st -= (aa<<1)*(--y);
      }

      if (_y > 0)
      {
        if (_st < 0)
        {
          _st += _bb*((_x<<1)+3);
          _tt += (_bb<<1)*(++_x);
          _pxb[_pxb.length] = _y-1;
        }
        else if (_tt < 0)
        {
          _st += _bb*((_x<<1)+3) - (_aa<<1)*(_y-1);
          _tt += (_bb<<1)*(++_x) - _aa*(((_y--)<<1)-3);
          _pxb[_pxb.length] = _y-1;
        }
        else
        {
          _tt -= _aa*((_y<<1)-3);
          _st -= (_aa<<1)*(--_y);
          _pxb[_pxb.length-1]--;
        }
      }
    }

    var ox = 0, oy = b,
    _oy = _pxb[0],
    l = pxl.length,
    w, h;
    for (var i = 0; i < l; i++)
    {
      if (typeof _pxb[i] != "undefined")
      {
        if (_pxb[i] < _oy || pxt[i] < oy)
        {
          x = pxl[i];
          this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, _oy+hod, x-ox, oy-_oy);
          ox = x;
          oy = pxt[i];
          _oy = _pxb[i];
        }
      }
      else
      {
        x = pxl[i];
        this.mkDiv(cx-x+1, cy-oy, 1, (oy<<1)+hod);
        this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
        ox = x;
        oy = pxt[i];
      }
    }
    this.mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);
    this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
  }
}


function mkOvDott(left, top, width, height)
{
  var a = width>>1, b = height>>1,
  wod = width&1, hod = height&1,
  cx = left+a, cy = top+b,
  x = 0, y = b,
  aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
  st = (aa2>>1)*(1-(b<<1)) + bb,
  tt = (bb>>1) - aa2*((b<<1)-1),
  drw = true;
  while (y > 0)
  {
    if (st < 0)
    {
      st += bb*((x<<1)+3);
      tt += (bb<<1)*(++x);
    }
    else if (tt < 0)
    {
      st += bb*((x<<1)+3) - aa4*(y-1);
      tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);
    }
    else
    {
      tt -= aa2*((y<<1)-3);
      st -= aa4*(--y);
    }
    if (drw) this.mkOvQds(cx, cy, -x, x+wod, -y, y+hod, 1, 1);
    drw = !drw;
  }
}


function mkRect(x, y, w, h)
{
  var s = this.stroke;
  this.mkDiv(x, y, w, s);
  this.mkDiv(x+w, y, s, h);
  this.mkDiv(x, y+h, w+s, s);
  this.mkDiv(x, y+s, s, h-s);
}


function mkRectDott(x, y, w, h)
{
  this.drawLine(x, y, x+w, y);
  this.drawLine(x+w, y, x+w, y+h);
  this.drawLine(x, y+h, x+w, y+h);
  this.drawLine(x, y, x, y+h);
}


function jsgFont()
{
  this.PLAIN = 'font-weight:normal;';
  this.BOLD = 'font-weight:bold;';
  this.ITALIC = 'font-style:italic;';
  this.ITALIC_BOLD = this.ITALIC + this.BOLD;
  this.BOLD_ITALIC = this.ITALIC_BOLD;
}
var Font = new jsgFont();


function jsgStroke()
{
  this.DOTTED = -1;
}
var Stroke = new jsgStroke();


function jsGraphics(id, wnd)
{
  this.setColor = new Function('arg', 'this.color = arg.toLowerCase();');

  this.setStroke = function(x)
  {
    this.stroke = x;
    if (!(x+1))
    {
      this.drawLine = mkLinDott;
      this.mkOv = mkOvDott;
      this.drawRect = mkRectDott;
    }
    else if (x-1 > 0)
    {
      this.drawLine = mkLin2D;
      this.mkOv = mkOv2D;
      this.drawRect = mkRect;
    }
    else
    {
      this.drawLine = mkLin;
      this.mkOv = mkOv;
      this.drawRect = mkRect;
    }
  };


  this.setPrintable = function(arg)
  {
    this.printable = arg;
    if (jg_fast)
    {
      this.mkDiv = mkDivIe;
      this.htmRpc = arg? htmPrtRpc : htmRpc;
    }
    else this.mkDiv = jg_n4? mkLyr : arg? mkDivPrt : mkDiv;
  };


  this.setFont = function(fam, sz, sty)
  {
    this.ftFam = fam;
    this.ftSz = sz;
    this.ftSty = sty || Font.PLAIN;
  };


  this.drawPolyline = this.drawPolyLine = function(x, y, s)
  {
    for (var i=0 ; i<x.length-1 ; i++ )
      this.drawLine(x[i], y[i], x[i+1], y[i+1]);
  };


  this.fillRect = function(x, y, w, h)
  {
    this.mkDiv(x, y, w, h);
  };


  this.drawPolygon = function(x, y)
  {
    this.drawPolyline(x, y);
    this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);
  };


  this.drawEllipse = this.drawOval = function(x, y, w, h)
  {
    this.mkOv(x, y, w, h);
  };


  this.fillEllipse = this.fillOval = function(left, top, w, h)
  {
    var a = (w -= 1)>>1, b = (h -= 1)>>1,
    wod = (w&1)+1, hod = (h&1)+1,
    cx = left+a, cy = top+b,
    x = 0, y = b,
    ox = 0, oy = b,
    aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
    st = (aa2>>1)*(1-(b<<1)) + bb,
    tt = (bb>>1) - aa2*((b<<1)-1),
    pxl, dw, dh;
    if (w+1) while (y > 0)
    {
      if (st < 0)
      {
        st += bb*((x<<1)+3);
        tt += (bb<<1)*(++x);
      }
      else if (tt < 0)
      {
        st += bb*((x<<1)+3) - aa4*(y-1);
        pxl = cx-x;
        dw = (x<<1)+wod;
        tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);
        dh = oy-y;
        this.mkDiv(pxl, cy-oy, dw, dh);
        this.mkDiv(pxl, cy+y+hod, dw, dh);
        ox = x;
        oy = y;
      }
      else
      {
        tt -= aa2*((y<<1)-3);
        st -= aa4*(--y);
      }
    }
    this.mkDiv(cx-a, cy-oy, w+1, (oy<<1)+hod);
  };


/* fillPolygon method, implemented by Matthieu Haller.
This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.
C source of GD 1.8.4 found at http://www.boutell.com/gd/

THANKS to Kirsten Schulz for the polygon fixes!

The intersection finding technique of this code could be improved
by remembering the previous intertersection, and by using the slope.
That could help to adjust intersections to produce a nice
interior_extrema. */
  this.fillPolygon = function(array_x, array_y)
  {
    var i;
    var y;
    var miny, maxy;
    var x1, y1;
    var x2, y2;
    var ind1, ind2;
    var ints;

    var n = array_x.length;

    if (!n) return;


    miny = array_y[0];
    maxy = array_y[0];
    for (i = 1; i < n; i++)
    {
      if (array_y[i] < miny)
        miny = array_y[i];

      if (array_y[i] > maxy)
        maxy = array_y[i];
    }
    for (y = miny; y <= maxy; y++)
    {
      var polyInts = new Array();
      ints = 0;
      for (i = 0; i < n; i++)
      {
        if (!i)
        {
          ind1 = n-1;
          ind2 = 0;
        }
        else
        {
          ind1 = i-1;
          ind2 = i;
        }
        y1 = array_y[ind1];
        y2 = array_y[ind2];
        if (y1 < y2)
        {
          x1 = array_x[ind1];
          x2 = array_x[ind2];
        }
        else if (y1 > y2)
        {
          y2 = array_y[ind1];
          y1 = array_y[ind2];
          x2 = array_x[ind1];
          x1 = array_x[ind2];
        }
        else continue;

         // modified 11. 2. 2004 Walter Zorn
        if ((y >= y1) && (y < y2))
          polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);

        else if ((y == maxy) && (y > y1) && (y <= y2))
          polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);
      }
      polyInts.sort(integer_compare);
      for (i = 0; i < ints; i+=2)
        this.mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);
    }
  };


  this.drawString = function(txt, x, y)
  {
    this.htm += '<div style="position:absolute;white-space:nowrap;'+
      'left:' + x + 'px;'+
      'top:' + y + 'px;'+
      'font-family:' +  this.ftFam + ';'+
      'font-size:' + this.ftSz + ';'+
      'color:' + this.color + ';' + this.ftSty + '">'+
      txt +
      '<\/div>';
  };


/* drawStringRect() added by Rick Blommers.
Allows to specify the size of the text rectangle and to align the
text both horizontally (e.g. right) and vertically within that rectangle */
  this.drawStringRect = function(txt, x, y, width, halign)
  {
    this.htm += '<div style="position:absolute;overflow:hidden;'+
      'left:' + x + 'px;'+
      'top:' + y + 'px;'+
      'width:'+width +'px;'+
      'text-align:'+halign+';'+
      'font-family:' +  this.ftFam + ';'+
      'font-size:' + this.ftSz + ';'+
      'color:' + this.color + ';' + this.ftSty + '">'+
      txt +
      '<\/div>';
  };


  this.drawImage = function(imgSrc, x, y, w, h, a)
  {
    this.htm += '<div style="position:absolute;'+
      'left:' + x + 'px;'+
      'top:' + y + 'px;'+
      'width:' +  w + ';'+
      'height:' + h + ';">'+
      '<img src="' + imgSrc + '" width="' + w + '" height="' + h + '"' + (a? (' '+a) : '') + '>'+
      '<\/div>';
  };


  this.clear = function()
  {
    this.htm = "";
    if (this.cnv) this.cnv.innerHTML = this.defhtm;
  };


  this.mkOvQds = function(cx, cy, xl, xr, yt, yb, w, h)
  {
    this.mkDiv(xr+cx, yt+cy, w, h);
    this.mkDiv(xr+cx, yb+cy, w, h);
    this.mkDiv(xl+cx, yb+cy, w, h);
    this.mkDiv(xl+cx, yt+cy, w, h);
  };

  this.setStroke(1);
  this.setFont('verdana,geneva,helvetica,sans-serif', String.fromCharCode(0x31, 0x32, 0x70, 0x78), Font.PLAIN);
  this.color = '#000000';
  this.htm = '';
  this.wnd = wnd || window;

  if (!(jg_ie || jg_dom || jg_ihtm)) chkDHTM();
  if (typeof id != 'string' || !id) this.paint = pntDoc;
  else
  {
    this.cnv = document.all? (this.wnd.document.all[id] || null)
      : document.getElementById? (this.wnd.document.getElementById(id) || null)
      : null;
    this.defhtm = (this.cnv && this.cnv.innerHTML)? this.cnv.innerHTML : '';
    this.paint = jg_dom? pntCnvDom : jg_ie? pntCnvIe : jg_ihtm? pntCnvIhtm : pntCnv;
  }

  this.setPrintable(false);
}



function integer_compare(x,y)
{
  return (x < y) ? -1 : ((x > y)*1);
}

// Title: Tigra Color Picker
// URL: http://www.softcomplex.com/products/tigra_color_picker/
// Version: 1.1
// Date: 06/26/2003 (mm/dd/yyyy)
// Note: Permission given to use this script in ANY kind of applications if
//    header lines are left unchanged.
// Note: Script consists of two files: picker.js and picker.html

var TCP = new TColorPicker();
var g_sSwatch = "";

function TCPopup(field, palette, sSwatch) {
  g_sSwatch = sSwatch;
  this.field = field;
  this.initPalette = !palette || palette > 3 ? 0 : palette;
  var w = 207, h = 220,
  move = screen ?
    ',left=' + ((screen.width - w) >> 1) + ',top=' + ((screen.height - h) >> 1) : '',
  o_colWindow = window.open('/shared_php/picker.php', null, "help=no,status=no,scrollbars=yes,resizable=no,address=no" + move + ",width=" + w + ",height=" + h + ",dependent=yes", true);
  o_colWindow.opener = window;
  o_colWindow.focus();
}

function TCBuildCell (R, G, B, w, h) {
  return '<td style="border:1px solid #000000;cursor:pointer;cursor:hand;height:' + h + 'px;width:' + w + 'px" onmouseover="P.P(\'' + this.dec2hex((R << 16) + (G << 8) + B) + '\')" onclick="P.S(\'' + this.dec2hex((R << 16) + (G << 8) + B) + '\');" bgcolor="#' + this.dec2hex((R << 16) + (G << 8) + B) + '"><!--<a href="javascript:P.S(\'' + this.dec2hex((R << 16) + (G << 8) + B) + '\')" onmouseover="P.P(\'' + this.dec2hex((R << 16) + (G << 8) + B) + '\')"><img alt="pick color" src="../images/pixel.gif" width="' + w + '" height="' + h + '" border="0" /></a>--></td>';
}

function TCSelect(c) {
  this.field.value = '#' + c.toUpperCase();
  document.getElementById(g_sSwatch).style.background = '#' + c.toUpperCase();
  this.win.close();
}

function TCPaint(c, b_noPref) {
  c = (b_noPref ? '' : '#') + c.toUpperCase();
  if (this.o_samp)
    this.o_samp.innerHTML = '<font face="Tahoma" size="2">' + c +' <font color="white">' + c + '</font></font>'
  if(this.doc.layers)
    this.sample.bgColor = c;
  else {
    if (this.sample.backgroundColor != null) this.sample.backgroundColor = c;
    else if (this.sample.background != null) this.sample.background = c;
  }
}

function TCGenerateSafe() {
  var s = '';
  for (j = 0; j < 12; j ++) {
    s += "<tr>";
    for (k = 0; k < 3; k ++)
      for (i = 0; i <= 5; i ++)
        s += this.bldCell(k * 51 + (j % 2) * 51 * 3, Math.floor(j / 2) * 51, i * 51, 10, 12);
    s += "</tr>";
  }
  return s;
}

function TCGenerateWind() {
  var s = '';
  for (j = 0; j < 12; j ++) {
    s += '<tr>';
    for (k = 0; k < 3; k ++)
      for (i = 0; i <= 5; i++)
        s += this.bldCell(i * 51, k * 51 + (j % 2) * 51 * 3, Math.floor(j / 2) * 51, 10, 12);
    s += "</tr>";
  }
  return s
}
function TCGenerateMac() {
  var s = '';
  var c = 0,n = 1;
  var r,g,b;
  for (j = 0; j < 15; j ++) {
    s += "<tr>";
    for (k = 0; k < 3; k ++)
      for (i = 0; i <= 5; i++){
        if(j<12){
        s += this.bldCell( 255-(Math.floor(j / 2) * 51), 255-(k * 51 + (j % 2) * 51 * 3),255-(i * 51), 10, 12);
        }else{
          if(n<=14){
            r = 255-(n * 17);
            g=b=0;
          }else if(n>14 && n<=28){
            g = 255-((n-14) * 17);
            r=b=0;
          }else if(n>28 && n<=42){
            b = 255-((n-28) * 17);
            r=g=0;
          }else{
            r=g=b=255-((n-42) * 17);
          }
          s += this.bldCell( r, g,b, 10, 12);
          n++;
        }
      }
    s += "</tr>";
  }
  return s;
}

function TCGenerateGray() {
  var s = '';
  for (j = 0; j <= 15; j ++) {
    s += "<tr>";
    for (k = 0; k <= 15; k ++) {
      g = Math.floor((k + j * 16) % 256);
      s += this.bldCell(g, g, g, 10, 12);
    }
    s += '</tr>';
  }
  return s
}

function TCDec2Hex(v) {
  v = v.toString(16);
  for(; v.length < 6; v = '0' + v);
  return v;
}

function TCChgMode(v) {
  for (var k in this.divs) this.hide(k);
  this.show(v);
}

function TColorPicker(field) {
  this.build0 = TCGenerateSafe;
  this.build1 = TCGenerateWind;
  this.build2 = TCGenerateGray;
  this.build3 = TCGenerateMac;
  this.show = document.layers ?
    function (div) { this.divs[div].visibility = 'show' } :
    function (div) { this.divs[div].visibility = 'visible' };
  this.hide = document.layers ?
    function (div) { this.divs[div].visibility = 'hide' } :
    function (div) { this.divs[div].visibility = 'hidden' };
  // event handlers
  this.C       = TCChgMode;
  this.S       = TCSelect;
  this.P       = TCPaint;
  this.popup   = TCPopup;
  this.draw    = TCDraw;
  this.dec2hex = TCDec2Hex;
  this.bldCell = TCBuildCell;
  this.divs = [];
}

function TCDraw(o_win, o_doc) {
  this.win = o_win;
  this.doc = o_doc;
  var
  s_tag_openT  = o_doc.layers ?
    'layer visibility="hidden" top="54" left="5" width="182"' :
    'div style="visibility:hidden;position:absolute;left:6px;top:54px;width:182px;height:0"',
  s_tag_openS  = o_doc.layers ? 'layer top="32" left="6"' : 'div',
  s_tag_close  = o_doc.layers ? 'layer' : 'div'

  this.doc.write('<' + s_tag_openS + ' id="sam"><table cellpadding="0" cellspacing="0" border="1" width="181" align="center" class="bd"><tr><td align="center" height="18"><div id="samp"><font face="Tahoma" size="2">sample <font color="white">sample</font></font></div></td></tr></table></' + s_tag_close + '>');
  this.sample = o_doc.layers ? o_doc.layers['sam'] :
    o_doc.getElementById ? o_doc.getElementById('sam').style : o_doc.all['sam'].style

  for (var k = 0; k < 4; k ++) {
    this.doc.write('<' + s_tag_openT + ' id="p' + k + '" name="p' + k + '"><table style="margin-top:3px;" cellpadding="0" cellspacing="0" align="center">' + this['build' + k]() + '</table></' + s_tag_close + '>');
    this.divs[k] = o_doc.layers
      ? o_doc.layers['p' + k] : o_doc.all
        ? o_doc.all['p' + k].style : o_doc.getElementById('p' + k).style
  }
  if (!o_doc.layers && o_doc.body.innerHTML)
    this.o_samp = o_doc.all
      ? o_doc.all.samp : o_doc.getElementById('samp');
  this.C(this.initPalette);
  if (this.field.value) this.P(this.field.value, true)
}

// Title: tigra slider control
// Description: See the demo at url
// URL: http://www.softcomplex.com/products/tigra_slider_control/
// Version: 1.0 (commented source)
// Date: 02/15/2006
// Tech. Support: http://www.softcomplex.com/forum/
// Notes: This script is free. Visit official site for further details.

function slider (a_init, a_tpl) {

  this.f_setValue  = f_sliderSetValue;
  this.f_getPos    = f_sliderGetPos;
  
  // register in the global collection  
  if (!window.A_SLIDERS)
    window.A_SLIDERS = [];
  this.n_id = window.A_SLIDERS.length;
  window.A_SLIDERS[this.n_id] = this;

  // save config parameters in the slider object
  var s_key;
  if (a_tpl)
    for (s_key in a_tpl)
      this[s_key] = a_tpl[s_key];
  for (s_key in a_init)
    this[s_key] = a_init[s_key];

  this.n_pix2value = this.n_pathLength / (this.n_maxValue - this.n_minValue);
  if (this.n_value == null)
    this.n_value = this.n_minValue;

  // generate the control's HTML
  var container = get_element(this.s_container);
  
  if (container == null) {
    document.write(
      '<div style="width:' + this.n_controlWidth + 'px;height:' + this.n_controlHeight + 'px;border:0; background-image:url(' + this.s_imgControl + ')" id="sl' + this.n_id + 'base">' +
      '<img src="' + this.s_imgSlider + '" width="' + this.n_sliderWidth + '" height="' + this.n_sliderHeight + '" border="0" style="position:relative;left:' + this.n_pathLeft + 'px;top:' + this.n_pathTop + 'px;z-index:' + this.n_zIndex + ';cursor:hand;visibility:hidden;" name="sl' + this.n_id + 'slider" id="sl' + this.n_id + 'slider" onmousedown="return f_sliderMouseDown(' + this.n_id + ')"/></div>'
    );  
  } else {
    container.innerHTML = '<div style="width:' + this.n_controlWidth + 'px;height:' + this.n_controlHeight + 'px;border:0; background-image:url(' + this.s_imgControl + ')" id="sl' + this.n_id + 'base">' +
      '<img src="' + this.s_imgSlider + '" width="' + this.n_sliderWidth + '" height="' + this.n_sliderHeight + '" border="0" style="position:relative;left:' + this.n_pathLeft + 'px;top:' + this.n_pathTop + 'px;z-index:' + this.n_zIndex + ';cursor:hand;visibility:hidden;" name="sl' + this.n_id + 'slider" id="sl' + this.n_id + 'slider" onmousedown="return f_sliderMouseDown(' + this.n_id + ')"/></div>';
  }

  this.e_base   = get_element('sl' + this.n_id + 'base');
  this.e_slider = get_element('sl' + this.n_id + 'slider');
  
  // safely hook document/window events
  if (document.onmousemove != f_sliderMouseMove) {
    window.f_savedMouseMove = document.onmousemove;
    document.onmousemove = f_sliderMouseMove;
  }
  if (document.onmouseup != f_sliderMouseUp) {
    window.f_savedMouseUp = document.onmouseup;
    document.onmouseup = f_sliderMouseUp;
  }
  // preset to the value in the input box if available
  var e_input = this.s_form == null
    ? get_element(this.s_name)
    : document.forms[this.s_form]
      ? document.forms[this.s_form].elements[this.s_name]
      : null;
  this.f_setValue(e_input && e_input.value != '' ? e_input.value : null, 1);
  this.e_slider.style.visibility = 'visible';
}

function f_sliderSetValue (n_value, b_noInputCheck) {
  if (n_value == null)
    n_value = this.n_value == null ? this.n_minValue : this.n_value;
  if (isNaN(n_value))
    return false;
  // round to closest multiple if step is specified
  if (this.n_step)
    n_value = Math.round((n_value - this.n_minValue) / this.n_step) * this.n_step + this.n_minValue;
  // smooth out the result
  if (n_value % 1)
    n_value = Math.round(n_value * 1e5) / 1e5;

  if (n_value < this.n_minValue)
    n_value = this.n_minValue;
  if (n_value > this.n_maxValue)
    n_value = this.n_maxValue;

  this.n_value = n_value;

  // move the slider
  if (this.b_vertical)
    this.e_slider.style.top  = (this.n_pathTop + this.n_pathLength - Math.round((n_value - this.n_minValue) * this.n_pix2value)) + 'px';
  else
    this.e_slider.style.left = (this.n_pathLeft + Math.round((n_value - this.n_minValue) * this.n_pix2value)) + 'px';

  // save new value
  var e_input;
  if (this.s_form == null) {
    e_input = get_element(this.s_name);
    if (!e_input)
      return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the input with ID='" + this.s_name + "'.");
  }
  else {
    var e_form = document.forms[this.s_form];
    if (!e_form)
      return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the form with NAME='" + this.s_form + "'.");
    e_input = e_form.elements[this.s_name];
    if (!e_input)
      return b_noInputCheck ? null : f_sliderError(this.n_id, "Can not find the input with NAME='" + this.s_name + "'.");
  }
  e_input.value = n_value;
}

// get absolute position of the element in the document
function f_sliderGetPos (b_vertical, b_base) {
  var n_pos = 0,
    s_coord = (b_vertical ? 'Top' : 'Left');
  var o_elem = o_elem2 = b_base ? this.e_base : this.e_slider;
  
  while (o_elem) {
    n_pos += o_elem["offset" + s_coord];
    o_elem = o_elem.offsetParent;
  }
  o_elem = o_elem2;

  var n_offset;
  while (o_elem.tagName != "BODY") {
    n_offset = o_elem["scroll" + s_coord];
    if (n_offset)
      n_pos -= o_elem["scroll" + s_coord];
    o_elem = o_elem.parentNode;
  }
  return n_pos;
}

function f_sliderMouseDown (n_id) {
  window.n_activeSliderId = n_id;
  return false;
}

function f_sliderMouseUp (e_event, b_watching) {
  if (window.n_activeSliderId != null) {
    var o_slider = window.A_SLIDERS[window.n_activeSliderId];
    o_slider.f_setValue(o_slider.n_minValue + (o_slider.b_vertical
      ? (o_slider.n_pathLength - parseInt(o_slider.e_slider.style.top) + o_slider.n_pathTop)
      : (parseInt(o_slider.e_slider.style.left) - o_slider.n_pathLeft)) / o_slider.n_pix2value);
    if (b_watching) return;
    window.n_activeSliderId = null;
  }
  if (window.f_savedMouseUp)
    return window.f_savedMouseUp(e_event);
}

function f_sliderMouseMove (e_event) {

  if (!e_event && window.event) e_event = window.event;

  // save mouse coordinates
  if (e_event) {
    window.n_mouseX = e_event.clientX + f_scrollLeft();
    window.n_mouseY = e_event.clientY + f_scrollTop();
  }

  // check if in drag mode
  if (window.n_activeSliderId != null) {
    var o_slider = window.A_SLIDERS[window.n_activeSliderId];

    var n_pxOffset;
    if (o_slider.b_vertical) {
      var n_sliderTop = window.n_mouseY - o_slider.n_sliderHeight / 2 - o_slider.f_getPos(1, 1) - 3;
      // limit the slider movement
      if (n_sliderTop < o_slider.n_pathTop)
        n_sliderTop = o_slider.n_pathTop;
      var n_pxMax = o_slider.n_pathTop + o_slider.n_pathLength;
      if (n_sliderTop > n_pxMax)
        n_sliderTop = n_pxMax;
      o_slider.e_slider.style.top = n_sliderTop + 'px';
      n_pxOffset = o_slider.n_pathLength - n_sliderTop + o_slider.n_pathTop;
    }
    else {
      var n_sliderLeft = window.n_mouseX - o_slider.n_sliderWidth / 2 - o_slider.f_getPos(0, 1) - 3;
      // limit the slider movement
      if (n_sliderLeft < o_slider.n_pathLeft)
        n_sliderLeft = o_slider.n_pathLeft;
      var n_pxMax = o_slider.n_pathLeft + o_slider.n_pathLength;
      if (n_sliderLeft > n_pxMax)
        n_sliderLeft = n_pxMax;
      o_slider.e_slider.style.left = n_sliderLeft + 'px';
      n_pxOffset = n_sliderLeft - o_slider.n_pathLeft;
    }
    if (o_slider.b_watch)
       f_sliderMouseUp(e_event, 1);

    return false;
  }
  
  if (window.f_savedMouseMove)
    return window.f_savedMouseMove(e_event);
}

// get the scroller positions of the page
function f_scrollLeft() {
  return f_filterResults (
    window.pageXOffset ? window.pageXOffset : 0,
    document.documentElement ? document.documentElement.scrollLeft : 0,
    document.body ? document.body.scrollLeft : 0
  );
}
function f_scrollTop() {
  return f_filterResults (
    window.pageYOffset ? window.pageYOffset : 0,
    document.documentElement ? document.documentElement.scrollTop : 0,
    document.body ? document.body.scrollTop : 0
  );
}
function f_filterResults(n_win, n_docel, n_body) {
  var n_result = n_win ? n_win : 0;
  if (n_docel && (!n_result || (n_result > n_docel)))
    n_result = n_docel;
  return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

function f_sliderError (n_id, s_message) {
  alert("Slider #" + n_id + " Error:\n" + s_message);
  window.n_activeSliderId = null;
}

get_element = document.all ?
  function (s_id) { return document.all[s_id] } :
  function (s_id) { return document.getElementById(s_id) };

var A_TPL5h={b_vertical:false,b_watch:true,n_controlWidth:60,n_controlHeight:17,n_sliderWidth:9,n_sliderHeight:17,n_pathLeft:1,n_pathTop:1,n_pathLength:50,s_imgControl:"http://cdn.sidwellco.com/shared_images/ajaxgis/sldr5h_bg.gif",s_imgSlider:"http://cdn.sidwellco.com/shared_images/ajaxgis/sldr5h_sl.gif",n_zIndex:1};
var A_INIT5h={s_form:0,s_name:"sliderValue",s_container:"sliderContainer",n_minValue:0,n_maxValue:10,n_value:0,n_step:1};
new slider(A_INIT5h,A_TPL5h);
var A_TPL6v={b_vertical:true,b_watch:true,n_controlWidth:17,n_controlHeight:149,n_sliderWidth:17,n_sliderHeight:9,n_pathLeft:1,n_pathTop:2,n_pathLength:136,s_imgControl:"http://cdn.sidwellco.com/shared_images/ajaxgis/sldr5v_bg.gif",s_imgSlider:"http://cdn.sidwellco.com/shared_images/ajaxgis/sldr5v_sl.gif",n_zIndex:1};
var A_INIT6v={s_form:1,s_name:"zoomSliderValue",s_container:"zoomSliderContainer",n_minValue:1,n_maxValue:100,n_value:1,n_step:1};
new slider(A_INIT6v,A_TPL6v);
