Index: trunk/src/cptms/cms_messages.json
===================================================================
--- trunk/src/cptms/cms_messages.json	(revision 314)
+++ 	(revision )
@@ -1,1 +1,0 @@
-{"data":[{"cms":{"index":"1200022","message":{"displayTime":"","phase1":{"Line1":"   Near Vista","Line2":"    Hermosa","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200023","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200024","message":{"displayTime":"","phase1":{"Line1":"bottom of fifth","Line2":"dodgers up by 2","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200025","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200026","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200027","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200028","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200029","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200030","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200031","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200032","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200033","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200034","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200035","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200036","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200037","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200038","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200039","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200040","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200041","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200042","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200043","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200044","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200045","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200046","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200047","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200048","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200049","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200050","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200051","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200052","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200053","message":{"displayTime":"","phase1":{"Line1":"  slow for the","Line2":"   cone zone","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200055","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200056","message":{"displayTime":"","phase1":{"Line1":"    caution","Line2":"  slow traffic","Line3":"     ahead"},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200057","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200058","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1208488","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211184","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211185","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211967","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211978","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212138","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212822","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212823","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214503","message":{"displayTime":"","phase1":{"Line1":" You're heading","Line2":"     south.","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214504","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214505","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214506","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214507","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214508","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214509","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214510","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214511","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214512","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214513","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214514","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214956","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1217542","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218442","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218482","message":{"displayTime":"","phase1":{"Line1":"  San Clemente","Line2":"   Next Exit","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218483","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218484","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218485","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218486","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}}]}
Index: trunk/src/cptms/cms_demo.html
===================================================================
--- trunk/src/cptms/cms_demo.html	(revision 301)
+++ 	(revision )
@@ -1,389 +1,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-<!-- Launch with  python -m CGIHTTPServer 8080  -->
-    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
-    <meta charset="utf-8">
-    <title>CMS Manager Demo</title>
-    <style>
-        @font-face {
-          font-family: Scoreboard;
-          src: url('scoreboard.ttf');
-        }
-      html, body {
-            height: 370px;
-            padding: 0;
-            margin: 0;
-        }
-        textarea {
-           height: 33px;
-           width: 272px;
-           resize: none;
-           font-family: Scoreboard;
-           font-size: xx-large;
-           background-color: #2F4F4F;
-           color: yellow;
-        }
-       input {
-           border: thin solid #333;
-           padding: 2px;
-           font-family: monospace;
-           font-size: large;
-        }
-      #map {
-           height: 550px;
-           width: 100%;
-           overflow: hidden;
-           border: thin solid #333;
-       }
-      #cms-info-label {
-           height: 20px;
-           width: 540px;
-           overflow: hidden;
-           background-color: #A8C5FF;  /*#ECECFB; */
-           border: thin solid #BDBDBD;
-           padding: 5px;
-       }
-      #message-display {
-           height: 172px;
-           width: 300px;
-           overflow: hidden;
-           float: left;
-           /* border: thin solid #333;*/
-           /* border-left: none;*/
-       }
-      #message-input {
-           height: 122px;
-           width: 135px;
-           background-color: #729FFF;
-           float: left;
-           
-       }
-       #buttonPanel {
-           height: 122px;
-           width: 100px;
-           background-color: #729FFF;
-           border-left: none;
-           float: left;
-           padding: 20px;
-        }
-       .wrapper {
-           position: relative;\
-        }
-       #dialog {
-          position: absolute;
-          top: 10%;
-          right: 20%;
-          background-color: #729FFF; /* #ECECFB; */
-          margin: auto;
-          padding: 20px;
-          border: 1px solid #888;
-          width: 52%;
-          display: none;           
-        }
-      .unstyled-button {
-        border: 0 none;
-        padding: 0;
-        background: none;
-        cursor: pointer;
-      }    
-
-
-    /* The Close Button */
-    .close {
-      color: orange;
-      float: right;
-      font-size: 20px;
-      font-weight: bold;
-    }
-
-    .close:hover,
-    .close:focus {
-      color: red;
-      text-decoration: none;
-      cursor: pointer;
-    }
-</style>
-  </head>
-  <body>
-    <div id="map"></div>
-    <!--The div element where the show/hide button appears -->
-    <!-- div id="hideButton">&#128065;</div -->
-    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/btnDepressed_CMS.png"></button>
-    <button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/btnDepressed_VDS.png"></button>
-    <div id="map" class = "wrapper"></div>
-    <!-- The div element for the popup dialog -->
-    <div id="dialog" style="display:none;">
-        <span class="close">&times;</span>
-        <br>
-        <div id="cms-info-label" style="font-family:monospace">CMS ID: xxx LOCATION: </div>
-        <br>
-        <div><pre>Proposed:                              Current:</pre></div>
-        <input id='cmsID' value="" type='hidden'/>
-        <div id="message-input">
-        <input id="msgcontent1" size="16" maxlength="16" type="text"/><br><br>
-        <input id="msgcontent2" size="16" maxlength="16"/><br><br>
-        <input id="msgcontent3" size="16" maxlength="16"/>
-        </div>        
-        <div id="buttonPanel"    style="display: block;">
-        <button onclick="handleSubmit();">Send >></button><br>
-        <button onclick="handleClear();">Clear >></button><br>
-        <button onclick="handleClose();">Close </button>
-        </div>
-        <div id="message-display"  style="display: block;">
-         <textarea readonly id="msgdisplay1" maxlength="16" rows="1" cols="16"></textarea>
-         <textarea readonly id="msgdisplay2" maxlength="16" rows="1" cols="16"></textarea>
-         <textarea readonly id="msgdisplay3" maxlength="16" rows="1" cols="16"></textarea>
-        </div>
-    </div>
-
-    <script>
-var centerPoint = {
-    lat: 33.693385,
-    lng: -117.798937
-};
-var map;
-var kMapStartupFile = "cmsStatusD12.json";
-var blueFlag = "images/icon_cmsBlue.png";
-var yellowFlag = "images/icon_cmsYellow.png";
-var messageList;
-var cms_info;
-var markerList = [];
-var cms_showing = true;
-var vds_showing = true;
-
-function initMap()
-{
-    map = new google.maps.Map(document.getElementById('map'),
-    {
-        center: centerPoint,
-        zoom: 11,
-        mapTypeControl: false,
-        streetViewControl: false
-    });
-    initButton();
-    getMessage(1); // load the current message file
-    setMarkers();
-}
-// Initialize the view/hide buttons 
-function initButton()
-{
-    var cmsBtnDiv = document.getElementById('cmsButton');
-    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cmsBtnDiv)
-    cmsBtnDiv.title = 'Click to toggle cms view';
-
-    // Setup the click event listeners to toggle icon display
-    cmsBtnDiv.addEventListener('click', function() {
-            cms_showing = !cms_showing;
-            // reveal or hide all the icons
-            for (var i = 0; i < markerList.length; i++)
-            {
-                markerList[i].setVisible(cms_showing);
-            }
-            // Determine which button image to show
-            if (cms_showing)
-            {
-                pic = "images/btnDepressed_CMS.png"
-            }
-            else
-            {
-                pic = "images/btnReady_CMS.png"
-            }
-            document.getElementById('cmsBtnImg').src=pic;
-    });
-    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 icons
-            alert("Not implemented yet")
-            // Determine which button image to show
-            if (vds_showing)
-            {
-                pic = "btnDepressed_VDS.png"
-            }
-            else
-            {
-                pic = "btnReady_VDS.png"
-            }
-            document.getElementById('vdsBtnImg').src=pic;
-    });
-}
-function setMarkers()
-{
-    var simpleImage = "";
-    loadcmsJSON(function(response)
-    {
-        // Parse JSON string into object
-        cms_info = JSON.parse(response);
-        console.log(cms_info.data[0].cms);
-        // Process each new marker 
-        for (var i = 0; i < cms_info.data.length; i++)
-        {
-            var cms = cms_info.data[i].cms;
-            var currLat = Number(cms.location.latitude);
-            var currLong = Number(cms.location.longitude);
-            // load a yellow flag if there's currently no message
-            if (messageList[i] == "||")
-                simpleImage = yellowFlag;
-            else
-                simpleImage = blueFlag;
-            var directionCode = cms.location.direction.charAt(0);
-            var locationInfo = directionCode + " " + cms.location
-                .route + " " + cms.location.postmile + " " + cms
-                .location.locationName
-            markerList[i] = new google.maps.Marker(
-            {
-                position:
-                {
-                    lat: currLat,
-                    lng: currLong
-                },
-                map: map,
-                icon: simpleImage,
-                title: "#"+i+" " +locationInfo,
-                cmsid: "" + i,
-                location: locationInfo
-            });
-            google.maps.event.addListener(markerList[i], 'click',
-                function()
-                {
-                    var dialog = document.getElementById('dialog');
-                    dialog.style.display = 'block';
-                    // fetch the sequential msg #
-                    cmsID = Number(this.cmsid);
-                    // Assign to the hidden field
-                    document.getElementById('cmsID').value = cmsID;
-                    getMessage(cmsID); // note: this is async
-                    document.getElementById('cms-info-label').innerHTML = "CMS ID: " +
-                        cmsID + "&nbsp;&nbsp;&nbsp;LOCATION: " + this.location;
-                    // clear input fields
-                    document.getElementById('msgcontent1').value = "";
-                    document.getElementById('msgcontent2').value = "";
-                    document.getElementById('msgcontent3').value = "";
-                    document.getElementById('msgcontent1').focus();
-                    var span = document.getElementsByClassName("close")[0]
-                    // When the user clicks on <span> (x), close the modal
-                    span.onclick = function() {
-                      handleClose();
-                    }
-                });
-        }
-    });
-}
-
-function loadcmsJSON(callback)
-{
-    var xobj = new XMLHttpRequest();
-    xobj.overrideMimeType("application/json");
-    xobj.open('GET', kMapStartupFile, true);
-    xobj.onreadystatechange = function()
-    {
-        if (xobj.readyState == 4 && xobj.status == "200")
-        {
-            callback(xobj.responseText);
-        }
-    };
-    // We want ajax to ignore any cached responses
-    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
-    xobj.send(null);
-}
-
-function handleSubmit()
-{
-    // recover the user's response
-    var response1 = document.getElementById('msgcontent1').value;
-    var response2 = document.getElementById('msgcontent2').value;
-    var response3 = document.getElementById('msgcontent3').value;
-    var newMsg = response1+response2+response3;
-    if (newMsg.length == 0)
-    {
-        alert("Nothing to Send ... Proposed is empty.");
-    }
-    else
-    {
-        document.getElementById('msgdisplay1').value = response1;
-        document.getElementById('msgdisplay2').value = response2;
-        document.getElementById('msgdisplay3').value = response3;
-        saveMessage(response1 + "|" + response2 + "|" + response3);
-    }
-}
-
-function handleClose()
-{
-    // hide the display
-    document.getElementById('dialog').style.display = 'none'
-}
-
-function handleClear()
-{
-    document.getElementById('msgdisplay1').value = "";
-    document.getElementById('msgdisplay2').value = "";
-    document.getElementById('msgdisplay3').value = "";
-    saveMessage("||");
-}
-
-function loadJSON(inFile, callback)
-{
-    var xobj = new XMLHttpRequest();
-    xobj.overrideMimeType("application/json");
-    xobj.open('GET', inFile, true);
-    xobj.onreadystatechange = function()
-    {
-        if (xobj.readyState == 4 && xobj.status == "200")
-        {
-            callback(xobj.responseText);
-        }
-    };
-    // We want ajax to ignore any cached responses
-    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
-    xobj.send(null);
-}
-// retrieve the current cms message file
-function getMessage(cmsID)
-{
-    loadJSON("http://localhost:8080/messagefile.txt", function(response)
-    {
-        // Parse JSON string into object
-        messageList = JSON.parse(response);
-        // select a message from json for the given cmsID
-        console.log("get by cmsID=" + cmsID);
-        var cmsSign = document.getElementById('msgdisplay1');
-        messageparts = messageList[cmsID].split("|");
-        cmsSign.value = messageparts[0];
-        document.getElementById('msgdisplay2').value = messageparts[1];
-        document.getElementById('msgdisplay3').value = messageparts[2];
-    });
-}
-// Save an updated cms message to the file
-// NB: cms id's are one-based, json array is zero-based.
-function saveMessage(outMessage, cmsID)
-{
-    var cmsID = document.getElementById('cmsID').value;
-    console.log("Saving " + outMessage + " for cmsID " + cmsID)
-    messageList[cmsID] = outMessage;
-    // Change icon if something was saved
-    if (outMessage == "||")
-        markerList[cmsID].setIcon(yellowFlag);
-    else
-        markerList[cmsID].setIcon(blueFlag);
-
-    var xhttp = new XMLHttpRequest();
-    xhttp.open("GET", "http://localhost:8080/cgi-bin/saveMessage.py?msg=" + JSON
-        .stringify(messageList), true);
-    xhttp.send();
-    // Using POST might be a better idea ... haven't tried this yet
-    //      var xhr = new XMLHttpRequest();
-    //      xhr.open("POST", "/cgi-bin/saveMessage.py?", true);
-    //      xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
-    // send the collected data as JSON
-    //      xhr.send(JSON.stringify(messageList));
-}    </script>
-    <script async defer
-    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD6iTyN0DjP-9OVkAgicyp4tkC10naE_B8&callback=initMap">
-    </script>
-  </body>
-</html>
Index: trunk/src/cptms/cptms.html
===================================================================
--- trunk/src/cptms/cptms.html	(revision 312)
+++ 	(revision )
@@ -1,908 +1,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-<!-- Launch with  python -m CGIHTTPServer 80  -->
-<!-- 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>CPTMS Map v0.6.2</title> 
-    <style>
-        @font-face {
-          font-family: Scoreboard;
-          src: url('scoreboard.ttf');
-        }
-      /* Set the size of the div element that contains the map */
-      #mapdiv {
-        height: 100%;
-        width: 100%;  
-       }
-        /* Makes the page fill the window. */
-      html, body {
-        height: 100%;
-        margin: 0;
-        padding: 0;
-      }
-        textarea {
-           height: 33px;
-           width: 272px;
-           resize: none;
-           font-family: Scoreboard;
-           font-size: xx-large;
-           background-color: #2F4F4F;
-           color: yellow;
-        }
-       input {
-           border: thin solid #333;
-           padding: 2px;
-           font-family: "Lucida Console", Monaco, monospace;
-           font-size: medium;
-        }
-      #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;
-        background-color: #fff;
-        margin-right: 7px;
-        border: thick solid white;
-      }
-      #cms-info-label {
-           height: 20px;
-           width: 590px;
-           overflow: hidden;
-           background-color: #A8C5FF;  /*#ECECFB; */
-           border: thin solid #BDBDBD;
-           padding: 5px;
-       }
-      #message-display {
-           height: 172px;
-           width: 300px;
-           overflow: hidden;
-           float: left;
-       }
-      #message-input {
-           height: 122px;
-           width: 165px;
-           background-color: #729FFF;
-           float: left;
-       }
-       #buttonPanel {
-           height: 122px;
-           width: 130px;
-           background-color: #729FFF;
-           border-left: none;
-           float: left;
-           padding: 20px;
-        }
-       .wrapper {
-           position: relative;\
-        }
-       #dialog {
-          position: absolute;
-          top: 10%;
-          right: 20%;
-          background-color: #729FFF; /* #ECECFB; */
-          margin: auto;
-          padding: 20px;
-          border: 1px solid #888;
-          width: 680px;
-          display: none;           
-        }
-      .unstyled-button {
-        border: 0 none;
-        padding: 0;
-        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;
-    }
-
-    </style>
-  </head>
-  <body>
-    <!-- 
-         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 text area input for the Search Box -->
-    <input id="search-input" class="controls" type="text" placeholder="Search Box">
-    <!--The div element where the map appears -->
-    <div id="mapdiv"></div>
-    <!-- The div element for the popup dialog -->
-    <div id="dialog" style="display:none;">
-        <span class="close">&#x2612;</span>  <!-- close button symbol -->
-        <br>
-        <div id="cms-info-label" style="font-family:'Courier New'">CMS ID: xxx LOCATION: </div>
-        <br>
-        <input id='cmsID' value="" type='hidden'/>
-        <div id="message-input">Proposed:
-        <input id="msgcontent1"  maxlength="16" type="text"/><br><br>
-        <input id="msgcontent2"  maxlength="16" type="text"/><br><br>
-        <input id="msgcontent3"  maxlength="16" type="text"/>
-        </div>        
-        <div id="buttonPanel"    style="display: block;">
-        <button onclick="handleCMSsubmit();">Send >></button><br>
-        <button onclick="handleCMSclear();">Clear >></button><br>
-        <button onclick="handleDialogClose();">Close </button>
-        </div>
-        <div id="message-display"  style="display: block;">Current:
-         <textarea readonly id="msgdisplay1" maxlength="16" rows="1" cols="16"></textarea>
-         <textarea readonly id="msgdisplay2" maxlength="16" rows="1" cols="16"></textarea>
-         <textarea readonly id="msgdisplay3" maxlength="16" rows="1" cols="16"></textarea>
-        </div>
-    </div>
-    <!--The div elements where the buttons appear  -->
-    <div id="ctrButton"><img width="30" src="images/CPTMSImages/btn_mapcenter.png"</div>
-    <button id="cctvButton" class="unstyled-button"><img id="cctvBtnImg" src="images/CPTMSImages/btnReady_CCTV.png"></button>
-    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/CPTMSImages/btnReady_CMS.png"></button>
-    <button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/CPTMSImages/btnDepressed_VDS.png"></button>
-
-    <script>
-//TODO:  
-// Add phase 2 to messages.
-// cms set visible gets undefined error after last icon is processed.
-
-    // a global variable for the google map
-    var map;
-    // a global dictionary to lookup a station's original coordinates
-    var vds_coords = {};
-    // a global variable to hold locations of marked search places
-    var placePins = [];
-    // Constant name of dynamic json data file created by CADserver
-    var kMapPointsFile = "highways.json";
-    // Constant name of initial (static) highways file used once at startup
-    var kMapStartupFile = "highways_startup.json";
-    // Constant for map center location: The John Wayne Airport
-    //var centerPoint = {lat: 33.687228, lng: -117.872148};
-    // Constant for map center location in District 12
-    var centerPoint = {
-        lat: 33.693385,
-        lng: -117.798937
-    };
-    // Initial map zoom
-    var initZoom = 11;
-    // Dot colors used in traffic model to indicate free-flowing, slowed, and stopped traffic
-    // and their associated zvalues so slower traffic dots are more visible.
-    // white means a disabled spot
-    var colorZvalues = {
-        "white": 5,
-        "lime": 10,
-        "yellow": 20,
-        "red": 30
-    };
-    var kCMSstartupFile = "cmsStatusD12.json";
-    var kCCTVfile = "cctv_locations_D12.json";
-    var blueFlag = "images/CPTMSImages/icon_cmsBlue.png";
-    var yellowFlag = "images/CPTMSImages/icon_cmsYellow.png";
-    var cctvIcon = "images/CPTMSImages/icon_cctvCyan.png";
-    var cctvIconWhite = "images/CPTMSImages/icon_cctvWhite.png";
-    var vdsIconGreen = "images/CPTMSImages/circle-green.png"
-    var vdsIconYellow = "images/CPTMSImages/circle-yellow.png"
-    var vdsIconRed = "images/CPTMSImages/circle-red.png"
-    var cms_info;
-    var messageDict = {};
-    var cms_showing = false;
-    var vds_showing = true;
-    var cctv_showing = false;
-    var cctv_infowindow; // We create just a single instance of info window.
-
-    // Build a solid colored icon to use instead of the classic pin
-    // Use a diamond on N and E directions, circle on S and W directions
-    function dotSymbol(color) //,direction)
-    {
-//        var circle = google.maps.SymbolPath.CIRCLE;
-//        var diamond = 'M -1,0 0,-1 1,0 0,1 z';
-//        var myShape = circle;
-        var iconPath = vdsIconGreen;
-        if (color == 'red')
-        {
-           iconPath = vdsIconRed;
-        }
-        else if (color == 'yellow')
-        {
-            iconPath = vdsIconYellow;
-        }
-        return {
-//            path: iconPath,
-//            icon: 
-//                    {
-                        url: iconPath, 
-                        anchor: new google.maps.Point(6, 6)
-//                    };
-//            anchor: new google.maps.Point(6, 6),
-//            scale: 5,
-//            strokeColor: "black", // the border color
-//            strokeWeight: 1, // the border thickness
-//            fillColor: color,
-//            fillOpacity: 1.0
-        };
-    }
-
-    // Load the map data from a json file and style all the points
-    function loadVDSlayer()
-    {
-        // Load the static map data and call saveCoords when done
-        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
-//        var d = new Date();
-//        var start = d.getTime();
-        // 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,
-/*                    icon: 
-                    {
-                        url: vdsIconGreen, 
-                        anchor: new google.maps.Point(6, 6)
-                    }, */
-                title: name + " @" + street, // set rollover text
-                // set zIndex for slowed traffic to a higher value so they overlap
-                zIndex: colorZvalues[ptColor]
-            };
-        });
-    }
-    // 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]);
-        }
-    }
-
-    // Load the dynamic json file for highways, etc.
-    // Ref: https://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript
-    function loadJSON(inFile, callback)
-    {
-        var xobj = new XMLHttpRequest();
-        xobj.overrideMimeType("application/json");
-        xobj.open('GET', inFile, true);
-        xobj.onreadystatechange = function()
-        {
-            if (xobj.readyState == 4 && xobj.status == "200")
-            {
-                callback(xobj.responseText);
-            }
-        };
-        // We want ajax to ignore any cached responses
-        xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
-        xobj.send(null);
-    }
-    // Load the highways dynamic json file and update the map
-    function updateVDSlayer()
-    {
-        var parsed_JSON;
-        loadJSON(kMapPointsFile, 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);
-        });
-    }
-
-    // Initialize the center button (to re-center the map)
-    function initCenter()
-    {
-        var centerBtnDiv = document.getElementById('ctrButton');
-        map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(centerBtnDiv)
-        centerBtnDiv.title = 'Click to recenter the map';
-
-        // Setup the click event listeners: reset center location and zoom factor
-        centerBtnDiv.addEventListener('click', function()
-        {
-            map.setCenter(centerPoint);
-            map.setZoom(initZoom);
-            clearPlacePins();
-        });
-    }
-
-    // Initialize the search box and listener 
-    function initSearch()
-    {
-        // Create the search box and link it to the UI element.
-        var input = document.getElementById('search-input');
-        var searchBox = new google.maps.places.SearchBox(input);
-        map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
-
-        // Bias the SearchBox results towards current map's viewport.
-        map.addListener('bounds_changed', function()
-        {
-            searchBox.setBounds(map.getBounds());
-        });
-
-        // Listen for the event fired when the user selects a prediction and retrieve
-        // more details for that place.
-        searchBox.addListener('places_changed', function()
-        {
-            var places = searchBox.getPlaces();
-
-            if (places.length == 0)
-            {
-                return;
-            }
-
-            clearPlacePins();
-
-            // Create a bounding region to include the search result places
-            var bounds = new google.maps.LatLngBounds();
-            // For each place, get the icon, name and location.
-            // There may be multiple search results
-            places.forEach(function(place)
-            {
-                if (!place.geometry)
-                {
-                    console.log("Returned place contains no geometry");
-                    return;
-                }
-
-                // Create a marker for each place.
-                placeMarker = new google.maps.Marker(
-                {
-                    map: map,
-                    title: place.name,
-                    position: place.geometry.location
-                })
-
-                // Click on the marker to remove it from the display
-                placeMarker.addListener('click', function()
-                {
-                    placeMarker.setMap(null);
-                });
-
-                // Add this marker to the collection of current markers 
-                placePins.push(placeMarker);
-
-                // Create a bounding region to include this place
-                if (place.geometry.viewport)
-                {
-                    // Only geocodes have viewport.
-                    bounds.union(place.geometry.viewport);
-                }
-                else
-                {
-                    bounds.extend(place.geometry.location);
-                }
-            });
-            // This will pan and zoom to the area around the marker
-            //map.fitBounds(bounds);
-            // This will center the map on the new marker(s) but not zoom
-            map.setCenter(bounds.getCenter());
-        });
-    }
-
-    // Remove any place pins from a previous search
-    function clearPlacePins()
-    {
-        placePins.forEach(function(marker)
-        {
-            marker.setMap(null);
-        });
-        placePins = [];
-    }
-    // Initialize the view/hide buttons 
-    function initLayerButtons()
-    {
-        var cctvBtnDiv = document.getElementById('cctvButton');
-        map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cctvBtnDiv)
-        cctvBtnDiv.title = 'Click to toggle cctv view';
-        // Setup the click event listeners to toggle icon display
-        cctvBtnDiv.addEventListener('click', function()
-        {
-            cctv_showing = !cctv_showing;
-            // reveal or hide all the icons
-            cctvLayer.forEach(function(feature)
-            {
-                cctvLayer.overrideStyle(feature,
-                {
-                    visible: cctv_showing
-                });
-            });
-            // Determine which button image to show
-            if (cctv_showing)
-            {
-                pic = "images/CPTMSImages/btnDepressed_CCTV.png"
-            }
-            else
-            {
-                pic = "images/CPTMSImages/btnReady_CCTV.png"
-            }
-            document.getElementById('cctvBtnImg').src = pic;
-        });
-
-        var cmsBtnDiv = document.getElementById('cmsButton');
-        map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cmsBtnDiv)
-        cmsBtnDiv.title = 'Click to toggle cms view';
-        // Setup the click event listeners to toggle icon display
-        cmsBtnDiv.addEventListener('click', function()
-        {
-            cms_showing = !cms_showing;
-            // Determine which button image to show
-            if (cms_showing)
-            {
-                pic = "images/CPTMSImages/btnDepressed_CMS.png"
-                // It's nice when icons become visible that the messages have been refreshed.
-                loadAllMessages();
-            }
-            else
-            {
-                pic = "images/CPTMSImages/btnReady_CMS.png"
-            }
-            document.getElementById('cmsBtnImg').src = pic;
-            // reveal or hide all the icons
-            cmsLayer.forEach(function(feature)
-            {
-                cmsLayer.overrideStyle(feature,
-                {
-                    visible: cms_showing
-                });
-            });
-        });
-
-        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/CPTMSImages/btnDepressed_VDS.png"
-            }
-            else
-            {
-                pic = "images/CPTMSImages/btnReady_VDS.png"
-            }
-            document.getElementById('vdsBtnImg').src = pic;
-        });
-    }
-
-function loadCMSlayer()
-{
-    cmsLayer = new google.maps.Data();
-    cmsLayer.setMap(map);
-    cmsLayer.loadGeoJson("cms_locations_D12.gjson");
-    cmsLayer.setStyle(function(feature)
-    {
-        // return the StyleOptions
-        return {
-            icon: yellowFlag,
-            title: feature.getId()+ " " +feature.getProperty("location"),
-            visible: false
-        };
-    });
-    
-    cmsLayer.addListener('click', function(event)
-    {
-        var dialog = document.getElementById('dialog');
-        // Note: If the dialog is already being displayed when someone else
-        // updates the message, it won't be reflected in the dialog, until
-        // you close and reopen it.
-        dialog.style.display = 'block';
-        cmsID = event.feature.getId();
-        // Assign to the hidden field
-        document.getElementById('cmsID').value = cmsID;
-        showMessage(cmsID); // note: this is async
-        document.getElementById('cms-info-label').innerHTML = "CMS ID: " +
-            cmsID + "&nbsp;&nbsp;&nbsp;LOCATION: " + event.feature.getProperty("location");
-        // clear input fields
-        document.getElementById('msgcontent1').value = "";
-        document.getElementById('msgcontent2').value = "";
-        document.getElementById('msgcontent3').value = "";
-        document.getElementById('msgcontent1').focus();
-        var span = document.getElementsByClassName("close")[0]
-            // When the user clicks on <span> (x), close the modal
-        span.onclick = function()
-        {
-            handleDialogClose();
-        }
-    });
-}
-function makecctvIcon(nearVDS)
-{
-    var imgIcon = cctvIcon
-    if ((typeof map.data.getFeatureById(nearVDS)) == "undefined")
-    {
-        imgIcon = cctvIconWhite;
-    }
-    return imgIcon
-}
-function loadCCTVlayer()
-{
-    var imgTag = '<IMG WIDTH="700" SRC="images/CPTMSImages/';
-    cctv_infowindow = new google.maps.InfoWindow();
-    cctvLayer = new google.maps.Data();
-    cctvLayer.loadGeoJson("cctv_locations_D12.gjson");
-    cctvLayer.setStyle(function(feature)
-    {
-        // return the StyleOptions
-        return {
-            icon: makecctvIcon(feature.getProperty("nearVDS")),
-            title: feature.getId() + " " +feature.getProperty('locationName'),
-            visible: false  
-        };
-    });
-    cctvLayer.addListener('click', function(event)
-    {
-        //console.log("cctv layer was clicked at " + event.feature.getId());
-        cctvIndex = event.feature.getId();
-        //console.log(this.title + " is looking for " + this.nearVDS);
-        nearVDS = map.data.getFeatureById(event.feature.getProperty("nearVDS"));
-        currentColor = nearVDS.getProperty("color");
-        var imgDir = "CCTVFast/";
-        if (currentColor == "red" || currentColor == "yellow")
-        {
-            imgDir = "CCTVSlow/"
-        }
-
-        cctv_infowindow.setContent('<div style="font-weight:bold;font-family: monospace">' +  nearVDS.getId() + "&nbsp;" + currentColor + "<BR>" + imgTag + imgDir + cctvIndex + '.jpg">' + "</div>");
-        cctv_infowindow.setPosition(event.feature.getGeometry().get());
-        cctv_infowindow.open(map);
-
-    });
-    cctvLayer.setMap(map);
-}
-
-    // Center justify message text in a 16 column field
-    function justifyCMStext(message)
-    {
-        var kBlanks = "                ";
-        var padLen = (16 - message.length) / 2;
-        var padding = kBlanks.substring(0, padLen);
-        return padding + message;
-    }
-
-    function handleCMSsubmit()
-    {
-        // recover the user's response
-        var response1 = justifyCMStext(document.getElementById('msgcontent1').value.trim());
-        var response2 = justifyCMStext(document.getElementById('msgcontent2').value.trim());
-        var response3 = justifyCMStext(document.getElementById('msgcontent3').value.trim());
-        var newMsg = response1 + response2 + response3;
-        if (newMsg.length == 0)
-        {
-            alert("Nothing to Send ... Proposed is empty.");
-        }
-        else
-        {
-            document.getElementById('msgdisplay1').value = response1;
-            document.getElementById('msgdisplay2').value = response2;
-            document.getElementById('msgdisplay3').value = response3;
-            saveMessage(response1 + "|" + response2 + "|" + response3);
-        }
-    }
-
-    function handleDialogClose()
-    {
-        // hide the display
-        document.getElementById('dialog').style.display = 'none'
-    }
-
-    function handleCMSclear()
-    {
-        document.getElementById('msgdisplay1').value = "";
-        document.getElementById('msgdisplay2').value = "";
-        document.getElementById('msgdisplay3').value = "";
-        saveMessage("||");
-    }
-    // retrieve the current cms message file
-    function showMessage(cmsID)
-    {
-        loadAllMessages();  // because someone else may have made a recent update
-        // lookup the message for this cms ID
-        var message = messageDict[cmsID].cms.message;
-        // show the message in the display
-        document.getElementById('msgdisplay1').value = message.phase1.Line1;
-        document.getElementById('msgdisplay2').value = message.phase1.Line2;
-        document.getElementById('msgdisplay3').value = message.phase1.Line3;
-    }
-    function loadAllMessages()
-    {
-        loadJSON("cms_messages.json", function(response)
-        {
-            // Parse JSON string into object
-            messagejson = JSON.parse(response);
-            // Add each message to a lookup dictionary 
-            for (var i = 0; i < messagejson.data.length; i++)
-            {
-                var item = messagejson.data[i];
-                messageDict[item.cms.index] = item;
-                // Set the appropriate icon on the cms icon
-                // set a yellow flag if there's currently no message
-                if (item.cms.message.phase1.Line1 + 
-                    item.cms.message.phase1.Line2 +
-                    item.cms.message.phase1.Line3 == "")
-                {
-                    cmsLayer.overrideStyle(cmsLayer.getFeatureById(item.cms.index), {icon: yellowFlag})
-                }
-                else
-                {
-                    cmsLayer.overrideStyle(cmsLayer.getFeatureById(item.cms.index), {icon: blueFlag})
-                }
-            }
-        });
-    }
-
-    // Save an updated cms message to the file
-    function saveMessage(outMessage)
-    {
-        // Fetch cmsID from hidden field where it was put when dialog opened.
-        var cmsID = document.getElementById('cmsID').value;
-        //console.log("Saving " + outMessage + " for cmsID " + cmsID)
-        msgParts = outMessage.split("|");
-        messageDict[cmsID].cms.message.phase1.Line1 = msgParts[0];
-        messageDict[cmsID].cms.message.phase1.Line2 = msgParts[1];
-        messageDict[cmsID].cms.message.phase1.Line3 = msgParts[2];
-        // Set icon to reflect message state
-        if (outMessage == "||")
-        {
-            currentIcon = {icon: yellowFlag};
-        }
-        else
-        {
-            currentIcon = {icon: blueFlag};
-        }
-        cmsLayer.overrideStyle(cmsLayer.getFeatureById(cmsID), currentIcon)
-        outString = "{\n\t\"data\":\n\t\t" + JSON.stringify(Object.values(messageDict)) + "}";
-
-        var xhttp = new XMLHttpRequest();
-        xhttp.open("GET", "cgi-bin/saveMessage.py?msg=" + outString, true);
-        xhttp.send();
-        // Using POST might be a better idea ... haven't tried this yet
-        //      var xhr = new XMLHttpRequest();
-        //      xhr.open("POST", "/cgi-bin/saveMessage.py?", true);
-        //      xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
-        // send the collected data as JSON
-        //      xhr.send(JSON.stringify(messageList));
-    }
-
-    // Initialize the map and load the points
-    function initMap()
-    {
-        // Declare the map and where it belongs on the page
-        map = new google.maps.Map(document.getElementById('mapdiv'),
-        {
-            zoom: initZoom,
-            center: centerPoint,
-            styles: night_mode,
-            mapTypeControl: false,
-            streetViewControl: false
-        });
-        loadVDSlayer(); // go load the map data
-        // setup the search box and center button
-        initSearch();
-        initCenter();
-
-loadCMSlayer();
-
-loadCCTVlayer();
-
-        initLayerButtons();
-
-        // Start a timer to refresh the vds dots every 10 seconds
-        var myTimer = setInterval(updateVDSlayer, 10000);
-        // start an interval timer to refresh the cms icons every 10 seconds
-        var cmsTimer = setInterval(loadAllMessages, 10000);
-        // Listen for zoom changes and move the placePins so as to keep a nice
-        // visual distance between them appropriate to the zoom factor
-        map.addListener('zoom_changed', function()
-        {
-            // fetch how much the map is currently zoomed
-            currentZoom = map.getZoom();
-            // only bother adjusting within this range
-            if ((currentZoom < 16) && (currentZoom > 10))
-            {
-                // magic formula controls distance between dots
-                adjustCoords(calcDistanceFactor());
-            }
-        });
-
-    }
-    // Styles array for Night Mode map
-    // Ref: https://developers.google.com/maps/documentation/javascript/styling
-    var night_mode = [
-                {elementType: 'geometry', stylers: [{color: '#242f3e'}]},
-                {elementType: 'labels.text.stroke', stylers: [{color: '#242f3e'}]},
-                {elementType: 'labels.text.fill', stylers: [{color: '#746855'}]},
-                {
-                  featureType: 'administrative.locality',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#d59563'}]
-                },
-                {
-                  featureType: 'poi',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#d59563'}]
-                },
-                {
-                  featureType: 'poi.park',
-                  elementType: 'geometry',
-                  stylers: [{color: '#263c3f'}]
-                },
-                {
-                  featureType: 'poi.park',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#6b9a76'}]
-                },
-                {
-                  featureType: 'road',
-                  elementType: 'geometry',
-                  stylers: [{color: '#38414e'}]
-                },
-                {
-                  featureType: 'road',
-                  elementType: 'geometry.stroke',
-                  stylers: [{color: '#212a37'}]
-                },
-                {
-                  featureType: 'road',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#9ca5b3'}]
-                },
-                {
-                  featureType: 'road.highway',
-                  elementType: 'geometry',
-                  stylers: [{color: '#746855'}]
-                },
-                {
-                  featureType: 'road.highway',
-                  elementType: 'geometry.stroke',
-                  stylers: [{color: '#1f2835'}]
-                },
-                {
-                  featureType: 'road.highway',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#f3d19c'}]
-                },
-                {
-                  featureType: 'transit',
-                  elementType: 'geometry',
-                  stylers: [{color: '#2f3948'}]
-                },
-                {
-                  featureType: 'transit.station',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#d59563'}]
-                },
-                {
-                  featureType: 'water',
-                  elementType: 'geometry',
-                  stylers: [{color: '#17263c'}]
-                },
-                {
-                  featureType: 'water',
-                  elementType: 'labels.text.fill',
-                  stylers: [{color: '#515c6d'}]
-                },
-                {
-                  featureType: 'water',
-                  elementType: 'labels.text.stroke',
-                  stylers: [{color: '#17263c'}]
-                }
-              ]
-
-    // Using John's API Key
-    </script>
-    <script async defer
-    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD6iTyN0DjP-9OVkAgicyp4tkC10naE_B8&libraries=places&callback=initMap">
-    </script>
-  </body>
-</html>
Index: trunk/webapps/cgi-bin/saveMessage.py
===================================================================
--- trunk/webapps/cgi-bin/saveMessage.py	(revision 311)
+++ trunk/webapps/cgi-bin/saveMessage.py	(revision 311)
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+# Save parameter to a file
+# Import modules for CGI handling 
+import cgi, cgitb, os 
+
+# Create instance of FieldStorage 
+form = cgi.FieldStorage() 
+
+# Get data from fields
+outMessage = form.getvalue('msg')
+   
+# write message to file
+text_file = open("cms_messages.json", "w")
+text_file.write(outMessage)
+text_file.close()
+
+#print "Content-type:text/html\n\n"
+#print "<html><body>"
+#print "Here is the message<br>"
+#print outMessage
+#print "<br>"
+#print "</body></html>"
Index: trunk/webapps/cms_demo.html
===================================================================
--- trunk/webapps/cms_demo.html	(revision 320)
+++ trunk/webapps/cms_demo.html	(revision 320)
@@ -0,0 +1,389 @@
+<!DOCTYPE html>
+<html>
+  <head>
+<!-- Launch with  python -m CGIHTTPServer 8080  -->
+    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
+    <meta charset="utf-8">
+    <title>CMS Manager Demo</title>
+    <style>
+        @font-face {
+          font-family: Scoreboard;
+          src: url('scoreboard.ttf');
+        }
+      html, body {
+            height: 370px;
+            padding: 0;
+            margin: 0;
+        }
+        textarea {
+           height: 33px;
+           width: 272px;
+           resize: none;
+           font-family: Scoreboard;
+           font-size: xx-large;
+           background-color: #2F4F4F;
+           color: yellow;
+        }
+       input {
+           border: thin solid #333;
+           padding: 2px;
+           font-family: monospace;
+           font-size: large;
+        }
+      #map {
+           height: 550px;
+           width: 100%;
+           overflow: hidden;
+           border: thin solid #333;
+       }
+      #cms-info-label {
+           height: 20px;
+           width: 540px;
+           overflow: hidden;
+           background-color: #A8C5FF;  /*#ECECFB; */
+           border: thin solid #BDBDBD;
+           padding: 5px;
+       }
+      #message-display {
+           height: 172px;
+           width: 300px;
+           overflow: hidden;
+           float: left;
+           /* border: thin solid #333;*/
+           /* border-left: none;*/
+       }
+      #message-input {
+           height: 122px;
+           width: 135px;
+           background-color: #729FFF;
+           float: left;
+           
+       }
+       #buttonPanel {
+           height: 122px;
+           width: 100px;
+           background-color: #729FFF;
+           border-left: none;
+           float: left;
+           padding: 20px;
+        }
+       .wrapper {
+           position: relative;\
+        }
+       #dialog {
+          position: absolute;
+          top: 10%;
+          right: 20%;
+          background-color: #729FFF; /* #ECECFB; */
+          margin: auto;
+          padding: 20px;
+          border: 1px solid #888;
+          width: 52%;
+          display: none;           
+        }
+      .unstyled-button {
+        border: 0 none;
+        padding: 0;
+        background: none;
+        cursor: pointer;
+      }    
+
+
+    /* The Close Button */
+    .close {
+      color: orange;
+      float: right;
+      font-size: 20px;
+      font-weight: bold;
+    }
+
+    .close:hover,
+    .close:focus {
+      color: red;
+      text-decoration: none;
+      cursor: pointer;
+    }
+</style>
+  </head>
+  <body>
+    <div id="map"></div>
+    <!--The div element where the show/hide button appears -->
+    <!-- div id="hideButton">&#128065;</div -->
+    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/btnDepressed_CMS.png"></button>
+    <button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/btnDepressed_VDS.png"></button>
+    <div id="map" class = "wrapper"></div>
+    <!-- The div element for the popup dialog -->
+    <div id="dialog" style="display:none;">
+        <span class="close">&times;</span>
+        <br>
+        <div id="cms-info-label" style="font-family:monospace">CMS ID: xxx LOCATION: </div>
+        <br>
+        <div><pre>Proposed:                              Current:</pre></div>
+        <input id='cmsID' value="" type='hidden'/>
+        <div id="message-input">
+        <input id="msgcontent1" size="16" maxlength="16" type="text"/><br><br>
+        <input id="msgcontent2" size="16" maxlength="16"/><br><br>
+        <input id="msgcontent3" size="16" maxlength="16"/>
+        </div>        
+        <div id="buttonPanel"    style="display: block;">
+        <button onclick="handleSubmit();">Send >></button><br>
+        <button onclick="handleClear();">Clear >></button><br>
+        <button onclick="handleClose();">Close </button>
+        </div>
+        <div id="message-display"  style="display: block;">
+         <textarea readonly id="msgdisplay1" maxlength="16" rows="1" cols="16"></textarea>
+         <textarea readonly id="msgdisplay2" maxlength="16" rows="1" cols="16"></textarea>
+         <textarea readonly id="msgdisplay3" maxlength="16" rows="1" cols="16"></textarea>
+        </div>
+    </div>
+
+    <script>
+var centerPoint = {
+    lat: 33.693385,
+    lng: -117.798937
+};
+var map;
+var kMapStartupFile = "cmsStatusD12.json";
+var blueFlag = "images/icon_cmsBlue.png";
+var yellowFlag = "images/icon_cmsYellow.png";
+var messageList;
+var cms_info;
+var markerList = [];
+var cms_showing = true;
+var vds_showing = true;
+
+function initMap()
+{
+    map = new google.maps.Map(document.getElementById('map'),
+    {
+        center: centerPoint,
+        zoom: 11,
+        mapTypeControl: false,
+        streetViewControl: false
+    });
+    initButton();
+    getMessage(1); // load the current message file
+    setMarkers();
+}
+// Initialize the view/hide buttons 
+function initButton()
+{
+    var cmsBtnDiv = document.getElementById('cmsButton');
+    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cmsBtnDiv)
+    cmsBtnDiv.title = 'Click to toggle cms view';
+
+    // Setup the click event listeners to toggle icon display
+    cmsBtnDiv.addEventListener('click', function() {
+            cms_showing = !cms_showing;
+            // reveal or hide all the icons
+            for (var i = 0; i < markerList.length; i++)
+            {
+                markerList[i].setVisible(cms_showing);
+            }
+            // Determine which button image to show
+            if (cms_showing)
+            {
+                pic = "images/btnDepressed_CMS.png"
+            }
+            else
+            {
+                pic = "images/btnReady_CMS.png"
+            }
+            document.getElementById('cmsBtnImg').src=pic;
+    });
+    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 icons
+            alert("Not implemented yet")
+            // Determine which button image to show
+            if (vds_showing)
+            {
+                pic = "btnDepressed_VDS.png"
+            }
+            else
+            {
+                pic = "btnReady_VDS.png"
+            }
+            document.getElementById('vdsBtnImg').src=pic;
+    });
+}
+function setMarkers()
+{
+    var simpleImage = "";
+    loadcmsJSON(function(response)
+    {
+        // Parse JSON string into object
+        cms_info = JSON.parse(response);
+        console.log(cms_info.data[0].cms);
+        // Process each new marker 
+        for (var i = 0; i < cms_info.data.length; i++)
+        {
+            var cms = cms_info.data[i].cms;
+            var currLat = Number(cms.location.latitude);
+            var currLong = Number(cms.location.longitude);
+            // load a yellow flag if there's currently no message
+            if (messageList[i] == "||")
+                simpleImage = yellowFlag;
+            else
+                simpleImage = blueFlag;
+            var directionCode = cms.location.direction.charAt(0);
+            var locationInfo = directionCode + " " + cms.location
+                .route + " " + cms.location.postmile + " " + cms
+                .location.locationName
+            markerList[i] = new google.maps.Marker(
+            {
+                position:
+                {
+                    lat: currLat,
+                    lng: currLong
+                },
+                map: map,
+                icon: simpleImage,
+                title: "#"+i+" " +locationInfo,
+                cmsid: "" + i,
+                location: locationInfo
+            });
+            google.maps.event.addListener(markerList[i], 'click',
+                function()
+                {
+                    var dialog = document.getElementById('dialog');
+                    dialog.style.display = 'block';
+                    // fetch the sequential msg #
+                    cmsID = Number(this.cmsid);
+                    // Assign to the hidden field
+                    document.getElementById('cmsID').value = cmsID;
+                    getMessage(cmsID); // note: this is async
+                    document.getElementById('cms-info-label').innerHTML = "CMS ID: " +
+                        cmsID + "&nbsp;&nbsp;&nbsp;LOCATION: " + this.location;
+                    // clear input fields
+                    document.getElementById('msgcontent1').value = "";
+                    document.getElementById('msgcontent2').value = "";
+                    document.getElementById('msgcontent3').value = "";
+                    document.getElementById('msgcontent1').focus();
+                    var span = document.getElementsByClassName("close")[0]
+                    // When the user clicks on <span> (x), close the modal
+                    span.onclick = function() {
+                      handleClose();
+                    }
+                });
+        }
+    });
+}
+
+function loadcmsJSON(callback)
+{
+    var xobj = new XMLHttpRequest();
+    xobj.overrideMimeType("application/json");
+    xobj.open('GET', kMapStartupFile, true);
+    xobj.onreadystatechange = function()
+    {
+        if (xobj.readyState == 4 && xobj.status == "200")
+        {
+            callback(xobj.responseText);
+        }
+    };
+    // We want ajax to ignore any cached responses
+    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
+    xobj.send(null);
+}
+
+function handleSubmit()
+{
+    // recover the user's response
+    var response1 = document.getElementById('msgcontent1').value;
+    var response2 = document.getElementById('msgcontent2').value;
+    var response3 = document.getElementById('msgcontent3').value;
+    var newMsg = response1+response2+response3;
+    if (newMsg.length == 0)
+    {
+        alert("Nothing to Send ... Proposed is empty.");
+    }
+    else
+    {
+        document.getElementById('msgdisplay1').value = response1;
+        document.getElementById('msgdisplay2').value = response2;
+        document.getElementById('msgdisplay3').value = response3;
+        saveMessage(response1 + "|" + response2 + "|" + response3);
+    }
+}
+
+function handleClose()
+{
+    // hide the display
+    document.getElementById('dialog').style.display = 'none'
+}
+
+function handleClear()
+{
+    document.getElementById('msgdisplay1').value = "";
+    document.getElementById('msgdisplay2').value = "";
+    document.getElementById('msgdisplay3').value = "";
+    saveMessage("||");
+}
+
+function loadJSON(inFile, callback)
+{
+    var xobj = new XMLHttpRequest();
+    xobj.overrideMimeType("application/json");
+    xobj.open('GET', inFile, true);
+    xobj.onreadystatechange = function()
+    {
+        if (xobj.readyState == 4 && xobj.status == "200")
+        {
+            callback(xobj.responseText);
+        }
+    };
+    // We want ajax to ignore any cached responses
+    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
+    xobj.send(null);
+}
+// retrieve the current cms message file
+function getMessage(cmsID)
+{
+    loadJSON("http://localhost:8080/messagefile.txt", function(response)
+    {
+        // Parse JSON string into object
+        messageList = JSON.parse(response);
+        // select a message from json for the given cmsID
+        console.log("get by cmsID=" + cmsID);
+        var cmsSign = document.getElementById('msgdisplay1');
+        messageparts = messageList[cmsID].split("|");
+        cmsSign.value = messageparts[0];
+        document.getElementById('msgdisplay2').value = messageparts[1];
+        document.getElementById('msgdisplay3').value = messageparts[2];
+    });
+}
+// Save an updated cms message to the file
+// NB: cms id's are one-based, json array is zero-based.
+function saveMessage(outMessage, cmsID)
+{
+    var cmsID = document.getElementById('cmsID').value;
+    console.log("Saving " + outMessage + " for cmsID " + cmsID)
+    messageList[cmsID] = outMessage;
+    // Change icon if something was saved
+    if (outMessage == "||")
+        markerList[cmsID].setIcon(yellowFlag);
+    else
+        markerList[cmsID].setIcon(blueFlag);
+
+    var xhttp = new XMLHttpRequest();
+    xhttp.open("GET", "http://localhost:8080/cgi-bin/saveMessage.py?msg=" + JSON
+        .stringify(messageList), true);
+    xhttp.send();
+    // Using POST might be a better idea ... haven't tried this yet
+    //      var xhr = new XMLHttpRequest();
+    //      xhr.open("POST", "/cgi-bin/saveMessage.py?", true);
+    //      xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
+    // send the collected data as JSON
+    //      xhr.send(JSON.stringify(messageList));
+}    </script>
+    <script async defer
+    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD6iTyN0DjP-9OVkAgicyp4tkC10naE_B8&callback=initMap">
+    </script>
+  </body>
+</html>
Index: trunk/webapps/cptms.html
===================================================================
--- trunk/webapps/cptms.html	(revision 320)
+++ trunk/webapps/cptms.html	(revision 320)
@@ -0,0 +1,908 @@
+<!DOCTYPE html>
+<html>
+  <head>
+<!-- Launch with  python -m CGIHTTPServer 80  -->
+<!-- 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>CPTMS Map v0.6.2</title> 
+    <style>
+        @font-face {
+          font-family: Scoreboard;
+          src: url('scoreboard.ttf');
+        }
+      /* Set the size of the div element that contains the map */
+      #mapdiv {
+        height: 100%;
+        width: 100%;  
+       }
+        /* Makes the page fill the window. */
+      html, body {
+        height: 100%;
+        margin: 0;
+        padding: 0;
+      }
+        textarea {
+           height: 33px;
+           width: 272px;
+           resize: none;
+           font-family: Scoreboard;
+           font-size: xx-large;
+           background-color: #2F4F4F;
+           color: yellow;
+        }
+       input {
+           border: thin solid #333;
+           padding: 2px;
+           font-family: "Lucida Console", Monaco, monospace;
+           font-size: medium;
+        }
+      #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;
+        background-color: #fff;
+        margin-right: 7px;
+        border: thick solid white;
+      }
+      #cms-info-label {
+           height: 20px;
+           width: 590px;
+           overflow: hidden;
+           background-color: #A8C5FF;  /*#ECECFB; */
+           border: thin solid #BDBDBD;
+           padding: 5px;
+       }
+      #message-display {
+           height: 172px;
+           width: 300px;
+           overflow: hidden;
+           float: left;
+       }
+      #message-input {
+           height: 122px;
+           width: 165px;
+           background-color: #729FFF;
+           float: left;
+       }
+       #buttonPanel {
+           height: 122px;
+           width: 130px;
+           background-color: #729FFF;
+           border-left: none;
+           float: left;
+           padding: 20px;
+        }
+       .wrapper {
+           position: relative;\
+        }
+       #dialog {
+          position: absolute;
+          top: 10%;
+          right: 20%;
+          background-color: #729FFF; /* #ECECFB; */
+          margin: auto;
+          padding: 20px;
+          border: 1px solid #888;
+          width: 680px;
+          display: none;           
+        }
+      .unstyled-button {
+        border: 0 none;
+        padding: 0;
+        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;
+    }
+
+    </style>
+  </head>
+  <body>
+    <!-- 
+         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 text area input for the Search Box -->
+    <input id="search-input" class="controls" type="text" placeholder="Search Box">
+    <!--The div element where the map appears -->
+    <div id="mapdiv"></div>
+    <!-- The div element for the popup dialog -->
+    <div id="dialog" style="display:none;">
+        <span class="close">&#x2612;</span>  <!-- close button symbol -->
+        <br>
+        <div id="cms-info-label" style="font-family:'Courier New'">CMS ID: xxx LOCATION: </div>
+        <br>
+        <input id='cmsID' value="" type='hidden'/>
+        <div id="message-input">Proposed:
+        <input id="msgcontent1"  maxlength="16" type="text"/><br><br>
+        <input id="msgcontent2"  maxlength="16" type="text"/><br><br>
+        <input id="msgcontent3"  maxlength="16" type="text"/>
+        </div>        
+        <div id="buttonPanel"    style="display: block;">
+        <button onclick="handleCMSsubmit();">Send >></button><br>
+        <button onclick="handleCMSclear();">Clear >></button><br>
+        <button onclick="handleDialogClose();">Close </button>
+        </div>
+        <div id="message-display"  style="display: block;">Current:
+         <textarea readonly id="msgdisplay1" maxlength="16" rows="1" cols="16"></textarea>
+         <textarea readonly id="msgdisplay2" maxlength="16" rows="1" cols="16"></textarea>
+         <textarea readonly id="msgdisplay3" maxlength="16" rows="1" cols="16"></textarea>
+        </div>
+    </div>
+    <!--The div elements where the buttons appear  -->
+    <div id="ctrButton"><img width="30" src="images/CPTMSImages/btn_mapcenter.png"</div>
+    <button id="cctvButton" class="unstyled-button"><img id="cctvBtnImg" src="images/CPTMSImages/btnReady_CCTV.png"></button>
+    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/CPTMSImages/btnReady_CMS.png"></button>
+    <button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/CPTMSImages/btnDepressed_VDS.png"></button>
+
+    <script>
+//TODO:  
+// Add phase 2 to messages.
+// cms set visible gets undefined error after last icon is processed.
+
+    // a global variable for the google map
+    var map;
+    // a global dictionary to lookup a station's original coordinates
+    var vds_coords = {};
+    // a global variable to hold locations of marked search places
+    var placePins = [];
+    // Constant name of dynamic json data file created by CADserver
+    var kMapPointsFile = "highways.json";
+    // Constant name of initial (static) highways file used once at startup
+    var kMapStartupFile = "highways_startup.json";
+    // Constant for map center location: The John Wayne Airport
+    //var centerPoint = {lat: 33.687228, lng: -117.872148};
+    // Constant for map center location in District 12
+    var centerPoint = {
+        lat: 33.693385,
+        lng: -117.798937
+    };
+    // Initial map zoom
+    var initZoom = 11;
+    // Dot colors used in traffic model to indicate free-flowing, slowed, and stopped traffic
+    // and their associated zvalues so slower traffic dots are more visible.
+    // white means a disabled spot
+    var colorZvalues = {
+        "white": 5,
+        "lime": 10,
+        "yellow": 20,
+        "red": 30
+    };
+    var kCMSstartupFile = "cmsStatusD12.json";
+    var kCCTVfile = "cctv_locations_D12.json";
+    var blueFlag = "images/CPTMSImages/icon_cmsBlue.png";
+    var yellowFlag = "images/CPTMSImages/icon_cmsYellow.png";
+    var cctvIcon = "images/CPTMSImages/icon_cctvCyan.png";
+    var cctvIconWhite = "images/CPTMSImages/icon_cctvWhite.png";
+    var vdsIconGreen = "images/CPTMSImages/circle-green.png"
+    var vdsIconYellow = "images/CPTMSImages/circle-yellow.png"
+    var vdsIconRed = "images/CPTMSImages/circle-red.png"
+    var cms_info;
+    var messageDict = {};
+    var cms_showing = false;
+    var vds_showing = true;
+    var cctv_showing = false;
+    var cctv_infowindow; // We create just a single instance of info window.
+
+    // Build a solid colored icon to use instead of the classic pin
+    // Use a diamond on N and E directions, circle on S and W directions
+    function dotSymbol(color) //,direction)
+    {
+//        var circle = google.maps.SymbolPath.CIRCLE;
+//        var diamond = 'M -1,0 0,-1 1,0 0,1 z';
+//        var myShape = circle;
+        var iconPath = vdsIconGreen;
+        if (color == 'red')
+        {
+           iconPath = vdsIconRed;
+        }
+        else if (color == 'yellow')
+        {
+            iconPath = vdsIconYellow;
+        }
+        return {
+//            path: iconPath,
+//            icon: 
+//                    {
+                        url: iconPath, 
+                        anchor: new google.maps.Point(6, 6)
+//                    };
+//            anchor: new google.maps.Point(6, 6),
+//            scale: 5,
+//            strokeColor: "black", // the border color
+//            strokeWeight: 1, // the border thickness
+//            fillColor: color,
+//            fillOpacity: 1.0
+        };
+    }
+
+    // Load the map data from a json file and style all the points
+    function loadVDSlayer()
+    {
+        // Load the static map data and call saveCoords when done
+        map.data.loadGeoJson(kMapStartupFile, null, saveCoords)
+//        var d = new Date();
+//        var start = d.getTime();
+        // 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,
+/*                    icon: 
+                    {
+                        url: vdsIconGreen, 
+                        anchor: new google.maps.Point(6, 6)
+                    }, */
+                title: name + " @" + street, // set rollover text
+                // set zIndex for slowed traffic to a higher value so they overlap
+                zIndex: colorZvalues[ptColor]
+            };
+        });
+    }
+    // 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]);
+        }
+    }
+
+    // Load the dynamic json file for highways, etc.
+    // Ref: https://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript
+    function loadJSON(inFile, callback)
+    {
+        var xobj = new XMLHttpRequest();
+        xobj.overrideMimeType("application/json");
+        xobj.open('GET', inFile, true);
+        xobj.onreadystatechange = function()
+        {
+            if (xobj.readyState == 4 && xobj.status == "200")
+            {
+                callback(xobj.responseText);
+            }
+        };
+        // We want ajax to ignore any cached responses
+        xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT')
+        xobj.send(null);
+    }
+    // Load the highways dynamic json file and update the map
+    function updateVDSlayer()
+    {
+        var parsed_JSON;
+        loadJSON(kMapPointsFile, 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);
+        });
+    }
+
+    // Initialize the center button (to re-center the map)
+    function initCenter()
+    {
+        var centerBtnDiv = document.getElementById('ctrButton');
+        map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(centerBtnDiv)
+        centerBtnDiv.title = 'Click to recenter the map';
+
+        // Setup the click event listeners: reset center location and zoom factor
+        centerBtnDiv.addEventListener('click', function()
+        {
+            map.setCenter(centerPoint);
+            map.setZoom(initZoom);
+            clearPlacePins();
+        });
+    }
+
+    // Initialize the search box and listener 
+    function initSearch()
+    {
+        // Create the search box and link it to the UI element.
+        var input = document.getElementById('search-input');
+        var searchBox = new google.maps.places.SearchBox(input);
+        map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
+
+        // Bias the SearchBox results towards current map's viewport.
+        map.addListener('bounds_changed', function()
+        {
+            searchBox.setBounds(map.getBounds());
+        });
+
+        // Listen for the event fired when the user selects a prediction and retrieve
+        // more details for that place.
+        searchBox.addListener('places_changed', function()
+        {
+            var places = searchBox.getPlaces();
+
+            if (places.length == 0)
+            {
+                return;
+            }
+
+            clearPlacePins();
+
+            // Create a bounding region to include the search result places
+            var bounds = new google.maps.LatLngBounds();
+            // For each place, get the icon, name and location.
+            // There may be multiple search results
+            places.forEach(function(place)
+            {
+                if (!place.geometry)
+                {
+                    console.log("Returned place contains no geometry");
+                    return;
+                }
+
+                // Create a marker for each place.
+                placeMarker = new google.maps.Marker(
+                {
+                    map: map,
+                    title: place.name,
+                    position: place.geometry.location
+                })
+
+                // Click on the marker to remove it from the display
+                placeMarker.addListener('click', function()
+                {
+                    placeMarker.setMap(null);
+                });
+
+                // Add this marker to the collection of current markers 
+                placePins.push(placeMarker);
+
+                // Create a bounding region to include this place
+                if (place.geometry.viewport)
+                {
+                    // Only geocodes have viewport.
+                    bounds.union(place.geometry.viewport);
+                }
+                else
+                {
+                    bounds.extend(place.geometry.location);
+                }
+            });
+            // This will pan and zoom to the area around the marker
+            //map.fitBounds(bounds);
+            // This will center the map on the new marker(s) but not zoom
+            map.setCenter(bounds.getCenter());
+        });
+    }
+
+    // Remove any place pins from a previous search
+    function clearPlacePins()
+    {
+        placePins.forEach(function(marker)
+        {
+            marker.setMap(null);
+        });
+        placePins = [];
+    }
+    // Initialize the view/hide buttons 
+    function initLayerButtons()
+    {
+        var cctvBtnDiv = document.getElementById('cctvButton');
+        map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cctvBtnDiv)
+        cctvBtnDiv.title = 'Click to toggle cctv view';
+        // Setup the click event listeners to toggle icon display
+        cctvBtnDiv.addEventListener('click', function()
+        {
+            cctv_showing = !cctv_showing;
+            // reveal or hide all the icons
+            cctvLayer.forEach(function(feature)
+            {
+                cctvLayer.overrideStyle(feature,
+                {
+                    visible: cctv_showing
+                });
+            });
+            // Determine which button image to show
+            if (cctv_showing)
+            {
+                pic = "images/CPTMSImages/btnDepressed_CCTV.png"
+            }
+            else
+            {
+                pic = "images/CPTMSImages/btnReady_CCTV.png"
+            }
+            document.getElementById('cctvBtnImg').src = pic;
+        });
+
+        var cmsBtnDiv = document.getElementById('cmsButton');
+        map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cmsBtnDiv)
+        cmsBtnDiv.title = 'Click to toggle cms view';
+        // Setup the click event listeners to toggle icon display
+        cmsBtnDiv.addEventListener('click', function()
+        {
+            cms_showing = !cms_showing;
+            // Determine which button image to show
+            if (cms_showing)
+            {
+                pic = "images/CPTMSImages/btnDepressed_CMS.png"
+                // It's nice when icons become visible that the messages have been refreshed.
+                loadAllMessages();
+            }
+            else
+            {
+                pic = "images/CPTMSImages/btnReady_CMS.png"
+            }
+            document.getElementById('cmsBtnImg').src = pic;
+            // reveal or hide all the icons
+            cmsLayer.forEach(function(feature)
+            {
+                cmsLayer.overrideStyle(feature,
+                {
+                    visible: cms_showing
+                });
+            });
+        });
+
+        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/CPTMSImages/btnDepressed_VDS.png"
+            }
+            else
+            {
+                pic = "images/CPTMSImages/btnReady_VDS.png"
+            }
+            document.getElementById('vdsBtnImg').src = pic;
+        });
+    }
+
+function loadCMSlayer()
+{
+    cmsLayer = new google.maps.Data();
+    cmsLayer.setMap(map);
+    cmsLayer.loadGeoJson("cms_locations_D12.gjson");
+    cmsLayer.setStyle(function(feature)
+    {
+        // return the StyleOptions
+        return {
+            icon: yellowFlag,
+            title: feature.getId()+ " " +feature.getProperty("location"),
+            visible: false
+        };
+    });
+    
+    cmsLayer.addListener('click', function(event)
+    {
+        var dialog = document.getElementById('dialog');
+        // Note: If the dialog is already being displayed when someone else
+        // updates the message, it won't be reflected in the dialog, until
+        // you close and reopen it.
+        dialog.style.display = 'block';
+        cmsID = event.feature.getId();
+        // Assign to the hidden field
+        document.getElementById('cmsID').value = cmsID;
+        showMessage(cmsID); // note: this is async
+        document.getElementById('cms-info-label').innerHTML = "CMS ID: " +
+            cmsID + "&nbsp;&nbsp;&nbsp;LOCATION: " + event.feature.getProperty("location");
+        // clear input fields
+        document.getElementById('msgcontent1').value = "";
+        document.getElementById('msgcontent2').value = "";
+        document.getElementById('msgcontent3').value = "";
+        document.getElementById('msgcontent1').focus();
+        var span = document.getElementsByClassName("close")[0]
+            // When the user clicks on <span> (x), close the modal
+        span.onclick = function()
+        {
+            handleDialogClose();
+        }
+    });
+}
+function makecctvIcon(nearVDS)
+{
+    var imgIcon = cctvIcon
+    if ((typeof map.data.getFeatureById(nearVDS)) == "undefined")
+    {
+        imgIcon = cctvIconWhite;
+    }
+    return imgIcon
+}
+function loadCCTVlayer()
+{
+    var imgTag = '<IMG WIDTH="700" SRC="images/CPTMSImages/';
+    cctv_infowindow = new google.maps.InfoWindow();
+    cctvLayer = new google.maps.Data();
+    cctvLayer.loadGeoJson("cctv_locations_D12.gjson");
+    cctvLayer.setStyle(function(feature)
+    {
+        // return the StyleOptions
+        return {
+            icon: makecctvIcon(feature.getProperty("nearVDS")),
+            title: feature.getId() + " " +feature.getProperty('locationName'),
+            visible: false  
+        };
+    });
+    cctvLayer.addListener('click', function(event)
+    {
+        //console.log("cctv layer was clicked at " + event.feature.getId());
+        cctvIndex = event.feature.getId();
+        //console.log(this.title + " is looking for " + this.nearVDS);
+        nearVDS = map.data.getFeatureById(event.feature.getProperty("nearVDS"));
+        currentColor = nearVDS.getProperty("color");
+        var imgDir = "CCTVFast/";
+        if (currentColor == "red" || currentColor == "yellow")
+        {
+            imgDir = "CCTVSlow/"
+        }
+
+        cctv_infowindow.setContent('<div style="font-weight:bold;font-family: monospace">' +  nearVDS.getId() + "&nbsp;" + currentColor + "<BR>" + imgTag + imgDir + cctvIndex + '.jpg">' + "</div>");
+        cctv_infowindow.setPosition(event.feature.getGeometry().get());
+        cctv_infowindow.open(map);
+
+    });
+    cctvLayer.setMap(map);
+}
+
+    // Center justify message text in a 16 column field
+    function justifyCMStext(message)
+    {
+        var kBlanks = "                ";
+        var padLen = (16 - message.length) / 2;
+        var padding = kBlanks.substring(0, padLen);
+        return padding + message;
+    }
+
+    function handleCMSsubmit()
+    {
+        // recover the user's response
+        var response1 = justifyCMStext(document.getElementById('msgcontent1').value.trim());
+        var response2 = justifyCMStext(document.getElementById('msgcontent2').value.trim());
+        var response3 = justifyCMStext(document.getElementById('msgcontent3').value.trim());
+        var newMsg = response1 + response2 + response3;
+        if (newMsg.length == 0)
+        {
+            alert("Nothing to Send ... Proposed is empty.");
+        }
+        else
+        {
+            document.getElementById('msgdisplay1').value = response1;
+            document.getElementById('msgdisplay2').value = response2;
+            document.getElementById('msgdisplay3').value = response3;
+            saveMessage(response1 + "|" + response2 + "|" + response3);
+        }
+    }
+
+    function handleDialogClose()
+    {
+        // hide the display
+        document.getElementById('dialog').style.display = 'none'
+    }
+
+    function handleCMSclear()
+    {
+        document.getElementById('msgdisplay1').value = "";
+        document.getElementById('msgdisplay2').value = "";
+        document.getElementById('msgdisplay3').value = "";
+        saveMessage("||");
+    }
+    // retrieve the current cms message file
+    function showMessage(cmsID)
+    {
+        loadAllMessages();  // because someone else may have made a recent update
+        // lookup the message for this cms ID
+        var message = messageDict[cmsID].cms.message;
+        // show the message in the display
+        document.getElementById('msgdisplay1').value = message.phase1.Line1;
+        document.getElementById('msgdisplay2').value = message.phase1.Line2;
+        document.getElementById('msgdisplay3').value = message.phase1.Line3;
+    }
+    function loadAllMessages()
+    {
+        loadJSON("cms_messages.json", function(response)
+        {
+            // Parse JSON string into object
+            messagejson = JSON.parse(response);
+            // Add each message to a lookup dictionary 
+            for (var i = 0; i < messagejson.data.length; i++)
+            {
+                var item = messagejson.data[i];
+                messageDict[item.cms.index] = item;
+                // Set the appropriate icon on the cms icon
+                // set a yellow flag if there's currently no message
+                if (item.cms.message.phase1.Line1 + 
+                    item.cms.message.phase1.Line2 +
+                    item.cms.message.phase1.Line3 == "")
+                {
+                    cmsLayer.overrideStyle(cmsLayer.getFeatureById(item.cms.index), {icon: yellowFlag})
+                }
+                else
+                {
+                    cmsLayer.overrideStyle(cmsLayer.getFeatureById(item.cms.index), {icon: blueFlag})
+                }
+            }
+        });
+    }
+
+    // Save an updated cms message to the file
+    function saveMessage(outMessage)
+    {
+        // Fetch cmsID from hidden field where it was put when dialog opened.
+        var cmsID = document.getElementById('cmsID').value;
+        //console.log("Saving " + outMessage + " for cmsID " + cmsID)
+        msgParts = outMessage.split("|");
+        messageDict[cmsID].cms.message.phase1.Line1 = msgParts[0];
+        messageDict[cmsID].cms.message.phase1.Line2 = msgParts[1];
+        messageDict[cmsID].cms.message.phase1.Line3 = msgParts[2];
+        // Set icon to reflect message state
+        if (outMessage == "||")
+        {
+            currentIcon = {icon: yellowFlag};
+        }
+        else
+        {
+            currentIcon = {icon: blueFlag};
+        }
+        cmsLayer.overrideStyle(cmsLayer.getFeatureById(cmsID), currentIcon)
+        outString = "{\n\t\"data\":\n\t\t" + JSON.stringify(Object.values(messageDict)) + "}";
+
+        var xhttp = new XMLHttpRequest();
+        xhttp.open("GET", "cgi-bin/saveMessage.py?msg=" + outString, true);
+        xhttp.send();
+        // Using POST might be a better idea ... haven't tried this yet
+        //      var xhr = new XMLHttpRequest();
+        //      xhr.open("POST", "/cgi-bin/saveMessage.py?", true);
+        //      xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
+        // send the collected data as JSON
+        //      xhr.send(JSON.stringify(messageList));
+    }
+
+    // Initialize the map and load the points
+    function initMap()
+    {
+        // Declare the map and where it belongs on the page
+        map = new google.maps.Map(document.getElementById('mapdiv'),
+        {
+            zoom: initZoom,
+            center: centerPoint,
+            styles: night_mode,
+            mapTypeControl: false,
+            streetViewControl: false
+        });
+        loadVDSlayer(); // go load the map data
+        // setup the search box and center button
+        initSearch();
+        initCenter();
+
+loadCMSlayer();
+
+loadCCTVlayer();
+
+        initLayerButtons();
+
+        // Start a timer to refresh the vds dots every 10 seconds
+        var myTimer = setInterval(updateVDSlayer, 10000);
+        // start an interval timer to refresh the cms icons every 10 seconds
+        var cmsTimer = setInterval(loadAllMessages, 10000);
+        // Listen for zoom changes and move the placePins so as to keep a nice
+        // visual distance between them appropriate to the zoom factor
+        map.addListener('zoom_changed', function()
+        {
+            // fetch how much the map is currently zoomed
+            currentZoom = map.getZoom();
+            // only bother adjusting within this range
+            if ((currentZoom < 16) && (currentZoom > 10))
+            {
+                // magic formula controls distance between dots
+                adjustCoords(calcDistanceFactor());
+            }
+        });
+
+    }
+    // Styles array for Night Mode map
+    // Ref: https://developers.google.com/maps/documentation/javascript/styling
+    var night_mode = [
+                {elementType: 'geometry', stylers: [{color: '#242f3e'}]},
+                {elementType: 'labels.text.stroke', stylers: [{color: '#242f3e'}]},
+                {elementType: 'labels.text.fill', stylers: [{color: '#746855'}]},
+                {
+                  featureType: 'administrative.locality',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#d59563'}]
+                },
+                {
+                  featureType: 'poi',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#d59563'}]
+                },
+                {
+                  featureType: 'poi.park',
+                  elementType: 'geometry',
+                  stylers: [{color: '#263c3f'}]
+                },
+                {
+                  featureType: 'poi.park',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#6b9a76'}]
+                },
+                {
+                  featureType: 'road',
+                  elementType: 'geometry',
+                  stylers: [{color: '#38414e'}]
+                },
+                {
+                  featureType: 'road',
+                  elementType: 'geometry.stroke',
+                  stylers: [{color: '#212a37'}]
+                },
+                {
+                  featureType: 'road',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#9ca5b3'}]
+                },
+                {
+                  featureType: 'road.highway',
+                  elementType: 'geometry',
+                  stylers: [{color: '#746855'}]
+                },
+                {
+                  featureType: 'road.highway',
+                  elementType: 'geometry.stroke',
+                  stylers: [{color: '#1f2835'}]
+                },
+                {
+                  featureType: 'road.highway',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#f3d19c'}]
+                },
+                {
+                  featureType: 'transit',
+                  elementType: 'geometry',
+                  stylers: [{color: '#2f3948'}]
+                },
+                {
+                  featureType: 'transit.station',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#d59563'}]
+                },
+                {
+                  featureType: 'water',
+                  elementType: 'geometry',
+                  stylers: [{color: '#17263c'}]
+                },
+                {
+                  featureType: 'water',
+                  elementType: 'labels.text.fill',
+                  stylers: [{color: '#515c6d'}]
+                },
+                {
+                  featureType: 'water',
+                  elementType: 'labels.text.stroke',
+                  stylers: [{color: '#17263c'}]
+                }
+              ]
+
+    // Using John's API Key
+    </script>
+    <script async defer
+    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD6iTyN0DjP-9OVkAgicyp4tkC10naE_B8&libraries=places&callback=initMap">
+    </script>
+  </body>
+</html>
Index: trunk/webapps/cms_messages.json
===================================================================
--- trunk/webapps/cms_messages.json	(revision 320)
+++ trunk/webapps/cms_messages.json	(revision 320)
@@ -0,0 +1,1 @@
+{"data":[{"cms":{"index":"1200022","message":{"displayTime":"","phase1":{"Line1":"   Near Vista","Line2":"    Hermosa","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200023","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200024","message":{"displayTime":"","phase1":{"Line1":"bottom of fifth","Line2":"dodgers up by 2","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200025","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200026","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200027","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200028","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200029","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200030","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200031","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200032","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200033","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200034","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200035","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200036","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200037","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200038","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200039","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200040","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200041","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200042","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200043","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200044","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200045","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200046","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200047","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200048","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200049","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200050","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200051","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200052","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200053","message":{"displayTime":"","phase1":{"Line1":"  slow for the","Line2":"   cone zone","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200055","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200056","message":{"displayTime":"","phase1":{"Line1":"    caution","Line2":"  slow traffic","Line3":"     ahead"},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200057","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1200058","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1208488","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211184","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211185","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211967","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1211978","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212138","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212822","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1212823","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214503","message":{"displayTime":"","phase1":{"Line1":" You're heading","Line2":"     south.","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214504","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214505","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214506","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214507","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214508","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214509","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214510","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214511","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214512","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214513","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214514","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1214956","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1217542","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218442","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218482","message":{"displayTime":"","phase1":{"Line1":"  San Clemente","Line2":"   Next Exit","Line3":"        "},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218483","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218484","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218485","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}},{"cms":{"index":"1218486","message":{"displayTime":"","phase1":{"Line1":"","Line2":"","Line3":""},"phase2":{"Line1":"","Line2":"","Line3":""}}}}]}
Index: trunk/webapps/highways.json
===================================================================
--- trunk/webapps/highways.json	(revision 315)
+++ 	(revision )
@@ -1,2727 +1,0 @@
-{
-  "type": "FeatureCollection",
-  "features": [
-{
-   "type": "Feature",
-   "id": "405 S 0.77",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.744091,33.647015]
-       },
-   "properties": 
-       {"street": "IRVINE C1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 0.93",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.746598,33.64809]
-       },
-   "properties": 
-       {"street": "IRVINE C1", "color": "lime", "perpx": "0.282096", "perpy": "0.959386"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 0.96",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.747203,33.64795]
-       },
-   "properties": 
-       {"street": "IRVINE C2", "color": "lime", "perpx": "-0.287743", "perpy": "-0.957708"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 1.11",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.74955,33.648958]
-       },
-   "properties": 
-       {"street": "IRVINE C2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 1.57",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.757205,33.650789]
-       },
-   "properties": 
-       {"street": "N OF 133", "color": "lime", "perpx": "-0.197097", "perpy": "-0.980384"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 1.57",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.757101,33.651141]
-       },
-   "properties": 
-       {"street": "N OF 133", "color": "lime", "perpx": "0.202053", "perpy": "0.979375"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 1.93",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.763315,33.651837]
-       },
-   "properties": 
-       {"street": "S OF 133", "color": "lime", "perpx": "-0.209415", "perpy": "-0.977827"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 1.93",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.763194,33.652204]
-       },
-   "properties": 
-       {"street": "S OF 133", "color": "lime", "perpx": "0.206915", "perpy": "0.978359"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 2.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.770173,33.65368]
-       },
-   "properties": 
-       {"street": "LAGUNA CANYON RD", "color": "lime", "perpx": "0.206915", "perpy": "0.978359"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 2.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.770361,33.653346]
-       },
-   "properties": 
-       {"street": "LAGUNA CANYON RD", "color": "lime", "perpx": "-0.209415", "perpy": "-0.977827"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 2.88",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.778085,33.657534]
-       },
-   "properties": 
-       {"street": "SAND CANYON", "color": "lime", "perpx": "-0.484045", "perpy": "-0.875043"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 3.04",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.780107,33.659163]
-       },
-   "properties": 
-       {"street": "SAND CANYON", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 3.31",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.784046,33.661319]
-       },
-   "properties": 
-       {"street": "N OF SAND CANYON", "color": "lime", "perpx": "0.480131", "perpy": "0.877197"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 3.31",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.784273,33.660957]
-       },
-   "properties": 
-       {"street": "N OF SAND CANYON", "color": "lime", "perpx": "-0.484045", "perpy": "-0.875043"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 3.84",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.793047,33.66293]
-       },
-   "properties": 
-       {"street": "JEFFREY 1", "color": "lime", "perpx": "-0.144931", "perpy": "-0.989442"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 3.86",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.793258,33.663379]
-       },
-   "properties": 
-       {"street": "JEFFREY 1", "color": "lime", "perpx": "0.142134", "perpy": "0.989847"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 4.03",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.796283,33.663404]
-       },
-   "properties": 
-       {"street": "JEFFREY 2", "color": "lime", "perpx": "-0.144931", "perpy": "-0.989442"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 4.03",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.796176,33.663798]
-       },
-   "properties": 
-       {"street": "JEFFREY 2", "color": "lime", "perpx": "0.142134", "perpy": "0.989847"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 5.01",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.81298,33.666093]
-       },
-   "properties": 
-       {"street": "YALE", "color": "lime", "perpx": "-0.29192", "perpy": "-0.956443"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 5.01",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.812902,33.666407]
-       },
-   "properties": 
-       {"street": "YALE", "color": "lime", "perpx": "0.267568", "perpy": "0.963539"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 5.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.813632,33.666292]
-       },
-   "properties": 
-       {"street": "SPRUCE", "color": "lime", "perpx": "-0.29192", "perpy": "-0.956443"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 5.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.813561,33.66659]
-       },
-   "properties": 
-       {"street": "SPRUCE", "color": "lime", "perpx": "0.267568", "perpy": "0.963539"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 5.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.820882,33.668738]
-       },
-   "properties": 
-       {"street": "CULVER 1", "color": "lime", "perpx": "-0.30889", "perpy": "-0.951098"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 5.55",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.821657,33.669218]
-       },
-   "properties": 
-       {"street": "CULVER 1", "color": "lime", "perpx": "0.332642", "perpy": "0.943053"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 5.69",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.823958,33.669737]
-       },
-   "properties": 
-       {"street": "CULVER 2", "color": "lime", "perpx": "-0.30889", "perpy": "-0.951098"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 5.74",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.824699,33.670291]
-       },
-   "properties": 
-       {"street": "CULVER 2", "color": "lime", "perpx": "0.320278", "perpy": "0.947323"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 6.21",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.832329,33.672571]
-       },
-   "properties": 
-       {"street": "HARVARD", "color": "lime", "perpx": "-0.314462", "perpy": "-0.94927"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 6.21",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.832271,33.672851]
-       },
-   "properties": 
-       {"street": "HARVARD", "color": "lime", "perpx": "0.320278", "perpy": "0.947323"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 6.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.84179,33.675863]
-       },
-   "properties": 
-       {"street": "JAMBOREE1", "color": "lime", "perpx": "-0.402558", "perpy": "-0.915394"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 6.85",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.842488,33.676465]
-       },
-   "properties": 
-       {"street": "JAMBOREE1", "color": "lime", "perpx": "0.400805", "perpy": "0.916164"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 7.01",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.845019,33.677283]
-       },
-   "properties": 
-       {"street": "JAMBOREE2", "color": "lime", "perpx": "-0.402558", "perpy": "-0.915394"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 7.07",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.845871,33.677945]
-       },
-   "properties": 
-       {"street": "JAMBOREE2", "color": "lime", "perpx": "0.400805", "perpy": "0.916164"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 7.69",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.855449,33.681922]
-       },
-   "properties": 
-       {"street": "MACARTHUR1", "color": "lime", "perpx": "-0.399707", "perpy": "-0.916643"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 7.73",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.85598,33.682442]
-       },
-   "properties": 
-       {"street": "MACARTHUR 1", "color": "lime", "perpx": "0.408917", "perpy": "0.912572"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 8.26",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.86423,33.685751]
-       },
-   "properties": 
-       {"street": "AIRPORT", "color": "lime", "perpx": "-0.358185", "perpy": "-0.933651"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 8.26",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.864081,33.686072]
-       },
-   "properties": 
-       {"street": "AIRPORT", "color": "lime", "perpx": "0.321527", "perpy": "0.9469"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 8.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.866474,33.686517]
-       },
-   "properties": 
-       {"street": "RED HILL", "color": "lime", "perpx": "-0.259554", "perpy": "-0.965729"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 8.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.866348,33.686795]
-       },
-   "properties": 
-       {"street": "RED HILL", "color": "lime", "perpx": "0.126754", "perpy": "0.991934"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 8.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.875063,33.687245]
-       },
-   "properties": 
-       {"street": "N OF 55", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 9.46",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.884653,33.687523]
-       },
-   "properties": 
-       {"street": "BRISTOL 1", "color": "lime", "perpx": "0.0", "perpy": "1.0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 9.54",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.88618,33.687251]
-       },
-   "properties": 
-       {"street": "BRISTOL 1", "color": "lime", "perpx": "-0.013748", "perpy": "-0.999905"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 9.65",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.887956,33.687523]
-       },
-   "properties": 
-       {"street": "BRISTOL 2", "color": "lime", "perpx": "0.0", "perpy": "1.0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 10.28",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.899035,33.68748]
-       },
-   "properties": 
-       {"street": "FAIRVIEW", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 10.48",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.902507,33.687582]
-       },
-   "properties": 
-       {"street": "N OF 73", "color": "lime", "perpx": "-0.028158", "perpy": "-0.999603"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 10.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.909664,33.688017]
-       },
-   "properties": 
-       {"street": "FAIRVIEW", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 11.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.915002,33.687942]
-       },
-   "properties": 
-       {"street": "HARBOR 1", "color": "lime", "perpx": "-0.248611", "perpy": "-0.968603"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 11.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.918196,33.688872]
-       },
-   "properties": 
-       {"street": "HARBOR 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 11.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.91995,33.689212]
-       },
-   "properties": 
-       {"street": "HARBOR 2", "color": "lime", "perpx": "-0.364549", "perpy": "-0.931184"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 12.16",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.930222,33.693448]
-       },
-   "properties": 
-       {"street": "HAMPSHIRE", "color": "lime", "perpx": "-0.385484", "perpy": "-0.922714"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 12.16",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.930032,33.693692]
-       },
-   "properties": 
-       {"street": "HAMPSHIRE", "color": "lime", "perpx": "0.384478", "perpy": "0.923134"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 12.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.9355,33.695653]
-       },
-   "properties": 
-       {"street": "EUCLID", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 12.85",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.940729,33.69816]
-       },
-   "properties": 
-       {"street": "EUCLID", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 13.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.947913,33.700854]
-       },
-   "properties": 
-       {"street": "TALBERT", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 13.74",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.953701,33.704947]
-       },
-   "properties": 
-       {"street": "BROOKHUR1", "color": "lime", "perpx": "0.642988", "perpy": "0.765876"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 13.81",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.954762,33.705479]
-       },
-   "properties": 
-       {"street": "BROOKHURST2", "color": "lime", "perpx": "-0.559633", "perpy": "-0.828741"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 13.97",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.956518,33.707312]
-       },
-   "properties": 
-       {"street": "BROOKHUR2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 14.72",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.965935,33.714839]
-       },
-   "properties": 
-       {"street": "WARNER", "color": "lime", "perpx": "-0.642116", "perpy": "-0.766608"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 14.82",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.966959,33.716027]
-       },
-   "properties": 
-       {"street": "WARNER", "color": "lime", "perpx": "0.643494", "perpy": "0.765452"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 15.16",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.971343,33.71936]
-       },
-   "properties": 
-       {"street": "MAGNOLIA 1", "color": "lime", "perpx": "-0.644821", "perpy": "-0.764334"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 15.17",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.971245,33.719628]
-       },
-   "properties": 
-       {"street": "MAGNOLIA1", "color": "lime", "perpx": "0.639234", "perpy": "0.769012"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 15.39",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.973953,33.721879]
-       },
-   "properties": 
-       {"street": "MAGNOLIA2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 16.26",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.98561,33.72995]
-       },
-   "properties": 
-       {"street": "EDINGER", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 16.52",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.988885,33.732527]
-       },
-   "properties": 
-       {"street": "BEACH 1", "color": "lime", "perpx": "0.571725", "perpy": "0.820445"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 16.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.990146,33.733102]
-       },
-   "properties": 
-       {"street": "BEACH 1", "color": "lime", "perpx": "-0.580003", "perpy": "-0.814614"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 16.76",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.992088,33.734759]
-       },
-   "properties": 
-       {"street": "BEACH 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 17.66",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-118.003642,33.743534]
-       },
-   "properties": 
-       {"street": "BOLSA", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 17.92",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-118.00667,33.746378]
-       },
-   "properties": 
-       {"street": "GOLDEN WEST", "color": "lime", "perpx": "0.642886", "perpy": "0.765962"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 17.98",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-118.007585,33.7468]
-       },
-   "properties": 
-       {"street": "GOLDEN WEST", "color": "lime", "perpx": "-0.646922", "perpy": "-0.762556"}
-},  
-{
-   "type": "Feature",
-   "id": "405 S 19.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-118.020707,33.757778]
-       },
-   "properties": 
-       {"street": "WESTMINSTER", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "405 N 19.24",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-118.022852,33.759918]
-       },
-   "properties": 
-       {"street": "WESTMINISTER", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-
-{
-   "type": "Feature",
-   "id": "5 S 7.99",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.669881,33.481738]
-       },
-   "properties": 
-       {"street": "AEROPUERTO", "color": "lime", "perpx": "-0.815879", "perpy": "0.578222"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 7.99",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.669596,33.481685]
-       },
-   "properties": 
-       {"street": "AEROPUERTO", "color": "lime", "perpx": "0.816519", "perpy": "-0.577318"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 8.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.663917,33.489176]
-       },
-   "properties": 
-       {"street": "S JUAN CREEK", "color": "lime", "perpx": "-0.836267", "perpy": "0.548322"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 8.64",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.663255,33.489561]
-       },
-   "properties": 
-       {"street": "S JUAN CREEK", "color": "lime", "perpx": "0.839468", "perpy": "-0.54341"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 9.15",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.659442,33.496001]
-       },
-   "properties": 
-       {"street": "PLAZA", "color": "lime", "perpx": "-0.971491", "perpy": "0.237077"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 9.15",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.659127,33.495938]
-       },
-   "properties": 
-       {"street": "PLAZA", "color": "lime", "perpx": "0.972984", "perpy": "-0.230873"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 9.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.658583,33.499521]
-       },
-   "properties": 
-       {"street": "ORTEGA 1", "color": "lime", "perpx": "-0.996721", "perpy": "-0.080919"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 9.69",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.658585,33.503727]
-       },
-   "properties": 
-       {"street": "ORTEGA  2", "color": "lime", "perpx": "0.971921", "perpy": "0.235307"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 10.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.661127,33.5093]
-       },
-   "properties": 
-       {"street": "EL HORNO", "color": "lime", "perpx": "-0.918881", "perpy": "-0.394535"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 10.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.660803,33.50939]
-       },
-   "properties": 
-       {"street": "EL HORNO", "color": "lime", "perpx": "0.920027", "perpy": "0.391855"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 10.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.662568,33.513534]
-       },
-   "properties": 
-       {"street": "SERRA PARK", "color": "lime", "perpx": "0.919833", "perpy": "0.392311"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 10.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.662905,33.513441]
-       },
-   "properties": 
-       {"street": "SERRA PARK", "color": "lime", "perpx": "-0.920608", "perpy": "-0.390487"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 10.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.664664,33.517588]
-       },
-   "properties": 
-       {"street": "JUNIPERO SERRA", "color": "lime", "perpx": "-0.920608", "perpy": "-0.390487"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 11.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.666382,33.52247]
-       },
-   "properties": 
-       {"street": "JUNIPERO SERRA", "color": "lime", "perpx": "0.924678", "perpy": "0.38075"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 11.37",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.668912,33.526418]
-       },
-   "properties": 
-       {"street": "TRABUCO", "color": "lime", "perpx": "-0.878964", "perpy": "-0.476887"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 11.37",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.66866,33.526621]
-       },
-   "properties": 
-       {"street": "TRABUCO", "color": "lime", "perpx": "0.874948", "perpy": "0.484218"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 11.91",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.674488,33.53247]
-       },
-   "properties": 
-       {"street": "WILDWOOD", "color": "lime", "perpx": "0.999898", "perpy": "-0.014276"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 11.91",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.674919,33.53231]
-       },
-   "properties": 
-       {"street": "WILDWOOD", "color": "lime", "perpx": "-0.999508", "perpy": "0.03137"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 12.26",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.674416,33.537513]
-       },
-   "properties": 
-       {"street": "S OF 73", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 12.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.674695,33.539447]
-       },
-   "properties": 
-       {"street": "S of 73", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 12.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.673404,33.545217]
-       },
-   "properties": 
-       {"street": "AVERY 1", "color": "lime", "perpx": "-0.993564", "perpy": "0.113275"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 13.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.672686,33.548817]
-       },
-   "properties": 
-       {"street": "AVERY PARK", "color": "lime", "perpx": "0.999609", "perpy": "-0.027961"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 13.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.673131,33.556667]
-       },
-   "properties": 
-       {"street": "CROWN VA1", "color": "lime", "perpx": "-0.999988", "perpy": "0.004899"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 13.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.672848,33.558096]
-       },
-   "properties": 
-       {"street": "CROWN VA1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 13.87",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.672791,33.560549]
-       },
-   "properties": 
-       {"street": "CROWN VA2", "color": "lime", "perpx": "0.996005", "perpy": "-0.089297"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 15.03",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.671983,33.577397]
-       },
-   "properties": 
-       {"street": "OSO PARK1", "color": "lime", "perpx": "-0.999891", "perpy": "0.014798"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 15.13",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.67162,33.578849]
-       },
-   "properties": 
-       {"street": "OSO PARK 1", "color": "lime", "perpx": "0.999789", "perpy": "-0.020544"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 15.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.671925,33.581316]
-       },
-   "properties": 
-       {"street": "OSO PARK2", "color": "lime", "perpx": "-0.999911", "perpy": "0.013321"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 15.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.67157,33.582052]
-       },
-   "properties": 
-       {"street": "OSO PARK2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 16.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.673779,33.595354]
-       },
-   "properties": 
-       {"street": "LA PAZ 1", "color": "lime", "perpx": "-0.688838", "perpy": "-0.724915"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 16.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.67615,33.597607]
-       },
-   "properties": 
-       {"street": "LA PAZ 2", "color": "lime", "perpx": "-0.688838", "perpy": "-0.724915"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 16.51",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.676059,33.597861]
-       },
-   "properties": 
-       {"street": "LA PAZ 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 16.69",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.678685,33.599252]
-       },
-   "properties": 
-       {"street": "LA PAZ 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 17.26",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.687691,33.602645]
-       },
-   "properties": 
-       {"street": "ALICIA 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 17.43",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.68984,33.604242]
-       },
-   "properties": 
-       {"street": "ALICIA 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 17.49",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.69087,33.604617]
-       },
-   "properties": 
-       {"street": "ALICIA 2", "color": "lime", "perpx": "-0.527137", "perpy": "-0.849781"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 17.63",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.692734,33.606025]
-       },
-   "properties": 
-       {"street": "ALICIA 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 18.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.705361,33.612561]
-       },
-   "properties": 
-       {"street": "EL TORO 1", "color": "lime", "perpx": "-0.647397", "perpy": "-0.762153"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 18.61",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.706467,33.613883]
-       },
-   "properties": 
-       {"street": "EL TORO 1", "color": "lime", "perpx": "0.647648", "perpy": "0.761939"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 18.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.707825,33.614654]
-       },
-   "properties": 
-       {"street": "EL TORO 2", "color": "lime", "perpx": "-0.647397", "perpy": "-0.762153"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 19.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.719875,33.627286]
-       },
-   "properties": 
-       {"street": "LAKE FOR1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 19.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.720919,33.628454]
-       },
-   "properties": 
-       {"street": "LAKE FOR2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 20",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.721491,33.629553]
-       },
-   "properties": 
-       {"street": "LAKE FOR2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 20.24",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.724337,33.632102]
-       },
-   "properties": 
-       {"street": "OLDFIELD", "color": "lime", "perpx": "0.735536", "perpy": "0.677486"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 20.24",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.724813,33.631989]
-       },
-   "properties": 
-       {"street": "OLDFIELD", "color": "lime", "perpx": "-0.737725", "perpy": "-0.675102"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 20.59",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.728446,33.635959]
-       },
-   "properties": 
-       {"street": "BAKE 1", "color": "lime", "perpx": "-0.737725", "perpy": "-0.675102"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 20.59",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.72806,33.636144]
-       },
-   "properties": 
-       {"street": "BAKE 1", "color": "lime", "perpx": "0.735536", "perpy": "0.677486"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 20.94",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.731437,33.640323]
-       },
-   "properties": 
-       {"street": "BAKE 2", "color": "lime", "perpx": "0.77975", "perpy": "0.626091"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 20.95",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.731896,33.640308]
-       },
-   "properties": 
-       {"street": "BAKE 2", "color": "lime", "perpx": "-0.792319", "perpy": "-0.610107"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 21.25",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.734444,33.644068]
-       },
-   "properties": 
-       {"street": "At 405", "color": "lime", "perpx": "0.77975", "perpy": "0.626091"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 21.25",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.734722,33.643978]
-       },
-   "properties": 
-       {"street": "At 405", "color": "lime", "perpx": "-0.792319", "perpy": "-0.610107"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 22.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.74294,33.654255]
-       },
-   "properties": 
-       {"street": "ALTON 1", "color": "lime", "perpx": "-0.78542", "perpy": "-0.618963"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 22.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.742629,33.654371]
-       },
-   "properties": 
-       {"street": "ALTON 2", "color": "lime", "perpx": "0.780869", "perpy": "0.624695"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 22.14",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.743323,33.654741]
-       },
-   "properties": 
-       {"street": "ALTON 2", "color": "lime", "perpx": "-0.78542", "perpy": "-0.618963"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 22.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.743597,33.655581]
-       },
-   "properties": 
-       {"street": "ALTON 3", "color": "lime", "perpx": "0.780869", "perpy": "0.624695"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 22.75",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.749253,33.662021]
-       },
-   "properties": 
-       {"street": "BARRANCA", "color": "lime", "perpx": "-0.788481", "perpy": "-0.615059"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 22.75",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.748817,33.662274]
-       },
-   "properties": 
-       {"street": "BARRANCA", "color": "lime", "perpx": "0.770018", "perpy": "0.638022"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 23.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.75203,33.665581]
-       },
-   "properties": 
-       {"street": "S OF 133", "color": "lime", "perpx": "-0.781645", "perpy": "-0.623724"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 23.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.751722,33.66578]
-       },
-   "properties": 
-       {"street": "S OF 133", "color": "lime", "perpx": "0.776343", "perpy": "0.630311"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 23.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.7525,33.66617]
-       },
-   "properties": 
-       {"street": "N OF 133", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 23.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753237,33.667646]
-       },
-   "properties": 
-       {"street": "N OF 133", "color": "lime", "perpx": "0.776343", "perpy": "0.630311"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 23.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.755616,33.6716]
-       },
-   "properties": 
-       {"street": "S OF SAND CNYN", "color": "lime", "perpx": "-0.975596", "perpy": "-0.219572"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 23.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.755266,33.671657]
-       },
-   "properties": 
-       {"street": "S OF SAND CNYN", "color": "lime", "perpx": "0.972906", "perpy": "0.2312"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 23.69",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.756223,33.674297]
-       },
-   "properties": 
-       {"street": "SAND CANYON 1", "color": "lime", "perpx": "-0.809826", "perpy": "-0.58667"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 24.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.759083,33.67881]
-       },
-   "properties": 
-       {"street": "SAND CANYON 2", "color": "lime", "perpx": "0.701651", "perpy": "0.712521"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 24.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.759362,33.67863]
-       },
-   "properties": 
-       {"street": "SAND CANYON 2", "color": "lime", "perpx": "-0.809826", "perpy": "-0.58667"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 24.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.76413,33.68378]
-       },
-   "properties": 
-       {"street": "N OF SAND CNYN", "color": "lime", "perpx": "0.701651", "perpy": "0.712521"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 24.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.764425,33.683599]
-       },
-   "properties": 
-       {"street": "N OF SAND CNYN", "color": "lime", "perpx": "-0.835705", "perpy": "-0.549178"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 24.84",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.767277,33.687939]
-       },
-   "properties": 
-       {"street": "JEFFREY 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 25.08",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.768954,33.691182]
-       },
-   "properties": 
-       {"street": "JEFFREY 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 25.15",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.769532,33.692068]
-       },
-   "properties": 
-       {"street": "JEFFREY 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 25.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.775267,33.700148]
-       },
-   "properties": 
-       {"street": "YALE", "color": "lime", "perpx": "-0.828715", "perpy": "-0.559671"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 25.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.774934,33.700287]
-       },
-   "properties": 
-       {"street": "YALE", "color": "lime", "perpx": "0.835661", "perpy": "0.549245"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 26.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.779935,33.70706]
-       },
-   "properties": 
-       {"street": "CULVER 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 26.56",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.781713,33.709761]
-       },
-   "properties": 
-       {"street": "CULVER 1", "color": "lime", "perpx": "0.673811", "perpy": "0.738904"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 26.66",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.783134,33.710634]
-       },
-   "properties": 
-       {"street": "CULVER 2", "color": "lime", "perpx": "-0.654674", "perpy": "-0.755912"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 26.81",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.784619,33.712411]
-       },
-   "properties": 
-       {"street": "CULVER 2", "color": "lime", "perpx": "0.673811", "perpy": "0.738904"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 27.43",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.793071,33.717966]
-       },
-   "properties": 
-       {"street": "JAMBOREE 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 27.55",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.794408,33.719297]
-       },
-   "properties": 
-       {"street": "JAMBOREE 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 27.56",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.794541,33.719391]
-       },
-   "properties": 
-       {"street": "JAMBOREE 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 27.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.796638,33.72047]
-       },
-   "properties": 
-       {"street": "JAMBOREE 2", "color": "lime", "perpx": "-0.574555", "perpy": "-0.818466"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 28.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.801722,33.724394]
-       },
-   "properties": 
-       {"street": "TUSTIN RANCH", "color": "lime", "perpx": "0.570509", "perpy": "0.821292"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 28.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.801999,33.724136]
-       },
-   "properties": 
-       {"street": "TUSTIN RANCH", "color": "lime", "perpx": "-0.556796", "perpy": "-0.83065"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 29.02",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.814369,33.732587]
-       },
-   "properties": 
-       {"street": "RED HILL", "color": "lime", "perpx": "-0.566824", "perpy": "-0.823839"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 29.24",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.817068,33.73489]
-       },
-   "properties": 
-       {"street": "RED HILL", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 29.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.824499,33.737386]
-       },
-   "properties": 
-       {"street": "NEWPORT*", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 29.79",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.825811,33.738115]
-       },
-   "properties": 
-       {"street": "NEWPORT*", "color": "lime", "perpx": "0.29944", "perpy": "0.954115"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 29.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.827716,33.738432]
-       },
-   "properties": 
-       {"street": "B ST", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 30",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.829214,33.739183]
-       },
-   "properties": 
-       {"street": "B ST.", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 30.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.832416,33.740283]
-       },
-   "properties": 
-       {"street": "S OF 55", "color": "lime", "perpx": "0.333225", "perpy": "0.942847"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 30.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.832494,33.740098]
-       },
-   "properties": 
-       {"street": "S OF 55*", "color": "lime", "perpx": "-0.326161", "perpy": "-0.945314"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 30.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.835585,33.741403]
-       },
-   "properties": 
-       {"street": "N OF 55", "color": "lime", "perpx": "0.333225", "perpy": "0.942847"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 30.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.835743,33.741219]
-       },
-   "properties": 
-       {"street": "N OF 55", "color": "lime", "perpx": "-0.33389", "perpy": "-0.942612"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 30.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.841283,33.744413]
-       },
-   "properties": 
-       {"street": "1ST", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 30.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.842538,33.745553]
-       },
-   "properties": 
-       {"street": "1ST", "color": "lime", "perpx": "-0.927915", "perpy": "-0.372793"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 31.23",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.844652,33.749928]
-       },
-   "properties": 
-       {"street": "4TH", "color": "lime", "perpx": "-0.697138", "perpy": "-0.716937"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 31.23",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.844061,33.750124]
-       },
-   "properties": 
-       {"street": "4TH", "color": "lime", "perpx": "0.715791", "perpy": "0.698315"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 31.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.846535,33.751759]
-       },
-   "properties": 
-       {"street": "CONCORD", "color": "lime", "perpx": "-0.504083", "perpy": "-0.863655"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 31.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.845939,33.752049]
-       },
-   "properties": 
-       {"street": "CONCORD", "color": "lime", "perpx": "0.715791", "perpy": "0.698315"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 31.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.849326,33.753388]
-       },
-   "properties": 
-       {"street": "GRAND 1", "color": "lime", "perpx": "-0.504083", "perpy": "-0.863655"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 31.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.848788,33.753753]
-       },
-   "properties": 
-       {"street": "GRAND 1", "color": "lime", "perpx": "0.435561", "perpy": "0.900159"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 31.73",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.850781,33.754689]
-       },
-   "properties": 
-       {"street": "GRAND 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 31.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.853795,33.755475]
-       },
-   "properties": 
-       {"street": "GRAND 2", "color": "lime", "perpx": "-0.382512", "perpy": "-0.923951"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 32.25",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.859225,33.757943]
-       },
-   "properties": 
-       {"street": "17TH 1", "color": "lime", "perpx": "-0.583453", "perpy": "-0.812147"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 32.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.859664,33.758644]
-       },
-   "properties": 
-       {"street": "17TH 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 32.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.862379,33.760465]
-       },
-   "properties": 
-       {"street": "17TH 2", "color": "lime", "perpx": "0.753317", "perpy": "0.657658"}
-},  
-{
-   "type": "Feature",
-   "id": "5 N 32.6",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.863369,33.761599]
-       },
-   "properties": 
-       {"street": "17TH 3", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 33",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.866976,33.766429]
-       },
-   "properties": 
-       {"street": "MAIN 1", "color": "lime", "perpx": "-0.855987", "perpy": "-0.516997"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 33.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.868373,33.768742]
-       },
-   "properties": 
-       {"street": "MAIN 2", "color": "lime", "perpx": "-0.830562", "perpy": "-0.556927"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 33.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.869238,33.770032]
-       },
-   "properties": 
-       {"street": "BROADWAY", "color": "lime", "perpx": "-0.830562", "perpy": "-0.556927"}
-},  
-{
-   "type": "Feature",
-   "id": "5 S 33.8",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.874337,33.776289]
-       },
-   "properties": 
-       {"street": "S OF 22", "color": "lime", "perpx": "-0.780234", "perpy": "-0.625487"}
-},  
-
-{
-   "type": "Feature",
-   "id": "133 S 9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.7553,33.66184]
-       },
-   "properties": 
-       {"street": "BARRANCA2", "color": "lime", "perpx": "-0.952044", "perpy": "0.305962"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.754967,33.661697]
-       },
-   "properties": 
-       {"street": "BARRANCA1", "color": "lime", "perpx": "0.851313", "perpy": "-0.524659"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 9.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753976,33.663305]
-       },
-   "properties": 
-       {"street": "BARRANCA2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 9.37",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753044,33.667495]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "0.976143", "perpy": "-0.217128"}
-},  
-{
-   "type": "Feature",
-   "id": "133 S 9.37",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753428,33.667665]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "-0.952044", "perpy": "0.305962"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 9.77",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753243,33.672836]
-       },
-   "properties": 
-       {"street": "N OF 5", "color": "lime", "perpx": "0.971108", "perpy": "-0.23864"}
-},  
-{
-   "type": "Feature",
-   "id": "133 S 9.77",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.753623,33.673029]
-       },
-   "properties": 
-       {"street": "N OF 5", "color": "lime", "perpx": "-0.974264", "perpy": "0.225409"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 10.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.752421,33.676181]
-       },
-   "properties": 
-       {"street": "MARINE WAY", "color": "lime", "perpx": "0.971108", "perpy": "-0.23864"}
-},  
-{
-   "type": "Feature",
-   "id": "133 S 10.05",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.752844,33.676396]
-       },
-   "properties": 
-       {"street": "MARINE WAY", "color": "lime", "perpx": "-0.974264", "perpy": "0.225409"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 10.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.748819,33.680812]
-       },
-   "properties": 
-       {"street": "N OF MARINE", "color": "lime", "perpx": "0.780739", "perpy": "-0.624857"}
-},  
-{
-   "type": "Feature",
-   "id": "133 S 10.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.74924,33.68106]
-       },
-   "properties": 
-       {"street": "N OF MARINE", "color": "lime", "perpx": "-0.764221", "perpy": "0.644955"}
-},  
-{
-   "type": "Feature",
-   "id": "133 N 10.73",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.746935,33.683166]
-       },
-   "properties": 
-       {"street": "S OF PM 11", "color": "lime", "perpx": "0.780739", "perpy": "-0.624857"}
-},  
-{
-   "type": "Feature",
-   "id": "133 S 10.73",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.747277,33.683386]
-       },
-   "properties": 
-       {"street": "S OF PM 11", "color": "lime", "perpx": "-0.764221", "perpy": "0.644955"}
-},  
-
-{
-   "type": "Feature",
-   "id": "261 N 0.04",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.800349,33.712252]
-       },
-   "properties": 
-       {"street": "JAMBOREE", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "261 S 0.04",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.800638,33.7124]
-       },
-   "properties": 
-       {"street": "JAMBOREE", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "261 N 0.31",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.797696,33.715376]
-       },
-   "properties": 
-       {"street": "WALNUT 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "261 S 0.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.795434,33.717315]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "-0.497099", "perpy": "0.867694"}
-},  
-{
-   "type": "Feature",
-   "id": "261 N 0.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.795181,33.717083]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "0.493349", "perpy": "-0.869832"}
-},  
-{
-   "type": "Feature",
-   "id": "261 N 0.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.789435,33.720342]
-       },
-   "properties": 
-       {"street": "EL CAMINO REAL", "color": "lime", "perpx": "0.493349", "perpy": "-0.869832"}
-},  
-{
-   "type": "Feature",
-   "id": "261 S 0.9",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.789693,33.720604]
-       },
-   "properties": 
-       {"street": "EL CAMINO REAL", "color": "lime", "perpx": "-0.497099", "perpy": "0.867694"}
-},  
-{
-   "type": "Feature",
-   "id": "261 S 1.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.782999,33.723902]
-       },
-   "properties": 
-       {"street": "IRVINE BLVD 1", "color": "lime", "perpx": "-0.601686", "perpy": "0.798733"}
-},  
-{
-   "type": "Feature",
-   "id": "261 N 1.35",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.782735,33.72367]
-       },
-   "properties": 
-       {"street": "IRVINE BLVD 1", "color": "lime", "perpx": "0.607612", "perpy": "-0.794234"}
-},  
-
-{
-   "type": "Feature",
-   "id": "55 N 4.58",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.888101,33.671785]
-       },
-   "properties": 
-       {"street": "BRISTOL", "color": "lime", "perpx": "0.612685", "perpy": "-0.790327"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 4.58",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.888309,33.671928]
-       },
-   "properties": 
-       {"street": "BRISTOL", "color": "lime", "perpx": "-0.612257", "perpy": "0.790659"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 4.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.88678,33.673112]
-       },
-   "properties": 
-       {"street": "BAKER 1", "color": "lime", "perpx": "-0.639107", "perpy": "0.769118"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 4.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.886575,33.672968]
-       },
-   "properties": 
-       {"street": "BAKER 1", "color": "lime", "perpx": "0.649874", "perpy": "-0.760042"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 5.06",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.882355,33.676789]
-       },
-   "properties": 
-       {"street": "BAKER 2", "color": "lime", "perpx": "-0.639107", "perpy": "0.769118"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 5.06",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.882208,33.676702]
-       },
-   "properties": 
-       {"street": "BAKER 2", "color": "lime", "perpx": "0.649874", "perpy": "-0.760042"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 5.51",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.877327,33.681801]
-       },
-   "properties": 
-       {"street": "PAULARINO 1", "color": "lime", "perpx": "0.73612", "perpy": "-0.676851"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 5.51",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.87755,33.681935]
-       },
-   "properties": 
-       {"street": "PAULARINO 1", "color": "lime", "perpx": "-0.722093", "perpy": "0.691796"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 5.87",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.873498,33.685939]
-       },
-   "properties": 
-       {"street": "PAULARINO 2", "color": "lime", "perpx": "0.719864", "perpy": "-0.694115"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 5.87",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.873635,33.686016]
-       },
-   "properties": 
-       {"street": "PAULARINO 2", "color": "lime", "perpx": "-0.725185", "perpy": "0.688554"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 6.88",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.862677,33.697495]
-       },
-   "properties": 
-       {"street": "MACARTHU1", "color": "lime", "perpx": "-0.710326", "perpy": "0.703873"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 6.94",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.861831,33.698026]
-       },
-   "properties": 
-       {"street": "MACARTHU1", "color": "lime", "perpx": "0.740557", "perpy": "-0.671994"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 7.03",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.861041,33.699146]
-       },
-   "properties": 
-       {"street": "MACARTHU2", "color": "lime", "perpx": "-0.710326", "perpy": "0.703873"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 7.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.860155,33.699873]
-       },
-   "properties": 
-       {"street": "MACARTHU2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 7.85",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.85183,33.708364]
-       },
-   "properties": 
-       {"street": "DYER 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 8.12",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.848847,33.711314]
-       },
-   "properties": 
-       {"street": "DYER 2", "color": "lime", "perpx": "0.71172", "perpy": "-0.702463"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 8.12",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.849099,33.711451]
-       },
-   "properties": 
-       {"street": "DYER 2", "color": "lime", "perpx": "-0.708914", "perpy": "0.705295"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 9.19",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.837265,33.723387]
-       },
-   "properties": 
-       {"street": "EDINGER 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 9.41",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.83503,33.726049]
-       },
-   "properties": 
-       {"street": "EDINGER 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 9.84",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833996,33.73212]
-       },
-   "properties": 
-       {"street": "MCFADDEN", "color": "lime", "perpx": "-0.999946", "perpy": "-0.010425"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 9.84",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833555,33.732101]
-       },
-   "properties": 
-       {"street": "MCFADDEN", "color": "lime", "perpx": "0.999932", "perpy": "-0.011627"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 10.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833583,33.737088]
-       },
-   "properties": 
-       {"street": "N OF 5 OFF", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 10.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833908,33.739982]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "-0.999756", "perpy": "0.022109"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 10.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.83368,33.739982]
-       },
-   "properties": 
-       {"street": "S OF 5", "color": "lime", "perpx": "0.999923", "perpy": "0.012439"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 10.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833876,33.741429]
-       },
-   "properties": 
-       {"street": "N OF 5", "color": "lime", "perpx": "-0.987616", "perpy": "0.156888"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 10.5",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.833698,33.741429]
-       },
-   "properties": 
-       {"street": "N OF 5", "color": "lime", "perpx": "0.97478", "perpy": "-0.22317"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 11.1",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.831768,33.749859]
-       },
-   "properties": 
-       {"street": "FOURTH 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 11.62",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.831392,33.75738]
-       },
-   "properties": 
-       {"street": "17TH 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 11.74",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.830994,33.759105]
-       },
-   "properties": 
-       {"street": "17TH 1", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 12",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.830834,33.762898]
-       },
-   "properties": 
-       {"street": "17TH 2", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "55 S 12.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.831088,33.773138]
-       },
-   "properties": 
-       {"street": "FAIRHAVEN", "color": "lime", "perpx": "-0.999999", "perpy": "-0.001368"}
-},  
-{
-   "type": "Feature",
-   "id": "55 N 12.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.830912,33.773139]
-       },
-   "properties": 
-       {"street": "FAIRHAVEN", "color": "lime", "perpx": "0.999999", "perpy": "0.001196"}
-},  
-
-{
-   "type": "Feature",
-   "id": "73 S 25.25",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.871215,33.659515]
-       },
-   "properties": 
-       {"street": "ORCHID", "color": "lime", "perpx": "-0.566542", "perpy": "-0.824033"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 25.25",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.870921,33.659804]
-       },
-   "properties": 
-       {"street": "ORCHID", "color": "lime", "perpx": "0.565437", "perpy": "0.824792"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 25.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.87634,33.663519]
-       },
-   "properties": 
-       {"street": "CAMPUS", "color": "lime", "perpx": "0.565437", "perpy": "0.824792"}
-},  
-{
-   "type": "Feature",
-   "id": "73 S 25.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.876633,33.66324]
-       },
-   "properties": 
-       {"street": "CAMPUS", "color": "lime", "perpx": "-0.566542", "perpy": "-0.824033"}
-},  
-{
-   "type": "Feature",
-   "id": "73 S 26.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.88342,33.669908]
-       },
-   "properties": 
-       {"street": "S OF 55", "color": "lime", "perpx": "-0.750726", "perpy": "-0.660614"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 26.3",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.883175,33.67012]
-       },
-   "properties": 
-       {"street": "S OF 55", "color": "lime", "perpx": "0.756677", "perpy": "0.653789"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 26.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.887299,33.674893]
-       },
-   "properties": 
-       {"street": "N OF 55", "color": "lime", "perpx": "0.76071", "perpy": "0.649092"}
-},  
-{
-   "type": "Feature",
-   "id": "73 S 26.7",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.887584,33.67464]
-       },
-   "properties": 
-       {"street": "N OF 55", "color": "lime", "perpx": "-0.742508", "perpy": "-0.669837"}
-},  
-{
-   "type": "Feature",
-   "id": "73 S 27.2",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.892743,33.68058]
-       },
-   "properties": 
-       {"street": "BEAR 1", "color": "lime", "perpx": "-0.749261", "perpy": "-0.662275"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 27.4",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.894515,33.683052]
-       },
-   "properties": 
-       {"street": "BEAR 2", "color": "lime", "perpx": "0.737613", "perpy": "0.675223"}
-},  
-{
-   "type": "Feature",
-   "id": "73 S 27.72",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.898045,33.686456]
-       },
-   "properties": 
-       {"street": "FAIRVIEW", "color": "lime", "perpx": "0", "perpy": "0"}
-},  
-{
-   "type": "Feature",
-   "id": "73 N 27.72",
-   "geometry":
-       {
-        "type": "Point",
-        "coordinates": [-117.897754,33.686594]
-       },
-   "properties": 
-       {"street": "FAIRVIEW", "color": "lime", "perpx": "0", "perpy": "0"}
-}   
-  ]
-}
