Index: trunk/webapps/GTEC/css/styles.css
===================================================================
--- trunk/webapps/GTEC/css/styles.css	(revision 556)
+++ trunk/webapps/GTEC/css/styles.css	(revision 569)
@@ -14,4 +14,37 @@
         padding: 0;
       }
+      button {
+          display: inline-block;
+          border: 2px solid black;
+          border-radius: 8px;
+          padding: 1rem 2rem;
+          margin: 0;
+          text-decoration: none;
+          background: gray; 
+          color: #ffffff;
+          font-family: sans-serif;
+          font-size: 1rem;
+          cursor: pointer;
+          text-align: center;
+          transition: background 250ms ease-in-out, 
+                      transform 150ms ease;
+          -webkit-appearance: none;
+          -moz-appearance: none;
+      }
+
+      button:hover,
+      button:focus {
+          background: #0053ba;
+      }
+
+      button:focus {
+          outline: 1px solid #fff;
+          outline-offset: -4px;
+      }
+
+      button:active {
+          transform: scale(0.99);
+      }
+
         .test {
           width:200px;
@@ -21,39 +54,4 @@
           margin:0px auto;
           border:1px red solid;
-        }
-        /* A line of the CMS message display */
-        .cms_sign {
-           height: 37px;
-           width: 272px;
-           resize: none;
-           font-family: Scoreboard;
-           font-size: xx-large;
-           background-color: #2F4F4F;
-           color: yellow;
-        }
-        /* Field for entering CMS Message line */
-       .cms-input {
-           border: thin solid #333;
-           padding: 2px;
-           font-family: "Lucida Console", Monaco, monospace;
-           font-size: medium;
-           width: 163px;
-        }
-        /* Field for entering HAR Message line */
-       .har-input {
-           border: thin solid #333;
-           padding: 2px;
-           font-size: medium;
-        }
-        #har-msg-display {
-          margin-right: 50%; /*  100px; */
-          margin-left: 25%;  /*  100px; */
-        }
-        #har-msgcontent1 {
-          margin-bottom: 10px;
-        }
-        #har-msg {
-          margin-top: 300px;
-          margin-bottom: 300px;
         }
       #time {
@@ -66,19 +64,4 @@
       }
     
-      #search-input {
-        background-color: #17263c;  /* #CD853F;  /*#E6E6FA; /* lavender */
-        color: #E6E6FA;  /* #FFEFD5; */
-        font-family: Roboto;
-        font-size: 18px;
-        font-weight: 400;
-        margin-left: 12px;
-        padding: 0 11px 0 13px;
-        text-overflow: ellipsis;
-        border-color: #746855;   /* #4d90fe; */
-        width: 400px;
-      }
-      #search-input:focus {
-        border-color: #E6E6FA; 
-      }
       #ctrButton {
         cursor: pointer;
@@ -87,55 +70,4 @@
         border: thick solid white;
       }
-      #cms-info-label {
-           height: 20px;
-           width: 590px;
-           overflow: hidden;
-           background-color: #A8C5FF;  /*#ECECFB; */
-           border: thin solid #BDBDBD;
-           padding: 5px;
-       }
-      #cms-message-display {
-           height: 390px;
-           width: 300px;
-           overflow: hidden;
-           float: left;
-       }
-      #har-message-display {
-        margin-top: 50px;
-        margin-bottom: 50px;
-      }
-      #har-msgdisplay1 {
-            background-color: darkgray;
-      }
-      #message-input {
-           height: 122px;
-           width: 170px;
-           background-color: #729FFF;
-           float: left;
-       }
-        /* CMS Dialog button panel */
-       #buttonPanel {
-           height: 122px;
-           width: 125px;
-           background-color: #729FFF;
-           float: left;
-           padding: 20px;
-        }
-       .wrapper {
-           position: relative;\
-        }
-        /* CMS Edit Message Dialog */
-       .dialog {
-          position: absolute;
-          top: 10%;
-          left: 25%;
-          background-color: #729FFF; /* #ECECFB; */
-          margin: auto;
-          padding: 20px;
-          border: 1px solid #888;
-          width: 680px;
-          height: 390px;
-          display: none;           
-        }
       .unstyled-button {
         border: 0 none;
@@ -143,17 +75,3 @@
         background: none;
         cursor: pointer;
-      }    
-        /* The Close Button in the CMS Dialog */
-        .close {
-          color: #2E2E2E;
-          float: right;
-          font-size: 30px;
-          font-weight: bold;
-        }
-        .close:hover,
-        .close:focus {
-          color: black;
-          text-decoration: none;
-          cursor: pointer;
-        }
-
+      }
Index: trunk/webapps/GTEC/index.html
===================================================================
--- trunk/webapps/GTEC/index.html	(revision 556)
+++ trunk/webapps/GTEC/index.html	(revision 569)
@@ -5,5 +5,5 @@
 <!-- map center button icon from http://icons8.com/.  (Obligatory backlink, don't remove ) -->
   <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <title>Visualizer </title> 
+    <title>Graphic Traffic Events Creator</title> 
 <link rel="icon" 
       type="image/png" 
@@ -14,17 +14,43 @@
   <body>
     <!-- 
-         Visualizer created from CPTMS
-         @author tkumar and jdalbey 2019.11.23
+         Version 6.5 Adjust cms dialog dimensions for Chrome.
+	     Version 6.4 Remove fullscreen control. (Use Browser F11 instead).
+         Version 6.3 decomposed into modules for each layer
+         Version 6.2 puts cctv and cms and vds in separate data layers.   
+         Version 6.1 Puts cms messages in json formatted file.  Polls for updates.
+         Version 6.0 Adds speed-dependent images to infowindow for cctv icons
+         Version 5.8 Adds an infowindow with a static image for all cctv icons
+         Version 5.7 integrates CCTV icons and button (but empty click handler)
+         Version 5.6 integrates CMS features
+         Version 5.5 renames title to CPTMS, loads static data on startup and dynamic data
+         every ten seconds.  
+         Version 5.4 adds Search box and Center button
+         Version 5.3 fixed dot color update defect, increased refresh rate to 10 sec.
+         Version 5.2 places red dots overlapping yellow dots.
+         Version 5.1 removes the map and street view buttons and the H3 tag.
+         Version 5 uses precomputed perpendicular vector in dot adjustment function
+         Version 4 Adjust the spacing between dots when the map is zoomed.
+         Version 3 does loadGeoJson only once, and subsequently does an ajax load
+         of the highways file, and selectively updates only those placePins whose
+         color has changed. 
+         @author jdalbey  2019.2.17
     -->
+
     <!--The div element where the map appears. -->
     <div id="mapdiv"></div>
     <!-- The div element for the popup dialog. Best results when placed here. -->
-    </div>
    <!--The div elements where the buttons appear-->
     <div id="ctrButton"><img width="30" src="images/btn_mapcenter.png"></div>
+    <button id="redButton">Red</button>
+    <button id="greenButton">Green</button>
+    <button id="yellowButton">Yellow</button>
+    <!-- <button id="harButton" class="unstyled-button"><img id="harBtnImg" src="images/btnReady_HAR.png"></button>
+    <button id="cctvButton" class="unstyled-button"><img id="cctvBtnImg" src="images/btnReady_CCTV.png"></button>
+    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/btnReady_CMS.png"></button>-->
+    <!--<button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/btnDepressed_VDS.png"></button>
     <p id="time">00:00:00</p>
-    <button id="beginning" >Beginning</button>
+    <button id="start" >Beginning</button>
     <button id="forward" >Next</button>
-	<button id="backward" >Back</button>
+	<button id="backward" >Back</button> -->
     <script  src="../common/js/fileutils.js"></script>
     <script  src="../common/js/revision_number.dat"></script>
@@ -72,5 +98,5 @@
     var eventTimes = []; //array to hold times of each traffic event
     eventTimes[0] = "00:00:00";
-    var diff_arr = []; // 2d array containing difference in map state between each event
+    var diff_arr = []; // 2d array containing 
     var eventIndex = -1; //to index into above array
 
@@ -100,4 +126,13 @@
     }
 
+    // Initialize the view/hide buttons 
+    function initLayerButtons()
+    {
+       // initVDSbutton();
+        //initControlButtons();
+        initColorButtons();
+        initVDSicons();
+    }
+
     // Initialize the map and load the points
     function initMap()
@@ -114,12 +149,17 @@
         });
 
-        // setup the search box and center button
-        //initSearch();
+        // setup the center button
         initCenter();
         
-        initializeVDSlayer(); // go load the map data
+        loadVDSlayer(); // go load the map data
+       // processVDS();
 
-        initControlButtons();
-        initVDSicons()
+        initLayerButtons(); // setup the show/hide layer buttons
+
+        updateVDSlayer();
+        setTimeout(function() {
+         //   buildDiff();
+            updateVDSlayer();
+        }, 3000);
 
         // Listen for zoom changes and move the vds dots so as to keep a nice
Index: trunk/webapps/GTEC/js/vdsLayer_john.js
===================================================================
--- trunk/webapps/GTEC/js/vdsLayer_john.js	(revision 556)
+++ 	(revision )
@@ -1,368 +1,0 @@
-var postmileList = [];  // the list of postmiles saved from the json file.
-
-    // Load the map data from a json file and style all the points
-    function initializeVDSlayer()
-    {
-        // Load the static map data and call saveCoords when done
-        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
-        // Style the map data by applying the desired properties to each feature (marker)
-        // The function will be called every time a feature's properties are updated.
-        map.data.setStyle(function(feature)
-        {
-            // Get the postmile id 
-            var name = feature.getId();
-            // Get the desired color value
-            var ptColor = feature.getProperty("color");
-            var street = feature.getProperty("street");
-            // Build the marker
-            var iconSymbol = dotSymbol(ptColor);
-            // return the StyleOptions
-            return {
-                icon: iconSymbol,
-                title: name + " @" + street, // set rollover text
-                // set zIndex for slowed traffic to a higher value so they overlap
-                zIndex: colorZvalues[ptColor]
-            };
-        });
-        // Listen for clicks on a VDS dot.
-        map.data.addListener('click', function(event)
-        {
-            selectedID = event.feature.getId();  // get the id of the clicked dot
-            curr = postmileList.indexOf(selectedID); // find the id in the postmile list
-            var firstBlank = postmileList[curr].indexOf(" ", 0);  // find direction substring
-            var secondBlank = firstBlank+2;  
-            var direction = postmileList[curr].charAt(firstBlank+1); // extract direction
-            target = event.feature.getId().substring(0,secondBlank); // extract target string
-            console.log("making white dots from " + selectedID + " in direction "+direction)
-            // Decide whether to increment or decrement based on direction of hwy;
-            //  N and E increment,  S and W decrement 
-            if (direction == 'N' || direction == 'E')
-            {
-                // Process all dots with same hwy and direction
-                while  (postmileList[curr].startsWith(target) && curr < postmileList.length)
-                {
-                    // turn the dot white
-                    currFeat = map.data.getFeatureById(postmileList[curr]);
-                    currFeat.setProperty("color", "white");  
-                    curr++;
-                } 
-            }
-            else
-            {
-                // Process all dots with same hwy and direction
-                while  (postmileList[curr].startsWith(target) && curr > 0)
-                {
-                    currFeat = map.data.getFeatureById(postmileList[curr]);
-                    // turn the dot white
-                    currFeat.setProperty("color", "white");  
-                    curr--;
-                }                 
-            }
-            
-        });
-    }
-
-    // Build a solid colored icon to use instead of the classic pin
-    function dotSymbol(color) 
-    {
-        var iconPath = iconVDSwhite;
-        if (color == 'red')
-        {
-           iconPath = iconVDSred;
-        }
-        else if (color == 'yellow')
-        {
-            iconPath = iconVDSyellow;
-        }
-        else if (color == 'lime')
-        {
-            iconPath = iconVDSgreen;
-        }
-        return {
-            url: iconPath, 
-            anchor: new google.maps.Point(6, 6)
-        };
-    }
-
-    // callback when load GeoJson completes
-    // save each feature's Point as the original coordinates for later reference
-    function saveCoords(features)
-    {
-        // Iterate over all the features in the map
-        features.forEach(function(feature)
-        {
-            var pt = feature.getGeometry().get();
-            vds_coords[feature.getId()] = pt; // save the Point in a dictionary
-            // new for GTEC
-            postmileList.push(feature.getId());  // save the postmile in a list
-        });
-        
-        // go adjust the marker coordinates so dots don't overlap
-        adjustCoords(calcDistanceFactor());
-// not needed in GTEC
-//        processVDS();
-
-    } 
-
-    // magic formula controls distance between dots proportionate to zoom factor
-    function calcDistanceFactor()
-    {
-        // 15 is maximum zoom, the point at which no adjustment is needed
-        return (.0005 * (15 - map.getZoom()));
-    }
-
-    // Adjust the coordinates of dots so they appear side-by-side
-    // The perpendicular vector for each dot has been provided,
-    // so we just need to multiply by a scaling factor (adjAmount) 
-    // @param adjAmount amount by which to adjust coordinate 
-    function adjustCoords(adjAmount)
-    {
-        // Adjust the NB points a slight amount
-        map.data.forEach(function(feature)
-        {
-            // get the name of the current feature
-            var name = feature.getId();
-            // lookup the original coordinates for this feature
-            var coords = vds_coords[name];
-
-            //retrieve the perpendicular vector (precomputed)
-            var perpx = feature.getProperty("perpx")
-            var perpy = feature.getProperty("perpy")
-                // Make adjustment and save it
-            var myLat = coords.lat() + perpy * adjAmount
-            var myLong = coords.lng() + perpx * adjAmount
-            feature.setGeometry(
-            {
-                lat: myLat,
-                lng: myLong
-            });
-        });
-    }
-
-    // update the color (as needed) for a given marker
-    function updateMarker(marker)
-    {
-        target = marker.id;
-        newColor = marker.properties.color;
-        // see if new color is different than current color
-        currentFeature = map.data.getFeatureById(target);
-        currentColor = currentFeature.getProperty("color");
-        // if a new color is desired then assign it to the feature's color property
-        if (currentColor != newColor)
-        {
-            currentFeature.setProperty("color", newColor);
-            // set zIndex for slowed traffic to a higher value so they overlap
-            currentFeature.setProperty("zIndex", colorZvalues[newColor]);
-        }
-    }
-
-    // Load the highways static json file and update the map
-    function resetVDSlayer()
-    {
-        eventIndex = -1;
-        loadJSON(kMapStartupFile, function(response)
-        {
-            // Parse JSON string into object
-            //initialVDSjson = JSON.parse(response);
-            // Process each new marker - lookup in current map
-            var initialVDSjsonFeatures = JSON.parse(response).features
-            initialVDSjsonFeatures.forEach(updateMarker);
-        });
-    }
-
-    function getColorName(str){
-        if (str === "R\r" || str === "R")
-            return "red";
-        else if (str === "Y\r" || str === "Y")
-            return "yellow";
-        else if (str === "G\r" || str === "G")
-            return "lime";
-    }
-
-// Parses the traffic events file and builds an array of target dots for each line
-    function processVDS() {
-        //var parsed_JSON;
-        loadJSON(kMapStartupFile, function(response)
-        { 
-            // Parse JSON string into object
-            parsed_JSON = JSON.parse(response);
-            // Process each new marker - lookup in current map
-            var parsed_features =  parsed_JSON.features;
-            parsed_features.forEach(updateMarker);
-            var eventsFile = '';
-            // Request the traffic events data file
-            var xmlhttp = new XMLHttpRequest();
-            xmlhttp.open("GET",trafficEventsFile,true); // Ask the server for the traffic events file
-            // Establish listener for handling the traffic events once file is read
-            xmlhttp.onreadystatechange = function()
-            {
-                if(xmlhttp.status == 200 && xmlhttp.readyState == 4)
-                {
-                    eventsFile = xmlhttp.responseText;
-                    // Process the traffic events file
-                    var lines = eventsFile.toString().split("\n");
-                    // For each line in the events file
-                    for (var line = 1; line < lines.length; line++) 
-                    {
-                        var trimmedLine = lines[line].trim();
-                        if (trimmedLine[0] !== '#') //ignores lines with #
-                        {
-                            var dots = [];                            
-                            var event = trimmedLine.split(/[ ,]+/);
-                            var start = parseFloat(event[4]); // extract postmile field
-                            var range = parseFloat(event[5]); // extract distance
-                            var newColor = getColorName(event[6]); // extract DotColor
-                            eventTimes.push(event[1]);  // extract the event time
-                            // Process each VDS in the highway network
-                            parsed_features.forEach(function (marker) {
-                                var marker_fields = marker.id.split(" ");
-                                // See if this marker's highway and direction match to this event
-                                if (marker_fields[0] === event[2] && marker_fields[1] === event[3])
-                                {   //computes difference in postmiles
-                                    var dist = parseFloat(marker_fields[2]) - start; 
-                                    // If this marker is within computed range
-                                    if (dist <= range && dist >= 0) 
-                                    {
-                                        // Add the marker to the dots representing this event
-                                        dots.push({"marker": marker, "color": newColor});
-                                    }
-                                }
-                            });
-                            targetDots.push(dots); // add this events dots to the list of targetdots
-                        } // end if
-                    }  // end for              
-                    // After the traffic events are processed,  go build the differences array
-                    buildDiff();      // side effect: leaves map with last event showing
-                    resetVDSlayer();  // restore the map to initial state
-                }
-            };
-            xmlhttp.send();
-        });
-    }
-
-    // Calls updateMarker for all targetDots after storing the previous marker in diff_arr 
-    // This function only needs to be done once, during startup.
-    function buildDiff() 
-    {
-        for (var i = 0; i <= targetDots.length; i++)
-        {
-            if  (targetDots[i] !== undefined)
-            {
-                var targetMarkers = new Array();
-                targetDots[i].forEach(function(item)
-                {
-                    item.marker.properties.color = item.color;
-                    storePrev(item.marker, targetMarkers);
-                    updateMarker(item.marker);
-                });
-                diff_arr.push(targetMarkers);
-            }
-        }
-    }
-    // Helper function for BuildDiff
-    // Store the previous colors of the targetDots
-    // so it will available if the user goes "back".
-    function storePrev(marker, targetMarkers) 
-    {
-        target = marker.id;
-        newColor = marker.properties.color;
-        // see if new color is different than current color
-        currentFeature = map.data.getFeatureById(target);
-        currentColor = currentFeature.getProperty("color");
-        // if a new color is desired then assign it to the feature's color property
-        if (currentColor != newColor)
-        {
-            targetMarkers.push({"id" : currentFeature.getId(),
-                "properties" : {"color" : currentColor}});
-        }
-    }
-
-
-
-    // Increments the eventIndex from and updates all the targetDots on map
-    function updateForwards() {
-        eventIndex++;
-        // limit eventIndex to length of targetDots
-        if (eventIndex >= targetDots.length) 
-        {
-            eventIndex = targetDots.length - 1;
-        }
-        // update all the target dots
-        if  (targetDots[eventIndex] !== undefined) {
-            targetDots[eventIndex].forEach(function(item){
-                item.marker.properties.color = item.color;
-                updateMarker(item.marker);
-            });
-        }
-    }
-
-    // Decrements the eventIndex and updates all the targetDots from diff_arr on map
-    function updateBackwards() {
-        //update each target dot in order to revert to previous color
-        if  (diff_arr[eventIndex] !== undefined) {
-            diff_arr[eventIndex].forEach(function(item){
-                updateMarker(item);
-            });
-        }
-        eventIndex--; 
-        // restrict eventIndex to -1
-        if (eventIndex < -1)
-        {
-            eventIndex = -1;
-        }
-    }
-    
-
-// init beginning, forward and back buttons as well as time display on map
-function initControlButtons()
-{
-    var i = 0;
-    // setup the time display
-    var time = document.getElementById('time');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time)
-    // set up the "beginning" button
-    var beginning = document.getElementById('beginning');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(beginning)
-    beginning.title = 'Click to see the first event';
-    // set up the "next" button
-    var forward = document.getElementById('forward');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward)
-    // set up the "back" button
-	var backward = document.getElementById('backward');
-	map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward)
-    forward.title = 'Click to see the next event';
-    //console.log(targetDots, eventTimes);
-    // Establish the listeners for each button
-    forward.addEventListener('click', function() {
-        updateForwards();
-        backward.disabled = false;
-        if (i < eventTimes.length - 1) // get the next eventTime 
-        {
-            ++i;
-            time.innerHTML = eventTimes[i];
-        }
-        if (eventIndex === targetDots.length - 1) // disable next button if last event reached
-        {
-            forward.disabled = true;
-        }
-    });
-	backward.addEventListener('click', function() {
-        updateBackwards();
-        forward.disabled = false;
-        if (i > 0)  // get the prev eventTime 
-        {
-            --i;
-            time.innerHTML = eventTimes[i];
-        }
-        if (eventIndex < 0) // disable back button if at first event 
-        {
-            backward.disabled = true;
-        }
-	});
-    beginning.addEventListener('click', function() {
-        resetVDSlayer(); // redraw markers on map from startup file
-        i = 0;
-        time.innerHTML = "00:00:00";
-    });
-}
-
Index: trunk/webapps/GTEC/js/vdsLayer_tk1.js
===================================================================
--- trunk/webapps/GTEC/js/vdsLayer_tk1.js	(revision 556)
+++ 	(revision )
@@ -1,381 +1,0 @@
-    // Build a solid colored icon to use instead of the classic pin
-    function dotSymbol(color) 
-    {
-        var iconPath = iconVDSwhite;
-        if (color == 'red')
-        {
-           iconPath = iconVDSred;
-        }
-        else if (color == 'yellow')
-        {
-            iconPath = iconVDSyellow;
-        }
-        else if (color == 'lime')
-        {
-            iconPath = iconVDSgreen;
-        }
-        return {
-            url: iconPath, 
-            anchor: new google.maps.Point(6, 6)
-        };
-    }
-
-    // Load the map data from a json file and style all the points
-    function initializeVDSlayer()
-    {
-        // Load the static map data and call saveCoords when done
-        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
-        // Style the map data by applying the desired properties to each feature (marker)
-        // The function will be called every time a feature's properties are updated.
-        map.data.setStyle(function(feature)
-        {
-            // Get the postmile id 
-            var name = feature.getId();
-            // Get the desired color value
-            var ptColor = feature.getProperty("color");
-            var street = feature.getProperty("street");
-            // Build the marker
-            var iconSymbol = dotSymbol(ptColor);
-            // return the StyleOptions
-            return {
-                icon: iconSymbol,
-                title: name + " @" + street, // set rollover text
-                // set zIndex for slowed traffic to a higher value so they overlap
-                zIndex: colorZvalues[ptColor]
-            };
-        });
-        var clicked = false;
-        var first = [];
-        var asc = false;
-        var color_arr = [];
-        map.data.addListener('click', function(event) 
-        {
-            var event_arr = event.feature.getId().split(/[ ,]+/);
-            // var start = parseFloat(event[4]); // extract postmile field
-            if (clicked && event_arr[0] === first[0] && event_arr[1] === first[1])
-            {
-                // console.log('clicked ' + first + "/" + event_arr + event.feature);
-                var range = Math.abs(parseFloat(event_arr[2]) - parseFloat(first[2]));
-                var clicked_dots = [];
-                if (event_arr[2] < first[2])
-                {
-                    asc = false;
-                }
-                else 
-                {
-                    asc = true;
-                }
-                map.data.forEach(function (marker) 
-                {
-                    var marker_arr = marker.getId().split(/[ ,]+/);
-                    if (marker_arr[0] === event_arr[0] && marker_arr[1] === event_arr[1])
-                    {
-                        if (asc)
-                        {
-                            var dist = parseFloat(marker_arr[2]) - parseFloat(first[2]);
-                        }
-                        else 
-                        {
-                            var dist = parseFloat(parseFloat(first[2]) - (marker_arr[2]));
-                        }
-                        if (dist <= range && dist >= 0)
-                        {
-                            clicked_dots.push(marker);
-                        }
-                    }
-                });
-                color_arr.push(clicked_dots);
-                console.log(clicked_dots);
-                console.log(range);
-            }
-            else if (!clicked)
-            {
-                first = event_arr;
-            }
-            else 
-            {
-                console.log('wrong choice');
-            }
-            clicked = !clicked;
-
-        });
-    }
-    // callback when load GeoJson completes
-    // save each feature's Point as the original coordinates for later reference
-    function saveCoords(features)
-    {
-        // Iterate over all the features in the map
-        features.forEach(function(feature)
-        {
-            var pt = feature.getGeometry().get();
-            vds_coords[feature.getId()] = pt; // save the Point in a dictionary
-        });
-        // update the dot colors from the dynamic json data 
-        updateVDSlayer();
-        // go adjust the marker coordinates so dots don't overlap
-        adjustCoords(calcDistanceFactor());
-    } 
-
-    // magic formula controls distance between dots proportionate to zoom factor
-    function calcDistanceFactor()
-    {
-        // 15 is maximum zoom, the point at which no adjustment is needed
-        return (.0005 * (15 - map.getZoom()));
-    }
-
-    // Adjust the coordinates of dots so they appear side-by-side
-    // The perpendicular vector for each dot has been provided,
-    // so we just need to multiply by a scaling factor (adjAmount) 
-    // @param adjAmount amount by which to adjust coordinate 
-    function adjustCoords(adjAmount)
-    {
-        // Adjust the NB points a slight amount
-        map.data.forEach(function(feature)
-        {
-            // get the name of the current feature
-            var name = feature.getId();
-            // lookup the original coordinates for this feature
-            var coords = vds_coords[name];
-
-            //retrieve the perpendicular vector (precomputed)
-            var perpx = feature.getProperty("perpx")
-            var perpy = feature.getProperty("perpy")
-                // Make adjustment and save it
-            var myLat = coords.lat() + perpy * adjAmount
-            var myLong = coords.lng() + perpx * adjAmount
-            feature.setGeometry(
-            {
-                lat: myLat,
-                lng: myLong
-            });
-        });
-    }
-
-    // update the color (as needed) for a given marker
-    function updateMarker(marker)
-    {
-        target = marker.id;
-        newColor = marker.properties.color;
-        // see if new color is different than current color
-        currentFeature = map.data.getFeatureById(target);
-        currentColor = currentFeature.getProperty("color");
-        // if a new color is desired then assign it to the feature's color property
-        if (currentColor != newColor)
-        {
-            currentFeature.setProperty("color", newColor);
-            // set zIndex for slowed traffic to a higher value so they overlap
-            currentFeature.setProperty("zIndex", colorZvalues[newColor]);
-        }
-    }
-
-    // Builds array to store the previous colors of the targetDots
-    /*function storePrev(marker, targetMarkers) 
-    {
-        target = marker.id;
-        newColor = marker.properties.color;
-        // see if new color is different than current color
-        currentFeature = map.data.getFeatureById(target);
-        currentColor = currentFeature.getProperty("color");
-        // if a new color is desired then assign it to the feature's color property
-        if (currentColor != newColor)
-        {
-            targetMarkers.push({"id" : currentFeature.getId(),
-                "properties" : {"color" : currentColor}});
-        }
-    }*/
-
-    // Load the highways dynamic json file and update the map
-    function updateVDSlayer()
-    {
-        eventIndex = -1;
-        var parsed_JSON;
-        loadJSON(kVDSstatusFile, function(response)
-        {
-            // Parse JSON string into object
-            parsed_JSON = JSON.parse(response);
-            // Process each new marker - lookup in current map
-            parsed_JSON.features.forEach(updateMarker);
-        });
-    }
-
-    function getColorName(str){
-        if (str === "R\r" || str === "R")
-            return "red";
-        else if (str === "Y\r" || str === "Y")
-            return "yellow";
-        else if (str === "G\r" || str === "G")
-            return "lime";
-    }
-
-// Parses the traffic events file and builds an array of target dots for each line
-    /*function processVDS() {
-        var parsed_JSON;
-        loadJSON(kVDSstatusFile, function(response)
-        { 
-            // Parse JSON string into object
-            parsed_JSON = JSON.parse(response);
-            // Process each new marker - lookup in current map
-            var parsed_features =  parsed_JSON.features;
-            var eventsFile = '';
-            var xmlhttp = new XMLHttpRequest();
-            xmlhttp.onreadystatechange = function(){
-                if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
-                    eventsFile = xmlhttp.responseText;
-                    var lines = eventsFile.toString().split("\n");
-                    for (var line = 1; line < lines.length; line++) {
-                        if (lines[line][0] !== '#') //ignores lines with #
-                        {
-                            var dots = [];
-                            var event = lines[line].split(/[ ,]+/);
-                            var start = parseFloat(event[4]); // extract postmile field
-                            var range = parseFloat(event[5]); // extract distance
-                            var newColor = getColorName(event[6]); // extract DotColor
-                            eventTimes.push(event[1]);
-                            parsed_features.forEach(function (marker) {
-                                var id_arr = marker.id.split(" ");
-                                if (id_arr[0] === event[2] && id_arr[1] === event[3]){
-                                    var dist = parseFloat(id_arr[2]) - start; //computes difference in postmiles
-                                    if (dist <= range && dist >= 0){ // adds all dots within computed range
-                                        dots.push({"marker": marker, "color": newColor});
-                                    }
-                                }
-                            });
-                            targetDots.push(dots);
-                        }
-                    }
-                }
-            };
-            xmlhttp.open("GET",trafficEventsFile,true); //read traffic events text file
-            xmlhttp.send();
-        });
-    }
-
-    // Increments the eventIndex from and updates all the targetDots on map
-    function updateForwards() {
-        eventIndex++;
-        // limit eventIndex to length of targetDots
-        if (eventIndex >= targetDots.length) 
-        {
-            eventIndex = targetDots.length - 1;
-        }
-        // update all the target dots
-        if  (targetDots[eventIndex] !== undefined) {
-            targetDots[eventIndex].forEach(function(item){
-            item.marker.properties.color = item.color;
-            updateMarker(item.marker);
-            });
-        }
-    }
-
-    // Decrements the eventIndex and updates all the targetDots from diff_arr on map
-    function updateBackwards() {
-        //update each target dot in order to revert to previous color
-        if  (diff_arr[eventIndex] !== undefined) {
-            diff_arr[eventIndex].forEach(function(item){
-                updateMarker(item);
-            });
-        }
-        eventIndex--; 
-        // restrict eventIndex to -1
-        if (eventIndex < -1)
-        {
-            eventIndex = -1;
-        }
-    }
-    
-    // Calls updateMarker for all targetDots after storing the previous marker in diff_arr 
-    function buildDiff() {
-        for (var i = 0; i <= targetDots.length; i++)
-        {
-            if  (targetDots[i] !== undefined)
-            {
-                var targetMarkers = new Array();
-                targetDots[i].forEach(function(item){
-                    item.marker.properties.color = item.color;
-                    storePrev(item.marker, targetMarkers);
-                    updateMarker(item.marker);
-                });
-                diff_arr.push(targetMarkers);
-            }
-        }
-    }
-*/
-/*function initVDSbutton()
-{
-
-    var vdsBtnDiv = document.getElementById('vdsButton');
-    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(vdsBtnDiv)
-    vdsBtnDiv.title = 'Click to toggle vds view';
-
-    // Setup the click event listeners to toggle icon display
-    vdsBtnDiv.addEventListener('click', function()
-    {
-        vds_showing = !vds_showing;
-        // reveal or hide all the dots
-        map.data.forEach(function(feature)
-        {
-            map.data.overrideStyle(feature,
-            {
-                visible: vds_showing
-            });
-        });
-        // Determine which button image to show
-        if (vds_showing)
-        {
-            pic = "images/btnDepressed_VDS.png"
-        }
-        else
-        {
-            pic = "images/btnReady_VDS.png"
-        }
-        document.getElementById('vdsBtnImg').src = pic;
-    });
-}*/
-
-// init beginning, forward and back buttons as well as time display on map
-function initControlButtons()
-{
-    var i = 0;
-    /*var time = document.getElementById('time');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(time)
-    var start = document.getElementById('start');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(start)
-    start.title = 'Click to see the first event';
-    var forward = document.getElementById('forward');
-    map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(forward)
-	var backward = document.getElementById('backward');
-	map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(backward)
-    forward.title = 'Click to see the next event';
-    forward.addEventListener('click', function() {
-        updateForwards();
-        backward.disabled = false;
-        if (i < eventTimes.length - 1) // get the next eventTime 
-        {
-            ++i;
-            time.innerHTML = eventTimes[i];
-        }
-        if (eventIndex === targetDots.length - 1) // disable next button if last event reached
-        {
-            forward.disabled = true;
-        }
-    });
-	backward.addEventListener('click', function() {
-        updateBackwards();
-        forward.disabled = false;
-        if (i > 0)  // get the prev eventTime 
-        {
-            --i;
-            time.innerHTML = eventTimes[i];
-        }
-        if (eventIndex < 0) // disable back button if at first event 
-        {
-            backward.disabled = true;
-        }
-	});
-    start.addEventListener('click', function() {
-        updateVDSlayer(); // redraw markers on map from startup file
-        i = 0;
-        time.innerHTML = "00:00:00";
-    });*/
-}
-
