map.totaltraffic.com Open in urlscan Pro
3.94.222.241  Public Scan

Submitted URL: http://map.totaltraffic.com/
Effective URL: https://map.totaltraffic.com/map/
Submission: On March 25 via api from US — Scanned from US

Form analysis 1 forms found in the DOM

POST ./

<form method="post" action="./" id="ctl01" autocomplete="off">
  <div class="aspNetHidden">
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="">
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="">
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="ejZbtX6EVKQdtn6zJUErEEwZtRgnyfFvJSDFjJYVH82rK1/PH04z2HZH5u9y+lt1kO9cwaHj99jU0ubIgDyrjvOGqCwH2EX8N0DzdwEjhL4=">
  </div>
  <script type="text/javascript">
    //<![CDATA[
    var theForm = document.forms['ctl01'];
    if (!theForm) {
      theForm = document.ctl01;
    }

    function __doPostBack(eventTarget, eventArgument) {
      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
      }
    }
    //]]>
  </script>
  <script src="/bundles/MsAjaxJs?v=D6VN0fHlwFSIWjbVzi6mZyE9Ls-4LNrSSYVGRU46XF81" type="text/javascript"></script>
  <script src="../Scripts/umd/popper.min.js" type="text/javascript"></script>
  <script src="../Scripts/jquery-3.5.1.min.js" type="text/javascript"></script>
  <script src="../Scripts/bootstrap.min.js" type="text/javascript"></script>
  <script src="/bundles/WebFormsJs?v=N8tymL9KraMLGAMFuPycfH3pXe6uUlRXdhtYv8A_jUU1" type="text/javascript"></script>
  <script src="../Scripts/moment.min.js" type="text/javascript"></script>
  <script src="../Scripts/moment-timezone-with-data.min.js" type="text/javascript"></script>
  <div class="aspNetHidden">
    <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="9477F8F5">
    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION"
      value="7WbR41b+hmeRDQv8mtvFPIqbNAr+G1o1gyreaEk/nwV8L1J+BsItG9ZI4GsHvAQ1oxlIjphfdHzUKkWWDDiiy/rZz8mV3G8flWBLLfRhA+d6zSd4JhuNSEJ9qiTJjmHG6Mr2hJvfsMLoKMbMoq294p3sPeFzg+oEZjR8gPjMIKQHtetXxGss98BAxGE95O+pzkMAHLRlpShanx9ipYG/gnEFKkYlCwaePLPFRP5lz4VtQjRk+zY8LcRG5K1++Wr5G8ZaDpGtagO8n6fKY/Snyw==">
  </div>
  <script type="text/javascript">
    //<![CDATA[
    Sys.WebForms.PageRequestManager._initialize('ctl00$ctl08', 'ctl01', [], [], [], 90, 'ctl00');
    //]]>
  </script>
  <script type="text/javascript" src="/Scripts/custom/config.js?ver=0.0056"></script>
  <script type="text/javascript" src="/Scripts/custom/utility.js?ver=0.0056"></script>
  <script type="text/javascript" src="/Scripts/custom/ui.js?ver=0.0056"></script>
  <!-- dialog box (modal) -->
  <div id="pnlMasterDialog" class="master-dialog modal fade" tabindex="-1" data-backdrop="true" data-keyboard="false" aria-labelledby="pnlMasterDialog_Title" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable">
      <div class="modal-content">
        <div class="modal-header" style="padding: 5px 5px; background-color: #eee;">
          <div id="pnlMasterDialog_Title" class="modal-title font-18" style="font-weight: bold;"></div>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body"></div>
        <div class="modal-footer"></div>
      </div>
    </div>
  </div>
  <!-- window (modal) -->
  <div id="pnlMasterWindow" class="master-window modal fade" tabindex="-1" data-backdrop="static" data-keyboard="false" aria-labelledby="pnlMasterWindow_Title" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable">
      <div class="modal-content">
        <div class="modal-header" style="padding: 5px 5px; background-color: #eee;">
          <div id="pnlMasterWindow_Title" class="modal-title font-16" style="width: 95%; font-weight: bold;"></div>
          <div id="pnlMasterWindow_TitleMenu" class="modal-title-menu font-16" style="width: 5%; float: right; text-align: right; padding-right: 5px;"></div>
          <button type="button" class="close modal-close-btn" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body embed-responsive overflow-hidden" style="padding: 0; margin: 0;"></div>
        <div class="modal-footer font-14" style="display: none; padding: 3px 5px; background-color: #eee;"></div>
      </div>
    </div>
  </div>
  <!-- push notification -->
  <div id="pnlMasterNotification" class="master-notification font-dark" aria-live="polite" aria-atomic="true" style="position: relative;">
    <div id="pnlMasterNotification_Content" class="master-notification-content" style="position: absolute; top: 0; right: 0;"></div>
  </div>
  <!-- left column overlay -->
  <div id="pnlMasterLeftOverlay" class="master-overlay-left overlay card border-top-0" style="display: none; position: absolute; left: 0; z-index: 3; height: 100%;">
    <div id="pnlMasterLeftOverlay_Content" class="overlay-content" style="display: inline-block; width: 100%; padding-right: 5px; overflow-x: hidden; overflow-y: auto;">
    </div>
  </div>
  <!-- right column overlay -->
  <div id="pnlMasterRightOverlay" class="master-overlay-right overlay card shadow-lg border-top-0" style="display: none; position: absolute; right: 0; z-index: 3; height: 100%;">
    <div id="pnlMasterRightOverlay_Header" class="overlay-header border" style="display: inline-block; width: 100%; min-height: 27px; padding: 3px 8px; background-color: #eee; overflow-x: hidden; overflow-y: auto;">
      <button type="button" class="close" aria-label="Close" onclick="ShowRightOverlay(false)">
        <span aria-hidden="true">×</span>
      </button>
      <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
    </div>
    <div class="overlay-content" style="display: inline-block; width: 100%; padding: 3px 7px; overflow-x: hidden; overflow-y: auto;">
    </div>
  </div>
  <!-- right column (static) -->
  <div id="pnlMasterRight" class="master-right card shadow" style="display: none; float: right; margin-left: 5px; overflow: hidden; border-left: 1px solid rgb(238, 238, 238);">
    <div id="pnlMasterRight_Header" class="master-right-header border" style="display: inline-block; width: 100%; min-height: 27px; padding: 3px 8px; background-color: #eee; overflow-x: hidden; overflow-y: auto;">
      <button type="button" class="close" aria-label="Close" onclick="ShowRightPanel(false)">
        <span aria-hidden="true">×</span>
      </button>
      <div class="master-right-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
    </div>
    <div id="pnlMasterRight_Content" class="master-right-content" style="display: inline-block; width: 100%; padding: 3px 7px; overflow-x: hidden; overflow-y: auto;">
    </div>
  </div>
  <!-- main body (static) -->
  <div id="pnlMasterContent" class="master-content" data-section="" data-subsection="" style="width: 1600px; padding: 2px 4px; float: right; overflow: hidden auto; height: 1113px;">
    <input type="hidden" name="ctl00$MainContent$Demo" id="MainContent_Demo">
    <input type="hidden" name="ctl00$MainContent$Key" id="MainContent_Key">
    <input type="hidden" name="ctl00$MainContent$Alias" id="MainContent_Alias">
    <input type="hidden" name="ctl00$MainContent$Tagline" id="MainContent_Tagline">
    <input type="hidden" name="ctl00$MainContent$Position" id="MainContent_Position">
    <input type="hidden" name="ctl00$MainContent$LatLng" id="MainContent_LatLng">
    <input type="hidden" name="ctl00$MainContent$Zoom" id="MainContent_Zoom" value="11">
    <input type="hidden" name="ctl00$MainContent$CityID" id="MainContent_CityID" value="0">
    <div id="pnlMap" class="font-14 border shadow-sm rounded" style="width: 100%; margin: 0px; padding: 0px; overflow: hidden; height: 1109px;">
      <div id="map" class="map mapboxgl-map" style="overflow: hidden; width: 1590px; height: 1107px;">
        <div class="mapboxgl-canary" style="visibility: hidden;"></div>
        <div class="mapboxgl-canvas-container mapboxgl-interactive mapboxgl-touch-drag-pan mapboxgl-touch-zoom-rotate"><canvas class="mapboxgl-canvas" tabindex="0" aria-label="Map" role="region" width="1590" height="1107"
            style="width: 1590px; height: 1107px;"></canvas></div>
        <div class="mapboxgl-control-container">
          <div class="mapboxgl-ctrl-top-left"></div>
          <div class="mapboxgl-ctrl-top-right">
            <div class="mapboxgl-ctrl mapboxgl-ctrl-group"><button class="mapboxgl-ctrl-zoom-in" type="button" title="Zoom in" aria-label="Zoom in" aria-disabled="false"><span class="mapboxgl-ctrl-icon" aria-hidden="true"></span></button><button
                class="mapboxgl-ctrl-zoom-out" type="button" title="Zoom out" aria-label="Zoom out" aria-disabled="false"><span class="mapboxgl-ctrl-icon" aria-hidden="true"></span></button><button class="mapboxgl-ctrl-compass" type="button"
                title="Reset bearing to north" aria-label="Reset bearing to north"><span class="mapboxgl-ctrl-icon" aria-hidden="true" style="transform: rotate(0deg);"></span></button></div>
          </div>
          <div class="mapboxgl-ctrl-bottom-left">
            <div class="mapboxgl-ctrl" style="display: block;"><a class="mapboxgl-ctrl-logo" target="_blank" rel="noopener nofollow" href="https://www.mapbox.com/" aria-label="Mapbox logo"></a></div>
          </div>
          <div class="mapboxgl-ctrl-bottom-right">
            <div class="mapboxgl-ctrl mapboxgl-ctrl-attrib"><button class="mapboxgl-ctrl-attrib-button" title="Toggle attribution" aria-label="Toggle attribution"></button>
              <div class="mapboxgl-ctrl-attrib-inner" role="list"><a href="https://www.mapbox.com/about/maps/" target="_blank" title="Mapbox" aria-label="Mapbox">© Mapbox</a>
                <a href="https://www.openstreetmap.org/about/" target="_blank" title="OpenStreetMap" aria-label="OpenStreetMap">© OpenStreetMap</a>
                <a class="mapbox-improve-map" href="https://apps.mapbox.com/feedback/?owner=ttwn&amp;id=ckg15d94d02cw19mxew101vv2&amp;access_token=pk.eyJ1IjoidHR3biIsImEiOiJjajIxM3FtZWQwMDB0MndxaXFyZXIzNDR1In0.FHH0LU0K4tnSB3vPf5jUEA" target="_blank" title="Map feedback" aria-label="Map feedback" rel="noopener nofollow">Improve this map</a>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- map overlay form: traffic (exactly same as the map-right-overlay so we can have toggle between the two without rebuilding them) -->
      <div class="map-right-traffic-overlay ui-progressbar-overlay card shadow-lg" style="position: absolute; z-index: 5; width: 25%; opacity: 0.9; right: 4px; top: 0px; height: 1111px;" data-position="">
        <div class="overlay-header border" style="width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: rgb(238, 238, 238); overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapTrafficInfo(false)">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;">Traffic within view</div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: calc(100% - 35px); padding: 3px 7px; overflow-x: hidden; overflow-y: auto;">
          <div class="row" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; height: 25px; margin: 0 1px; padding: 5px 5px; overflow: hidden;">Traffic<span style="display: inline-block; float: right; margin-top: 4px; font-size: 11px; font-style: italic;">* delay in
                minutes</span></div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">Delay</div>
          </div>
          <div id="CCT-42443325" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Decatur on I-285 Outer loop between Flat Shoals Rd (GA-155)/Exit 48 and Glenwood Rd/Exit 44. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">23</div>
          </div>
          <div id="CCT-42443328" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Panthersville on I 20 EB between Columbia Dr/Exit 66 (EB) and Evans Mill Rd/Exit 74. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">7</div>
          </div>
          <div id="CCT-43124351" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Buckhead on GA-400 NB/SB between Old Toll Plaza and I-285/Exit 4. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">5</div>
          </div>
          <div id="CCT-42815119" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Repaving work in Georgia Tech on Howell Mill Rd NW NB/SB between 8th St NW and Holmes St NW/Chattahoochee Ave NW. Reported by ATLDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">2</div>
          </div>
          <div id="CCT-42443329" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Decatur on I-285 Inner loop between Glenwood Rd/Exit 44 and Flat Shoals Rd (GA-155)/Exit 48. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">1</div>
          </div>
          <div id="CCT-43226868" class="traffic row severity-moderate" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Road work. Off-ramp partially blocked in Doraville on I-285 EB off-ramp to NB I-85. Reported by GDOT<br><i class="font-12">ETC 4pm</i></div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-43226416" class="traffic row severity-minor" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Road construction. Right lane closed in Sandy Springs on GA-400 NB at Glenridge Connector/Exit 3 (SB). Reported by GDOT<br><i class="font-12">ETC 3pm</i></div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-43203079" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Bridge closed in Morningside on Cheshire Bridge Rd NB/SB between Liddell Dr NE and Faulkner Rd. Reported by ATLDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-43079856" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Water main replacement in Decatur on E Ponce De Leon Ave EB/WB between Grove Place and N Clarendon Ave. Reported by Press Release</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-42956213" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Closed due to road construction in Atlanta on Lavista Rd EB/WB between Cheshire Bridge Rd and Lavista Walk. Reported by ATLDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-43112556" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Roundabout installation in South Fulton on Butner Rd EB/WB at Union Rd. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-42533167" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Road work. HOV lane closed in Smyrna on I 75 NB between Akers Mill Rd/Exit 258 (HOV NB) and I-75 Express Lanes/Exit 260 (NB). Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-42866343" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Beltline Construction in Midtown on 10th St EB/WB at Monroe Dr. Reported by ATLDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-42896689" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Cumberland on Cumberland Blvd SE at Overton Park Dr</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-41792284" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Marietta on Callaway Rd SW NB/SB between Austell Rd and Al Bishop Drive. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
          <div id="CCT-41792273" class="traffic row severity-construction" style="width: 100%; margin: 1px 0; padding: 0;">
            <div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">Long-term road construction in Conley on I-285 EB/WB between Moreland Ave (US-23)/Exit 53 and Bouldercrest Rd/Exit 51. Reported by GDOT</div>
            <div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;"></div>
          </div>
        </div>
      </div>
      <!-- map affiliate overlay -->
      <div class="map-affiliate-overlay ui-progressbar-overlay card shadow-lg" style="display: none; position: absolute; z-index: 3; width: calc(100% - 8px); opacity: 0.90;" data-position="">
        <div class="overlay-header border" style="display: none; width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: #eee; overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapOverlay({ type: 'affiliate', show: false})">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: calc(100% - 35px); padding: 3px 7px; overflow-x: hidden; overflow-y: auto;"></div>
      </div>
      <!-- map route overlay -->
      <div class="map-route-overlay ui-progressbar-overlay card shadow-lg" style="display: none; position: absolute; z-index: 5; width: calc(100% - 8px); opacity: 0.9; height: 85px;">
        <div class="overlay-header border" style="display: none; width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: #eee; overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapOverlay({ type: 'route', show: false })">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: 80px; padding: 3px 7px; overflow: hidden auto;"></div>
      </div>
      <!-- map overlay form: top, left, right, bottom -->
      <div class="map-top-overlay ui-progressbar-overlay card shadow-lg" style="display: none; position: absolute; z-index: 5; width: calc(100% - 8px); opacity: 0.90;">
        <div class="overlay-header border" style="display: none; width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: #eee; overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapOverlay({ type: 'top', show: false })">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: calc(100% - 35px); padding: 3px 7px; overflow-x: hidden; overflow-y: auto;"></div>
      </div>
      <div class="map-left-overlay ui-progressbar-overlay card shadow-lg" style="position: absolute; z-index: 5; width: 170px; opacity: 0.9; left: 4px; top: 0px; height: 1111px;" data-position="">
        <div class="overlay-header border" style="width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: rgb(238, 238, 238); overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapMenu(false)" style="display: none;">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"><span class="clickable" style="display: inline-block; font-weight: bolder; opacity: 1.0 !important; margin-top: -7px !important; float: left;" title="Settings"
              onclick="ShowMapMenu(false)"><span class="material-icons-outlined md-32">menu</span></span><span style="display: inline-block; margin-left: 10px; margin-top: -2px; float: left;">Settings</span></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: calc(100% - 35px); padding: 3px 7px; overflow-x: hidden; overflow-y: auto;">
          <div id="pnlMenu"><span id="pnlMenuCity" style="display: block; margin: 2px 2px;" data-visible="true"><span class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: 'city' })">Change cities</span><span
                class="content" style="display: block;"><select id="selMarket" class="form-control form-control-sm" onchange="Map_SwitchMarket(this.value)">
                  <option value="0" selected="" disabled="" hidden="">Select a city</option>
                  <option class="form-control-sm" value="33">Albany</option>
                  <option class="form-control-sm" value="96">Albuquerque</option>
                  <option class="form-control-sm" value="99">Allentown</option>
                  <option class="form-control-sm" value="202">Appleton/Oshkosh</option>
                  <option class="form-control-sm" value="157">Asheville</option>
                  <option class="form-control-sm" value="1">Atlanta</option>
                  <option class="form-control-sm" value="51">Augusta</option>
                  <option class="form-control-sm" value="63">Austin</option>
                  <option class="form-control-sm" value="117">Bakersfield</option>
                  <option class="form-control-sm" value="64">Baltimore</option>
                  <option class="form-control-sm" value="145">Baton Rouge</option>
                  <option class="form-control-sm" value="116">Biloxi-Gulfport</option>
                  <option class="form-control-sm" value="125">Binghamton</option>
                  <option class="form-control-sm" value="43">Birmingham</option>
                  <option class="form-control-sm" value="75">Boston</option>
                  <option class="form-control-sm" value="76">Buffalo</option>
                  <option class="form-control-sm" value="169">Cedar Rapids/Iowa City </option>
                  <option class="form-control-sm" value="34">Charleston</option>
                  <option class="form-control-sm" value="67">Charlotte</option>
                  <option class="form-control-sm" value="59">Chattanooga</option>
                  <option class="form-control-sm" value="18">Chicago</option>
                  <option class="form-control-sm" value="77">Cincinnati</option>
                  <option class="form-control-sm" value="50">Ciudad de Mexico, D. F.</option>
                  <option class="form-control-sm" value="78">Cleveland</option>
                  <option class="form-control-sm" value="90">Colorado Springs</option>
                  <option class="form-control-sm" value="73">Columbia</option>
                  <option class="form-control-sm" value="79">Columbus</option>
                  <option class="form-control-sm" value="168">Columbus, GA</option>
                  <option class="form-control-sm" value="179">Corpus Christi</option>
                  <option class="form-control-sm" value="2">Dallas</option>
                  <option class="form-control-sm" value="171">Davenport</option>
                  <option class="form-control-sm" value="112">Dayton</option>
                  <option class="form-control-sm" value="3">Denver</option>
                  <option class="form-control-sm" value="124">Des Moines</option>
                  <option class="form-control-sm" value="17">Detroit</option>
                  <option class="form-control-sm" value="139">El Paso</option>
                  <option class="form-control-sm" value="127">Erie</option>
                  <option class="form-control-sm" value="178">Florida Keys</option>
                  <option class="form-control-sm" value="89">Fort Collins</option>
                  <option class="form-control-sm" value="93">Fort Myers</option>
                  <option class="form-control-sm" value="94">Frederick</option>
                  <option class="form-control-sm" value="138">Fresno</option>
                  <option class="form-control-sm" value="164">Ft Wayne</option>
                  <option class="form-control-sm" value="186">Gainesville-Ocala</option>
                  <option class="form-control-sm" value="21">Grand Rapids</option>
                  <option class="form-control-sm" value="210">Green Bay, WI</option>
                  <option class="form-control-sm" value="68">Greensboro</option>
                  <option class="form-control-sm" value="53">Greenville</option>
                  <option class="form-control-sm" value="23">Harrisburg</option>
                  <option class="form-control-sm" value="160">Harrisonburg</option>
                  <option class="form-control-sm" value="47">Hartford/New Haven</option>
                  <option class="form-control-sm" value="191">Hattiesburg/Laurel</option>
                  <option class="form-control-sm" value="110">Honolulu</option>
                  <option class="form-control-sm" value="4">Houston</option>
                  <option class="form-control-sm" value="226">Huntington-Charleston</option>
                  <option class="form-control-sm" value="48">Huntsville</option>
                  <option class="form-control-sm" value="5">Indianapolis</option>
                  <option class="form-control-sm" value="158">Jackson</option>
                  <option class="form-control-sm" value="81">Jacksonville</option>
                  <option class="form-control-sm" value="72">Kansas City</option>
                  <option class="form-control-sm" value="161">Knoxville</option>
                  <option class="form-control-sm" value="6">Las Vegas</option>
                  <option class="form-control-sm" value="140">Lexington</option>
                  <option class="form-control-sm" value="91">Little Rock</option>
                  <option class="form-control-sm" value="56">Los Angeles</option>
                  <option class="form-control-sm" value="7">Louisville</option>
                  <option class="form-control-sm" value="22">Macon</option>
                  <option class="form-control-sm" value="115">Madison</option>
                  <option class="form-control-sm" value="114">McAllen</option>
                  <option class="form-control-sm" value="42">Memphis</option>
                  <option class="form-control-sm" value="82">Miami/Fort Lauderdale</option>
                  <option class="form-control-sm" value="66">Milwaukee</option>
                  <option class="form-control-sm" value="41">Minneapolis</option>
                  <option class="form-control-sm" value="83">Mobile/Pensacola</option>
                  <option class="form-control-sm" value="159">Monterey-Salinas</option>
                  <option class="form-control-sm" value="141">Montgomery</option>
                  <option class="form-control-sm" value="146">Montreal</option>
                  <option class="form-control-sm" value="187">Myrtle Beach</option>
                  <option class="form-control-sm" value="65">Nashville</option>
                  <option class="form-control-sm" value="55">New Orleans</option>
                  <option class="form-control-sm" value="24">Norfolk</option>
                  <option class="form-control-sm" value="12">NYC</option>
                  <option class="form-control-sm" value="62">Oklahoma City</option>
                  <option class="form-control-sm" value="30">Omaha</option>
                  <option class="form-control-sm" value="69">Orlando</option>
                  <option class="form-control-sm" value="147">Ottawa</option>
                  <option class="form-control-sm" value="182">Pachuca, MX</option>
                  <option class="form-control-sm" value="119">Panama City</option>
                  <option class="form-control-sm" value="224">Parkersburg/Marietta</option>
                  <option class="form-control-sm" value="11">Philadelphia</option>
                  <option class="form-control-sm" value="8">Phoenix</option>
                  <option class="form-control-sm" value="37">Pittsburgh</option>
                  <option class="form-control-sm" value="39">Portland</option>
                  <option class="form-control-sm" value="88">Portsmouth/Manchester</option>
                  <option class="form-control-sm" value="80">Providence</option>
                  <option class="form-control-sm" value="184">Puebla, MX</option>
                  <option class="form-control-sm" value="183">Queretara, MX</option>
                  <option class="form-control-sm" value="70">Raleigh-Durham</option>
                  <option class="form-control-sm" value="142">Reading</option>
                  <option class="form-control-sm" value="111">Richmond</option>
                  <option class="form-control-sm" value="170">Roanoke/Lynchburg</option>
                  <option class="form-control-sm" value="87">Rochester, NY</option>
                  <option class="form-control-sm" value="57">Sacramento</option>
                  <option class="form-control-sm" value="54">Salt Lake City</option>
                  <option class="form-control-sm" value="9">San Antonio</option>
                  <option class="form-control-sm" value="36">San Diego</option>
                  <option class="form-control-sm" value="35">San Francisco/San Jose</option>
                  <option class="form-control-sm" value="121">Sarasota</option>
                  <option class="form-control-sm" value="52">Savannah</option>
                  <option class="form-control-sm" value="84">Seattle</option>
                  <option class="form-control-sm" value="60">Spokane</option>
                  <option class="form-control-sm" value="46">Springfield</option>
                  <option class="form-control-sm" value="192">Springfield, MO</option>
                  <option class="form-control-sm" value="19">St. Louis</option>
                  <option class="form-control-sm" value="151">Stockton / Modesto</option>
                  <option class="form-control-sm" value="44">Syracuse</option>
                  <option class="form-control-sm" value="118">Tallahassee</option>
                  <option class="form-control-sm" value="20">Tampa</option>
                  <option class="form-control-sm" value="25">Toledo</option>
                  <option class="form-control-sm" value="148">Toronto</option>
                  <option class="form-control-sm" value="10">Tucson</option>
                  <option class="form-control-sm" value="61">Tulsa</option>
                  <option class="form-control-sm" value="49">Tuscaloosa</option>
                  <option class="form-control-sm" value="152">Vancouver</option>
                  <option class="form-control-sm" value="40">Washington</option>
                  <option class="form-control-sm" value="85">West Palm Beach/Treasure Coast</option>
                  <option class="form-control-sm" value="97">Wheeling</option>
                  <option class="form-control-sm" value="155">Wichita</option>
                  <option class="form-control-sm" value="165">Wilkes-Barre</option>
                  <option class="form-control-sm" value="172">Williamsport</option>
                  <option class="form-control-sm" value="98">Worcester</option>
                  <option class="form-control-sm" value="177">Youngstown</option>
                </select></span></span><span id="pnlMenuFeature" class="font-14" style="display: block; margin: 2px 2px;" data-visible="true"><span class="font-bold header clickable"
                style="display: block; margin-bottom: 5px; margin-top: 15px !important;" onclick="Menu_ShowSection({ type: 'feature' })">Toggle view on/off</span><span class="content" style="display: block;"><span
                  class="form-major-roadway-item form-check form-check-inline"><input class="form-check-input" type="checkbox" checked="checked" value="0,1,2,3" id="chkMajorRoadway" onchange="Map_SettingsOnChange()"><label class="form-check-label"
                    for="chkMajorRoadway" style="width: 100%;">Major roadway</label></span><span class="form-local-roadway-item form-check form-check-inline"><input class="form-check-input" type="checkbox" value="4,5,6,7" id="chkLocalRoadway"
                    onchange="Map_SettingsOnChange()"><label class="form-check-label" for="chkLocalRoadway" style="width: 100%;">Local roadway</label></span><span class="form-traffic-item form-check form-check-inline"><input class="form-check-input"
                    type="checkbox" checked="checked" value="true" id="chkTraffic" onchange="Map_SettingsOnChange()"><label class="form-check-label" for="chkTraffic" style="width: 100%;">Traffic icon</label></span><span
                  class="form-traffic-list-item form-check form-check-inline"><input class="form-check-input" type="checkbox" checked="checked" value="true" id="chkTrafficList" onchange="Map_SettingsOnChange()"><label class="form-check-label"
                    for="chkTrafficList" style="width: 100%;">Traffic list</label></span><span class="form-camera-stream-item form-check form-check-inline"><input class="form-check-input" type="checkbox" checked="checked" value="true"
                    id="chkCamStream" onchange="Map_SettingsOnChange()"><label class="form-check-label" for="chkCamStream" style="width: 100%;">Camera stream</label></span><span class="form-camera-still-item form-check form-check-inline"><input
                    class="form-check-input" type="checkbox" checked="checked" value="true" id="chkCamStill" onchange="Map_SettingsOnChange()"><label class="form-check-label" for="chkCamStill" style="width: 100%;">Camera
                    still</label></span></span></span><span id="pnlMenuAction" class="font-14" style="display: block; margin: 2px 2px; margin-top: 15px !important;" data-visible="true"><span class="font-bold header clickable"
                style="display: block; margin-bottom: 5px;" onclick="Menu_ShowSection({ type: 'action' })">Click map action</span><span class="content" style="display: block;"><span class="form-action-route-item form-check form-check-inline"><input
                    class="form-check-input" type="radio" checked="checked" id="chkActionSpeed" name="chkPageAction" value="speed" onchange="Page_ActionOnChange()"><label class="form-check-label" for="chkActionSpeed" style="width: 100%;">Show
                    speed</label></span><span class="form-action-route-item form-check form-check-inline"><input class="form-check-input" type="radio" id="chkActionRoute" name="chkPageAction" value="route" onchange="Page_ActionOnChange()"><label
                    class="form-check-label" for="chkActionRoute" style="width: 100%;">Build route</label></span></span></span><span style="position: absolute; bottom: 35px;"><span id="pnlMenuHelp" style="display: block;" data-visible="false"><span
                  class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: 'help' })">Help</span><span class="content" style="display: none;"><span class="font-13"
                    style="display: block;"><a class="reverse" href="/About" target="_blank">Contact us</a></span><span class="font-13" style="display: block;"><a class="reverse" href="/Privacy" target="_blank">Pricacy policy</a></span><span
                    class="font-13" style="display: block;"><a class="reverse" href="/Terms" target="_blank">Terms of service</a></span></span></span><span id="pnlMenuLegend" style="display: block; margin-top: 15px;" data-visible="false"><span
                  class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: 'legend' })">Legend</span><span class="content" style="display: none;"><span class="font-13" style="display: block;"><span
                      class="severity-key-extreme severity-extreme shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Stopped
                      traffic</span></span><span class="font-13" style="display: block;"><span class="severity-key-major severity-major shadow rounded"
                      style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Stop and go traffic</span></span><span class="font-13"
                    style="display: block;"><span class="severity-key-moderate severity-moderate shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span
                      style="display: inline-block; margin-left: 5px;">Slow traffic</span></span><span class="font-13" style="display: block;"><span class="severity-key-minor severity-minor shadow rounded"
                      style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Heavy traffic</span></span><span class="font-13" style="display: block;"><span
                      class="severity-key-freely severity-freely shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">No
                      congestion</span></span><span class="font-11" style="display: block; margin-top: 10px;">* click any congestion lines to get details</span></span></span></span></div>
        </div>
      </div>
      <div class="map-right-overlay ui-progressbar-overlay card shadow-lg" style="display: none; position: absolute; z-index: 5; width: calc(100% - 8px); opacity: 0.90;">
        <div class="overlay-header border" style="display: none; width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: #eee; overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapOverlay({ type: 'right', show: false })">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: calc(100% - 35px); padding: 3px 7px; overflow-x: hidden; overflow-y: auto;"></div>
      </div>
      <div class="map-bottom-overlay ui-progressbar-overlay card shadow-lg" style="position: absolute; z-index: 6; width: 170px; opacity: 0.9; bottom: 2px; height: 29px;" data-position="">
        <div class="overlay-header border" style="display: none; width: 100%; min-height: 27px; max-height: 35px; padding: 3px 8px; background-color: #eee; overflow: hidden;">
          <button type="button" class="close" aria-label="Close" onclick="ShowMapOverlay({ type: 'bottom', show: false})">
            <span aria-hidden="true">×</span>
          </button>
          <div class="overlay-title font-16" style="padding-top: 3px; font-weight: bold;"></div>
        </div>
        <div class="overlay-content" style="display: inline-block; width: 100%; height: 27px; padding: 3px 7px; overflow: hidden;"><span data-toggle="tooltip" data-placement="top"
            style="display: inline-block; cursor: default; white-space: nowrap; overflow: hidden;">Last updated: <b>11:13 AM</b></span></div>
      </div>
    </div>
    <script type="text/javascript">
      //define page global variables
      var demo = '';
      var key = '';
      var alias = '';
      var tagline = '';
      var position = '';
      var latlng = '';
      var zoom = '11';
      var cityId = '0';
      var oCity = null;
      var maxSavedRoute = 7;
      //validate parameters passed in
      if (typeof demo == 'string' && demo > '') demo = parseInt(demo);
      else demo = 0;
      if (typeof zoom == 'string' && zoom > '') zoom = parseInt(zoom);
      else zoom = 11;
      if (typeof cityId == 'string' && cityId > '') cityId = parseInt(cityId);
      else cityId = 0;
      if (latlng == '') latlng = null;
      //determine which site theme color: [classic, light]
      var theme = "";
      if (theme == null || theme == 'classic') theme = '';
      //define the language / speed type = [mph, kph]
      var speedType = "mph";
      var language = "EN";
      if (language != 'EN') speedType = "kph";
      //get window dimension
      var wdWidth = $(window).width();
      var wdHeight = $(window).height();
      //map default panel overlay dimension (if available)
      var minPanelWidth = 500;
      var minPanelHeight = 650;
      var plWidth = 170;
      var pbHeight = 29;
      var plIconWidth = 50;
      var plIconHeight = 48;
      var prWidth = "25%";
      if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true) {
        prWidth = "40%";
      }
      //default map settings
      var defaultAction = 'speed'; //action = [speed (default), travel] when roadway is clicked/right-clicked
      //define the default settings: traffic, camera, travel
      //NOTE: congestiontype = [speed (pure speed), speedoverride (allow override speed)]
      var defaulMenuSettings = {
        city: true,
        feature: true,
        action: true,
        help: false,
        legend: false
      };
      var defaultCameraSettings = {
        stream: true,
        still: true
      };
      var defaultTrafficSettings = {
        congestion: true,
        congestiontype: "speedoverride",
        type: "flow,incident,construction,event,transit",
        list: true,
        frc: "0,1,2,3"
      };
      if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true && mobileType != 'ipad') defaultTrafficSettings.list = false;
      var defaultRouteSettings = {
        id: null,
        city: 0,
        title: null,
        description: null,
        start: null,
        end: null,
        routes: null
      };
      //update default settings for demo account (preview account)
      if (demo == 1) {
        defaultTrafficSettings.list = false;
      }
      //get all accessible market object
      var accessibleCityId = null;
      if (typeof gblValidCityId != 'undefined' && gblValidCityId != null && gblValidCityId.length > 0) accessibleCityId = gblValidCityId.join(",");
      var marketOptions = [];
      var arrMarket = GetCityData({
        fetch: true,
        map: true,
        id: accessibleCityId,
        sort: "name"
      });
      if (typeof arrMarket == 'undefined' || arrMarket == null) arrMarket = [];
      if (arrMarket.length > 0) {
        //add first item
        var item = '<option value="0" selected disabled hidden>Select a city</option>';
        marketOptions.push(item);
        //build the menu options (only once)
        var lenMarket = arrMarket.length;
        for (var i = 0; i < lenMarket; i++) {
          var aCity = arrMarket[i];
          if (typeof aCity.properties != 'undefined') aCity = aCity.properties;
          var aId = aCity.id;
          var aName = aCity.name;
          var isValid = true;
          if (isValid == true && typeof aCity.status != 'undefined' && aCity.status != null && typeof aCity.status.active != 'undefined' && aCity.status.active != null && aCity.status.active == false) isValid = false;
          if (isValid == true && typeof aCity.status != 'undefined' && aCity.status != null && typeof aCity.status.private != 'undefined' && aCity.status.private != null && aCity.status.private == true) isValid = false;
          //error check T3 markets
          if (aName.indexOf("-T3") >= 0) {
            aName = aName.replace("-T3", "").trim();
            //validate if this market name is already used
            var chkName = arrMarket.find(x => x.properties.name == aName && x.properties.id != aId);
            if (chkName != null) {
              //another market exists with same name
              isValid = false;
            } else {
              //no other market contains this, rename it
              aCity.name = aName;
            }
          }
          if (isValid == true) {
            var item = '<option class="form-control-sm" value="' + aId + '">' + aName + '</option>';
            marketOptions.push(item);
          }
        }
      }
      //validate the latlng (if needed)
      if (latlng != null && typeof latlng == 'string' && latlng > '') {
        var aLat = null;
        var aLng = null;
        //error check the delimitor passed in, convert to comma
        latlng = latlng.trim();
        if (latlng.indexOf("/") > 0) latlng = latlng.replace("/", ",");
        else if (latlng.indexOf(";") > 0) latlng = latlng.replace(";", ",");
        else if (latlng.indexOf(" ") > 0) latlng = latlng.replace(" ", ",");
        else if (latlng.indexOf("|") > 0) latlng = latlng.replace("|", ",");
        var aLatLng = latlng.split(",");
        if (aLatLng != null && aLatLng.length == 2) {
          aLat = aLatLng[0];
          aLng = aLatLng[1];
          if (typeof aLat == 'string') aLat = parseFloat(aLat);
          if (typeof aLng == 'string') aLng = parseFloat(aLng);
        }
        //get nearest cityId (if available)
        if (cityId <= 0 && arrMarket != null && arrMarket.length > 0 && aLat != null && aLng != null) {
          oCity = GetCityData({
            data: arrMarket,
            nearestlatlng: latlng,
            nearest: true,
            fetch: true
          });
          if (oCity != null) {
            if (typeof oCity.properties != 'undefined') oCity = oCity.properties;
            //get this nearby market's location to go to
            if (typeof oCity.location != 'undefined' && oCity.location != null && typeof oCity.location.lat != 'undefined' && typeof oCity.location.lng != 'undefined' && oCity.location.lat != null && oCity.location.lng != null) {
              aLat = oCity.location.lat;
              aLng = oCity.location.lng;
            }
            if (typeof oCity.id != 'undefined' && oCity.id != null) cityId = oCity.id;
            if (typeof cityId == 'string') cityId = parseInt(cityId);
          } else {
            oCity = null;
          }
        }
        if (aLat != null && aLng != null) latlng = new LatLng(aLat, aLng);
        else latlng = null;
      }
      //OVERWRITE: get previously saved viewstate info to overwrite when no params passed in: city, map
      if (latlng == null && cityId <= 0) {
        //only load previous info (if no param passed in)
        var pCity = GetViewstateProp("city");
        if (pCity != null) {
          if (typeof pCity.properties != 'undefined') pCity = pCity.properties;
          //save it
          oCity = pCity;
          cityId = oCity.id;
        }
        //get the previously viewed center point
        var pMap = GetViewstateProp("map");
        if (pMap != null) {
          if (typeof pMap.center != 'undefined') latlng = pMap.center;
          if (typeof pMap.zoom != 'undefined') zoom = pMap.zoom;
        }
      }
      //DEFAULT: auto-load Atlanta first time hitting the site
      if (cityId <= 0) {
        cityId = 1;
        latlng = null;
      }
      //initialize variables (market and lat/lng info if needed)
      if (cityId > 0 && (oCity == null || latlng == null)) {
        if (oCity == null) {
          oCity = GetCityData({
            data: arrMarket,
            id: cityId,
            fetch: true
          });
          if (typeof oCity.properties != 'undefined') oCity = oCity.properties;
        }
        if (latlng == null && oCity != null && typeof oCity.location != 'undefined' && oCity.location != null && typeof oCity.location.lat != 'undefined' && typeof oCity.location.lng != 'undefined' && oCity.location.lat != null && oCity.location
          .lng != null) {
          latlng = new LatLng(oCity.location.lat, oCity.location.lng);
        }
      }
      //save viewstate info: city
      if (oCity != null) {
        SaveViewstateProp({
          city: oCity
        });
      }
      //current page viewstate
      var oPage = {
        id: "map",
        menu: Object.copy(defaulMenuSettings),
        action: defaultAction,
        traffic: Object.copy(defaultTrafficSettings),
        camera: Object.copy(defaultCameraSettings),
        route: Object.copy(defaultRouteSettings)
      };
      //DISABLE "action" (until route logic figured out)
      //get previous session page viewstate (if saved) latest settings and update the page variables
      if (demo == 0) {
        //if NOT demo account, get saved viewstate to use as initial page variables
        var pPage = GetPageViewstate();
        if (typeof pPage != 'undefined' && pPage != null) {
          if (typeof pPage.action != 'undefined' && pPage.action != null) oPage.action = pPage.action;
          if (typeof pPage.traffic != 'undefined' && pPage.traffic != null) oPage.traffic = pPage.traffic;
          if (typeof pPage.camera != 'undefined' && pPage.camera != null) oPage.camera = pPage.camera;
          if (typeof pPage.menu != 'undefined' && pPage.menu != null) oPage.menu = pPage.menu;
        }
      }
      //DISABLE "action" (until route logic figured out)
      //FEATURE: (1) allow saving a "previous" created route's they built (similar to how google tracks your previous map searches for easy access)
      //NOTE: format similar to travel settings but only the settings part since we will need to fetch the latest speed data for each location
      //format: { id: {roadwayId}_{dirCode}_{startId}_{endId}, roadway: null, dircode: null, start: null, end: null, title: null }
      var arrRoute = [];
      //var pRoute = GetRouteViewstate();
      //if (typeof pRoute != 'undefined' && pRoute != null && pRoute.length > 0)
      //    arrRoute = pRoute;
      ////remove all local storage data
      //DeleteAllStorage();
      //get affiliate info
      var oAffiliate = null;
      if (key != null && key > '') {
        oAffiliate = GetAffiliateData({
          callsign: key,
          fetch: true
        });
        if (Array.isArray(oAffiliate) == true) {
          if (oAffiliate.length > 0) oAffiliate = oAffiliate[0];
          else oAffiliate = null;
        }
      }
      if (demo == 1) {
        //demo version, override affiliate object
        //if no account exists, create "fake" account
        if (oAffiliate == null) oAffiliate = {
          id: "",
          active: false,
          callsign: "",
          name: "",
          alias: "",
          logo: "",
          url: "",
          description: "",
          notes: "",
          position: null,
          lat: null,
          lng: null,
          geopoint: null,
          cityid: 0,
          accessiblecity: null
        };
        //override some properites (if passed in)
        if (cityId != null && cityId > 0) oAffiliate.cityid = cityId;
        if (key != null && key > '') oAffiliate.callsign = key;
        if (alias != null && alias > '') oAffiliate.alias = alias;
        if (tagline != null && tagline > '') oAffiliate.description = tagline;
        if (position != null && position > '') oAffiliate.position = position;
        if (latlng != null && typeof latlng == 'string' && latlng > '') {
          var aLat = null;
          var aLng = null;
          var aLatLng = latlng.split(",");
          if (aLatLng != null && aLatLng.length == 2) {
            aLat = aLatLng[0];
            aLng = aLatLng[1];
            if (typeof aLat == 'string') aLat = parseFloat(aLat);
            if (typeof aLng == 'string') aLng = parseFloat(aLng);
            //save it
            oAffiliate.lat = aLat;
            oAffiliate.lng = aLng;
          }
        }
      }
      /* MENU FUNCTIONS */
      //handler to manage the action for click/right-click on the map
      function Page_ActionOnChange() {
        //get the action value
        var pnlMenu = $("#pnlMenu");
        var action = pnlMenu.find("input[name='chkPageAction']:checked").val();
        //save the page settings
        var oRouteSettings = Object.copy(defaultRouteSettings);
        SavePageProp([{
          name: "action",
          value: action
        }, {
          name: "route",
          value: oRouteSettings
        }]);
        //save the traffic congestion flag FIRST, before updating to new one when switching between the two actions?
        //turn on/off flow layers
        if (action == 'speed') {
          //turn back on flow layers: (a) turn on what needs to be visible
          Map_ShowCongestion();
          //hide any route info
          Route_ClearMap();
          ShowRouteMenu(false);
        } else if (action == 'route') {
          //turn off flow layers: (a) show all possible features, (b) set visibility=0
          Map_ShowCongestion(false);
          //show the route menu UI
          ShowRouteMenu();
        }
        //save latest map viewstate changes
        SavePageProp({
          traffic: oPage.traffic
        });
        SaveMapViewstate();
      }
      //show / hide affiliate info on map (if available)
      function ShowAffiliateOnMap(options) {
        var show = true;
        var width = null;
        var height = null;
        var overlayPosition = null;
        var opacity = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
            if (typeof options.position != 'undefined') overlayPosition = options.position;
            if (typeof options.opacity != 'undefined') opacity = options.opacity;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check
        if (width == null) width = plIconWidth;
        if (height == null) height = plIconHeight;
        if (overlayPosition == null) overlayPosition = "bottom";
        if (opacity == null) opacity = 0.90;
        //error check screen size (if too small do not show)
        //validate: (1) only show if there is an affiliate object (or demo object), (2) must have logo/text
        var logo = "";
        if (oAffiliate == null) show = false;
        else if (oAffiliate != null) {
          //get the position (if available)
          if (typeof oAffiliate.position != 'undefined' && oAffiliate.position != null && oAffiliate.position > '') {
            overlayPosition = oAffiliate.position;
          }
          //logo/text priority: (1) logo, (2) text
          if (typeof oAffiliate.logo != 'undefined' && oAffiliate.logo != null && oAffiliate.logo > '') {
            //image logo
            logo = '<img width="25px" height="25px" src="' + oAffiliate.logo + '" />';
          } else {
            //text: {alias, callsign, name}: {tagline}
            if (typeof oAffiliate.alias != 'undefined' && oAffiliate.alias != null && oAffiliate.alias > '') logo = oAffiliate.alias;
            else if (typeof oAffiliate.callsign != 'undefined' && oAffiliate.callsign != null && oAffiliate.callsign > '') logo = oAffiliate.callsign.toUpperCase();
            else if (typeof oAffiliate.name != 'undefined' && oAffiliate.name != null && oAffiliate.name > '') logo = oAffiliate.name;
            //add tagline
            if (typeof oAffiliate.description != 'undefined' && oAffiliate.description != null && oAffiliate.description > '') {
              if (logo > '') logo += ": ";
              logo += oAffiliate.description;
            }
          }
          //validate position = menu (MUST have a logo icon)
          if (overlayPosition == 'menu' && logo != null && logo.indexOf('<img') < 0) {
            //no icon exists for position=menu, change it to display at bottom
            overlayPosition = 'bottom';
          }
        }
        //validate: (1) logo/text exists, (2) not position=menu (this will be replacing the settings icon)
        if (logo == null || logo == "") show = false;
        if (show == true && overlayPosition != null && overlayPosition == 'menu') show = false;
        //make sure the page size is correct
        PageResize();
        //determine action to take
        if (show == true) {
          var content = '<span class="logo font-16 font-bold" style="padding: 2px 0; white-space: nowrap;">' + logo + '</span>';
          ShowMapOverlay({
            type: "affiliate",
            close: false,
            position: overlayPosition,
            float: "right",
            height: "30px",
            content: content,
            overflow: "hidden",
            opacity: opacity
          });
          //adjust the width/height based on the content's width/height
          Affiliate_OnResize();
        } else {
          //hide panel
          ShowMapOverlay({
            type: "affiliate",
            show: false
          });
        }
      }
      //handler to move/resize the affiliate logo/text overlay
      function Affiliate_OnResize(options) {
        var oOverlay = $(".map-affiliate-overlay");
        var oOverlayContent = oOverlay.find(".overlay-content");
        var oOverlayLogo = oOverlayContent.find(".logo");
        //initialize variables
        var width = null;
        var height = null;
        var opacity = null;
        var overlayPosition = null;
        var marginLeft = null;
        var marginRight = null;
        var marginTop = null;
        var marginBottom = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
            if (typeof options.opacity != 'undefined') opacity = options.opacity;
            if (typeof options.position != 'undefined') overlayPosition = options.position;
            if (typeof options.marginleft != 'undefined') marginLeft = options.marginleft;
            if (typeof options.marginright != 'undefined') marginRight = options.marginright;
            if (typeof options.margintop != 'undefined') marginTop = options.margintop;
            if (typeof options.marginbottom != 'undefined') marginBottom = options.marginbottom;
          }
        }
        if (oOverlay.length > 0 && oOverlay.is(":visible") == true) {
          //get default: (a) position
          if (overlayPosition == null || overlayPosition == '') {
            //get data from overlay panel (if available)
            overlayPosition = oOverlay.attr("data-position");
            if (typeof overlayPosition == 'undefined' || overlayPosition == null) overlayPosition = '';
          }
          //determine the width/height
          if (width == null || height == null) {
            //define the size
            var padding = 10;
            var paddingWidth = 6;
            var paddingHeight = 4;
            width = oOverlayLogo.width() + padding + paddingWidth;
            height = oOverlayLogo.height() + padding + paddingHeight;
          }
          //determine the margin info
          if (overlayPosition == 'top' || overlayPosition == 'bottom') {
            //get default (or reset to default)
            if (overlayPosition == "top") {
              marginTop = "12px";
              marginRight = "45px";
            } else {
              marginBottom = "20px";
            }
            //determine any special movement: (1) right panel is open: (a) speed overlay, (b) traffic overlay
            var isSpeedOverlayOpen = IsMapOverlayOpen("right");
            var isTrafficOverlayOpen = IsMapOverlayOpen("right-traffic");
            if ((isSpeedOverlayOpen == true || isTrafficOverlayOpen == true) && (overlayPosition == 'top' || overlayPosition == 'bottom')) {
              if (overlayPosition == 'top') {
                marginTop = "3px";
              } else if (overlayPosition == 'bottom') {
                marginBottom = "4px";
              }
            }
          }
          //resize/move overlay
          if (width != null || height != null || opacity != null || marginLeft != null || marginRight != null || marginTop != null || marginBottom != null) ResizeMapOverlay({
            type: "affiliate",
            width: width,
            height: height,
            opacity: opacity,
            marginleft: marginLeft,
            marginright: marginRight,
            margintop: marginTop,
            marginbottom: marginBottom
          });
        }
      }
      //show / hide map menu options on the left panel
      function ShowMapMenu(options) {
        var show = true;
        var width = null;
        var height = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check
        if (width == null) width = plWidth;
        if (wdWidth <= minPanelWidth) width = "100%";
        //error check screen size (if too small do not show)
        //make sure the page size is correct
        PageResize();
        if (show == true) {
          //close any map info window (if opened)
          CloseInfoWindow();
          //get the current menu options
          var oMenuSettings = GetPageProp("menu");
          //show: show OPEN menu options
          var icon =
            '<span class="clickable" style="display: inline-block; font-weight: bolder; opacity: 1.0 !important; margin-top: -7px !important; float: left;" title="Settings" onclick="ShowMapMenu(false)"><span class="material-icons-outlined md-32">menu</span></span>';
          var title = icon + '<span style="display: inline-block; margin-left: 10px; margin-top: -2px; float: left;">Settings</span>';
          //FUTURE: build city menu options (allow user to jump to specific markets)
          var menuMarkets = '';
          if (marketOptions != null && marketOptions.length > 0) {
            var selMarkets = '<select id="selMarket" class="form-control form-control-sm" onchange="Map_SwitchMarket(this.value)">';
            selMarkets += marketOptions.join("");
            selMarkets += '</select>';
            //deteremine visibility state
            var secMarketVisible = "true";
            var secMarketDisplay = "block";
            if (oMenuSettings != null && typeof oMenuSettings.city != 'undefined' && oMenuSettings.city == false) {
              secMarketVisible = "false";
              secMarketDisplay = "none";
            }
            menuMarkets = '<span id="pnlMenuCity" style="display: block; margin: 2px 2px;" data-visible="' + secMarketVisible + '">';
            menuMarkets += '<span class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: \'city\' })">Change cities</span>';
            menuMarkets += '<span class="content" style="display: ' + secMarketDisplay + ';">' + selMarkets + '</span>';
            menuMarkets += '</span>';
          }
          //get current map settings for the checkboxes
          var oTrafficSettings = GetPageProp("traffic");
          var oCameraSettings = GetPageProp("camera");
          var chkMajorRoadway = '';
          var chkLocalRoadway = '';
          var chkTraffic = '';
          var chkTrafficList = '';
          var cssTrafficList = '';
          var chkCameraStream = '';
          var cssCameraStream = '';
          var chkCameraStill = '';
          if (typeof oTrafficSettings.frc != 'undefined') {
            var chkFrc = oTrafficSettings.frc;
            if (Array.isArray(chkFrc) == false) {
              if (typeof chkFrc != 'string') chkFrc = chkFrc.toString();
              chkFrc = chkFrc.split(',');
            }
            if (chkFrc.indexOf("2") >= 0) chkMajorRoadway = 'checked="checked"';
            if (chkFrc.indexOf("6") >= 0) chkLocalRoadway = 'checked="checked"';
          }
          if (typeof oTrafficSettings.type != 'undefined' && oTrafficSettings.type != null && oTrafficSettings.type > '') chkTraffic = 'checked="checked"';
          if (typeof oTrafficSettings.list != 'undefined' && oTrafficSettings.list != null && oTrafficSettings.list == true) chkTrafficList = 'checked="checked"';
          if (oCameraSettings != null) {
            if (typeof oCameraSettings.stream != 'undefined' && oCameraSettings.stream != null && oCameraSettings.stream == true) chkCameraStream = 'checked="checked"';
            if (typeof oCameraSettings.still != 'undefined' && oCameraSettings.still != null && oCameraSettings.still == true) chkCameraStill = 'checked="checked"';
          }
          if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true && mobileType != 'ipad') {
            cssTrafficList = ' style="display: none;"';
            cssCameraStream = ' style="display: none;"';
          }
          //deteremine visibility state
          var secFeatureVisible = "true";
          var secFeatureDisplay = "block";
          if (oMenuSettings != null && typeof oMenuSettings.feature != 'undefined' && oMenuSettings.feature == false) {
            secFeatureVisible = "false";
            secFeatureDisplay = "none";
          }
          //build menu features options: (1) turn on/off the congestion layer (major and local roadways), (2) turn on/off traffic icons, (2) turn on/off cameras (stream, still)
          var menuMajorRoadway = '<span class="form-major-roadway-item form-check form-check-inline"><input class="form-check-input" type="checkbox" ' + chkMajorRoadway +
            ' value="0,1,2,3" id="chkMajorRoadway" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkMajorRoadway" style="width: 100%;">Major roadway</label></span>';
          var menuLocalRoadway = '<span class="form-local-roadway-item form-check form-check-inline"><input class="form-check-input" type="checkbox" ' + chkLocalRoadway +
            ' value="4,5,6,7" id="chkLocalRoadway" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkLocalRoadway" style="width: 100%;">Local roadway</label></span>';
          var menuTraffic = '<span class="form-traffic-item form-check form-check-inline"><input class="form-check-input" type="checkbox" ' + chkTraffic +
            ' value="true" id="chkTraffic" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkTraffic" style="width: 100%;">Traffic icon</label></span>';
          var menuTrafficList = '<span class="form-traffic-list-item form-check form-check-inline"' + cssTrafficList + '><input class="form-check-input" type="checkbox" ' + chkTrafficList +
            ' value="true" id="chkTrafficList" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkTrafficList" style="width: 100%;">Traffic list</label></span>';
          var menuCameraStream = '<span class="form-camera-stream-item form-check form-check-inline"' + cssCameraStream + '><input class="form-check-input" type="checkbox" ' + chkCameraStream +
            ' value="true" id="chkCamStream" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkCamStream" style="width: 100%;">Camera stream</label></span>';
          var menuCameraStill = '<span class="form-camera-still-item form-check form-check-inline"><input class="form-check-input" type="checkbox" ' + chkCameraStill +
            ' value="true" id="chkCamStill" onchange="Map_SettingsOnChange()" /><label class="form-check-label" for="chkCamStill" style="width: 100%;">Camera still</label></span>';
          var featureContent = '<span class="content" style="display: ' + secFeatureDisplay + ';">' + menuMajorRoadway + menuLocalRoadway + menuTraffic + menuTrafficList + menuCameraStream + menuCameraStill + '</span>';
          var menuFeature = '<span id="pnlMenuFeature" class="font-14" style="display: block; margin: 2px 2px;" data-visible="' + secFeatureVisible + '">';
          menuFeature += '<span class="font-bold header clickable" style="display: block; margin-bottom: 5px; margin-top: 15px !important;" style="display: block;" onclick="Menu_ShowSection({ type: \'feature\' })">Toggle view on/off</span>';
          menuFeature += featureContent;
          menuFeature += '</span>';
          ////DISABLE "action" (until route logic figured out)
          //var menuAction = '';
          //build map action feature: (1) show roadway speed info, (2) build route
          //deteremine visibility state
          var secActionVisible = "true";
          var secActionDisplay = "block";
          if (oMenuSettings != null && typeof oMenuSettings.action != 'undefined' && oMenuSettings.action == false) {
            secActionVisible = "false";
            secActionDisplay = "none";
          }
          var chkActionSpeed = '';
          var chkActionRoute = '';
          if (typeof oPage.action != 'undefined' && oPage.action != null) {
            if (oPage.action == 'route') chkActionRoute = 'checked="checked"';
            else chkActionSpeed = 'checked="checked"';
          }
          var menuActionRoute = '<span class="form-action-route-item form-check form-check-inline"><input class="form-check-input" type="radio" ' + chkActionRoute +
            ' id="chkActionRoute" name="chkPageAction" value="route" onchange="Page_ActionOnChange()" /><label class="form-check-label" for="chkActionRoute" style="width: 100%;">Build route</label></span>';
          var menuActionSpeed = '<span class="form-action-route-item form-check form-check-inline"><input class="form-check-input" type="radio" ' + chkActionSpeed +
            ' id="chkActionSpeed" name="chkPageAction" value="speed" onchange="Page_ActionOnChange()" /><label class="form-check-label" for="chkActionSpeed" style="width: 100%;">Show speed</label></span>';
          var actionContent = '<span class="content" style="display: ' + secActionDisplay + ';">' + menuActionSpeed + menuActionRoute + '</span>';
          var menuAction = '<span id="pnlMenuAction" class="font-14" style="display: block; margin: 2px 2px; margin-top: 15px !important;" data-visible="' + secActionVisible + '">';
          menuAction += '<span class="font-bold header clickable" style="display: block; margin-bottom: 5px;" onclick="Menu_ShowSection({ type: \'action\' })">Click map action</span>';
          menuAction += actionContent;
          menuAction += '</span>';
          //DISABLE "action" (until route logic figured out)
          var menuRoute = "";
          ////show saved built routes (if available)
          ////deteremine visibility state
          //var secRouteVisible = "true";
          //var secRouteDisplay = "block";
          //if (oMenuSettings != null && typeof oMenuSettings.route != 'undefined' && oMenuSettings.route == false) {
          //    secRouteVisible = "false";
          //    secRouteDisplay = "none";
          //}
          //var sShowRoute = 'none';
          //var sRouteMenu = '';
          //if (typeof oPage.action != 'undefined' && oPage.action != null && oPage.action == 'route' && arrRoute != null && arrRoute.length > 0) {
          //    sShowRoute = 'block';
          //    sRouteMenu = Route_BuildSavedMenu();
          //    if (sRouteMenu == '') {
          //        //no data to show
          //        sShowRoute = "none";
          //        secRouteVisible = "false";
          //        secRouteDisplay = "none";
          //    }
          //}
          //var btnClearRoute = '<span style="display: inline-block; height: 20px; float: right; padding-top: 1px; overflow: hidden;" title="Clear history"><button type="button" class="close" aria-label="Close" onclick="Route_ClearSaved()"><span style="font-size: 18px; float: left;" aria-hidden="true">&times;</span></button></span>';
          //var menuRoute = '<span id="pnlMenuRoute" class="font-14" style="display: ' + sShowRoute + '; margin: 2px 2px; margin-top: 15px !important;" data-visible="' + secRouteVisible + '">';
          //menuRoute += '<span class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: \'route\' })">' + btnClearRoute + 'Previous routes</span>';
          //menuRoute += '<span class="font-13 content" style="display: ' + secRouteDisplay + ';">' + sRouteMenu + '</span>';
          //menuRoute += '</span>';
          //show links for privacy, terms, etc...
          //deteremine visibility state
          var secHelpVisible = "true";
          var secHelpDisplay = "block";
          if (oMenuSettings != null && typeof oMenuSettings.help != 'undefined' && oMenuSettings.help == false) {
            secHelpVisible = "false";
            secHelpDisplay = "none";
          }
          var cssHelp = 'block';
          if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true) {
            if (wdHeight <= (minPanelHeight - 200)) cssHelp = 'none';
          }
          var lnkContact = '<span class="font-13" style="display: block;"><a class="reverse" href="/About" target="_blank">Contact us</a></span>';
          var lnkPrivacy = '<span class="font-13" style="display: block;"><a class="reverse" href="/Privacy" target="_blank">Pricacy policy</a></span>';
          var lnkTerms = '<span class="font-13" style="display: block;"><a class="reverse" href="/Terms" target="_blank">Terms of service</a></span>';
          var lnkContent = '<span class="content" style="display: ' + secHelpDisplay + ';">' + lnkContact + lnkPrivacy + lnkTerms + '</span>';
          var links = '<span id="pnlMenuHelp" style="display: ' + cssHelp + ';" data-visible="' + secHelpVisible + '"><span class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: \'help\' })">Help</span>' +
            lnkContent + '</span>';
          //build the keys/legend, show speed range with event name
          //deteremine visibility state
          var secLegendVisible = "true";
          var secLegendDisplay = "block";
          if (oMenuSettings != null && typeof oMenuSettings.legend != 'undefined' && oMenuSettings.legend == false) {
            secLegendVisible = "false";
            secLegendDisplay = "none";
          }
          var cssLegend = 'block';
          if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true) {
            if (wdHeight <= minPanelHeight) cssLegend = 'none';
          }
          var thmExtremeCss = 'severity-key-extreme severity-extreme';
          var thmMajorCss = 'severity-key-major severity-major';
          var thmModerateCss = 'severity-key-moderate severity-moderate';
          var thmMinorCss = 'severity-key-minor severity-minor';
          var thmFreelyCss = 'severity-key-freely severity-freely';
          if (theme > '') {
            thmExtremeCss = 'severity-key-extreme severity-extreme-' + theme;
            thmMajorCss = 'severity-key-major severity-major-' + theme;
            thmModerateCss = 'severity-key-moderate severity-moderate-' + theme;
            thmMinorCss = 'severity-key-minor severity-minor-' + theme;
            thmFreelyCss = 'severity-key-freely severity-freely-' + theme;
          }
          var keyExtreme = '<span class="font-13" style="display: block;"><span class="' + thmExtremeCss +
            ' shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Stopped traffic</span></span>';
          var keyMajor = '<span class="font-13" style="display: block;"><span class="' + thmMajorCss +
            ' shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Stop and go traffic</span></span>';
          var keyModerate = '<span class="font-13" style="display: block;"><span class="' + thmModerateCss +
            ' shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Slow traffic</span></span>';
          var keyMinor = '<span class="font-13" style="display: block;"><span class="' + thmMinorCss +
            ' shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">Heavy traffic</span></span>';
          var keyFreely = '<span class="font-13" style="display: block;"><span class="' + thmFreelyCss +
            ' shadow rounded" style="display: inline-block; float: left; width: 21px; height: 8px; margin-top: 6px;"></span><span style="display: inline-block; margin-left: 5px;">No congestion</span></span>';
          var keyNotes = '<span class="font-11" style="display: block; margin-top: 10px;">* click any congestion lines to get details</span>';
          var legendContent = '<span class="content" style="display: ' + secLegendDisplay + ';">' + keyExtreme + keyMajor + keyModerate + keyMinor + keyFreely + keyNotes + '</span>';
          var legend = '<span id="pnlMenuLegend" style="display: ' + cssLegend + '; margin-top: 15px;" data-visible="' + secLegendVisible +
            '"><span class="font-bold header clickable" style="display: block;" onclick="Menu_ShowSection({ type: \'legend\' })">Legend</span>' + legendContent + '</span>';
          //show items at the bottom of the page
          var bottom = '<span style="position: absolute; bottom: 35px;">' + links + legend + '</span>';
          //combine the options
          var content = '<div id="pnlMenu">' + menuMarkets + menuFeature + menuAction + menuRoute + bottom + '</div>';
          //show panel
          //var content = "<p>Toggle show/hide options menus here.</p><p>Initially have the icon display but not open, and when click, it opens and displays the possible menu options</p><p>Maybe show key options at the bottom?</p> ";
          ShowMapOverlay({
            type: "left",
            width: width,
            title: title,
            content: content,
            close: false,
            onclose: "ShowMapMenu(false)"
          });
        } else {
          //hide: show panel BUT only show the menu icon
          var icon = '<span class="clickable" style="font-weight: bolder; opacity: 1.0 !important;" title="Settings" onclick="ShowMapMenu()"><span class="material-icons-outlined md-32">menu</span></span>';
          ShowMapOverlay({
            type: "left",
            close: false,
            height: plIconHeight,
            width: plIconWidth,
            content: icon,
            opacity: 0.50
          });
        }
        //adjust the route UI (if exists)
        ShowRouteMenu_OnResize();
      }
      //handler to show/hide the menu sections
      function Menu_ShowSection(options) {
        var show = null;
        var type = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.type != 'undefined') type = options.type;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //get menu
        var oMenu = null;
        if (type != null) {
          switch (type) {
            case "city":
              oMenu = $("#pnlMenuCity");
              break;
            case "feature":
              oMenu = $("#pnlMenuFeature");
              break;
            case "action":
              oMenu = $("#pnlMenuAction");
              break;
            case "route":
              oMenu = $("#pnlMenuRoute");
              break;
            case "help":
              oMenu = $("#pnlMenuHelp");
              break;
            case "legend":
              oMenu = $("#pnlMenuLegend");
              break;
          }
        }
        if (oMenu != null && oMenu.length > 0) {
          //toggle show/hide based on current view state
          if (show == null) {
            var curShow = oMenu.attr("data-visible");
            if (typeof curShow == 'string') curShow = (curShow.toLowerCase() == 'true');
            if (curShow == true) show = false;
            else show = true;
          }
          //determine show/hide the contents
          if (show == true) {
            //show the content
            oMenu.find(".content").slideDown();
          } else {
            //hide the content
            oMenu.find(".content").slideUp();
          }
          //update the data value
          oMenu.attr("data-visible", show);
        }
      }
      /* SPEED (A.K.A. SENSOR) PANEL FUNCTIONS */
      //show roadway speed panel
      function ShowRoadwaySpeedPanel(options) {
        var show = true;
        var width = null;
        var height = null;
        var tmcId = null;
        var roadId = null;
        var roadwayId = null;
        var dirCode = null;
        var showInternal = false;
        var clickable = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
            if (typeof options.tmc != 'undefined') tmcId = options.tmc;
            if (typeof options.road != 'undefined') roadId = options.road;
            if (typeof options.roadway != 'undefined') roadwayId = options.roadway;
            if (typeof options.dircode != 'undefined') dirCode = options.dircode;
            if (typeof options.internal != 'undefined' && options.internal != null) showInternal = options.internal;
            if (typeof options.clickable != 'undefined') clickable = options.clickable;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check
        if (width == null) width = prWidth;
        if (wdWidth <= minPanelWidth) width = "100%";
        if (tmcId == null && roadId == null && roadwayId == null) show = false;
        if (clickable != null && typeof clickable == 'string') clickable = (clickable.toLowerCase() == 'true');
        //error check screen size (if too small do not show)
        //make sure the page size is correct
        PageResize();
        //keep track of visibility of traffic panel
        var oTrafficPanel = $(".map-right-traffic-overlay");
        if (show == true) {
          //close any map info window (if opened)
          CloseInfoWindow();
          //show roadway info
          var oRoadway = null;
          var arrRoads = [];
          //get necessary parameters
          if (tmcId != null && roadId == null) {
            //get specific roadway and direction of travel
            var oProp = GetTmcIdProp(tmcId);
            if (oProp != null) {
              roadId = "CC-" + oProp.ltn + "-" + oProp.locid;
              //check for direction
              if (dirCode == null && oProp.dirSymbol > '') {
                if (oProp.dirSymbol == "-") dirCode = 1;
                else dirCode = 0;
              }
            }
          }
          if (roadId != null && roadwayId == null) {
            //get the roadway this road is on
            var oRoad = GetRoadData({
              id: roadId,
              fetch: true
            });
            if (oRoad != null) {
              if (typeof oRoad.properties != 'undefined') oRoad = oRoad.properties;
              if (typeof oRoad.toplinearid != 'undefined' && oRoad.toplienarid != null && oRoad.toplinearid > '') roadwayId = oRoad.toplinearid;
              else if (typeof oRoad.mainid != 'undefined' && oRoad.mainid != null && oRoad.mainid > '') roadwayId = oRoad.mainid;
            }
          }
          //get info for this roadway
          if (roadwayId != null) {
            oRoadway = GetRoadwayData({
              id: roadwayId,
              fetch: true
            });
            //get all cross streets related to this roadway
            arrRoads = FetchRoadData({
              action: "roadway",
              value: roadwayId,
              city: cityId,
              alias: true,
              speed: true,
              fetchoverride: true,
              async: false,
              global: true
            });
            if (arrRoads == null) arrRoads = [];
            //assign speed object to internal roads (based on direction of travel) (if available)
            if (arrRoads.length > 0) arrRoads = AssignSpeedDataToInternalRoad({
              data: arrRoads,
              roadway: roadwayId
            });
          }
          //build the display
          var title = '';
          var content = '';
          if (oRoadway != null && arrRoads != null && arrRoads.length > 0) {
            //get roadway info
            var roadwayName = null;
            var roadwayDirNeg = null;
            var roadwayDirPos = null;
            if (typeof oRoadway.combine != 'undefined' && oRoadway.combine != null && oRoadway.combine > '') roadwayName = oRoadway.combine;
            if (roadwayName == null && typeof oRoadway.alias != 'undefined' && oRoadway.alias != null && oRoadway.alias > '') roadwayName = oRoadway.alias;
            if (roadwayName == null && typeof oRoadway.name != 'undefined' && oRoadway.name != null && oRoadway.name > '') roadwayName = oRoadway.name;
            if (typeof oRoadway.dirneg != 'undefined' && oRoadway.dirneg != null && oRoadway.dirneg > '') roadwayDirNeg = oRoadway.dirneg;
            if (typeof oRoadway.dirpos != 'undefined' && oRoadway.dirpos != null && oRoadway.dirpos > '') roadwayDirPos = oRoadway.dirpos;
            if (roadwayDirNeg != null && roadwayDirNeg > '') roadwayDirNeg = GetAbbrDirName(roadwayDirNeg);
            if (roadwayDirPos != null && roadwayDirPos > '') roadwayDirPos = GetAbbrDirName(roadwayDirPos);
            if (roadwayDirNeg == null) roadwayDirNeg = "Neg";
            if (roadwayDirPos == null) roadwayDirPos = "Pos";
            //LOGIC: (1) display roads in the positive direction of travel (arrPosRoads), (2) positive columns use the positive direction of travel speed array (arrPosRoads), (3) negative column use the direction of travel array (arrNegRoads)
            var arrPosRoads = [];
            var arrNegRoads = [];
            if (arrRoads != null && arrRoads.length > 0) arrPosRoads = arrRoads.copy();
            if (arrPosRoads != null && arrPosRoads.length > 0) {
              //get the negative direction of travel
              var oSort = {
                type: "decimal",
                field: "roadorder",
                order: -1
              };
              arrNegRoads = GetRoadData({
                data: arrPosRoads,
                sort: oSort
              });
              if (arrNegRoads == null) arrNegRoads = [];
              //assign speed object to internal roads (based on direction of travel) (if available)
              arrNegRoads = AssignSpeedDataToInternalRoad({
                data: arrNegRoads,
                roadway: roadwayId,
                dircode: -1
              });
            }
            //build location/speed info
            var pnlSpeedInfo = '';
            if (arrPosRoads != null && arrPosRoads.length > 0) {
              //build the header/content
              var notes = '<span style="display: inline-block; float: right; margin-top: 4px; font-size: 11px; font-style: italic;">* Note: speed are in mph</span>';
              var header = '<div class="row" style="width: 100%; margin: 1px 0; padding: 0;"><div class="col" style="min-width: 75%; height: 25px; margin: 0 1px; padding: 5px 5px; overflow: hidden;">' + notes +
                '</div><div class="col" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center; font-weight: bold;">' + roadwayDirPos +
                '</div><div class="col" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center; font-weight: bold;">' + roadwayDirNeg + '</div></div>';
              if (dirCode != null) {
                if (dirCode == 1) header = '<div class="row" style="width: 100%; margin: 1px 0; padding: 0;"><div class="col" style="min-width: calc(100% - 50px); height: 25px; margin: 0 1px; padding: 5px 5px; overflow: hidden;">' + notes +
                  '</div><div class="col" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center; font-weight: bold;">' + roadwayDirNeg + '</div></div>';
                else header = '<div class="row" style="width: 100%; margin: 1px 0; padding: 0;"><div class="col" style="min-width: calc(100% - 50px); height: 25px; margin: 0 1px; padding: 5px 5px; overflow: hidden;">' + notes +
                  '</div><div class="col" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center; font-weight: bold;">' + roadwayDirPos + '</div></div>';
              }
              var arrSpeed = [];
              var arrDirTravel = arrPosRoads.copy();
              if (dirCode != null && dirCode == 1) arrDirTravel = arrNegRoads.copy();
              var lenRoads = arrDirTravel.length;
              for (var i = 0; i < lenRoads; i++) {
                var oRoad = arrDirTravel[i];
                if (typeof oRoad.properties != 'undefined') oRoad = oRoad.properties;
                //initialize variables
                var aRoadId = null;
                var aName = null;
                var aGeopoint = null;
                var aNegSpeed = null;
                var aNegSeverity = null;
                var aPosSpeed = null;
                var aPosSeverity = null;
                //get the negative direction of travel object
                if (aRoadId == null && typeof oRoad.roadid != 'undefined' && oRoad.roadid != null && oRoad.roadid > '') aRoadId = oRoad.roadid;
                else if (aRoadId == null && typeof oRoad.id != 'undefined' && oRoad.id != null && oRoad.id > '') aRoadId = oRoad.id;
                var oRoadNeg = null;
                if (aRoadId != null && arrNegRoads != null && arrNegRoads.length > 0) {
                  oRoadNeg = arrNegRoads.find(x => (typeof x.properties != 'undefined' && ((typeof x.properties.roadid != 'undefined' && x.properties.roadid == aRoadId) || (typeof x.properties.id != 'undefined' && x.properties.id == aRoadId))) || ((
                    typeof x.roadid != 'undefined' && x.roadid == aRoadId) || (typeof x.id != 'undefined' && x.id == aRoadId)));
                  if (oRoadNeg != null && typeof oRoadNeg.properties != 'undefined') oRoadNeg = oRoadNeg.properties;
                }
                if (typeof oRoadNeg == 'undefined' || oRoadNeg == null) oRoadNeg = oRoad;
                //validate if location should be shown
                var isValid = true;
                if (showInternal == false && aRoadId.indexOf("CC-") < 0) isValid = false;
                if (isValid == true) {
                  //get road name
                  if (typeof oRoad.combine != 'undefined' && oRoad.combine != null && oRoad.combine > '') aName = oRoad.combine;
                  if (aName == null && typeof oRoad.alias != 'undefined' && oRoad.alias != null && oRoad.alias > '') aName = oRoad.alias;
                  if (aName == null && typeof oRoad.name != 'undefined' && oRoad.name != null && oRoad.name > '') aName = oRoad.name;
                  //get geopoint (if available)
                  if (typeof oRoad.location != 'undefined' && oRoad.location != null && typeof oRoad.location.geopoint != 'undefined' && oRoad.location.geopoint != null) aGeopoint = oRoad.location.geopoint;
                  else if (typeof oRoad.geopoint != 'undefined' && oRoad.geopoint != null) aGeopoint = oRoad.geopoint;
                  //get speed data
                  //(2) positive columns use the positive direction of travel speed array (arrRoads), (3) negative column use the direction of travel array (arrRoadsDirOfTravel)
                  if (typeof oRoad.posspeed != 'undefined' && oRoad.posspeed != null) {
                    if (typeof oRoad.posspeed.speed != 'undefined' && oRoad.posspeed.speed != null) aPosSpeed = oRoad.posspeed.speed;
                    if (typeof oRoad.posspeed.severity != 'undefined' && oRoad.posspeed.severity != null) aPosSeverity = oRoad.posspeed.severity;
                  }
                  if (typeof oRoadNeg.negspeed != 'undefined' && oRoadNeg.negspeed != null) {
                    if (typeof oRoadNeg.negspeed.speed != 'undefined' && oRoadNeg.negspeed.speed != null) aNegSpeed = oRoadNeg.negspeed.speed;
                    if (typeof oRoadNeg.negspeed.severity != 'undefined' && oRoadNeg.negspeed.severity != null) aNegSeverity = oRoadNeg.negspeed.severity;
                  }
                  //get speed override (if available)
                  if (typeof oRoad.posspeedoverride != 'undefined' && oRoad.posspeedoverride != null) {
                    if (typeof oRoad.posspeedoverride.speed != 'undefined' && oRoad.posspeedoverride.speed != null) aPosSpeed = oRoad.posspeedoverride.speed;
                    if (typeof oRoad.posspeedoverride.severity != 'undefined' && oRoad.posspeedoverride.severity != null) aPosSeverity = oRoad.posspeedoverride.severity;
                  }
                  if (typeof oRoadNeg.negspeedoverride != 'undefined' && oRoadNeg.negspeedoverride != null) {
                    if (typeof oRoadNeg.negspeedoverride.speed != 'undefined' && oRoadNeg.negspeedoverride.speed != null) aNegSpeed = oRoadNeg.negspeedoverride.speed;
                    if (typeof oRoadNeg.negspeedoverride.severity != 'undefined' && oRoadNeg.negspeedoverride.severity != null) aNegSeverity = oRoadNeg.negspeedoverride.severity;
                  }
                  //round the values
                  if (aNegSpeed != null) aNegSpeed = Math.round(aNegSpeed);
                  if (aPosSpeed != null) aPosSpeed = Math.round(aPosSpeed);
                  //error check data
                  var negCss = '';
                  var posCss = '';
                  if (aNegSpeed == null) {
                    aNegSpeed = 'n/a';
                    negCss = 'border';
                  } else {
                    //aNegSpeed += ' mph';
                    negCss = 'severity-' + aNegSeverity;
                    if (theme > '') negCss += "-" + theme;
                  }
                  if (aPosSpeed == null) {
                    aPosSpeed = 'n/a';
                    posCss = 'border';
                  } else {
                    //aPosSpeed += ' mph';
                    posCss = 'severity-' + aPosSeverity;
                    if (theme > '') posCss += "-" + theme;
                  }
                  //determine if item clickable
                  var cssItem = '';
                  var onClick = '';
                  if (clickable == true) {
                    cssItem += " clickable";
                    onClick = ' onclick="Map_MoveTo({ lnglat: \'' + aGeopoint + '\'})"';
                  }
                  //build the item
                  var item = '<div id="' + aRoadId + '" class="sensor row' + cssItem + '" style="width: 100%; margin: 1px 0; padding: 0;"><div class="col border font-bold" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">' + aName +
                    '</div><div class="col ' + posCss + '" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center;">' + aPosSpeed + '</div><div class="col ' + negCss +
                    '" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center;">' + aNegSpeed + '</div></div>';
                  if (dirCode != null) {
                    if (dirCode == 1) item = '<div id="' + aRoadId + '" class="sensor row' + cssItem + '" style="width: 100%; margin: 1px 0; padding: 0;"' + onClick +
                      '><div class="col border font-bold" style="min-width: calc(100% - 50px); margin: 0 1px; padding: 5px 5px;">' + aName + '</div><div class="col ' + negCss +
                      '" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center;">' + aNegSpeed + '</div></div>';
                    else item = '<div id="' + aRoadId + '" class="sensor row' + cssItem + '" style="width: 100%; margin: 1px 0; padding: 0;"' + onClick +
                      '><div class="col border font-bold" style="min-width: calc(100% - 50px); margin: 0 1px; padding: 5px 5px;">' + aName + '</div><div class="col ' + posCss +
                      '" style="max-width: 40px; margin: 0 1px; padding: 5px 5px; text-align: center;">' + aPosSpeed + '</div></div>';
                  }
                  arrSpeed.push(item);
                }
              }
              pnlSpeedInfo = '';
              if (arrSpeed.length > 0) {
                pnlSpeedInfo = header + arrSpeed.join("");
              } else {
                pnlSpeedInfo = '';
              }
            }
            //build traffic list along this path
            //get traffic along this roadway/dir
            var pnlTrafficInfo = '';
            var arrTraffic = GetTrafficData({
              roadway: roadwayId,
              dircode: dirCode,
              fetch: true
            });
            if (arrTraffic != null && arrTraffic.length > 0) {
              pnlTrafficInfo = BuildMapTrafficList({
                data: arrTraffic,
                clickable: true,
                sort: {
                  type: "numeric",
                  field: "path.sortorder",
                  order: dirCode
                }
              });
            }
            //build the title/content
            title = roadwayName;
            if (dirCode != null) {
              if (dirCode == 1) title += ' ' + roadwayDirNeg;
              else title += ' ' + roadwayDirPos;
            }
            if (pnlSpeedInfo > '' && pnlTrafficInfo > '') {
              content = '<div id="pnlSpeed" class="border" style="height: calc(60% - 10px); margin-bottom: 10px; overflow-x: hidden; overflow-y: auto;">' + pnlSpeedInfo +
                '</div><div id="pnlTraffic" class="border" style="height: calc(40% - 10px); margin-top: 10px; overflow-x: hidden; overflow-y: auto;">' + pnlTrafficInfo + '</div>';
            } else if (pnlSpeedInfo > '') {
              content = pnlSpeedInfo;
            } else if (pnlTrafficInfo > '') {
              content = pnlTrafficInfo;
            }
          }
          //show panel
          if (content != null && content > '') {
            //hide right traffic panel (if opened)
            if (oTrafficPanel.is(":visible") == true) ChangeMapOverlayVisibility({
              type: "right-traffic",
              show: false
            });
            //show this panel
            ShowMapOverlay({
              type: "right",
              width: width,
              title: title,
              content: content,
              onclose: "ShowRoadwaySpeedPanel(false)"
            });
            //hover over effect on each item
            var oPanel = $(".map-right-overlay");
            oPanel.find(".sensor").hover(function() {
              //hover over:
              $(this).addClass("highlight-background");
            }, function() {
              //hover out:
              $(this).removeClass("highlight-background");
            }, );
            //check if there is a scroll bar, if so, go to specific area where the road was selected
            var oContent = oPanel.find(".overlay-content");
            if (oContent.find("#pnlSpeed").length > 0) oContent = oContent.find("#pnlSpeed");
            var isScrollExists = oContent.hasScrollBar();
            if (isScrollExists == true && roadId != null) {
              //show this item in the middle of the panel: (itemPos - panelPos) - (panelHeight / 2)
              var oItem = oContent.find("#" + roadId);
              oContent.animate({
                scrollTop: (oItem.offset().top - oContent.offset().top) - (oContent.height() / 2)
              });
              //highlight the location for 5 seconds
              oItem.addClass("active-shadow");
              setTimeout(function() {
                oItem.removeClass("active-shadow");
              }, 5000);
            } else if (roadId != null) {
              var oItem = oContent.find("#" + roadId);
              //highlight the location for 5 seconds
              oItem.addClass("active-shadow");
              setTimeout(function() {
                oItem.removeClass("active-shadow");
              }, 5000);
            }
          } else {
            ShowMapOverlay({
              type: "right",
              show: false
            });
          }
        } else {
          //hide panel
          ShowMapOverlay({
            type: "right",
            show: false
          });
          //check if previously opened speed sensor panel
          if (oTrafficPanel.find(".traffic").length > 0) {
            //previously open and was just hidden when the traffic panel was open
            ChangeMapOverlayVisibility({
              type: "right-traffic",
              show: true
            });
          }
        }
        //adjust affiliate logo
        Affiliate_OnResize();
      }
      /* ROUTE PANEL FUNCTIONS */
      //handler to clear/reset route travel info on the map
      function Route_ClearMap() {
        //get current route settings
        var oRouteSettings = GetPageProp("route");
        if (typeof oRouteSettings == 'undefined' || oRouteSettings == null) oRouteSettings = Object.copy(defaultRouteSettings);
        //clear route UI
        var oStartTextbox = $(".route-start-textbox");
        var oDestinationTextbox = $(".route-destination-textbox");
        var pnlTravel = $(".route-travel-panel");
        if (oRouteSettings.start == null && oRouteSettings.end == null) {
          //reset the textbox
          oStartTextbox.val("");
          oDestinationTextbox.val("");
          //hide the travel info
          pnlTravel.hide();
          //resize the overlay
          ShowRouteMenu_OnResize();
        }
        //clear the Directions API polyline
        ClearDirectionsPath();
      }
      //handler to dynamically build the route info based on selection of start/end road along a roadway
      function Route_BuildRouteInfo(options, onHandler) {
        var show = true;
        var oData = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.data != 'undefined' && options.data != null) oData = Object.copy(options.data);
          } else if (typeof options == 'boolean') {
            show = options;
          } else if (typeof options == 'string') {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //get current route settings
        var oRouteSettings = GetPageProp("route");
        if (typeof oRouteSettings == 'undefined' || oRouteSettings == null) oRouteSettings = Object.copy(defaultRouteSettings);
        //route UI
        var oStartTextbox = $(".route-start-textbox");
        var oDestinationTextbox = $(".route-destination-textbox");
        if (oRouteSettings.start == null && oRouteSettings.end == null) {
          //reset the textbox / map
          Route_ClearMap();
        }
        if (show == true) {
          //show
          //determine what the data is (start or end)
          if (oData != null) {
            if (typeof oData.properties != 'undefined' && oData.properties != null) oData = oData.properties;
            //get data
            var geopoint = null;
            var roadId = null;
            var roadwayId = null;
            var dirCode = null;
            if (typeof oData.id != 'undefined' && oData.id != null && oData.id > '') roadId = oData.id;
            if (typeof oData.roadway != 'undefined' && oData.roadway != null && typeof oData.roadway.id != 'undefined' && oData.roadway.id != null && oData.roadway.id > '') roadwayId = oData.roadway.id;
            if (typeof oData.direction != 'undefined' && oData.direction != null && typeof oData.direction.code != 'undefined' && oData.direction.code != null) dirCode = oData.direction.code;
            if (typeof oData.location != 'undefined' && oData.location != null && typeof oData.location.geopoint != 'undefined' && oData.location.geopoint != null) geopoint = oData.location.geopoint;
            else if (typeof oData.geopoint != 'undefined' && oData.geopoint != null) geopoint = oData.geopoint;
            //validate data
            if (oRouteSettings.start == null) {
              //save start location
              oRouteSettings.start = {
                id: roadId,
                roadway: roadwayId,
                geopoint: geopoint
              };
              //show the lat/lng in textbox
              oStartTextbox.val(geopoint.join(','));
              //show the starting icon
              DrawDirectionsPath({
                start: oRouteSettings.start
              });
            } else if (oRouteSettings.start != null && oRouteSettings.end == null) {
              oRouteSettings.end = {
                id: roadId,
                roadway: roadwayId,
                geopoint: geopoint
              };
              //show the lat/lng in textbox
              oDestinationTextbox.val(geopoint.join(','));
              //get the route's result
              var startEnd = [oRouteSettings.start.geopoint, oRouteSettings.end.geopoint];
              var oData = GetMapDirectionsData({
                type: "driving-traffic",
                lnglat: startEnd
              });
              //console.log("DATA: " + JSON.stringify(oData));
              //update the route menu UI info
              ShowRouteMenu_UpdateInfo(oData);
              //draw the route
              if (oData != null && typeof oData.route != 'undefined' && oData.route != null && oData.route.length > 0) {
                //draw the primary route (0)
                DrawDirectionsPath({
                  format: "simple",
                  data: oData
                });
              }
              //reset
              oRouteSettings = Object.copy(defaultRouteSettings);
            }
          }
        } else {
          //hide
          //reset
          oRouteSettings = Object.copy(defaultRouteSettings);
          //clear map of any items related to this
          Route_ClearMap();
        }
        //save the route viewstate
        SavePageProp({
          route: oRouteSettings
        });
        //execute onHandler commands
        if (typeof onHandler != 'undefined') {
          if (typeof onHandler == 'function') onHandler();
          else eval(onHandler);
        }
      }
      //show/hide the route UI/form overlay
      function ShowRouteMenu(options) {
        var show = true;
        var width = null;
        var height = null;
        var overlayPosition = null;
        var opacity = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
            if (typeof options.position != 'undefined') overlayPosition = options.position;
            if (typeof options.opacity != 'undefined') opacity = options.opacity;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check
        //if (width == null)
        //    width = plIconWidth;
        //if (height == null)
        //    height = plIconHeight;
        if (overlayPosition == null) overlayPosition = "top";
        if (opacity == null) opacity = 0.90;
        //make sure the page size is correct
        PageResize();
        //determine the action to take
        if (show == true) {
          var marginLeft = 50;
          var oSettingsMenu = $(".map-left-overlay");
          if (oSettingsMenu.length > 0 && oSettingsMenu.is(":visible") == true) {
            var mWidth = oSettingsMenu.width();
            if (mWidth > marginLeft) marginLeft = mWidth + 5;
          }
          //build the content
          var content = '';
          //start row
          var sRow = '<span style="display: inline-block; width: 100%; float: left;">';
          sRow += '<span style="display: inline-block; float: left; width: 31px; height: 31px; overflow: hidden;"><span class="svg-route-start" style="display: inline-block; width: 32px; height: 26px; margin-top: 2px;"></span></span>';
          sRow += '<span style="display: inline-block; float: left; width: calc(100% - 31px);"><input type="text" class="route-start-textbox form-control form-control-sm" value="" placeholder="Starting place" readonly="readonly" /></span>';
          //sRow += '<span style="display: inline-block; float: left; width: 25px;"> </span>';
          sRow += '</span>';
          //end row: with "save" button
          var eRow = '<span style="display: inline-block; width: 100%; float: left; margin-top: 3px;">';
          eRow += '<span style="display: inline-block; float: left; width: 31px; height: 31px; overflow: hidden;"><span class="svg-route-stop" style="display: inline-block; width: 32px; height: 26px; margin-top: 2px;"></span></span>';
          eRow += '<span style="display: inline-block; float: left; width: calc(100% - 31px);"><input type="text" class="route-destination-textbox form-control form-control-sm" value="" placeholder="Destination" readonly="readonly" /></span>';
          //eRow += '<span style="display: inline-block; float: left; width: 25px;">button</span>';
          eRow += '</span>';
          //travel time row
          var tRow = '<span class="route-travel-panel" style="display: none; width: 100%; float: left; margin-top: 10px;">';
          tRow += '<span style="display: inline-block; float: left; width: 31px;"><span class="material-icons-outlined md-24" style="float: left; margin-left: 5px; padding-top: 1px;">commute</span></span>';
          tRow += '<span class="route-travel-info" style="display: inline-block; float: left; width: calc(100% - 31px); padding-left: 8px; padding-top: 3px;"></span>';
          tRow += '</span>';
          if (sRow > '' && eRow > '') content = sRow + eRow + tRow;
          //show panel
          ShowMapOverlay({
            type: "route",
            close: false,
            position: overlayPosition,
            width: "300px",
            height: "80px",
            marginleft: marginLeft,
            content: content,
            overflow: "hidden",
            opacity: opacity
          });
        } else {
          //hide panel
          ShowMapOverlay({
            type: "route",
            show: false
          });
        }
      }
      //handler to update route menu info
      function ShowRouteMenu_UpdateInfo(options) {
        var start = null;
        var end = null;
        var distance = null;
        var duration = null;
        var durationTypical = null;
        //define local variables
        var offsetMetersToMi = 0.000621371;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.start != 'undefined' && options.start != null) {
              //get the starting location name
              if (typeof options.start == 'object' && options.start != null && typeof options.start.name != 'undefined' && options.start.name != null && options.start.name > '') {
                //object
                start = options.start.name;
              } else if (typeof options.start == 'string') {
                //text
                start = options.start;
              }
            }
            if (typeof options.end != 'undefined' && options.end != null) {
              //get the destination location name
              if (typeof options.end == 'object' && options.end != null && typeof options.end.name != 'undefined' && options.end.name != null && options.end.name > '') {
                //object
                end = options.end.name;
              } else if (typeof options.end == 'string') {
                //text
                end = options.end;
              }
            }
            if (typeof options.route != 'undefined' && options.route != null && options.route.length > 0) {
              if (typeof options.route[0].distance != 'undefined' && options.route[0].distance != null) distance = options.route[0].distance;
              if (typeof options.route[0].duration != 'undefined' && options.route[0].duration != null) duration = options.route[0].duration;
              if (typeof options.route[0].durationtypical != 'undefined' && options.route[0].durationtypical != null) durationTypical = options.route[0].durationtypical;
              //distance ==> meters, time ==> seconds
              //convert meters ==> miles
              if (typeof distance != 'undefined' && distance != null) {
                if (typeof distance == 'string') distance = parseFloat(distance);
                distance = distance * offsetMetersToMi;
              }
            }
            if (typeof options.distance != 'undefined' && options.distance != null) distance = options.distance;
            if (typeof options.duration != 'undefined' && options.duration != null) duration = options.duration;
            if (typeof options.durationtypical != 'undefined' && options.durationtypical != null) durationTypical = options.durationtypical;
          }
        }
        var oStartTextbox = $(".route-start-textbox");
        var oDestinationTextbox = $(".route-destination-textbox");
        var pnlTravel = $(".route-travel-panel");
        var oTravelInfo = $(".route-travel-info");
        //update textboxes
        if (oStartTextbox.length > 0 && oDestinationTextbox.length > 0) {
          if (start != null && end != null && start > '' && end > '') {
            oStartTextbox.val(start);
            oDestinationTextbox.val(end);
          }
        }
        if (distance != null || duration != null) {
          //calculate the duration in min/seconds
          var time = '';
          var delayTime = "";
          if (duration != null) {
            //calculate the delay (if available)
            if (durationTypical != null) {
              if (duration > durationTypical) {
                //calculate the delay time
                var delay = duration - durationTypical;
                if (delay > 3600) {
                  //more than 1 hour
                  var hour = Math.floor(delay / 60);
                  delay = delay % 60;
                  var min = Math.round(delay / 60);
                  delayTime = hour + " hr, " + min + ' min';
                } else if (delay > 60) {
                  //more than 1 min
                  var min = Math.round(delay / 60);
                  delayTime = min + " min";
                }
              }
            }
            //convert duration to hr/min
            if (duration > 3600) {
              //more than 1 hour
              var hour = Math.floor(duration / 60);
              duration = duration % 60;
              var min = Math.round(duration / 60);
              time = hour + " hr, " + min + ' min';
            } else if (duration > 60) {
              //more than 1 min
              var min = Math.round(duration / 60);
              time = min + " min";
            }
          }
          //round distance 2 decimal
          if (distance != null && distance > 0) {
            distance = Round(distance, 2);
          } else {
            distance = null;
          }
          var info = '<b class="font-16">' + time + '</b>';
          if (delayTime != null && delayTime > '') {
            info += ', <span class="font-alert"> delay of ' + delayTime + '</span>';
          }
          if (distance != null) info += " (" + distance + " mi)";
          oTravelInfo.html(info);
          pnlTravel.show();
        } else {
          pnlTravel.hide();
        }
        //resize the overlay
        ShowRouteMenu_OnResize();
      }
      //handler to move the route UI based on resize (i.e. open/close of the settings menu)
      function ShowRouteMenu_OnResize() {
        var oRouteMenu = $(".map-route-overlay");
        var oSettingsMenu = $(".map-left-overlay");
        //define the margin
        var marginLeft = 50;
        if (oSettingsMenu.length > 0 && oSettingsMenu.is(":visible") == true) {
          var mWidth = oSettingsMenu.width();
          if (mWidth > marginLeft) marginLeft = mWidth + 5;
        }
        if (oRouteMenu.length > 0 && oRouteMenu.is(":visible") == true) {
          //update the overlay appropriately
          oRouteMenu.css({
            "margin-left": marginLeft + "px"
          });
        }
        //resize overlay height (based on travel info visible or not)
        var oRouteBody = oRouteMenu.find(".overlay-content");
        var pnlTravel = oRouteMenu.find(".route-travel-panel");
        var height = 80;
        if (pnlTravel.length > 0 && pnlTravel.is(":visible") == true) {
          //extra height
          height = 110;
        }
        oRouteBody.css({
          "height": height + "px"
        });
        oRouteMenu.css({
          "height": (height + 5) + "px"
        });
      }
      /* TRAFFIC PANEL FUNCTIONS */
      //build the traffic content
      function BuildMapTrafficList(options) {
        var result = '';
        var arrData = [];
        var sort = null;
        var clickable = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (Array.isArray(options) == true) {
            arrData = options.copy();
          } else if (typeof options == 'object') {
            if (typeof options.data != 'undefined' && options.data != null) arrData = options.data.copy();
            if (typeof options.clickable != 'undefined') clickable = options.clickable;
            if (typeof options.sort != 'undefined') {
              if (typeof options.sort == 'object') sort = options.sort;
              else sort = {
                type: "string",
                field: options.sort,
                order: 1
              };
            }
          }
        }
        //error check the data
        if (arrData == null) arrData = [];
        if (arrData.length <= 0) {
          //get all traffic within map's viewport, i.e. saved to gblMapTraffic
          arrData = GetGlobalVariableData({
            type: "map-traffic",
            format: "array"
          });
          if (typeof arrData == 'undefined' || arrData == null) arrData = GetTrafficData({
            city: cityId,
            fetch: true
          });
          if (typeof arrData == 'undefined' || arrData == null) arrData = [];
        }
        if (sort == null) {
          sort = {
            type: "numeric",
            field: "travel.delaytime",
            order: -1
          }
        }
        if (clickable != null && typeof clickable == 'string') clickable = (clickable.toLowerCase() == 'true');
        if (arrData != null && arrData.length > 1) {
          //sort by most delay
          arrData = SortArrayBy({
            array: arrData,
            order: sort.order,
            type: sort.type,
            value: sort.field
          });
        }
        //build the list
        if (arrData != null && arrData.length > 0) {
          //build the header: description, delay? OR just description??
          var header =
            '<div class="row" style="width: 100%; margin: 1px 0; padding: 0;"><div class="col" style="min-width: 75%; height: 25px; margin: 0 1px; padding: 5px 5px; overflow: hidden;">Traffic<span style="display: inline-block; float: right; margin-top: 4px; font-size: 11px; font-style: italic;">* delay in minutes</span></div><div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">Delay</div></div>';
          var arrItem = [];
          var lenData = arrData.length;
          for (var i = 0; i < lenData; i++) {
            var oData = arrData[i];
            if (typeof oData.properties != 'undefined') oData = oData.properties;
            //initialize variables
            var aId = '';
            var aSeverity = '';
            var aDescription = '';
            var aNotes = '';
            var aDelay = '';
            var aGeopoint = null;
            //get the data
            if (typeof oData.id != 'undefined' && oData.id != null && oData.id > '') aId = oData.id;
            if (typeof oData.severity != 'undefined' && oData.severity != null && typeof oData.severity.type != 'undefined' && oData.severity.type != null && oData.severity.type > '') aSeverity = oData.severity.type;
            if (typeof oData.description != 'undefined' && oData.description != null && oData.description > '') aDescription = oData.description;
            if (typeof oData.notes != 'undefined' && oData.notes != null && typeof oData.notes.public != 'undefined' && oData.notes.public != null && oData.notes.public > '') aNotes = oData.notes.public;
            if (typeof oData.travel != 'undefined' && oData.travel != null) {
              if (typeof oData.travel.delaytime != 'undefined' && oData.travel.delaytime != null) {
                aDelay = Math.round(oData.travel.delaytime);
                if (aDelay <= 0) aDelay = '';
              }
            }
            if (typeof oData.location != 'undefined' && oData.location != null && typeof oData.location.geopoint != 'undefined' && oData.location.geopoint != null) aGeopoint = oData.location.geopoint;
            //combine description/notes
            if (aDescription > '' && aNotes > '') {
              aDescription += '<br /><i class="font-12">' + aNotes + '</i>';
            }
            //build the style
            var cssTraffic = 'severity-' + aSeverity;
            if (theme > '' && theme != 'classic') cssTraffic += '-' + theme;
            //determine if item clickable
            var onClick = '';
            if (clickable == true) {
              if (cssTraffic > '') cssTraffic += ' ';
              cssTraffic += "clickable";
              onClick = ' onclick="Map_MoveTo({ lnglat: \'' + aGeopoint + '\'})"';
            }
            //build sort/search parameters
            var sortParam = '';
            var searchParam = '';
            //build the item
            var item = '<div id="' + aId + '" class="traffic row ' + cssTraffic + '" style="width: 100%; margin: 1px 0; padding: 0;"' + onClick + '><div class="col" style="min-width: 75%; margin: 0 1px; padding: 5px 5px;">' + aDescription +
              '</div><div class="col" style="max-width: 50px; margin: 0 1px; padding: 5px 5px; text-align: center;">' + aDelay + '</div></div>';
            arrItem.push(item);
          }
          if (arrItem.length > 0) {
            result = header + arrItem.join("");
          } else {
            result = '';
          }
        }
        return result;
      }
      //show traffic info within map view (right panel)
      function ShowMapTrafficInfo(options) {
        var show = true;
        var width = null;
        var height = null;
        var data = null;
        //get the current traffic settings
        var oTrafficSettings = GetPageProp("traffic");
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.width != 'undefined') width = options.width;
            if (typeof options.height != 'undefined') height = options.height;
            if (typeof options.data != 'undefined') data = options.data;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check
        if (width == null) width = prWidth;
        if (wdWidth <= minPanelWidth) width = "100%";
        //error check
        if (oTrafficSettings != null && typeof oTrafficSettings.list != 'undefined' && oTrafficSettings.list != null && oTrafficSettings.list == true && typeof oTrafficSettings.type != 'undefined' && oTrafficSettings.type > '') {
          //valid
        } else {
          //no traffic data requested
          show = false;
        }
        if (data != null && data.length <= 0) show = false;
        //error check screen size (if too small do not show)
        //make sure the page size is correct
        PageResize();
        //keep track of the speed panel
        var oSpeedPanel = $(".map-right-overlay");
        if (show == true) {
          //close any map info window (if opened)
          CloseInfoWindow();
          //hide right panel (if opened)
          if (oSpeedPanel.is(":visible") == true) ChangeMapOverlayVisibility({
            type: "right",
            show: false
          });
          //build the display
          var title = 'Traffic within view';
          var content = BuildMapTrafficList({
            data: data
          });
          //show this panel
          ShowMapOverlay({
            type: "right-traffic",
            width: width,
            title: title,
            content: content,
            onclose: "ShowMapTrafficInfo(false)"
          });
          //hover over effect on each item
          var oPanel = $(".map-right-traffic-overlay");
          oPanel.find(".traffic").hover(function() {
            //hover over:
            $(this).addClass("hover");
          }, function() {
            //hover out:
            $(this).removeClass("hover");
          }, );
          ////check if there is a scroll bar, if so, go to specific area where the road was selected
          //var oContent = oPanel.find(".overlay-content");
          //var isScrollExists = oContent.hasScrollBar();
          //if (isScrollExists == true && roadId != null) {
          //    //show this item in the middle of the panel: (itemPos - panelPos) - (panelHeight / 2)
          //    var oItem = oContent.find("#" + roadId);
          //    oContent.animate({ scrollTop: (oItem.offset().top - oContent.offset().top) - (oContent.height() / 2) });
          //    //highlight the location for 5 seconds
          //    oItem.addClass("active-shadow");
          //    setTimeout(function () { oItem.removeClass("active-shadow"); }, 5000);
          //} else if (roadId != null) {
          //    var oItem = oContent.find("#" + roadId);
          //    //highlight the location for 5 seconds
          //    oItem.addClass("active-shadow");
          //    setTimeout(function () { oItem.removeClass("active-shadow"); }, 5000);
          //}
        } else {
          //hide panel
          ShowMapOverlay({
            type: "right-traffic",
            show: false
          });
          //check if previously opened speed sensor panel
          if (oSpeedPanel.find(".sensor").length > 0) {
            //previously open and was just hidden when the traffic panel was open
            ChangeMapOverlayVisibility({
              type: "right",
              show: true
            });
          }
        }
        //adjust affiliate logo
        Affiliate_OnResize();
      }
      /* MAP FUNCTIONS */
      //OVERLOAD FUNCTION: this map function (within mapbox-draw.js)
      //handler to rebuild the traffic info panel and display new content
      function ShowMapTrafficList(options, onHandler) {
        var show = true;
        var data = [];
        var oTrafficPanel = $(".map-right-traffic-overlay");
        var oSpeedPanel = $(".map-right-overlay");
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (Array.isArray(options) == true) {
            data = options.copy();
          } else if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
            if (typeof options.data != 'undefined' && options.data != null) data = options.data.copy();
          } else if (typeof options == 'boolean') {
            show = options;
          } else if (typeof options == 'string') {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        //error check: (1) no data or (2) speed panel showing do not show the traffic listing
        if (data != null && data.length <= 0) show = false;
        if (oSpeedPanel.is(":visible") == true) show = false;
        if (show == true) {
          //validate if panel is open/closed                
          if (oTrafficPanel.is(":visible") == true) {
            //rebuild this list
            var content = BuildMapTrafficList({
              data: data
            });
            WriteMapOverlayContent({
              type: "right-traffic",
              data: content
            });
          } else {
            //build new list
            ShowMapTrafficInfo({
              data: data,
              show: show
            });
          }
        } else {
          //hide
          if (oTrafficPanel.is(":visible") == true || oSpeedPanel.is(":visible") == true) ShowMapTrafficInfo(false);
        }
        //execute onHandler commands
        if (typeof onHandler != 'undefined') {
          if (typeof onHandler == 'function') onHandler();
          else eval(onHandler);
        }
      }
      //handler to show congestion layer
      function Map_ShowCongestion(options) {
        var show = true;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (typeof options == 'object') {
            if (typeof options.show != 'undefined') show = options.show;
          } else if (typeof options == 'boolean') {
            show = options;
          } else {
            show = (options.toString().toLowerCase() == 'true');
          }
        }
        if (show == true) {
          //show the congestion layer: (1) update oPage variable, (2) update mapViewstate variable
          oPage.traffic.congestion = true;
          mapViewstate.traffic.congestion = true;
          CongestionMap_ShowLayer();
        } else {
          //hide the congestio layer: (1) update oPage variable, (2) update mapViewstate variable
          oPage.traffic.congestion = false;
          mapViewstate.traffic.congestion = false;
          CongestionMap_ShowLayer({
            show: false,
            opacity: 0
          });
        }
      }
      //handler to move the map to the specific lnglat location
      //ARGUMENT: lnglat = [lng lat], {object with lat, lng property}, lat, lng
      function Map_MoveTo(options) {
        var lnglat = null;
        var zoom = null;
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (Array.isArray(options) == true) {
            lnglat = options;
          } else if (typeof options == 'object') {
            if (typeof options.lnglat != 'undefined') {
              if (Array.isArray(options.lnglat) == true) lnglat = options.lnglat;
              else if (typeof options.lnglat == 'string') lnglat = options.lnglat.split(',').map(Number);
              else lnglat = options.lnglat;
            }
            if (typeof options.zoom != 'undefined') zoom = options.zoom;
          } else if (typeof options == 'string' && options.indexOf(",") >= 0) {
            lnglat = options.split(',').map(Number);
          }
        }
        if (lnglat != null) {
          var cOptions = {
            action: 'fly',
            latlng: lnglat,
            zoom: zoom
          };
          ChangeLocation(cOptions);
        }
      }
      //handler to clear map
      //NOTE: if no type passed in ==> clear all
      //type = [route]
      function Map_OnClear(options) {
        var arrType = [];
        var arrPolylineId = [];
        //get options passed in
        if (options != null && typeof options != 'undefined') {
          if (Array.isArray(options) == true) {
            arrType = options;
          } else if (typeof options == 'object') {
            if (typeof options.type != 'undefined') {
              if (Array.isArray(options.type) == true) arrType = options.type;
              else if (typeof options.type == 'string' && options.type > '') arrType = options.type.split(",");
            }
            if (typeof options.polylineid != 'undefined' && options.polylineid != null) {
              if (Array.isArray(options.polylineid) == true) arrPolylineId = options.polylineid;
              else if (typeof options.polylineid == 'string' && options.polylineid > '') arrPolylineId = options.polylineid.split(",");
            }
          } else if (typeof options == 'string' && options > '') {
            arrType = options.split(",");
          }
        }
        //close any map info window (if opened)
        CloseInfoWindow();
        //clear any items related to route
        if (arrType.length <= 0 || arrType.indexOf("route") >= 0) {
          //clear the Directions API polyline
          ClearDirectionsPath();
          ////clear map markers
          //ClearMarker({ type: "startpoint" });
          ////determine how to clear out the polyline
          //if (arrPolylineId != null && arrPolylineId.length > 0) {
          //    //clear out specific polyline items
          //    var lenPolylineId = arrPolylineId.length;
          //    for (var i = 0; i < lenPolylineId; i++) {
          //        var aPolylineId = arrPolylineId[i];
          //        //remove from global list
          //        if (arrPolyline != null && arrPolyline.length > 0) {
          //            var iIndex = arrPolyline.findIndex(x => x.id == aPolylineId);
          //            if (iIndex >= 0) {
          //                //item found, remove it
          //                arrPolyline.splice(iIndex, 1);
          //                //remove map features
          //                ClearPolyline({ id: aPolylineId });
          //            }
          //        }
          //    }
          //} else {
          //    //clear map polyline
          //    ResetPolyline();
          //}
        }
      }
      //handler to manage what action to take when user click/right-click the map
      //action = [speed (default), route]
      function Map_OnClickAction(event, onHandler) {
        //get the current action
        var action = oPage.action;
        //determine action to take
        if (action == 'speed') {
          Map_ShowRoadwaySpeedPanel(event, onHandler);
        } else if (action == 'route') {
          Map_BuildRouteInfo(event, onHandler);
        }
      }
      //handler on map when click to show the map speed data
      function Map_ShowRoadwaySpeedPanel(event, onHandler) {
        if (map != null && event != null) {
          var oData = GetMapFeatureData({
            event: event
          });
          if (oData != null) {
            if (typeof oData.properties != 'undefined' && oData.properties != null) oData = oData.properties;
            var roadId = null;
            var roadwayId = null;
            var dirCode = null;
            if (typeof oData.id != 'undefined' && oData.id != null && oData.id > '') roadId = oData.id;
            if (typeof oData.roadway != 'undefined' && oData.roadway != null && typeof oData.roadway.id != 'undefined' && oData.roadway.id != null && oData.roadway.id > '') roadwayId = oData.roadway.id;
            if (typeof oData.direction != 'undefined' && oData.direction != null && typeof oData.direction.code != 'undefined' && oData.direction.code != null) dirCode = oData.direction.code;
            //show the panel
            if (roadId != null || roadwayId != null) {
              ShowRoadwaySpeedPanel({
                roadway: roadwayId,
                road: roadId,
                dircode: dirCode,
                clickable: true
              });
            }
            //execute onHandler commands
            if (typeof onHandler != 'undefined') {
              if (typeof onHandler == 'function') onHandler();
              else eval(onHandler);
            }
          }
        }
      }
      //handler on map when click to build the route
      function Map_BuildRouteInfo(event, onHandler) {
        if (map != null && event != null) {
          var oData = GetMapFeatureData({
            event: event
          });
          if (oData == null) {
            //NO visible features detected, so just pass in the location where the mouse was clicked
            //USING: MapBox Directions API, you only need to have [lng lat] for start and end and it finds the route needed
            oData = {
              geopoint: [event.lngLat.lng, event.lngLat.lat]
            };
          }
          if (oData != null) {
            if (typeof oData.properties != 'undefined' && oData.properties != null) oData = oData.properties;
            //show the building route travel info feature
            if (oData != null) {
              Route_BuildRouteInfo({
                data: oData
              });
            }
            //execute onHandler commands
            if (typeof onHandler != 'undefined') {
              if (typeof onHandler == 'function') onHandler();
              else eval(onHandler);
            }
          }
        }
      }
      //handler for checkbox changes
      function Map_SettingsOnChange() {
        //get the latest settings: congestion, traffic, camera, congestion type
        var isMajorRoadway = $("#chkMajorRoadway").prop("checked");
        var isLocalRoadway = $("#chkLocalRoadway").prop("checked");
        var isTraffic = $("#chkTraffic").prop("checked");
        var isTrafficList = $("#chkTrafficList").prop("checked");
        var isCamera = $("#chkCamStream").prop("checked");
        var isCameraStill = $("#chkCamStill").prop("checked");
        //define the frc for major/minor
        var frcMajorRoadway = $("#chkMajorRoadway").attr("value");
        var frcLocalRoadway = $("#chkLocalRoadway").attr("value");
        //define what to show/hide
        var congestionType = 'speedoverride';
        var isCongestion = true;
        var frc = frcMajorRoadway;
        var incidentType = 'flow,incident,construction,event,transit';
        if (isTraffic == false) incidentType = '';
        if (isMajorRoadway == false && isLocalRoadway == false) {
          isCongestion = false;
          frc = '';
        } else {
          frc = '';
          if (isMajorRoadway == true) {
            if (frc > '') frc += ',';
            frc += frcMajorRoadway;
          }
          if (isLocalRoadway == true) {
            if (frc > '') frc += ',';
            frc += frcLocalRoadway;
          }
        }
        //define the traffic settings and save to viewstate
        var oTrafficSettings = {
          congestion: isCongestion,
          congestiontype: congestionType,
          type: incidentType,
          list: isTrafficList,
          frc: frc
        };
        //define the camera settings and save to viewsate
        var oCameraSettings = {
          stream: isCamera,
          still: isCameraStill
        };
        //save the traffic/camera settings
        SavePageProp({
          traffic: oTrafficSettings,
          camera: oCameraSettings
        });
        //update map viewstate
        mapViewstate.traffic = oTrafficSettings;
        mapViewstate.camera = oCameraSettings;
        SaveMapViewstate();
        //note: since the map is NOT moving, it will not call the function to close the traffic when set to false
        var oTrafficPanel = $(".map-right-traffic-overlay");
        if (oTrafficPanel.is(":visible") == true && isTrafficList == false) ShowMapTrafficInfo(false);
        //redraw the map
        DrawMap({
          wait: 500
        });
      }
      //handler to switch to a different market
      function Map_SwitchMarket(options) {
        var aCityId = null;
        //get parameters
        if (typeof options != 'undefined') {
          if (typeof options == 'object' && typeof options.city != 'undefined') {
            if (typeof options.city != 'undefined') aCityId = options.city;
          } else if (typeof options == 'number' || typeof options == 'string') {
            aCityId = options;
          }
        }
        //error check
        if (aCityId != null && typeof aCityId == 'string') aCityId = parseInt(aCityId);
        if (aCityId != null && aCityId > 0) {
          ////DISABLE (3/8/24): allow users to move freely
          ////reset the maxbounds so you can goto new location
          //ChangeMapMaxBounds(null);
          //update local variable
          cityId = aCityId;
          //get the city object
          oCity = GetCityData({
            data: arrMarket,
            id: cityId,
            fetch: true
          });
          if (typeof oCity.properties != 'undefined') oCity = oCity.properties;
          if (typeof oCity.location != 'undefined' && oCity.location != null && typeof oCity.location.lat != 'undefined' && typeof oCity.location.lng != 'undefined' && oCity.location.lat != null && oCity.location.lng != null) {
            latlng = new LatLng(oCity.location.lat, oCity.location.lng);
          }
          //save the viewstate of the market change
          SaveViewstateProp({
            city: oCity
          });
          //move map to new market
          var cOptions = {
            action: 'fly',
            latlng: latlng,
            zoom: 11
          };
          ChangeLocation(cOptions);
          //close any panels that are open
          var closePanel = 'top,right,right-traffic';
          CloseMapOverlays(closePanel);
          //clear any previously set map features
          Map_OnClear();
          ////define the new market's boundary so they can not move/pan outisde the bounds
          //var maxBounds = null;
          //if (oCity != null && typeof oCity.boundary != 'undefined' && oCity.boundary != null && typeof oCity.boundary.nw != 'undefined' && typeof oCity.boundary.se != 'undefined' && oCity.boundary.nw != null && oCity.boundary.se != null) {
          //    //maxbounds = array of lng/lat (2 records): first item = SouthWest lng/lat, second item = NorthEast lng/lat
          //    if (typeof oCity.boundary.nw.Lat != 'undefined') {
          //        //upper case for some reason, maybe old cache?
          //        var swLngLat = [oCity.boundary.nw.Lng, oCity.boundary.se.Lat];
          //        var neLngLat = [oCity.boundary.se.Lng, oCity.boundary.nw.Lat];
          //        maxBounds = [swLngLat, neLngLat];
          //    } else if (typeof oCity.boundary.nw.lat != 'undefined') {
          //        //lower case
          //        var swLngLat = [oCity.boundary.nw.lng, oCity.boundary.se.lat];
          //        var neLngLat = [oCity.boundary.se.lng, oCity.boundary.nw.lat];
          //        maxBounds = [swLngLat, neLngLat];
          //    }
          //}
          //if (maxBounds != null) {
          //    //wait a little bit for the map to pan over there, then set the new maxbounds variable
          //    setTimeout(function () { ChangeMapMaxBounds(maxBounds); }, 2000);
          //}
          //display this page's title on the window
          //format: {SiteName}: {CityName}
          if (oCity != null) {
            var title = window.document.title;
            if (typeof gblSiteAbbr != 'undefined' && gblSiteAbbr != null && gblSiteAbbr > '') title = gblSiteAbbr;
            else title = title.substr(0, title.lastIndexOf(":")).trim();
            if (typeof oCity.name != 'undefined' && oCity.name != null && oCity.name > '') title += ': ' + oCity.name;
            window.document.title = title;
          }
        }
      }
      //initialize the map
      function InitMap() {
        //get the size of the map panel
        var oMap = $("#pnlMap .map");
        var mWidth = oMap.width();
        var mHeight = oMap.height();
        //define the default map settings
        var mapId = oMap.attr("id");
        //get page settings
        var oTrafficSettings = GetPageProp("traffic");
        var oCameraSettings = GetPageProp("camera");
        ////DISABLE (3/8/24): allow users to move freely
        ////define the new market's boundary so they can not move/pan outisde the bounds
        //var maxBounds = null;
        //if (oCity != null && typeof oCity.boundary != 'undefined' && oCity.boundary != null && typeof oCity.boundary.nw != 'undefined' && typeof oCity.boundary.se != 'undefined' && oCity.boundary.nw != null && oCity.boundary.se != null) {
        //    //maxbounds = array of lng/lat (2 records): first item = SouthWest lng/lat, second item = NorthEast lng/lat
        //    if (typeof oCity.boundary.nw.Lat != 'undefined') {
        //        //upper case for some reason, maybe old cache?
        //        var swLngLat = [oCity.boundary.nw.Lng, oCity.boundary.se.Lat];
        //        var neLngLat = [oCity.boundary.se.Lng, oCity.boundary.nw.Lat];
        //        maxBounds = [swLngLat, neLngLat];
        //    } else if (typeof oCity.boundary.nw.lat != 'undefined') {
        //        //lower case
        //        var swLngLat = [oCity.boundary.nw.lng, oCity.boundary.se.lat];
        //        var neLngLat = [oCity.boundary.se.lng, oCity.boundary.nw.lat];
        //        maxBounds = [swLngLat, neLngLat];
        //    }
        //}
        //show the map
        var leftMenu = {
          active: true,
          type: "polyline",
          polylineclick: Map_OnClickAction
        };
        var contextMenu = {
          active: true,
          type: "polyline",
          polylineclick: Map_OnClickAction
        };
        var mOptions = {
          id: mapId,
          control: "navigation",
          menu: contextMenu,
          leftmenu: leftMenu,
          traffic: oTrafficSettings,
          camera: oCameraSettings,
          width: mWidth,
          height: mHeight,
          zoom: zoom,
          latlng: latlng
        };
        InitializeMap(mOptions);
      }
      /* LAYOUT */
      //keep track of when browser is resized (in order to resize the map)
      var isMapResize = true;
      //resize the page layout
      function PageResize() {
        var oContent = $(".master-content");
        var width = oContent.width();
        var height = oContent.height();
        var offset = 0;
        //get updated window dimension
        wdWidth = $(window).width();
        wdHeight = $(window).height();
        if (isMapResize == true) {
          //define the panel sizes
          var pnlMap = $("#pnlMap");
          var htMap = height - offset;
          pnlMap.css({
            "height": htMap + "px"
          });
          //define the map panel dimension			
          var mWidth = pnlMap.width();
          var mHeight = pnlMap.height();
          if (pnlMap.is(":visible") == true) {
            var oMap = pnlMap.find(".map");
            oMap.css({
              "width": mWidth + "px",
              "height": mHeight + "px"
            });
            ResizeMap();
          }
          //resize the menu panel (if open)
          var oLeftOverlay = $(".map-left-overlay");
          var oRightOverlay = $(".map-right-overlay");
          var oRightTrafficOverlay = $(".map-right-traffic-overlay");
          if (oLeftOverlay.is(":visible") == true && oLeftOverlay.find("#pnlMenu").length > 0) ResizeMapOverlay({
            type: "left",
            width: plWidth
          });
          if (oRightOverlay.is(":visible") == true) ResizeMapOverlay({
            type: "right",
            width: prWidth
          });
          if (oRightTrafficOverlay.is(":visible") == true) ResizeMapOverlay({
            type: "right-traffic",
            width: prWidth
          });
          //reset the variable
          isMapResize = false;
        }
        //SPECIAL MOBILE: (1) hide menu legend and/or help links
        var pnlMenuLegend = $("#pnlMenuLegend");
        var pnlMenuHelp = $("#pnlMenuHelp");
        if ((pnlMenuLegend.length > 0 || pnlMenuHelp.length > 0) && (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true)) {
          if (pnlMenuLegend.length > 0) {
            if (wdHeight <= minPanelHeight) {
              //hide the legend
              pnlMenuLegend.hide();
            } else {
              //show it
              pnlMenuLegend.show();
            }
          }
          if (pnlMenuHelp.length > 0) {
            if (wdHeight <= (minPanelHeight - 200)) {
              //hide the help links
              pnlMenuHelp.hide();
            } else {
              //show it
              pnlMenuHelp.show();
            }
          }
        }
      }
      /* LOADING */
      //initialize the page
      function InitPage() {
        //show menu (default to show unless mobile device)
        var isShowMenu = true;
        if (typeof isMobile != 'undefined' && typeof mobileType != 'undefined' && isMobile == true && mobileType != 'ipad') isShowMenu = false;
        //update default settings for demo account (preview account)
        if (demo == 1) {
          isShowMenu = false;
        }
        //show/hide the settings menu
        ShowMapMenu(isShowMenu);
        ShowAffiliateOnMap();
        //determine if we need to show the route UI
        if (oPage.action == 'route') ShowRouteMenu();
        //initialize map
        InitMap();
      }
      $(document).ready(function() {
        //display this page's title on the window
        if (oCity != null) {
          var title = window.document.title;
          if (typeof gblSiteAbbr != 'undefined' && gblSiteAbbr != null && gblSiteAbbr > '') title = gblSiteAbbr;
          else title = title.substr(0, title.lastIndexOf("-")).trim();
          if (typeof oCity.name != 'undefined' && oCity.name != null && oCity.name > '') title += ': ' + oCity.name;
          window.document.title = title;
        }
        //resize this page right away
        MasterPageResize();
        //REQUIRED
        setTimeout(function() {
          InitPage();
        }, 100);
      });
      //execute resize function when user resizes the browser
      $(window).resize(function() {
        isMapResize = true;
        MasterPageResize();
      });
    </script>
  </div>
</form>

Text Content

×



×




×


×


© Mapbox © OpenStreetMap Improve this map
×
Traffic within view
Traffic* delay in minutes
Delay
Long-term road construction in Decatur on I-285 Outer loop between Flat Shoals
Rd (GA-155)/Exit 48 and Glenwood Rd/Exit 44. Reported by GDOT
23
Long-term road construction in Panthersville on I 20 EB between Columbia Dr/Exit
66 (EB) and Evans Mill Rd/Exit 74. Reported by GDOT
7
Long-term road construction in Buckhead on GA-400 NB/SB between Old Toll Plaza
and I-285/Exit 4. Reported by GDOT
5
Repaving work in Georgia Tech on Howell Mill Rd NW NB/SB between 8th St NW and
Holmes St NW/Chattahoochee Ave NW. Reported by ATLDOT
2
Long-term road construction in Decatur on I-285 Inner loop between Glenwood
Rd/Exit 44 and Flat Shoals Rd (GA-155)/Exit 48. Reported by GDOT
1
Road work. Off-ramp partially blocked in Doraville on I-285 EB off-ramp to NB
I-85. Reported by GDOT
ETC 4pm

Road construction. Right lane closed in Sandy Springs on GA-400 NB at Glenridge
Connector/Exit 3 (SB). Reported by GDOT
ETC 3pm

Bridge closed in Morningside on Cheshire Bridge Rd NB/SB between Liddell Dr NE
and Faulkner Rd. Reported by ATLDOT

Water main replacement in Decatur on E Ponce De Leon Ave EB/WB between Grove
Place and N Clarendon Ave. Reported by Press Release

Closed due to road construction in Atlanta on Lavista Rd EB/WB between Cheshire
Bridge Rd and Lavista Walk. Reported by ATLDOT

Roundabout installation in South Fulton on Butner Rd EB/WB at Union Rd. Reported
by GDOT

Road work. HOV lane closed in Smyrna on I 75 NB between Akers Mill Rd/Exit 258
(HOV NB) and I-75 Express Lanes/Exit 260 (NB). Reported by GDOT

Beltline Construction in Midtown on 10th St EB/WB at Monroe Dr. Reported by
ATLDOT

Long-term road construction in Cumberland on Cumberland Blvd SE at Overton Park
Dr

Long-term road construction in Marietta on Callaway Rd SW NB/SB between Austell
Rd and Al Bishop Drive. Reported by GDOT

Long-term road construction in Conley on I-285 EB/WB between Moreland Ave
(US-23)/Exit 53 and Bouldercrest Rd/Exit 51. Reported by GDOT

×


×


×


×
menuSettings
Change citiesSelect a
cityAlbanyAlbuquerqueAllentownAppleton/OshkoshAshevilleAtlantaAugustaAustinBakersfieldBaltimoreBaton
RougeBiloxi-GulfportBinghamtonBirminghamBostonBuffaloCedar Rapids/Iowa City
CharlestonCharlotteChattanoogaChicagoCincinnatiCiudad de Mexico, D.
F.ClevelandColorado SpringsColumbiaColumbusColumbus, GACorpus
ChristiDallasDavenportDaytonDenverDes MoinesDetroitEl PasoErieFlorida KeysFort
CollinsFort MyersFrederickFresnoFt WayneGainesville-OcalaGrand RapidsGreen Bay,
WIGreensboroGreenvilleHarrisburgHarrisonburgHartford/New
HavenHattiesburg/LaurelHonoluluHoustonHuntington-CharlestonHuntsvilleIndianapolisJacksonJacksonvilleKansas
CityKnoxvilleLas VegasLexingtonLittle RockLos
AngelesLouisvilleMaconMadisonMcAllenMemphisMiami/Fort
LauderdaleMilwaukeeMinneapolisMobile/PensacolaMonterey-SalinasMontgomeryMontrealMyrtle
BeachNashvilleNew OrleansNorfolkNYCOklahoma CityOmahaOrlandoOttawaPachuca,
MXPanama
CityParkersburg/MariettaPhiladelphiaPhoenixPittsburghPortlandPortsmouth/ManchesterProvidencePuebla,
MXQueretara, MXRaleigh-DurhamReadingRichmondRoanoke/LynchburgRochester,
NYSacramentoSalt Lake CitySan AntonioSan DiegoSan Francisco/San
JoseSarasotaSavannahSeattleSpokaneSpringfieldSpringfield, MOSt. LouisStockton /
ModestoSyracuseTallahasseeTampaToledoTorontoTucsonTulsaTuscaloosaVancouverWashingtonWest
Palm Beach/Treasure
CoastWheelingWichitaWilkes-BarreWilliamsportWorcesterYoungstownToggle view
on/offMajor roadwayLocal roadwayTraffic iconTraffic listCamera streamCamera
stillClick map actionShow speedBuild routeHelpContact usPricacy policyTerms of
serviceLegendStopped trafficStop and go trafficSlow trafficHeavy trafficNo
congestion* click any congestion lines to get details
×


×

Last updated: 11:13 AM