Map Widget
Usage: modify the urls according to your systems and provide your Google Map API key.
This flow adds a map widget to Node-RED Dasboard nodes.
It employs a web template node and a ui_template dashboard node.
The web template node serves a map interface, which is then embedded into the ui_template node.
Inter-frames communication allows messages injected to ui_template node to be sent to the web template node, which eventually displays injected data to the map interface.
Final result looks like this:
[{"id":"7d033e9a.d1131","type":"ui_template","z":"4499b290.3eec5c","group":"88f77589.0122d8","name":"Map widget","order":0,"width":"24","height":"14","format":"<iframe \n id='frame'\n src='.../mapui'\n width='100%' \n height='100%'\n>\n</iframe>\n\n<script>\nscope.$watch('msg.payload', function(newv, oldv, scope) {\n $(\"#frame\")[0].contentWindow.postMessage(JSON.stringify(newv), '*');\n});\n</script>","storeOutMessages":false,"fwdInMessages":false,"x":724,"y":1698,"wires":[[]]},{"id":"c433a1b9.252a8","type":"http response","z":"4499b290.3eec5c","name":"","x":748,"y":1749,"wires":[]},{"id":"aa254267.9215f","type":"http in","z":"4499b290.3eec5c","name":"","url":".../mapui","method":"get","swaggerDoc":"","x":384,"y":1749,"wires":[["7b50d31e.26176c"]]},{"id":"7b50d31e.26176c","type":"template","z":"4499b290.3eec5c","name":"Map UI","field":"payload","fieldType":"msg","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n <title>Vancouver Buses</title>\n <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js\"></script>\n <script src=\"https://maps.googleapis.com/maps/api/js?key=<GOOGLE_MAP_KEY_HERE>\"></script>\n <script src=\"https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js\"></script>\n\n <style type=\"text/css\" media=\"screen\">\n #map {\n position:absolute;\n top: 0; bottom: 0; left: 0; right: 0;\n }\n </style>\n</head>\n<body>\n <div id=\"map\"></div>\n <script type=\"text/javascript\">\n\n$(document).ready(function(){\n var MAP_ZOOM = 12\n var MARKER_SIZE = 14\n \n var map = new google.maps.Map(document.getElementById('map'), {\n zoom: MAP_ZOOM,\n center: {lat: 49.269801, lng: -123.109489}\n });\n \n var markers = []\n \n window.onmessage = function(evt){\n for (var i = 0; i < markers.length; i++) {\n markers[i].setMap(null);\n }\n \n var data = JSON.parse(evt.data);\n map.setZoom(MAP_ZOOM);\n \n markers = data.map(function(el, i) {\n var marker = new google.maps.Marker({\n position: el,\n icon: {\n url: el.iconUrl,\n scaledSize: new google.maps.Size(MARKER_SIZE, MARKER_SIZE)\n },\n map:map\n });\n google.maps.event.addListener(marker , 'click', function(){\n var infowindow = new google.maps.InfoWindow({\n content:el.description,\n position: el,\n });\n infowindow.open(map);\n setTimeout(function () { infowindow.close(); }, 2000);\n });\n return marker\n });\n }\n});\n </script>\n</body>\n</html>","x":586,"y":1749,"wires":[["c433a1b9.252a8"]]},{"id":"d0c4c947.e3b1b8","type":"comment","z":"4499b290.3eec5c","name":"Iframe embedded inside Map widget node","info":"","x":444.5,"y":1790,"wires":[]},{"id":"f906d86d.fa7ac8","type":"inject","z":"4499b290.3eec5c","name":"","topic":"","payload":"[{\"lat\":49.268311, \"lng\":-123.148146, \"description\":\"awefa\", \"iconUrl\":\"http://cdn.mysitemyway.com/etc-mysitemyway/icons/legacy-previews/icons-256/pink-jelly-icons-arrows/009173-pink-jelly-icon-arrows-triangle-solid-left.png\"},{\"lat\":49.265311, \"lng\":-123.148146, \"description\":\"awefa\", \"iconUrl\":\"http://cdn.mysitemyway.com/etc-mysitemyway/icons/legacy-previews/icons-256/pink-jelly-icons-arrows/009173-pink-jelly-icon-arrows-triangle-solid-left.png\"}]","payloadType":"json","repeat":"","crontab":"","once":false,"x":531,"y":1697,"wires":[["7d033e9a.d1131"]]},{"id":"88f77589.0122d8","type":"ui_group","z":"","name":"Test","tab":"2b906797.81baa8","disp":true,"width":"24"},{"id":"2b906797.81baa8","type":"ui_tab","z":"","name":"Test2","icon":"dashboard"}]