Changeset 302 in tmcsimulator


Ignore:
Timestamp:
03/10/2019 01:54:49 PM (7 years ago)
Author:
jdalbey
Message:

cptms_map.html v0.5.6 integrates cms features

Location:
trunk/src/cptms
Files:
1 added
1 edited
8 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/cptms/cptms_map.html

    r293 r302  
    22<html> 
    33  <head> 
     4<!-- Launch with  python -m CGIHTTPServer 8080  --> 
    45  <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 
    5     <title>CPTMS Map v0.5.5</title>  
     6    <title>CPTMS Map v0.5.6</title>  
    67    <style> 
     8        @font-face { 
     9          font-family: Scoreboard; 
     10          src: url('scoreboard.ttf'); 
     11        } 
    712      /* Set the size of the div element that contains the map */ 
    813      #mapdiv { 
     
    1621        padding: 0; 
    1722      } 
     23        textarea { 
     24           height: 33px; 
     25           width: 272px; 
     26           resize: none; 
     27           font-family: Scoreboard; 
     28           font-size: xx-large; 
     29           background-color: #2F4F4F; 
     30           color: yellow; 
     31        } 
     32       input { 
     33           border: thin solid #333; 
     34           padding: 2px; 
     35           font-family: monospace; 
     36           font-size: large; 
     37        } 
    1838      #search-input { 
    1939        background-color: #17263c;  /* #CD853F;  /*#E6E6FA; /* lavender */ 
     
    4060        cursor: pointer; 
    4161      } 
     62      #cms-info-label { 
     63           height: 20px; 
     64           width: 540px; 
     65           overflow: hidden; 
     66           background-color: #A8C5FF;  /*#ECECFB; */ 
     67           border: thin solid #BDBDBD; 
     68           padding: 5px; 
     69       } 
     70      #message-display { 
     71           height: 172px; 
     72           width: 300px; 
     73           overflow: hidden; 
     74           float: left; 
     75       } 
     76      #message-input { 
     77           height: 122px; 
     78           width: 135px; 
     79           background-color: #729FFF; 
     80           float: left; 
     81       } 
     82       #buttonPanel { 
     83           height: 122px; 
     84           width: 100px; 
     85           background-color: #729FFF; 
     86           border-left: none; 
     87           float: left; 
     88           padding: 20px; 
     89        } 
     90       .wrapper { 
     91           position: relative;\ 
     92        } 
     93       #dialog { 
     94          position: absolute; 
     95          top: 10%; 
     96          right: 20%; 
     97          background-color: #729FFF; /* #ECECFB; */ 
     98          margin: auto; 
     99          padding: 20px; 
     100          border: 1px solid #888; 
     101          width: 52%; 
     102          display: none;            
     103        } 
     104      .unstyled-button { 
     105        border: 0 none; 
     106        padding: 0; 
     107        background: none; 
     108        cursor: pointer; 
     109      }     
     110    /* The Close Button */ 
     111    .close { 
     112      color: orange; 
     113      float: right; 
     114      font-size: 20px; 
     115      font-weight: bold; 
     116    } 
     117    .close:hover, 
     118    .close:focus { 
     119      color: red; 
     120      text-decoration: none; 
     121      cursor: pointer; 
     122    } 
    42123 
    43124    </style> 
    44125  </head> 
    45126  <body> 
    46     <!-- Version 5.5 renames title to CPTMS, loads static data on startup and dynamic data 
     127    <!--  
     128         Version 5.6 integrates CMS features 
     129         Version 5.5 renames title to CPTMS, loads static data on startup and dynamic data 
    47130         every ten seconds.   
    48131         Version 5.4 adds Search box and Center button 
     
    61144    <!--The div element where the map appears --> 
    62145    <div id="mapdiv"></div> 
    63     <!--The div element where the center button appears --> 
    64     <div id="ctrButton">&#x2295;</div> 
     146    <!--The div element where the buttons appears --> 
     147    <div id="ctrButton" class="unstyled-button">&#x2295;</div> 
     148    <button id="cmsButton" class="unstyled-button"><img id="cmsBtnImg" src="images/CPTMSImages/btnDepressed_CMS.png"></button> 
     149    <button id="vdsButton" class="unstyled-button"><img id="vdsBtnImg" src="images/CPTMSImages/btnDepressed_VDS.png"></button> 
     150    <!-- The div element for the popup dialog --> 
     151    <div id="dialog" style="display:none;"> 
     152        <span class="close">&times;</span> 
     153        <br> 
     154        <div id="cms-info-label" style="font-family:monospace">CMS ID: xxx LOCATION: </div> 
     155        <br> 
     156        <div><pre>Proposed:                              Current:</pre></div> 
     157        <input id='cmsID' value="" type='hidden'/> 
     158        <div id="message-input"> 
     159        <input id="msgcontent1" size="16" maxlength="16" type="text"/><br><br> 
     160        <input id="msgcontent2" size="16" maxlength="16"/><br><br> 
     161        <input id="msgcontent3" size="16" maxlength="16"/> 
     162        </div>         
     163        <div id="buttonPanel"    style="display: block;"> 
     164        <button onclick="handleSubmit();">Send >></button><br> 
     165        <button onclick="handleClear();">Clear >></button><br> 
     166        <button onclick="handleClose();">Close </button> 
     167        </div> 
     168        <div id="message-display"  style="display: block;"> 
     169         <textarea readonly id="msgdisplay1" maxlength="16" rows="1" cols="16"></textarea> 
     170         <textarea readonly id="msgdisplay2" maxlength="16" rows="1" cols="16"></textarea> 
     171         <textarea readonly id="msgdisplay3" maxlength="16" rows="1" cols="16"></textarea> 
     172        </div> 
     173    </div> 
     174 
    65175    <script> 
    66176    // a global variable for the google map 
     
    84194    // white means a disabled spot 
    85195    var colorZvalues = {"white":5,"lime":10,"yellow":20,"red":30}; 
     196var kMapStartupFile = "cmsStatusD12.json"; 
     197var blueFlag = "images/CPTMSImages/icon_cmsBlue.png"; 
     198var yellowFlag = "images/CPTMSImages/icon_cmsYellow.png"; 
     199var messageList; 
     200var cms_info; 
     201var markerList = []; 
     202var cms_showing = true; 
     203var vds_showing = true; 
    86204 
    87205    // Build a solid colored icon to use instead of the classic pin 
     
    197315     } 
    198316 
    199     // Load the dynamic highways file via ajax 
     317    // Load the dynamic json file for highways, etc. 
    200318    // Ref: https://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript 
    201      function loadJSON(callback) {    
    202  
    203         var xobj = new XMLHttpRequest(); 
    204             xobj.overrideMimeType("application/json"); 
    205         xobj.open('GET', kMapPointsFile, true);  
    206         xobj.onreadystatechange = function () { 
    207               if (xobj.readyState == 4 && xobj.status == "200") { 
    208                 // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode 
    209                 callback(xobj.responseText); 
    210               } 
    211         }; 
    212         xobj.send(null);   
    213      } 
    214  
     319function loadJSON(inFile, callback) 
     320{ 
     321    var xobj = new XMLHttpRequest(); 
     322    xobj.overrideMimeType("application/json"); 
     323    xobj.open('GET', inFile, true); 
     324    xobj.onreadystatechange = function() 
     325    { 
     326        if (xobj.readyState == 4 && xobj.status == "200") 
     327        { 
     328            callback(xobj.responseText); 
     329        } 
     330    }; 
     331    // We want ajax to ignore any cached responses 
     332    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT') 
     333    xobj.send(null); 
     334} 
    215335     // Load the highways dynamic json file and update the map 
    216336     function updateMap() 
    217337     { 
    218338        var parsed_JSON; 
    219         loadJSON(function(response) 
     339        loadJSON(kMapPointsFile,function(response) 
    220340        { 
    221341            // Parse JSON string into object 
     
    313433          placePins = []; 
    314434    } 
     435// Initialize the view/hide buttons  
     436function initButton() 
     437{ 
     438    var cmsBtnDiv = document.getElementById('cmsButton'); 
     439    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(cmsBtnDiv) 
     440    cmsBtnDiv.title = 'Click to toggle cms view'; 
     441 
     442    // Setup the click event listeners to toggle icon display 
     443    cmsBtnDiv.addEventListener('click', function() { 
     444            cms_showing = !cms_showing; 
     445            // reveal or hide all the icons 
     446            for (var i = 0; i < markerList.length; i++) 
     447            { 
     448                markerList[i].setVisible(cms_showing); 
     449            } 
     450            // Determine which button image to show 
     451            if (cms_showing) 
     452            { 
     453                pic = "images/CPTMSImages/btnDepressed_CMS.png" 
     454            } 
     455            else 
     456            { 
     457                pic = "images/CPTMSImages/btnReady_CMS.png" 
     458            } 
     459            document.getElementById('cmsBtnImg').src=pic; 
     460    }); 
     461    var vdsBtnDiv = document.getElementById('vdsButton'); 
     462    map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(vdsBtnDiv) 
     463    vdsBtnDiv.title = 'Click to toggle vds view'; 
     464 
     465    // Setup the click event listeners to toggle icon display 
     466    vdsBtnDiv.addEventListener('click', function() { 
     467            vds_showing = !vds_showing; 
     468            // reveal or hide all the icons 
     469            alert("Not implemented yet") 
     470            // Determine which button image to show 
     471            if (vds_showing) 
     472            { 
     473                pic = "btnDepressed_VDS.png" 
     474            } 
     475            else 
     476            { 
     477                pic = "btnReady_VDS.png" 
     478            } 
     479            document.getElementById('vdsBtnImg').src=pic; 
     480    }); 
     481} 
     482function setMarkers() 
     483{ 
     484    var simpleImage = ""; 
     485    loadcmsJSON(function(response) 
     486    { 
     487        // Parse JSON string into object 
     488        cms_info = JSON.parse(response); 
     489        console.log(cms_info.data[0].cms); 
     490        // Process each new marker  
     491        for (var i = 0; i < cms_info.data.length; i++) 
     492        { 
     493            var cms = cms_info.data[i].cms; 
     494            var currLat = Number(cms.location.latitude); 
     495            var currLong = Number(cms.location.longitude); 
     496            // load a yellow flag if there's currently no message 
     497            if (messageList[i] == "||") 
     498                simpleImage = yellowFlag; 
     499            else 
     500                simpleImage = blueFlag; 
     501            var directionCode = cms.location.direction.charAt(0); 
     502            var locationInfo = directionCode + " " + cms.location 
     503                .route + " " + cms.location.postmile + " " + cms 
     504                .location.locationName 
     505            markerList[i] = new google.maps.Marker( 
     506            { 
     507                position: 
     508                { 
     509                    lat: currLat, 
     510                    lng: currLong 
     511                }, 
     512                map: map, 
     513                icon: simpleImage, 
     514                title: "#"+i+" " +locationInfo, 
     515                cmsid: "" + i, 
     516                location: locationInfo 
     517            }); 
     518            google.maps.event.addListener(markerList[i], 'click', 
     519                function() 
     520                { 
     521                    var dialog = document.getElementById('dialog'); 
     522                    dialog.style.display = 'block'; 
     523                    // fetch the sequential msg # 
     524                    cmsID = Number(this.cmsid); 
     525                    // Assign to the hidden field 
     526                    document.getElementById('cmsID').value = cmsID; 
     527                    getMessage(cmsID); // note: this is async 
     528                    document.getElementById('cms-info-label').innerHTML = "CMS ID: " + 
     529                        cmsID + "&nbsp;&nbsp;&nbsp;LOCATION: " + this.location; 
     530                    // clear input fields 
     531                    document.getElementById('msgcontent1').value = ""; 
     532                    document.getElementById('msgcontent2').value = ""; 
     533                    document.getElementById('msgcontent3').value = ""; 
     534                    document.getElementById('msgcontent1').focus(); 
     535                    var span = document.getElementsByClassName("close")[0] 
     536                    // When the user clicks on <span> (x), close the modal 
     537                    span.onclick = function() { 
     538                      handleClose(); 
     539                    } 
     540                }); 
     541        } 
     542    }); 
     543} 
     544 
     545function loadcmsJSON(callback) 
     546{ 
     547    var xobj = new XMLHttpRequest(); 
     548    xobj.overrideMimeType("application/json"); 
     549    xobj.open('GET', kMapStartupFile, true); 
     550    xobj.onreadystatechange = function() 
     551    { 
     552        if (xobj.readyState == 4 && xobj.status == "200") 
     553        { 
     554            callback(xobj.responseText); 
     555        } 
     556    }; 
     557    // We want ajax to ignore any cached responses 
     558    xobj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 01:01:01 GMT') 
     559    xobj.send(null); 
     560} 
     561 
     562function handleSubmit() 
     563{ 
     564    // recover the user's response 
     565    var response1 = document.getElementById('msgcontent1').value; 
     566    var response2 = document.getElementById('msgcontent2').value; 
     567    var response3 = document.getElementById('msgcontent3').value; 
     568    var newMsg = response1+response2+response3; 
     569    if (newMsg.length == 0) 
     570    { 
     571        alert("Nothing to Send ... Proposed is empty."); 
     572    } 
     573    else 
     574    { 
     575        document.getElementById('msgdisplay1').value = response1; 
     576        document.getElementById('msgdisplay2').value = response2; 
     577        document.getElementById('msgdisplay3').value = response3; 
     578        saveMessage(response1 + "|" + response2 + "|" + response3); 
     579    } 
     580} 
     581 
     582function handleClose() 
     583{ 
     584    // hide the display 
     585    document.getElementById('dialog').style.display = 'none' 
     586} 
     587 
     588function handleClear() 
     589{ 
     590    document.getElementById('msgdisplay1').value = ""; 
     591    document.getElementById('msgdisplay2').value = ""; 
     592    document.getElementById('msgdisplay3').value = ""; 
     593    saveMessage("||"); 
     594} 
     595// retrieve the current cms message file 
     596function getMessage(cmsID) 
     597{ 
     598    loadJSON("http://localhost:8080/messagefile.txt", function(response) 
     599    { 
     600        // Parse JSON string into object 
     601        messageList = JSON.parse(response); 
     602        // select a message from json for the given cmsID 
     603        console.log("get by cmsID=" + cmsID); 
     604        var cmsSign = document.getElementById('msgdisplay1'); 
     605        messageparts = messageList[cmsID].split("|"); 
     606        cmsSign.value = messageparts[0]; 
     607        document.getElementById('msgdisplay2').value = messageparts[1]; 
     608        document.getElementById('msgdisplay3').value = messageparts[2]; 
     609    }); 
     610} 
     611// Save an updated cms message to the file 
     612// NB: cms id's are one-based, json array is zero-based. 
     613function saveMessage(outMessage, cmsID) 
     614{ 
     615    var cmsID = document.getElementById('cmsID').value; 
     616    console.log("Saving " + outMessage + " for cmsID " + cmsID) 
     617    messageList[cmsID] = outMessage; 
     618    // Change icon if something was saved 
     619    if (outMessage == "||") 
     620        markerList[cmsID].setIcon(yellowFlag); 
     621    else 
     622        markerList[cmsID].setIcon(blueFlag); 
     623 
     624    var xhttp = new XMLHttpRequest(); 
     625    xhttp.open("GET", "http://localhost:8080/cgi-bin/saveMessage.py?msg=" + JSON 
     626        .stringify(messageList), true); 
     627    xhttp.send(); 
     628    // Using POST might be a better idea ... haven't tried this yet 
     629    //      var xhr = new XMLHttpRequest(); 
     630    //      xhr.open("POST", "/cgi-bin/saveMessage.py?", true); 
     631    //      xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); 
     632    // send the collected data as JSON 
     633    //      xhr.send(JSON.stringify(messageList)); 
     634}  
    315635 
    316636    // Initialize the map and load the points 
     
    329649        initSearch(); 
    330650        initCenter(); 
     651        initButton(); 
     652        getMessage(1); // load the current message file 
     653        setMarkers(); 
    331654 
    332655        loadMapData();  // go load the map data 
Note: See TracChangeset for help on using the changeset viewer.