//// Copyright 2008 by Kelvin Thompson. All Rights Reserved.//// FILE: IsoLonLat.js//// REQIRES: mfutil.js//          FOR: isPosInteger() isNumber()var g_points = new Array();var g_dataText = null;var g_map1;var g_map2;function OPreset( center, l1, t1, l2 ){  this.center = center;  this.l1 = l1;  this.t1 = t1;  this.l2 = l2;}function removePoint( point ){  var count = 0;  for ( var i=0; i<g_points.length; i++ )  {    if ( g_points[i] != null )    {      if ( g_points[i].equals(point) )        g_points[i] = null;      else        count++;    }  }    // allow or disallow user setting of permalink  allowPermaLink( count>0, null );  updateDataText();}function addPoint( point ){  // see if there's already a null slot  found = false;  for ( var i=0; i<g_points.length; i++ )  {    if ( g_points[i] == null )    {      g_points[i] = point;      found = true;  // use this empty slot      break;    }  }  // add a new slot of no empty ones found  if ( ! found )    g_points.push(point);  // let user make a permalink  allowPermaLink( true, null );    updateDataText();}//=========================var ua = navigator.userAgent.toLowerCase();var linePosBias = {x:0,y:0};if ( ua.indexOf('msie') != -1 ){  // tweak DIV position for IE  linePosBias.x = +2;  linePosBias.y =  0;}else if ( ua.indexOf('gecko/') != -1 ){  // tweak DIV position for Mozilla/Firefox  linePosBias.x = +1;  linePosBias.y =  0;}else if ( ua.indexOf('safari/') != -1 ){  // tweak DIV position for Safari  linePosBias.x = +1;  linePosBias.y =  0;}//=========================// A HorizLine is an overlay that is a thin horizontal line// implemented as a translucent DIV.function HorizLine(ycoord, opt_weight, opt_color) {  this.ycoord_ = ycoord;  this.weight_ = opt_weight || 5;  this.color_  = opt_color || "Blue";}HorizLine.prototype = new GOverlay();// Creates the DIV representing this HorizLine.HorizLine.prototype.initialize = function(map){  // make a new, uninitialized DIV  var div = document.createElement("div");  // if no opacity, use IE6/IE7 workarounds  if ( typeof div.style.opacity == "undefined"  &&       navigator.appName == 'Microsoft Internet Explorer' )  {    // Dopey IE6/IE7 doesn't handle modern opacity.    div.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";        // Create the DIV representing our HorizLine    // IE6 won't accept a small DIV height unless we do this    var txt = document.createTextNode("");    div.appendChild(txt);    div.style.fontSize = "1px";    div.style.lineHeight = "0";  }  // set up positioning and 50% transparency  div.style.position = "absolute";  div.style.backgroundColor = this.color_;  div.style.opacity = "0.5";  // ignored on IE6/IE7  // Our HorizLine is flat against the map, so we add ourselves to the  // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,  // below the marker shadows).  map.getPane(G_MAP_MAP_PANE).appendChild(div);  this.map_ = map;  this.div_ = div;}// remove the main DIV from the map paneHorizLine.prototype.remove = function(){  this.div_.parentNode.removeChild(this.div_);}// copy our data to a new HorizLineHorizLine.prototype.copy = function(){  return new HorizLine(this.ycoord_, this.weight_, this.color_);}// redraw the HorizLine based on the current projection and zoom levelHorizLine.prototype.redraw = function(force){  // We only need to redraw if the coordinate system has changed  if (!force) return;  // Calculate the DIV coordinates...  var c1 = this.map_.fromLatLngToDivPixel( new GLatLng(this.ycoord_,0) );  // Now position our DIV based on the DIV coordinates of our bounds  this.div_.style.left   = -9999 + "px";  this.div_.style.top    = (c1.y - this.weight_/2 + linePosBias.y) + "px";  this.div_.style.height = this.weight_ + "px";  this.div_.style.width  = 2*9999 + "px";}//=========================// A VertLine is a simple overlay that <tbd>.// It has a border of the given weight and color and can optionally// have a semi-transparent background color.function VertLine(xcoord, opt_weight, opt_color){  this.xcoord_ = xcoord;  this.weight_ = opt_weight || 5;  this.color_  = opt_color || "Blue";}VertLine.prototype = new GOverlay();// Creates the DIV representing this VertLine .VertLine.prototype.initialize = HorizLine.prototype.initialize;// Remove the main DIV from the map paneVertLine.prototype.remove = HorizLine.prototype.remove;// Copy our data to a new VertLineVertLine.prototype.copy = function(){  return new VertLine(this.ycoord_, this.weight_, this.color_);}// Redraw the VertLine based on the current projection and zoom levelVertLine.prototype.redraw = function(force){  // We only need to redraw if the coordinate system has changed  if (!force) return;  // Calculate the DIV coordinates...  var c1 = this.map_.fromLatLngToDivPixel( new GLatLng(0,this.xcoord_) );  // Now position our DIV based on the DIV coordinates of our bounds  this.div_.style.left   = (c1.x - this.weight_/2 + linePosBias.x) + "px";  this.div_.style.top    = -9999 + "px";  this.div_.style.width  = this.weight_ + "px";  this.div_.style.height = 2*9999 + "px";}//=========================function showAgain( map ){  // wipe old overlays  map.clearOverlays();    // get map bounds  var bounds = map.getBounds();  var boundsMin = bounds.getSouthWest();  var boundsMax = bounds.getNorthEast();  var minX = boundsMin.lng();  var minY = boundsMin.lat();  var maxX = boundsMax.lng();  var maxY = boundsMax.lat();    if ( maxX<minX || bounds.isFullLng() )  {    minX = -180;    maxX =  180;  }  // make new overlays  for ( var i=0; i<g_points.length; i++ )  {    var gpt = g_points[i];    if ( gpt != null )    {      // track if marker is in zone      var markerFitsHoriz = false;      var markerFitsVert = false;       // see if we can add a horiz line for iso-latitude      if ( minY < gpt.lat()  &&  gpt.lat() < maxY )      {        markerFitsHoriz = true;        if ( map.useForm == null  ||  map.useForm.IsoLat.checked )          map.addOverlay( new HorizLine(gpt.lat(),5,"Blue") );      }            // see if we can add a horiz line for anti-iso-latitude      var negy = -gpt.lat();      if ( minY < negy  &&  negy < maxY  &&  gpt.lat() != 0  &&           (map.useForm == null  ||  map.useForm.AntiLat.checked) )      {        map.addOverlay( new HorizLine(negy,5,"Red") );      }       // see if we can add a vert line for iso-longitude      if ( minX < gpt.lng()  &&  gpt.lng() < maxX )      {        markerFitsVert = true;        if ( map.useForm == null  ||  map.useForm.IsoLon.checked )        {          map.addOverlay( new VertLine(gpt.lng(),5,"Blue") );        }      }         // see if we can add a horiz line for anti-iso-longitude      var opx = ((gpt.lng() + 360) % 360) - 180;      if ( minX < opx  &&  opx < maxX  &&          (map.useForm == null  ||  map.useForm.AntiLon.checked) )      {        map.addOverlay( new VertLine(opx,5,"Red") );      }       if ( markerFitsHoriz && markerFitsVert )      {        map.addOverlay( new GMarker(gpt) );      }    }  }}function mapPairControls( mapA, mapB ){  var clickFunc = function(marker, point)    {      if (marker)        removePoint(marker.getPoint());      else if (point)        addPoint(point);      showAgain(mapA);      showAgain(mapB);    };    GEvent.addListener( mapA, 'click', clickFunc );  GEvent.addListener( mapB, 'moveend', function(){showAgain(mapB);} );  GEvent.addListener( mapB, 'zoom', function(oldZoomLevel,newZoomLevel){showAgain(mapB);} );}function updateDataText(){  g_dataText = "";  for ( var i=0; i<g_points.length; i++ )  {    var gpt = g_points[i];    if ( gpt != null )    {      if ( g_dataText.length > 0 )      g_dataText += "\n";      g_dataText += gpt.lat() + "," + gpt.lng() + ";";    }  }  // remove the last newline  if ( g_dataText.length > 1 )    g_dataText.length = g_dataText.length - 1;  document.getElementById("dataText").value = g_dataText;}function getCheckBoxState ( id ){  var chkState = document.getElementById(id).checked;  return chkState ? "1" : "0";}function makeXMLForMap(num,mapObj){  var txt = "<map num='" + num + "' ";    var centerLatLng = mapObj.getCenter();  txt += "lat='" + centerLatLng.lat() + "' lng='" + centerLatLng.lng() + "' ";    txt += "zoom='" + mapObj.getZoom() + "' ";    var mapTypeName = mapObj.getCurrentMapType().getName(false);  if ( mapTypeName == G_NORMAL_MAP.getName(false) )    mapTypeName = "normal";  else if ( mapTypeName == G_SATELLITE_MAP.getName(false) )    mapTypeName = "satellite";  else if ( mapTypeName == G_HYBRID_MAP.getName(false) )    mapTypeName = "hybrid";  else if ( mapTypeName == G_PHYSICAL_MAP.getName(false) )    mapTypeName = "physical";  else    mapTypeName = "normal";  txt += "type='" + mapTypeName + "' ";  var enabled = getCheckBoxState( "m" + num + "ila" );  enabled    += getCheckBoxState( "m" + num + "ilo" );  enabled    += getCheckBoxState( "m" + num + "ala" );  enabled    += getCheckBoxState( "m" + num + "alo" );  txt += "en='" + enabled + "' />\n";    return txt;}function makeXML(){  var xmlText = "<save>\n<coords>\n";  for ( var i=0; i<g_points.length; i++ )  {    var gpt = g_points[i];    if ( gpt != null )      xmlText += "<coord lat='" + gpt.lat() + "' lng='" + gpt.lng() + "' />\n";  }  xmlText += "</coords>\n";  xmlText += "<maps>\n";  xmlText += makeXMLForMap(1,g_map1);  xmlText += makeXMLForMap(2,g_map2);  xmlText += "</maps>\n";    xmlText += "</save>";  return xmlText;}var g_regexpMatchWhitespace = /\s+/gm;function updateMarkersFromDataText(){    g_points = new Array();    // get textarea data and clear whitespace from string    var textAreaStr = document.getElementById("dataText").value;    var workStr = textAreaStr.replace( g_regexpMatchWhitespace,  "" );        if ( workStr.length >= 3 )    {      // subdivide whole string by ";"      var markerArray = workStr.split(";");      if ( markerArray.length > 0 )      {          // subdivide each marker string string by ","          for ( var i=0; i<markerArray.length; i++ )          {            var ptStr = markerArray[i];            if ( ptStr.length >2)            {              var coordStr = ptStr.split(",");              if ( coordStr.length == 2 )              {                 var lat = parseFloat(coordStr[0]);                 var lng = parseFloat(coordStr[1]);                 // tbd: ZZZ check ranges                 g_points.push(new GLatLng(lat,lng));              }            }          }      }    }    // center maps at first and second marker positions    if ( g_points.length > 0 )    g_map1.setCenter( g_points[0] );    if ( g_points.length > 1 )    g_map2.setCenter( g_points[1] );    showAgain(g_map1);    showAgain(g_map2);    updateDataText();        allowPermaLink( true, null );}function clearAllFunc(){  g_points = new Array();  g_map1.clearOverlays();  g_map2.clearOverlays();  g_dataTextElem.value = "";  allowPermaLink( false, null );}function allowPermaLink ( allowClick, newURL ){  if ( g_points.length <= 0 )  {    allowClick = false;    newURL     = null;  }  document.getElementById("persistButton").disabled = !allowClick;  var msgElem  = document.getElementById("URLempty");  var linkElem = document.getElementById("permURL");    if ( (typeof newURL) != "string" )  {    linkElem.style.display        = "none";    msgElem.firstChild.nodeValue  = "(not requested yet)";    msgElem.style.display         = "inline";  }  else if ( newURL == "WAIT" )  {    linkElem.style.display        = "none";    msgElem.firstChild.nodeValue  = "...request for URL in progress...";    msgElem.style.display         = "inline";  }  else  {    msgElem.style.display         = "none";    linkElem.href                 = newURL;    linkElem.firstChild.nodeValue = newURL;    linkElem.style.display        = "inline";  }}//=============================================================================//mfum_phpURL = "isoll_make.php";mfum_makeXML = makeXML;mfum_urlCallback = function ( newURL ){  allowPermaLink( false, newURL );}  mfum_abortCallback = function ( ){  allowPermaLink( true, null );    alert( "Unfortunately, the server is not able to generate permanent " +         "URLs at this time. Please try again later." );}function handleMakeURL ( ){  allowPermaLink( false, "WAIT" );  mfum_requestURL();}//=============================================================================//mfuf_phpURL = "isoll_get.php";// set checkbox with 'id' to on/off state// based on one-digit string 'stateChar' - "0" or "1"function setCheckBoxState ( id, stateChar ){  var state = stateChar=="0" ? false : true;   document.getElementById(id).checked = state;}function mfuf_parseXMLNode ( xmlNode ){  var coordElem = xmlNode.documentElement.getElementsByTagName("coord");  if ( coordElem.length < 1 )  {    alert( "Unfortunately, an error occurred attempting to retrieve the saved map." );    return;  }  clearAllFunc();  var added = false;  for ( var i=0; i<coordElem.length; i++ )  {    var latStr = coordElem[i].getAttribute("lat");    var lngStr = coordElem[i].getAttribute("lng");    if ( isNumber(latStr) && isNumber(lngStr) )    {      addPoint( new GLatLng(parseFloat(latStr),parseFloat(lngStr)) );      added = true;    }  }  var mapElem = xmlNode.documentElement.getElementsByTagName("map");  for ( var i=0; i<mapElem.length; i++ )  {    var numStr = mapElem[i].getAttribute("num");    var numVal = parseInt(numStr);    var latStr = mapElem[i].getAttribute("lat");    var lngStr = mapElem[i].getAttribute("lng");    if ( 1<=numVal && numVal<=2 && isNumber(latStr) && isNumber(lngStr) )    {      // derive zoom (or set to null)      var zoom = mapElem[i].getAttribute("zoom");      if ( !isPosInteger(zoom) )        zoom = null;      else        zoom = parseInt(zoom);            // derive map type (or set to null)      var type = null;      var typeName = mapElem[i].getAttribute("type");      if ( typeof typeName == "string" )      {        switch ( typeName )        {        case "normal":     type = G_NORMAL_MAP;     break;        case "satellite":  type = G_SATELLITE_MAP;  break;        case "hybrid":     type = G_HYBRID_MAP;     break;        case "physical":   type = G_PHYSICAL_MAP;   break;        }      }            // derive iso-line settings      var isoStr = mapElem[i].getAttribute("en");      if ( typeof isoStr == "string" )      {        setCheckBoxState( "m"+numStr+"ila", isoStr.charAt(0) );        setCheckBoxState( "m"+numStr+"ilo", isoStr.charAt(1) );        setCheckBoxState( "m"+numStr+"ala", isoStr.charAt(2) );        setCheckBoxState( "m"+numStr+"alo", isoStr.charAt(3) );      }            // set the map center, zoom and type      var mapObj = eval("g_map"+numStr);      var center = new GLatLng( parseFloat(latStr), parseFloat(lngStr) );      mapObj.setCenter( center, zoom, type );    }  }  if ( added )  {    allowPermaLink( false, null );    showAgain(g_map1);    showAgain(g_map2);    updateDataText();  }}  var g_queryString = null;mfuf_abortCallback = function ( ){  allowPermaLink( true, null );    alert( "The URL for this page contains the query string \"?" + g_queryString + "\". " +         "This is a request for a saved map.\n\n" +         "Unfortunately, your browser can't retrieve the saved map because the " +         "MAPfrappe server is nonresponsive. Please try again later." );}function evaluateURLParams ( ){  var qmarkIdx = location.href.indexOf( '?' );  if ( qmarkIdx > 7 )  {    var urlParams = location.href.slice( qmarkIdx+1 );    var eqIdx     = urlParams.indexOf( '=' );    var paramName = urlParams.substring( 0, eqIdx );    var paramVal  = urlParams.slice( eqIdx+1 );    g_queryString = urlParams;    if ( paramName.toLowerCase()=="show" && isPosInteger(paramVal) )      mfuf_fetchURL( paramVal );  }}//=============================================================================//function gmapSetup(){  g_dataTextElem = document.getElementById("dataText");  g_dataTextElem.value = "";    if ( ! GBrowserIsCompatible() )    return;    var adOptions =  // GGoogleBarAdsOptions  {    client : 'pub-2965340737172725'  };  var barOptions =  // GGoogleBarOptions  {    adsOptions                     : adOptions,    resultList                     : G_GOOGLEBAR_RESULT_LIST_SUPPRESS,    suppressInitialResultSelection : true  };  var mapOptions =  {    draggableCursor  : 'crosshair',    googleBarOptions : barOptions  };    scalePosition = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(3,36));   g_map1 = new GMap2(document.getElementById("map1div"), mapOptions);  g_map1.setCenter(new GLatLng(37.93,-92.90), 4);  g_map1.addControl(new GLargeMapControl());  g_map1.addControl(new GMapTypeControl());  g_map1.addControl(new GScaleControl(), scalePosition);  g_map1.enableGoogleBar();  g_map1.useForm = document.M1CheckBoxes;  g_map2 = new GMap2(document.getElementById("map2div"), mapOptions);  g_map2.setCenter(new GLatLng(37.93,-92.90), 4);  g_map2.addControl(new GLargeMapControl());  g_map2.addControl(new GMapTypeControl());  g_map2.addControl(new GScaleControl(), scalePosition);  g_map2.enableGoogleBar();  g_map2.useForm = document.M2CheckBoxes;  mapPairControls(g_map1,g_map2);  mapPairControls(g_map2,g_map1);  // monitor the window resize event and let the map know when it occurs  if (window.attachEvent)    window.attachEvent("onresize", function() {g_map1.checkResize();g_map2.checkResize();} );  else    window.addEventListener("resize", function() {g_map1.checkResize();g_map2.checkResize();}, false);  scrubExampleList();  evaluateURLParams();}