// Copyright New York State Thruway Authority. All rights reserved.
var map;
var cmarkers =  new Array();
var imarkers =  new Array();
var rmarkers =  new Array();
var clmarkers = new Array();
var intmarkers = new Array();
var rammarkers = new Array(); // associative array
var tpmarkers = new Array();
var tpnames = new Array();
var ramarkers = new Array();
var minClusterZoomLevel = 11;
var minPlinesZoomLevel = 12;
var minInterchangeZoomLevel = 13;
var minTravelPlazaZoomLevel = 11;
var checkedInterchangeOn = 0;
var zIndexCluster = 9;
var zIndexCamera = 9;
var zIndexRAM = 8;
var zIndexAccident = 7;
var zIndexTraffic = 6;
var zIndexRoadclose = 5;
var zIndexLaneclose = 4;
var zIndexRoadwork = 3;
var zIndexTravelplazas = 2;
var zIndexInterchange = 1;
var allowedBounds;
var incidentsType = "incidents";
var closuresType = "closures";
var roadworkType = "roadwork";
var camerasType = "cameras";
var interchangesType = "interchanges";
var travelplazasType = "travelplazas";
var restareasType = "restareas";
var ramType = "regionaladvisory";
var incidentsIndex = 0;
var closuresIndex  = 1;
var roadworkIndex  = 2;
var winTravelplzRest;
var userZoomedOrDragged = false;
var saveMapCenter;

var accidenticon = new GIcon();
var trafcondicon = new GIcon();
var roadworkicon = new GIcon();
var roadclosureicon = new GIcon();
var laneclosureicon = new GIcon();
var interchangeicon = new GIcon();
var travelplazaicon = new GIcon();
var restareaicon = new GIcon();
var ramicon = new GIcon();
var cameraicon = new GIcon();
var clustericon = new GIcon();
		
var timerID;
var intRefreshrate = 10;
var intPeak        = 0;
var intHoldPeak    = intPeak;
var intXmlLoopctr  = 0; 
var intXmlLoopmax  = Math.round(60 / intRefreshrate);

var cutoffXMLLastDateTime = "";
var httpReqCutoffXml      = null;
var httpReqTTCXml         = null;

/************************** END GLOBAL VARIABLES ********************************/
function showLoadingBox(cbIn, strShowbox) {
  if (strShowbox == "true") {
    document.getElementById("loadingbox").style.visibility="visible";
    if (cbIn == "allevents") {  // disable all together
	  document.getElementById('cbIncidents').disabled = true;
	  document.getElementById('cbClosures').disabled = true;
	  document.getElementById('cbRoadwork').disabled = true;
	} else if (cbIn == "alltprest") {  // disable all together
	  document.getElementById('cbTravelplazas').disabled = true;
	  document.getElementById('cbRestareas').disabled = true;
	} else {
	  document.getElementById(cbIn).disabled = true;
	} //end if cbIn
  } else {
    document.getElementById("loadingbox").style.visibility="hidden";
    if (cbIn == "allevents") { // enable all together
	  document.getElementById('cbIncidents').disabled = false;
	  document.getElementById('cbClosures').disabled = false;
	  document.getElementById('cbRoadwork').disabled = false;
	} else if (cbIn == "alltprest") {  // disable all together
	  document.getElementById('cbTravelplazas').disabled = false;
	  document.getElementById('cbRestareas').disabled = false;
	} else {
      document.getElementById(cbIn).disabled = false;
	} //end if cbIn
  } // end if strShow
} // end of function
// *****************************************************************************		
function popupInterchangeInfo(strExit, strRoute) {
  if (strExit.substr(0,2) == "tb"){
    switch (strExit) {
	  case 'tb-wtb':
	    var strURL = pathPrefix + "tolls/calc/ticket.cgi?entry=m15x";
	  break;
	  case 'tb-ctb':
	    var strURL = pathPrefix + "tolls/calc/ticket.cgi?entry=b3x";
	  break;
	  case 'tb-wms':
	    var strURL = pathPrefix + "tolls/calc/ticket.cgi?entry=m50x";
	  break;
	  case 'tb-lac':
	    var strURL = pathPrefix + "tolls/calc/ticket.cgi?entry=m55x";
	  break;
	  case 'tb-rip':
	    var strURL = pathPrefix + "tolls/calc/ticket.cgi?entry=m61x";
	  break;
	  default:
	    var strURL = pathPrefix + "tolls/barrier.html";
	  break;
	} //end switch
  } else {
	var myExit="";
    switch (strRoute.toUpperCase()) {
      case 'ML': 
	    if (strExit.substr(0,3) == "gsp") {
		  exitnum = "- New Jersey Line";
		  myExit = "m14a";
		} else if (strExit == "8a" || strExit == "8"){
		  myExit="m08x";
		}else{
		  myExit = 'm' + addX(zeroFill(strExit));
		}
	 break;
	 case '84':
	   myExit = 'i84-' + zeroFill(strExit);
	 break;
	 case 'NE':
	   if (strExit == "8b" || strExit == "8c"){
	     myExit = "ne08";
	   }else{
		 myExit = 'ne' + zeroFill(strExit);
	   }
	 break;
	 case 'CW':
	   myExit = 'cwe';
	 break;
	 case 'N': 
	   if (strExit == "18a" || strExit == "18b"){
		  myExit = "ns18x";
	   }else{
	     myExit = 'ns' + addX(zeroFill(strExit));
	   }
	 break;
	 case 'B': 
	   myExit = addX(strExit);
	 break;
	 case 'N': 
	   myExit = 'ns' + addX(zeroFill(strExit));
	 break;
    } //end switch
	
    var strURL = pathPrefix + "tolls/calc/interchange.cgi?" + myExit;
  } /* end if strExit */
  
  var winInterchange=window.open(strURL.toLowerCase(), "winint","width=800,height=600,top=0,left=0,menubar,resizable,toolbar,location,scrollbars,status");
  winInterchange.focus();  // need this because window can be minimized
} // end popupInterchangeInfo function
// *****************************************************************************	
function popupTravelplazaInfo(strName) {
  var strURL = pathPrefix + "travelplazas/gm-" + removeSpaces(strName) + ".html";
  winTravelplzRest=window.open(strURL.toLowerCase(), "wintp","height=515,width=500,top=0,left=0,scrollbars,status");	
} /* end of function */
// *****************************************************************************	
function popupTravelplazaNames(strName) {
  for (var i = 0; i < tpnames.length; i++) {
    if (strName.substr(0,5).toLowerCase() == tpnames[i].substr(0,5).toLowerCase()) {
	  var strArray = tpnames[i].split('~');  //expect 5 strings
      userZoomedOrDragged = true;  // do not allow map to auto pan back 
	  tpmarkers[i].openInfoWindowHtml(createTPInfoHTML(strArray[0], strArray[1], strArray[2], strArray[3], strArray[4]));
	  break;
    } 
  }
} /* end of function */
// *****************************************************************************	
function popupRestareaInfo(strName) {
  var strURL = pathPrefix + "travelplazas/restareas.html";
  winTravelplzRest=window.open(strURL.toLowerCase(), "winrest","width=800,height=600,top=0,left=0,menubar,resizable,toolbar,location,scrollbars,status");
  winTravelplzRest.focus();  // need this because window can be minimized
} /* end of function */
// *****************************************************************************	
function popupHelpFaq(strName) {
  var strURL = pathPrefix + "gmap/" + removeSpaces(strName) + ".html";
  winHelpFaq=window.open(strURL.toLowerCase(), "winhelpfaq","width=800,height=600,top=0,left=0,menubar,resizable,toolbar,location,scrollbars,status");
  winHelpFaq.focus();  // need this because window can be minimized
} /* end of function */
// *****************************************************************************		
function trim(strIn) {
	return strIn.replace(/^\s+|\s+$/g,"");
}
// *****************************************************************************		
function removeSpaces(strIn) {
  return(strIn.replace(/\s/g, ""));  //regexp
} /* end of function */
// *****************************************************************************	
function zeroFill(strIN) {
  var exittemp = strIN;
  if ((strIN.substr(0,1) != "b") && (strIN.substr(0,1) != "t")) {
    if (strIN.substr(strIN.length-1,1).match(/[a-z]/)) {
	  if (strIN.length < 3){
	    exittemp = '0' + strIN;
	  } else {
		exittemp = strIN;
	   }
    } else {
      if (strIN.length < 2){
	    exittemp = '0' + strIN;
	  } else {
		exittemp = strIN;
	  }
	}
  }  // end if ! b or t
  return(exittemp);
} // end function
// *****************************************************************************	
function addX(strIN) {
  var exittemp = strIN;
  if (strIN.substr(0,1) == "b"){
	exittemp = strIN + "x";
  } else if (!strIN.substr(strIN.length-1,1).match(/[a-z]/)){
	exittemp = strIN + "x";
  }
  return(exittemp);
} // end function
// *****************************************************************************	
function stopClock() {
  intXmlLoopctr = 1;  // must reset this global var
  clearTimeout(timerID); // must clear
} // End stopClock function
// *****************************************************************************	
function startClock(strImagein) {
  var now = new Date();     // get new date object
  if (document.images) {    // if browser supports document.images, load image
	document.images.imgToLoad.src = pathPrefix + "webcams/captures/img" + strImagein + ".jpg?" + now.getTime();
  }
	
  // read xml files on first time window opens and every x loops
  if (intXmlLoopctr >= intXmlLoopmax || intXmlLoopctr == 0) { // 0=firsttime
    // read TTCXml file first to get throttle values 
	readTTCXml();  
	readCutoffXml(strImagein); 
    writeRefreshInfo();
	  
    if (intXmlLoopctr >= intXmlLoopmax) {  // reached max
	  intXmlLoopctr = 0; // reset
	}
  } else {
    // check if need to rewrite refresh info
	if (intPeak != intHoldPeak) {
      intHoldPeak = intPeak;
	  writeRefreshInfo();
  	  //intXmlLoopctr = 0; // reset
    }
  } // end intXmlLoopctr
  intXmlLoopctr++;
  intXmlLoopmax = Math.round(60 / intRefreshrate);
  timerID=setTimeout("startClock('" + strImagein + "')", intRefreshrate * 1000);
}  // End startClock function
// *****************************************************************************	
function writeRefreshInfo()  {
  var TTCMsgLine1 = document.getElementById("ttcmsgline1");
  var TTCMsgLine2 = document.getElementById("ttcmsgline2");
  
  if (intPeak == "1" ) {
      TTCMsgLine1.firstChild.nodeValue = "Because of unusually high traffic to our website, we";
	  TTCMsgLine2.firstChild.nodeValue = "have adjusted the refresh rate to " + intRefreshrate + " seconds";
	  TTCMsgLine1.style.color = TTCMsgLine2.style.color = "DarkRed";
  } else {
      TTCMsgLine1.firstChild.nodeValue = "Image is refreshed every " + intRefreshrate + " seconds";
	  TTCMsgLine2.firstChild.nodeValue = " ";
	  TTCMsgLine1.style.color = TTCMsgLine2.style.color = "Black";
  }
} // end function
// *****************************************************************************	
function readTTCXml()  {
  var xmlFile = pathPrefix + "webcams/netdata/ttc.xml?" + new Date().getTime();

  // check if last req finished, if not, abort last req
  if (httpReqTTCXml != null) {
    httpReqTTCXml.abort();
	httpReqTTCXml = null;
  }
  
  httpReqTTCXml = GXmlHttp.create(); 
  httpReqTTCXml.open("GET", xmlFile, true);  // async
  httpReqTTCXml.onreadystatechange = function() {
    if (httpReqTTCXml.readyState == 4) {
      // status returns 0 in local file mode
      if (httpReqTTCXml.status==200 || httpReqTTCXml.status==0) {
        var settings = httpReqTTCXml.responseXML.documentElement.getElementsByTagName("settings");
        for (var i = 0; i < settings.length; i++) {
	      var intTmpRefreshrate = parseInt(settings[i].getAttribute("refreshrate"));
          var intTmpPeak = parseInt(settings[i].getAttribute("peak"));
          if (isNaN(intTmpRefreshrate)) { //make sure we have a number
            intRefreshrate=59;
          } else if (intTmpRefreshrate < 10) {
            intRefreshrate=59;
          } else if (intTmpRefreshrate > 60) {
            intRefreshrate=59;
          } else {
		    intRefreshrate=intTmpRefreshrate;
		  }
		  
          if (isNaN(intTmpPeak)) { //make sure we have a number
            intRefreshrate=58; intPeak=1;
          } else if (intTmpPeak < 0) {
            intRefreshrate=58; intPeak=1;
          } else if (intTmpPeak > 1) {
            intRefreshrate=58; intPeak=1;
          } else {
		    intPeak = intTmpPeak;
		  }
        } // end for loop
		
	    if (settings.length <= 0) {
	      // there was a problem, assume the worst and throttle
          intRefreshrate=57; intPeak=1;
	    }
      } else {  // not 200 status code 
	    // else there was a problem, assume the worst and throttle
        intRefreshrate=57; intPeak=1;
      } // end httpReqTTCXml.status==200
      
	  // reset to null to flag it completed successfully
      httpReqTTCXml = null;
	} //end if readystate==4
  } // end onreadystatechange function
  
  httpReqTTCXml.send(null);

}  // end function
// *****************************************************************************	
function readCutoffXml(strCamIdIn)  {
  var isCutoff = false;
  var readMore = false;
  var xmlFile = pathPrefix + "xml/netdata/cameracutoff.xml?" + new Date().getTime();
  
  // check if last req finished, if not, abort last req
  if (httpReqCutoffXml != null) {
    httpReqCutoffXml.abort();
	httpReqCutoffXml = null;
  }

  httpReqCutoffXml = GXmlHttp.create(); 
  httpReqCutoffXml.open("GET", xmlFile, true);  // async
  httpReqCutoffXml.onreadystatechange = function() {
    if (httpReqCutoffXml.readyState == 4) {
      // status returns 0 in local file mode
      if (httpReqCutoffXml.status==200 || httpReqCutoffXml.status==0) {
		var xml=httpReqCutoffXml.responseXML;
        var lastupdatetime = xml.documentElement.getElementsByTagName("lastupdatetime");
		if (lastupdatetime.length > 0 ) {
		  // should only be 1 tag, so use [0]
          if (lastupdatetime[0].firstChild.nodeValue != cutoffXMLLastDateTime) {
		    cutoffXMLLastDateTime = lastupdatetime[0].firstChild.nodeValue;
			readMore = true;
		  }
	    } else {
	      readMore = true;  // if tag missing always read
	    }
        
        if (readMore) {
          var markers = xml.documentElement.getElementsByTagName("camera");
          for (var i=0; i < markers.length; i++) {
            var cameraid = markers[i].getAttribute("cameraid");
            if (strCamIdIn == cameraid) {
              var cutoff = markers[i].getAttribute("cutoff");
              var cutoffdesc = markers[i].getAttribute("cutoffdesc");
			  if ( (cutoff != "0") && (cutoffdesc != null) ){
				isCutoff = true;
			  }  // end if cutoff
		      break;  // id matched no need to read more
		    }  // end if strCamIdIn
          } // end for loop markers
		  
          // only rewrite cutoffmsgline1 if we read the xml file
		  var cutoffMsgLine1 = document.getElementById("cutoffmsgline1");
		  if ( isCutoff == true ){
			cutoffMsgLine1.firstChild.nodeValue = cutoffdesc;
		  } else {
			cutoffMsgLine1.firstChild.nodeValue = " ";
		  }  // end if isCutoff
	    } // end if readMore
	  } // end if httpReqCutoffXml.status==200
		
	  // reset to null to flag it completed successfully
	  httpReqCutoffXml = null;
		
    } // end if httpReqCutoffXml.readyState==4
  } // end onreadystatechange function

  httpReqCutoffXml.send(null);
  
}  // end function
// *****************************************************************************	
function onclickIncidents()  {
  if (document.getElementById('cbIncidents').checked) {
    addEventMarkers((new Array(incidentsType, null, null)));
  } else {
    removeMarkers(incidentsType);
  }
} /* end of function */
// *****************************************************************************	
function onclickClosures()  {
  if (document.getElementById('cbClosures').checked) {
    addEventMarkers((new Array(null, closuresType,  null)));
  } else {
    removeMarkers(closuresType);
  }
} /* end of function */
// *****************************************************************************	
function onclickRoadwork()  {
  if (document.getElementById('cbRoadwork').checked) {
    addEventMarkers((new Array(null, null, roadworkType)));
  } else {
    removeMarkers(roadworkType);
  }
} /* end of function */
// *****************************************************************************	
function onclickCameras()  {
  if (document.getElementById('cbCameras').checked) {
    addCamClustMarkers();
  } else {
    removeMarkers(camerasType);
  }
} /* end of function */
// *****************************************************************************	
function onclickInterchanges()  {
  if (document.getElementById('cbInterchanges').checked) {
	checkedInterchangeOn = 1;
	addIntMarkers();
  } else {
	checkedInterchangeOn = 0;
	removeMarkers(interchangesType);
  }
} /* end of function */
// *****************************************************************************	
function onclickTravelplazas()  {
  if (document.getElementById('cbTravelplazas').checked) {
	document.getElementById('tplist').style.display = "block";
	addTravelplzRestMarkers(travelplazasType);
  } else {
	document.getElementById('tplist').style.display = "none";
    removeMarkers(travelplazasType);
  }
} /* end of function */
// *****************************************************************************	
function onclickRestareas()  {
  if (document.getElementById('cbRestareas').checked) {
	addTravelplzRestMarkers(restareasType);
  } else {
    removeMarkers(restareasType);
  }
} /* end of function */
// *****************************************************************************	
function onclickRAM()  {
  if (document.getElementById('cbRAM').checked) {
	addRAMMarkers();
  } else {
    removeMarkers(ramType);
  }
} /* end of function */
// *****************************************************************************	
function addEventMarkers(mtype) {
  var xmlFile = pathPrefix + "xml/netdata/events.xml?" + new Date().getTime();
  showLoadingBox("allevents", "true");

  if (mtype[incidentsIndex] == incidentsType) {
    removeMarkers(incidentsType);
  } 
  if (mtype[closuresIndex] == closuresType) {
    removeMarkers(closuresType);
  } 
  if (mtype[roadworkIndex] == roadworkType) {
    removeMarkers(roadworkType);
  }
	
  GDownloadUrl(xmlFile, function(data, responseCode) {
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
      var xml = GXml.parse(data);
      var markers = xml.documentElement.getElementsByTagName("event");
      for (var i = 0; i < markers.length; i++) {
        var lat = parseFloat(markers[i].getAttribute("latitude"));
	    var lng = parseFloat(markers[i].getAttribute("longitude"));
	    var category = markers[i].getAttribute("category");
        var point = new GLatLng(lat, lng);
        var milepost = parseFloat(markers[i].getAttribute("milepost"));
        var route = markers[i].getAttribute("route");
        var direction = markers[i].getAttribute("direction");
        var expirationdatetime = markers[i].getAttribute("expirationdatetime");
        var updatetime = markers[i].getAttribute("updatetime");
        var eventdesc = markers[i].getAttribute("eventdesc");
        var eventtype = markers[i].getAttribute("eventtype");
	    var eventtypeU = eventtype.toUpperCase();
	    var routeU = route.toUpperCase();
        var infoHTML = "<div class='eventbox'><div class='eventboxincident'>" +eventtypeU+"</div><p><strong>"+routeU+", Milepost "+milepost+"</strong><br />"+eventdesc+"<br /><span class='small'><strong>Estimated End Time:</strong> "+expirationdatetime+"</span><br /><br /><span class='small'>Updated "+updatetime+" </span></p></div>";			
			
	    if (direction.toLowerCase() == "eastbound" || direction.toLowerCase() == "westbound" || direction.toLowerCase() == "northbound" || direction.toLowerCase() == "southtbound") {
		  var tooltip = eventtypeU + ", " + routeU + ", " + direction.toUpperCase() + ", MILEPOST " + milepost;
		} else {
	      // non-directional, bi-directional or blank
	      var tooltip = eventtypeU + ", " + routeU + ", MILEPOST " + milepost;
		}
	    if (mtype[incidentsIndex] == incidentsType) {
	      if (category == "incident") {
            var marker = createIncidentMarker(point, tooltip, infoHTML, accidenticon, "accident");
 		    imarkers.push(marker);
            map.addOverlay(marker);
		  } else if (category == "traffic-condition") {
            var marker = createIncidentMarker(point, tooltip, infoHTML, trafcondicon, "traffic");
 		    imarkers.push(marker);
            map.addOverlay(marker);
		  }
	    } // end mtype[incidentsIndex]
		if (mtype[closuresIndex] == closuresType) {
		  if (category == "closure") {
            var marker = createIncidentMarker(point, tooltip, infoHTML, roadclosureicon, "roadclose");
 		    clmarkers.push(marker);
            map.addOverlay(marker);
	      } else if (category == "laneclose") {
            var marker = createIncidentMarker(point, tooltip, infoHTML, laneclosureicon, "laneclose");
 		    clmarkers.push(marker);
            map.addOverlay(marker);
		  }
	    } // end mtype[closuresIndex]
		if (mtype[roadworkIndex] == roadworkType && category == "roadwork") {
		  infoHTML = "<div class='eventbox'><div class='eventboxroadwork'>" +eventtypeU+"</div><p><strong>"+routeU+", Milepost "+milepost+"</strong><br />"+eventdesc+"<br /><span class='small'><strong>Estimated End Time:</strong> "+expirationdatetime+"</span><br /><br /><span class='small'>Updated "+updatetime+" </span></p></div>";			
          var marker = createIncidentMarker(point, tooltip, infoHTML, roadworkicon, "roadwork");
 		  rmarkers.push(marker);
          map.addOverlay(marker);
	    }  // end mtype[roadworkIndex]
      } // end for loop
	} else {
	  alert("Condition, Closure and Roadwork data are unavailable at this time.  Code: "+ responseCode);
      if (mtype[incidentsIndex] == incidentsType) {
		document.getElementById('cbIncidents').checked = false;
      }
	  if (mtype[closuresIndex] == closuresType) {
		document.getElementById('cbClosures').checked = false;
      }
	  if (mtype[roadworkIndex] == roadworkType) {
		document.getElementById('cbRoadwork').checked = false;
      }
	} // end if responseCode
    showLoadingBox("allevents", "false");
  }); //end GDownloadUrl
} // end function
// *****************************************************************************	
function addCamClustMarkers() {
  removeMarkers(camerasType);
  addCameraMarkers();
  addClusterMarkers();
} // end function
// *****************************************************************************	
function addCameraMarkers() {
  var clusterLevel = 1;
  if (parseInt(map.getZoom()) >= minClusterZoomLevel) {
	clusterLevel = 0;
  } 
  var xmlFile = pathPrefix + "xml/netdata/cameras.xml?" + new Date().getTime();
  showLoadingBox("cbCameras", "true");
  
  GDownloadUrl(xmlFile, function(data, responseCode) {
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
	  var xml = GXml.parse(data);
      var markers = xml.documentElement.getElementsByTagName("camera");
      for (var i=0; i < markers.length; i++) {
        var lat = parseFloat(markers[i].getAttribute("latitude"));
		var lng = parseFloat(markers[i].getAttribute("longitude"));
        var point = new GLatLng(lat, lng);
        var milepost = parseFloat(markers[i].getAttribute("milepost"));
        var display = markers[i].getAttribute("display");
        var cameraid = markers[i].getAttribute("cameraid");
        var cameradesc = markers[i].getAttribute("cameradesc");
        var cameradesc2 = markers[i].getAttribute("cameradesc2");
        var directiondesc = markers[i].getAttribute("directiondesc");
        var directiondesc2 = markers[i].getAttribute("directiondesc2");
			  
		var cameraiconTmp = new GIcon(cameraicon);
		// offset icons at same locations
		if (cameraid == "4ml42617a" || cameraid == "4ml43040a" || cameraid == "4ni01337a") {
      	  cameraiconTmp.iconAnchor = new GPoint(15, 7); 
	    } else if (cameraid== "4ml42617b" || cameraid== "4ml43040b" || cameraid== "4ni01337b") {
          cameraiconTmp.iconAnchor = new GPoint(0, 7);
	    } else{
		  cameraiconTmp.iconAnchor = new GPoint(7, 7);
	    }
		
		if ( (clusterLevel == 0 && display != "0") || 
		     (clusterLevel == 1 && display == "2") ) {
		  var tooltip = cameradesc;
		  var cameraHTML = "<div class='cameradesctop'>" +cameradesc;
		  if (cameradesc2 != null) {
			tooltip = tooltip + " " + cameradesc2;
			cameraHTML = cameraHTML + "<br />" +cameradesc2;
		  }
	      tooltip = tooltip + ", Milepost " + milepost;
		  cameraHTML = cameraHTML + "</div><img src='" +pathPrefix+ "webcams/captures/img" +cameraid+ ".jpg' border='1' alt='Image of Live Traffic' title='Image of Live Traffic'  name='imgToLoad' id='imgToLoad' width='352' height='240' /><div class='cameradescbot'>";

          cameraHTML = cameraHTML + directiondesc + "<br />";
		  if (directiondesc2 != null) {
			cameraHTML = cameraHTML + directiondesc2 + "<br />";  
		  }
		  // leave cutoffmsg blank, let timer function set message
		  cameraHTML = cameraHTML + "<span id='cutoffmsgline1' style='color:red'>&nbsp;</span><br />";
          var marker = createCameraMarker(point, tooltip, cameraid, cameraHTML, cameraiconTmp);
		  cmarkers.push(marker);
          map.addOverlay(marker);
		} // end if clusterLevel
      } // end for loop markers
	} else {
	  alert("Traffic Camera data is unavailable at this time.  Code: "+ responseCode);
	  // DO NOT set cbCameras.checked = false
	} // end if responseCode
    showLoadingBox("cbCameras", "false");
  });
} // end function
// *****************************************************************************	
function addClusterMarkers() {
  var clusterLevel = 1;
  if (parseInt(map.getZoom()) >= minClusterZoomLevel) {
	clusterLevel = 0;
  } 
		
  var xmlFile = pathPrefix + "xml/clusters.xml?" + new Date().getTime();
  GDownloadUrl(xmlFile, function(data, responseCode) {
    // responseCode returns 0 in local file mode
	if(responseCode == 200 || responseCode == 0) {
	  var xml = GXml.parse(data);
      var markers = xml.documentElement.getElementsByTagName("camera");
      for (var i=0; i < markers.length; i++) {
        // icon lat/long location
		var lat = parseFloat(markers[i].getAttribute("latitude"));
		var lng = parseFloat(markers[i].getAttribute("longitude"));
        var point = new GLatLng(lat, lng);
        // zoom lat/long center point
		var zlat = parseFloat(markers[i].getAttribute("zoomlatitude"));
		var zlng = parseFloat(markers[i].getAttribute("zoomlongitude"));
        var zpoint = new GLatLng(zlat, zlng);
        var display = markers[i].getAttribute("display");
        var tooltip = markers[i].getAttribute("cameradesc");
			  
		if (clusterLevel == 1 && display == "1") {
          var marker = createClusterMarker(point, zpoint, tooltip, clustericon);
		  cmarkers.push(marker);
          map.addOverlay(marker);
		} // end if clusterLevel
      } // end for loop markers
	} // end if responseCode
  });
} // end function
// *****************************************************************************	
function addIntMarkers() {
  var xmlFile = pathPrefix + "xml/interchanges.xml?" + new Date().getTime();
  showLoadingBox("cbInterchanges", "true");
  removeMarkers(interchangesType); // remove and init array

  GDownloadUrl(xmlFile, function(data, responseCode) { 
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
      var xml = GXml.parse(data);
	  var markers = xml.documentElement.getElementsByTagName("interchanges");
	  for (var i = 0; i < markers.length; i++) {
	    var lat = parseFloat(markers[i].getAttribute("latitude"));
	    var lng = parseFloat(markers[i].getAttribute("longitude"));
	    var point = new GLatLng(lat, lng);
	    var milepost = parseFloat(markers[i].getAttribute("milepost"));
        var description = markers[i].getAttribute("description");
        var type = markers[i].getAttribute("type");
        var exitnum = markers[i].getAttribute("exitid");
	    var routeid = markers[i].getAttribute("routeid");
	    var route = markers[i].getAttribute("route");
	    var exitnumL = exitnum.toLowerCase();
	
        var myExit = null;	
        if (exitnumL.substr(0,2) == "tb"){
	       var tooltip = description + " " + " at Milepost " + milepost;
           var infoHTML = "<div class='eventbox'><div class='eventboxinterchangetb'>" + description + "</div><p><strong>" +route+ ", Milepost " + milepost + "</strong></p>";
	       if (exitnumL == "tb-new") {
		     infoHTML = infoHTML + "<span class='small'><a href='http://www.nysba.state.ny.us/' target='_blank'>Additional information</a><br/>(This link opens in a new browser window to the New York State Bridge Authority's website)</span></div>";
		   }else{
	         infoHTML = infoHTML + "<span class='small'><a href='javascript:popupInterchangeInfo(&quot;" + exitnumL + "&quot;, &quot;" + routeid + "&quot;);'>Additional information</a><br/>(This link opens in a new browser window)</span></div>";
		   }
        }else{
		  if (exitnumL == "gsp"){
		    exitnum = "- New Jersey Line";
		  }
	      var tooltip = description  + " " + type +" " + exitnum +" at Milepost " + milepost;
          var infoHTML = "<div class='eventbox'><div class='eventboxinterchange'>" + type + " " + exitnum + " </div><p><strong>" +route+ ", Milepost " + milepost + "</strong><br />" + description + "</p><span class='small'><a href='javascript:popupInterchangeInfo(&quot;" + exitnumL + "&quot;, &quot;" + routeid + "&quot;);'>Additional information</a><br/>(This link opens in a new browser window)</span></div>";
        } //end if
			             
        var inticon = new GIcon(interchangeicon); 
	    if (exitnumL == "gsp"){
	      inticon.image = pathPrefix + "images/gmap/exit.gif";
	    } else if (exitnumL.substr(0,2) == "tb"){
	      inticon.image = pathPrefix + "images/gmap/exittb.gif";
	      if (exitnumL == "tb-gib"){
	        inticon.iconAnchor = new GPoint(20, 16);
	      }
	      if (exitnumL == "tb-rip"){
	        inticon.iconAnchor = new GPoint(5, 16);
	      }
	    }else{
	      inticon.image = pathPrefix + "images/gmap/exit" + exitnumL + ".gif";
	    }
			  
	    var marker = createInterchangeMarker(point, tooltip, infoHTML, inticon);
	    intmarkers.push(marker);
        map.addOverlay(marker);
	   
      } // end for loop
	} else {
		alert("Exit/Toll Barrier data is unavailable at this time.  Code: "+ responseCode);
		document.getElementById('cbInterchanges').checked = false;
	} // end if responseCode
    showLoadingBox("cbInterchanges", "false");
  }); //end GDownloadUrl
} // end function
// *****************************************************************************	
function addRAMMarkers() {
  var xmlFile = pathPrefix + "xml/ram-locations.xml?" + new Date().getTime();
  showLoadingBox("cbRAM", "true");
  removeMarkers(ramType); // remove and init array

  GDownloadUrl(xmlFile, function(data, responseCode) { 
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
      var xml = GXml.parse(data);
	  var markers = xml.documentElement.getElementsByTagName("station");
	  for (var i = 0; i < markers.length; i++) {
	    var lat = parseFloat(markers[i].getAttribute("latitude"));
	    var lng = parseFloat(markers[i].getAttribute("longitude"));
	    var point = new GLatLng(lat, lng);
        var stationid = markers[i].getAttribute("stationid");
		stationid = stationid.toLowerCase();
        var description = markers[i].getAttribute("description");
        var description2 = markers[i].getAttribute("description2");

        var alttext = description +" - "+description2;
		var marker = createRAMMarker(point, description, description2, alttext, ramicon, stationid);
	    rammarkers[stationid] = marker; // associative array
		map.addOverlay(marker);
	   
      } // end for loop
	} else {
		alert("Regional Advisory Message data is unavailable at this time.  Code: "+ responseCode);
		document.getElementById('cbRAM').checked = false;
	} // end if responseCode
    showLoadingBox("cbRAM", "false");
  }); //end GDownloadUrl
} // end function
// *****************************************************************************	
function addTravelplzRestMarkers(mtype) {
  var xmlFile = pathPrefix + "xml/travelplazas.xml?" + new Date().getTime();
  showLoadingBox("alltprest", "true");

  if (mtype == "all" ) {
    removeMarkers(travelplazasType); // remove and init array
    removeMarkers(restareasType); // remove and init array
  } else if (mtype == travelplazasType) {
    removeMarkers(travelplazasType); // remove and init array
  } else if (mtype == restareasType) {
    removeMarkers(restareasType); // remove and init array
  }
 
  GDownloadUrl(xmlFile, function(data, responseCode) { 
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
      var xml = GXml.parse(data);
      var markers = xml.documentElement.getElementsByTagName("travelplaza");
      for (var i=0; i < markers.length; i++) {
        var lat = parseFloat(markers[i].getAttribute("latitude"));
	    var lng = parseFloat(markers[i].getAttribute("longitude"));
	    var point = new GLatLng(lat, lng);
	    var milepost = parseFloat(markers[i].getAttribute("milepost"));
        var title = markers[i].getAttribute("title");
	    var location = markers[i].getAttribute("location");
	    var iconanchor = markers[i].getAttribute("iconanchor");
	    var tpid = markers[i].getAttribute("tpid");  
	    var direction = markers[i].getAttribute("direction");
	    var route = markers[i].getAttribute("route");

	    if (tpid == "rest" && (mtype == "all" || mtype == restareasType)) {
	      var infoHTML=createRAInfoHTML(title, route, milepost, direction, location);	
		  var tooltip = title + " - " + route + " - " + direction + " " + "between " + location +" at Milepost " + milepost;
		  var tpidicon = new GIcon(restareaicon);  
	      tpidicon.image = "../images/gmap/tp-" + tpid + ".gif";
		 
		  if (iconanchor == 1) {
      	    tpidicon.iconAnchor = new GPoint(0, 12); 
	      }else if (iconanchor == 2) {
            tpidicon.iconAnchor = new GPoint(20, 12);
	      }else if (iconanchor == 3) {
      	    tpidicon.iconAnchor = new GPoint(10, 0);
	      }else if (iconanchor == 4) {
      	    tpidicon.iconAnchor = new GPoint(10, 24);
	      }else{
		    tpidicon.iconAnchor = new GPoint(10, 12);
	      } // end iconanchor
	      var marker = createTravelplzRestMarker(point, tooltip, infoHTML, tpidicon);
	      ramarkers.push(marker);
          map.addOverlay(marker);
	    } else if (tpid != "rest" && (mtype == "all" || mtype == travelplazasType)){
	      var infoHTML=createTPInfoHTML(title, route, milepost, direction, location);						
  	      var tooltip = title + " " + "Travel Plaza" +" - " + route + " - " + direction + " " + "between " + location +" at Milepost " + milepost;
		  var tpidicon = new GIcon(travelplazaicon);  
	      tpidicon.image = "../images/gmap/tp-" + tpid + ".gif";
	 	
	      if (iconanchor == 1) {
      	   tpidicon.iconAnchor = new GPoint(0, 12); 
	      }else if (iconanchor == 2) {
           tpidicon.iconAnchor = new GPoint(20, 12);
	      }else if (iconanchor == 3) {
      	   tpidicon.iconAnchor = new GPoint(10, 0);
	      }else if (iconanchor == 4) {
      	   tpidicon.iconAnchor = new GPoint(10, 24);
	      }else{
		   tpidicon.iconAnchor = new GPoint(10, 12);
	      } // end iconanchor
	      var marker = createTravelplzRestMarker(point, tooltip, infoHTML, tpidicon);
		  tpmarkers.push(marker);
          map.addOverlay(marker);
	      tpnames.push(title+"~"+route+"~"+milepost+"~"+direction+"~"+location);
	     } // end if
	   } // end for loop
	} else {
		alert("Travel Plaza and Rest Area data are unavailable at this time.  Code: "+ responseCode);
		if (mtype == "all" || mtype == travelplazasType) {
		  document.getElementById('cbTravelplazas').checked = false;
		} 
		if (mtype == "all" || mtype == restareasType) {
		  document.getElementById('cbRestareas').checked = false;
		}
	} // end if responseCode
    showLoadingBox("alltprest", "false");
  }); //end GDownloadUrl
} // end function
// *****************************************************************************	
function createTPInfoHTML(titleIN, routeIN, milepostIN, directionIN, locationIN) {
  if (titleIN == null || routeIN == null || milepostIN == null || directionIN == null || locationIN == null){
	var infoHTML = "<div class='eventbox'><div class='eventboxtravelplaza'>Travel Plaza Information Not Available</div>This information is not available at this time. Please check back later.</div>";
  }else{
    var infoHTML = "<div class='eventbox'><div class='eventboxtravelplaza'>" +titleIN+ " Travel Plaza</div><p><strong>" +routeIN+ ", Milepost " +milepostIN+ "</strong><br /> Located "+directionIN+ " between " +locationIN+ " <br/><br/><span class='small'><a href='javascript:popupTravelplazaInfo(&quot;" + titleIN + "&quot;);'>Additional restaurant and service information</a> (This link opens in a new window)</span></p></div>";
  }
  return(infoHTML);
}  // end function
// *****************************************************************************	
function createRAInfoHTML(titleIN, routeIN, milepostIN, directionIN, locationIN) {
 if (titleIN == null || routeIN == null || milepostIN == null || directionIN == null || locationIN == null){
	var infoHTML = "<div class='eventbox'><div class='eventboxrestarea'>Parking/Rest Area Information Not Available</div>This information is not available at this time. Please check back later.</div>";
  }else{
    var infoHTML = "<div class='eventbox'><div class='eventboxrestarea'>" +titleIN+ " </div><p><strong>" +routeIN+ ", Milepost " +milepostIN+ "</strong><br /> Located "+directionIN+ " between " +locationIN+ " <br/><br/><span class='small'><a href='javascript:popupRestareaInfo(&quot;" + titleIN + "&quot;);'>Additional rest area information</a> (This link opens in a new window)</span></p></div>";
  }
  return(infoHTML);
}  // end function
// *****************************************************************************	
function setZindexOrder (marker,b) {
  return GOverlay.getZIndex(marker.getPoint().lat()) + marker.importance*1000000;
}  // end function
// *****************************************************************************	
function createIncidentMarker(point, title, html, icon, type) {
  var marker = new GMarker(point, {icon:icon, title:title, zIndexProcess:setZindexOrder});
  if (type == "accident") {
	marker.importance = zIndexAccident;
  } else if (type == "traffic") {
	marker.importance = zIndexTraffic;
  } else if (type == "roadclose") {
	marker.importance = zIndexRoadclose;
  } else if (type == "laneclose") {
	marker.importance = zIndexLaneclose;
  } else if (type == "roadwork") {
	marker.importance = zIndexRoadwork;
  }
		
  GEvent.addListener(marker, "click", function() {  
    userZoomedOrDragged = false;
	saveMapCenter = map.getCenter();
    marker.openInfoWindowHtml(html);
   });   

  GEvent.addListener(marker, "infowindowclose", function() {
    if (userZoomedOrDragged == false) { map.panTo(saveMapCenter); } // restore map center
  });

  return marker;
}   //end function
// *****************************************************************************	
function createClusterMarker(point, zpoint, title, icon) {
  var marker = new GMarker(point, {icon:icon, title:title, zIndexProcess:setZindexOrder});
  marker.importance = zIndexCluster;
	  
  GEvent.addListener(marker, "click", function() {  
    zoomIn(zpoint.lat(), zpoint.lng(), minClusterZoomLevel);
  });   

  return marker;
}   //end function
// *****************************************************************************	
function createCameraMarker(point, title, camid, html, icon) {
  var marker = new GMarker(point, {icon:icon, title:title, zIndexProcess:setZindexOrder});
  marker.importance = zIndexCamera;

  GEvent.addListener(marker, "click", function() {  
	// needed to do this here because of intRefreshrate value
	var htmlTmp = html + "<span id='ttcmsgline1'>Image is refreshed every " + intRefreshrate + " seconds</span><br />";
	htmlTmp = htmlTmp + "<span id='ttcmsgline2'>&nbsp;</span><br />";
	htmlTmp = htmlTmp + "<a href='javascript:map.closeInfoWindow();'>Close Window</a></div>";
    userZoomedOrDragged = false;
	saveMapCenter = map.getCenter();
	marker.openInfoWindowHtml(htmlTmp);
  });   
	  
  GEvent.addListener(marker, "infowindowopen", function() {
     cutoffXMLLastDateTime = "";
	 intXmlLoopctr = 0; // 0=firsttime
     startClock(camid);
  });
  
  GEvent.addListener(marker, "infowindowclose", function() {
     stopClock();
     if (userZoomedOrDragged == false) { map.panTo(saveMapCenter); } // restore map center
  });

  return marker;
}   //end function
// *****************************************************************************	
function createRAMMarker(point, title, description2, tooltip, icon, id) {
  var marker = new GMarker(point, {icon:icon, title:tooltip, zIndexProcess:setZindexOrder});
  marker.importance = zIndexRAM;
	  
  GEvent.addListener(marker, "click", function() {
    userZoomedOrDragged = false;
	saveMapCenter = map.getCenter();
    openRAMInfoWin(id, title, description2);
  }); //end of click listening function

  GEvent.addListener(marker, "infowindowclose", function() {
    if (userZoomedOrDragged == false) { map.panTo(saveMapCenter); } // restore map center
  });
  return marker;
}   //end function
// *****************************************************************************	
function openRAMInfoWin(inId, inTitle, inDesc2) {
  var xmlFile = pathPrefix + "xml/netdata/ram-" +inId+".xml?" + new Date().getTime();

  GDownloadUrl(xmlFile, function(data, responseCode) { 
    // responseCode returns 0 in local file mode
    if(responseCode == 200 || responseCode == 0) {
	  var xml = GXml.parse(data);
	  var markers = xml.documentElement.getElementsByTagName("station");
	  if (markers.length > 0 ) { // check if not well-formed or missing tag
	    for (var i = 0; i < markers.length; i++) {
	      var message = markers[i].getElementsByTagName("har-current-message")[0].firstChild.data;
	      var lastupdatetime = markers[i].getElementsByTagName("lastupdatetime")[0].firstChild.data;
        } // end for loop
	  
	    var header = "<p class='small'>Updated: " + lastupdatetime+"</p><p class='small'>"+inDesc2+".</p>"; 
	    var footer = "<p class='small'>Information is updated as conditions change.</p><p class='small'>Current Thruway road conditions also available at:<br /> 1-800-THRUWAY (1-800-847-8929)</p>";
	  
	    message = trim(message);
	    // if the msg is blank it will contain a &nbsp; from Brad's program
	    if (message == "&nbsp;" || message == "") {
	      message = "The text version of this Regional Advisory Message is unavailable at this time.";
	    }
	    var html = "<div class='rambox'><div class='ramboxtitle'>"+inTitle+"</div>";
	    //html = html + header + "<p><a href='../xml/netdata/ram-"+inId+".wav'><img class='inline' style='vertical-align:middle' src='../images/gmap/ramicon-yellow.gif' title='"+inTitle+"' alt='"+inTitle+"' width='20' height='20'  /></a> <a href='../xml/netdata/ram-"+inId+".wav'>Audio of "+inTitle+"</a><br /><span class='small'>(.wav file format, this link will open in a new window with your default audio player)</span></p>"+ "<p class='rammsg'>" + message + "</p>" + footer + "</div>";
	    html = html + header + "<p><a href='../xml/netdata/ram-"+inId+".wav'><img class='inline' style='vertical-align:middle' src='../images/gmap/ramicon-yellow.gif' title='"+inTitle+" Audio' alt='"+inTitle+" Audio' width='20' height='20' /></a> <a href='../xml/netdata/ram-"+inId+".wav'>Message in audio format</a><br /><span class='small'>(.wav file format, this link will open in a new window with your default audio player)</span></p>"+ "<p class='rammsg'><span class='rammsgtitle'>" +inTitle+"</span><br /><br />"+ message + "</p>" + footer + "</div>";
        rammarkers[inId].openInfoWindowHtml(html);
	  } else {
		alert("The Regional Advisory Message for this region is unavailable at this time.  Code: xmlparse");
	  }
	} else {
		alert("The Regional Advisory Message for this region is unavailable at this time.  Code: "+ responseCode);
	} // end if responseCode
  }); //end GDownloadUrl
}   //end function
// *****************************************************************************	
function createInterchangeMarker(point, title, html, icon) {
  var marker = new GMarker(point, {icon:icon, title:title, zIndexProcess:setZindexOrder});
  marker.importance = zIndexInterchange;
	  
  GEvent.addListener(marker, "click", function() {  
    userZoomedOrDragged = false;
	saveMapCenter = map.getCenter();
    marker.openInfoWindowHtml(html);
  });   
     
  GEvent.addListener(marker, "infowindowclose", function() {
    if (userZoomedOrDragged == false) { map.panTo(saveMapCenter); } // restore map center
  });

  return marker;
}   //end function
// *****************************************************************************	
function createTravelplzRestMarker(point, title, html, icon) {
  var marker = new GMarker(point, {icon:icon, title:title, zIndexProcess:setZindexOrder});
  marker.importance = zIndexTravelplazas;
	  
  GEvent.addListener(marker, "click", function() {  
    userZoomedOrDragged = false;
	saveMapCenter = map.getCenter();
    marker.openInfoWindowHtml(html);
   }); 
  
  GEvent.addListener(marker, "infowindowclose", function() {  
	if (typeof(winTravelplzRest) != "undefined") {
	  if (winTravelplzRest.closed == false) {
		winTravelplzRest.close();
	  }
	}
    if (userZoomedOrDragged == false) { map.panTo(saveMapCenter); } // restore map center
  });   
  return marker;
}   //end function
// *****************************************************************************	
function removeMarkers(mtype) {
  if (mtype == incidentsType) {
    for (var i = 0; i < imarkers.length; i++) {
      map.removeOverlay(imarkers[i]);
    }
	imarkers=new Array();
  } else if (mtype == closuresType) {
    for (var i = 0; i < clmarkers.length; i++) {
      map.removeOverlay(clmarkers[i]);
    }
	clmarkers=new Array();
  } else if (mtype == roadworkType) {
    for (var i = 0; i < rmarkers.length; i++) {
      map.removeOverlay(rmarkers[i]);
    }
	rmarkers=new Array();
  } else if (mtype == camerasType) {
    for (var i = 0; i < cmarkers.length; i++) {
      map.removeOverlay(cmarkers[i]);
    }
	cmarkers=new Array();
  } else if (mtype == interchangesType) {
    for (var i = 0; i < intmarkers.length; i++) {
      map.removeOverlay(intmarkers[i]);	
	}
	intmarkers=new Array();
  } else if (mtype == ramType) {
    for (var i in rammarkers) {  // associative array
      map.removeOverlay(rammarkers[i]);	
	}
	rammarkers=new Array();
  } else if (mtype == travelplazasType) {
	for (var i = 0; i < tpmarkers.length; i++) {
      map.removeOverlay(tpmarkers[i]);
	}
	tpnames=new Array();
	tpmarkers=new Array();
  } else if (mtype == restareasType) {
	for (var i = 0; i < ramarkers.length; i++) {
	  map.removeOverlay(ramarkers[i]);
	}
	ramarkers=new Array();
  } /* end if */
} /* end of function */
// *****************************************************************************	
function zoomIn( latitude, longitude, zoomLvl) {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(latitude, longitude), zoomLvl);
} //end of function
// *****************************************************************************	
function resetZoomMenu() {
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = " "; }
    selectedView.blur();
  }
} //end of function
// *****************************************************************************	
function zoomToSelected(sel) {
  if( sel == null || sel.value == " " ) { return; }
  eval(sel.value + ";");
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = sel.value; }
  }
} //end of function
// *****************************************************************************	
function zoomToRegional() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(42.20, -76.5020), 7); 
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = "zoomToRegional()"; }
  }
} //end of function
// *****************************************************************************	
function zoomToNYMetro() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(41.0100,-73.9368), minClusterZoomLevel);    
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById("selView");
    if( selectedView != null ) { selectedView.value = "zoomToNYMetro()"; }
  }
} //end of function
// *****************************************************************************	
function zoomToAlbany() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(42.6864,-73.9317), minClusterZoomLevel);    
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = "zoomToAlbany()"; }
  }
} //end of function
// *****************************************************************************	
function zoomToSyracuse() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(43.0654,-76.1685), minClusterZoomLevel);    
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = "zoomToSyracuse()"; }
  }
} //end of function
// *****************************************************************************	
function zoomToRochester() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(43.0071,-77.6850), minClusterZoomLevel);    
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = "zoomToRochester()"; }
  }
} //end of function
// *****************************************************************************	
function zoomToBuffalo() {
  map.closeInfoWindow();
  map.setCenter(new GLatLng(42.9194,-78.8141), minClusterZoomLevel);    
  if (document.getElementById('selView')) {
    var selectedView = document.getElementById( "selView" );
    if( selectedView != null ) { selectedView.value = "zoomToBuffalo()"; }
  }
} //end of function
// *****************************************************************************	
function refesh(mtype) {
  map.closeInfoWindow();
		
  if (mtype == incidentsType) {
    removeMarkers(incidentsType);
	if (document.getElementById('cbIncidents').checked) {
      addEventMarkers((new Array(incidentsType, null, null)));
	} else {
	  alert("If you want to display the Accidents/Traffic Conditions icons on the map, please select the Conditions checkbox first.");
	}
  } else if (mtype == closuresType) {
    removeMarkers(closuresType);
	if (document.getElementById('cbClosures').checked) {
      addEventMarkers((new Array(null, closuresType,  null)));
	} else {
	  alert("If you want to display the Closures icons on the map, please select the Closures checkbox first.");
	}
  } else if (mtype == roadworkType) {
    removeMarkers(roadworkType);
	if (document.getElementById('cbRoadwork').checked) {
      addEventMarkers((new Array(null, null, roadworkType)));
	} else {
	  alert("If you want to display the Roadwork icons on the map, please select the Roadwork checkbox first.");
	}
  } else if (mtype == camerasType ) {
	if (document.getElementById('cbCameras').checked) {
      addCamClustMarkers();
	} else {
	  alert("If you want to display the Traffic Camera icons on the map, please select the Traffic Cameras checkbox first.");
	}
  } // end if
} //end of function
// *****************************************************************************	
function checkBounds() {

  if (allowedBounds.contains(map.getCenter())) {
    return;
  }

  //reset bounding coordinates to keep map in range
  var C = map.getCenter();
  var X = C.lng();
  var Y = C.lat();

  var AmaxX = allowedBounds.getNorthEast().lng();
  var AmaxY = allowedBounds.getNorthEast().lat();
  var AminX = allowedBounds.getSouthWest().lng();
  var AminY = allowedBounds.getSouthWest().lat();

  if (X < AminX) {X = AminX;}
  if (X > AmaxX) {X = AmaxX;}
  if (Y < AminY) {Y = AminY;}
  if (Y > AmaxY) {Y = AmaxY;}

  map.setCenter(new GLatLng(Y,X));
}  // end function checkBounds
// *****************************************************************************	
function initIcons() {
  accidenticon.image = pathPrefix + "images/gmap/accident.gif";
  accidenticon.iconSize = new GSize(19, 19);
  accidenticon.iconAnchor = new GPoint(9, 9);
  accidenticon.infoWindowAnchor = new GPoint(9, 9);
		
  trafcondicon.image = pathPrefix + "images/gmap/trafcond.gif";
  trafcondicon.iconSize = new GSize(17, 17);
  trafcondicon.iconAnchor = new GPoint(8, 8);
  trafcondicon.infoWindowAnchor = new GPoint(8, 8);
		
  roadworkicon.image = pathPrefix + "images/gmap/roadwork.gif";
  roadworkicon.iconSize = new GSize(22, 22);
  roadworkicon.iconAnchor = new GPoint(11, 11);
  roadworkicon.infoWindowAnchor = new GPoint(11, 11);
		
  roadclosureicon.image = pathPrefix + "images/gmap/roadclosure.gif";
  roadclosureicon.iconSize = new GSize(17, 17);
  roadclosureicon.iconAnchor = new GPoint(8, 8);
  roadclosureicon.infoWindowAnchor = new GPoint(8, 8);
		
  laneclosureicon.image = pathPrefix + "images/gmap/laneclosure.gif";
  laneclosureicon.iconSize = new GSize(15, 15);
  laneclosureicon.iconAnchor = new GPoint(7, 7);
  laneclosureicon.infoWindowAnchor = new GPoint(7, 7);
		
  interchangeicon.image = pathPrefix + "images/gmap/exitblank.gif";
  interchangeicon.iconSize = new GSize(22, 15);
  interchangeicon.iconAnchor = new GPoint(11, 7);
  interchangeicon.infoWindowAnchor = new GPoint(11, 7);

  travelplazaicon.image = pathPrefix + "images/gmap/travelplaza.gif";
  travelplazaicon.iconSize = new GSize(20, 24);
  travelplazaicon.infoWindowAnchor = new GPoint(10, 12);
		
  restareaicon.image = pathPrefix + "images/gmap/rest.gif";
  restareaicon.iconSize = new GSize(16, 14);
  restareaicon.infoWindowAnchor = new GPoint(8, 7);

  ramicon.image = pathPrefix + "images/gmap/ramicon-yellow.gif";
  ramicon.iconSize = new GSize(20, 20);
  ramicon.iconAnchor = new GPoint(5, 2);
  ramicon.infoWindowAnchor = new GPoint(11, 11);

  cameraicon.image = pathPrefix + "images/gmap/cameraicon.gif";
  cameraicon.iconSize = new GSize(15, 15);
  cameraicon.iconAnchor = new GPoint(7, 7);
  cameraicon.infoWindowAnchor = new GPoint(7, 7);

  clustericon.image = pathPrefix + "images/gmap/clustericon.gif";
  clustericon.iconSize = new GSize(20, 20);
  clustericon.iconAnchor = new GPoint(10, 10);
  clustericon.infoWindowAnchor = new GPoint(10, 10);
} // # end function initIcons
// *****************************************************************************	
function load() {
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map"));
    map.addControl(new GLargeMapControl());  //Add zoom map control
    map.addControl(new GMapTypeControl());   //Add Hybrid and satellite availability    
    map.addControl(new GScaleControl());     //Add Map Scale  
    map.setCenter(new GLatLng(42.20, -76.5020), 7);  //Set centerpoint and scale of map
    map.enableDoubleClickZoom(); //Enable a Double click zoom in and out
    map.enableContinuousZoom();	//Enable continuous zooming from one level to next one
	var mini = new GOverviewMapControl();            //Set up overview control
	map.addControl(mini);                            //Add overview control 
	mini.hide();                                     //minimize overview

    map.clearOverlays();
    if (typeof(plines)!="undefined") {  // check if var exists
	  for (var i = 0; i < plines.length; i++) {
        map.addOverlay(plines[i]);
	  }
    }
		
	//set outermost zoom level for each map type
	var mt = map.getMapTypes();
    for (var i=0; i<mt.length; i++) {
      mt[i].getMinimumResolution = function() {return 6;}
    }

	//set outermost bounds of map   
    allowedBounds = new GLatLngBounds(new GLatLng(40.5,-81), new GLatLng(45.5,-70.5));

	initIcons();  // initialize icons
		
    var eventsToAdd = new Array(null, null, null);
    if (document.getElementById('cbIncidents') &&document.getElementById('cbIncidents').checked){
      eventsToAdd[incidentsIndex]=incidentsType;
	}
	if (document.getElementById('cbClosures') && document.getElementById('cbClosures').checked){
      eventsToAdd[closuresIndex]=closuresType;
	}
	if (document.getElementById('cbRoadwork') && document.getElementById('cbRoadwork').checked){
      eventsToAdd[roadworkIndex]=roadworkType;
	}
	// check to see if we need to add
	if (eventsToAdd[roadworkIndex] != null || eventsToAdd[closuresIndex] != null ||
	    eventsToAdd[incidentsIndex] != null) {
	  addEventMarkers(eventsToAdd);
	}
	
	if (document.getElementById('cbCameras') && document.getElementById('cbCameras').checked){
      addCamClustMarkers();
	}
	if (document.getElementById('cbInterchanges') && document.getElementById('cbInterchanges').checked){
      addIntMarkers();
	}
	if (document.getElementById('cbRAM') && document.getElementById('cbRAM').checked){
      addRAMMarkers();
	}
	if (document.getElementById('selView')){ // default to statewide view
      document.frmView.selView.options[1].selected = true;
	}

    if (document.getElementById('cbTravelplazas') && // make sure they exist
		document.getElementById('cbRestareas')) {
	  if (document.getElementById('cbTravelplazas').checked) {
	    document.getElementById('tplist').style.display = "block";
	    if (document.getElementById('cbRestareas').checked) {
	      addTravelplzRestMarkers("all");
        } else {
	      addTravelplzRestMarkers(travelplazasType);
	    }
      } else if (document.getElementById('cbRestareas').checked) {
	    addTravelplzRestMarkers(restareasType);
      }
	}

	GEvent.addListener(map, "dragend", function() {
 	  userZoomedOrDragged = true;
     }); 

	GEvent.addListener(map, "moveend", function() {
  	  resetZoomMenu();
    }); 

	GEvent.addListener(map, "zoomend", function(oldLevel, newLevel) {
 	  userZoomedOrDragged = true;
 	  // polylines auto on/zoomed out
      if (newLevel < minPlinesZoomLevel && oldLevel >= minPlinesZoomLevel) {
        if (typeof(plines)!="undefined") {  // check if var exists
	      for (var i = 0; i < plines.length; i++) {
            map.addOverlay(plines[i]);
          }
        }
 	  // polylines auto off/zoomed in
      } else if (newLevel >= minPlinesZoomLevel && oldLevel < minPlinesZoomLevel) {
        if (typeof(plines)!="undefined") {  // check if var exists
	      for (var i = 0; i < plines.length; i++) {
            map.removeOverlay(plines[i]);
          }
        }
	  }
	  // cameras/clusters auto off/on (zoomed out)
	  if (newLevel < minClusterZoomLevel && oldLevel >= minClusterZoomLevel) {
	    if (document.getElementById('cbCameras').checked) {
          addCamClustMarkers();
	    }
	  // cameras/clusters auto off/on (zoomed in)
	  } else if (newLevel >= minClusterZoomLevel && oldLevel < minClusterZoomLevel) {
	    if (document.getElementById('cbCameras').checked) {
           addCamClustMarkers();
	    }
      }
	  // interchange auto off/zoomed out
	  if (newLevel < minInterchangeZoomLevel && oldLevel >= minInterchangeZoomLevel) {
	    if (checkedInterchangeOn == 0) {
		  document.getElementById('cbInterchanges').checked = false;
		  removeMarkers("interchanges");
		}
	  // interchange auto on/zoomed in
	  } else if (newLevel >= minInterchangeZoomLevel && oldLevel < minInterchangeZoomLevel) {
	    if (!document.getElementById('cbInterchanges').checked) {
		  document.getElementById('cbInterchanges').checked = true;
		  addIntMarkers();
		}	      
	  } // end interchange auto on/off 
	}); // end zoomend addListener function
		
	//Check the outermost bounds of the map
	GEvent.addListener(map, "move", function() {
      checkBounds();
    });  // end move addListener function

  } else {
	alert("This section of our website uses the Google Maps API which is not compatible with your browser version.  We recommend that you upgrade to the latest version of your browser or use a newer standards compliant browser.  However, if you are not able to upgrade your browser you can use our 'Text View' pages instead.");
  }   // end if broswer compatible 
}  // end function load
// Copyright New York State Thruway Authority. All rights reserved.
