diff --git a/README.md b/README.md index 9c78655..59e9c3e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ map web page for plotting "things" on. ![Map Image](https://dceejay.github.io/pages/images/redmap.png) ### Changes + - v1.0.22 - Add example how to embed into Node-RED-Dashboard template. - v1.0.21 - If you specify range and icon then you get a marker and a range circle, if you just specify range with no icon, you just get a circle, and vice versa. - v1.0.20 - Add buildings overlay. - v1.0.19 - Add circle mode - specify name, lat, lon and radius. diff --git a/examples/Map in Dashboard.json b/examples/Map in Dashboard.json new file mode 100644 index 0000000..ae68556 --- /dev/null +++ b/examples/Map in Dashboard.json @@ -0,0 +1,158 @@ +[ + { + "id": "104f9b89.5daf04", + "type": "worldmap", + "z": "5ab56e5e.449a5", + "name": "", + "lat": "", + "lon": "", + "zoom": "", + "layer": "OSM", + "cluster": "", + "maxage": "", + "usermenu": "hide", + "panit": "true", + "x": 490, + "y": 280, + "wires": [] + }, + { + "id": "7892d55a.40864c", + "type": "inject", + "z": "5ab56e5e.449a5", + "name": "", + "topic": "", + "payload": "", + "payloadType": "str", + "repeat": "", + "crontab": "", + "once": false, + "x": 130, + "y": 220, + "wires": [ + [ + "45dc04c5.811fcc" + ] + ] + }, + { + "id": "45dc04c5.811fcc", + "type": "function", + "z": "5ab56e5e.449a5", + "name": "", + "func": "// create random position\nvar lat = 51 + Math.random() * 0.2;\nvar lon = -1.45 + Math.random() * 0.2;\nmsg.payload={lat:lat, lon:lon, name:\"Mike\", icon:\"male\", url:\"IBM link\"};\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 310, + "y": 280, + "wires": [ + [ + "104f9b89.5daf04" + ] + ] + }, + { + "id": "39ae2a4d.5a6f06", + "type": "inject", + "z": "5ab56e5e.449a5", + "name": "", + "topic": "", + "payload": "/red/worldmap", + "payloadType": "str", + "repeat": "", + "crontab": "", + "once": true, + "x": 140, + "y": 340, + "wires": [ + [ + "a8660ccf.d7166" + ] + ] + }, + { + "id": "be72c0ae.5925b", + "type": "ui_template", + "z": "5ab56e5e.449a5", + "group": "c60f4e05.ebb48", + "name": "", + "order": 0, + "width": "6", + "height": "6", + "format": "
", + "storeOutMessages": true, + "fwdInMessages": true, + "x": 480, + "y": 340, + "wires": [ + [] + ] + }, + { + "id": "a8660ccf.d7166", + "type": "template", + "z": "5ab56e5e.449a5", + "name": "", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "", + "x": 310, + "y": 340, + "wires": [ + [ + "be72c0ae.5925b" + ] + ] + }, + { + "id": "79411e5e.1af57", + "type": "ui_button", + "z": "5ab56e5e.449a5", + "name": "", + "group": "c60f4e05.ebb48", + "order": 0, + "width": 0, + "height": 0, + "label": "Move Mike", + "color": "", + "icon": "fa-male", + "payload": "", + "payloadType": "str", + "topic": "", + "x": 130, + "y": 280, + "wires": [ + [ + "45dc04c5.811fcc" + ] + ] + }, + { + "id": "235ad210.492b0e", + "type": "comment", + "z": "5ab56e5e.449a5", + "name": "How to embed Map in Dashboard", + "info": "This example shows how to embed the Worldmap \ninto a template node within the `node-red-dashboard`\n\nThe first flow creates a dashboard button that \ngenerates a randon position, with the required \nicon, and passes that to the worldmap. The\nmap is configured to automatically pan to the\nposition of any point that arrives.\n\nThe second flow initialise the dashboard template\nwith the initial map and sets it to a more square shape\nby adjusting the height.", + "x": 180, + "y": 160, + "wires": [] + }, + { + "id": "c60f4e05.ebb48", + "type": "ui_group", + "z": "5ab56e5e.449a5", + "name": "Default", + "tab": "6a3aec18.0bc474", + "disp": true, + "width": "6" + }, + { + "id": "6a3aec18.0bc474", + "type": "ui_tab", + "z": "5ab56e5e.449a5", + "name": "Home", + "icon": "dashboard" + } +] diff --git a/worldmap.html b/worldmap.html index 8b3c6c3..2b9846c 100644 --- a/worldmap.html +++ b/worldmap.html @@ -43,11 +43,22 @@
- zoom levels less than + zoom levels less than
- - Remove markers after seconds + + Remove markers after seconds +
+
+ + + Auto-pan
@@ -84,13 +95,15 @@ category: 'location', color:"darksalmon", defaults: { + name: {value:""}, lat: {value:""}, lon: {value:""}, zoom: {value:""}, layer: {value:""}, cluster: {value:""}, maxage: {value:""}, - name: {value:""} + usermenu: {value:"show"}, + panit: {value:"false"} }, inputs:1, outputs:0, diff --git a/worldmap.js b/worldmap.js index f4b0377..a9dfc16 100644 --- a/worldmap.js +++ b/worldmap.js @@ -29,6 +29,8 @@ module.exports = function(RED) { this.layer = n.layer || ""; this.cluster = n.cluster || ""; this.maxage = n.maxage || ""; + this.showmenu = n.usermenu || "show"; + this.panit = n.panit || "false"; var node = this; //node.log("Serving map from "+__dirname+" as "+RED.settings.httpNodeRoot.slice(0,-1)+"/worldmap"); RED.httpNode.use("/worldmap", express.static(__dirname + '/worldmap')); @@ -49,6 +51,8 @@ module.exports = function(RED) { if (node.layer && node.layer.length > 0) { c.layer = node.layer; } if (node.cluster && node.cluster.length > 0) { c.cluster = node.cluster; } if (node.maxage && node.maxage.length > 0) { c.maxage = node.maxage; } + c.showmenu = node.showmenu; + c.panit = node.panit; client.emit("worldmapdata",{command:c}); } }); @@ -57,14 +61,11 @@ module.exports = function(RED) { node.status({fill:"green",shape:"ring",text:"connected "+socket.engine.clientsCount}); }); node.on("close", function() { + node.status({}); client.disconnect(true); }); } - - node.on("close", function() { - node.status({}); - //socket.close(); - }); + node.status({}); socket.on('connection', callback); } RED.nodes.registerType("worldmap",WorldMap); diff --git a/worldmap/index.html b/worldmap/index.html index 8ae81f0..1b4ec03 100644 --- a/worldmap/index.html +++ b/worldmap/index.html @@ -77,7 +77,7 @@ Help
- + @@ -120,25 +120,33 @@ var maxage = 600; // default max age of icons on map in seconds - cleared afte var baselayername = "OSM grey"; // Default base layer OSM but uniform grey var ibmfoot = " © IBM 2015,2016" var initialposition = false; +var inIframe = false; +var showUserMenu = true; // Create the socket var ws = io(); ws.on('connect', function() { console.log("CONNECTED"); - document.getElementById("foot").innerHTML = ""+ibmfoot+""; + if (!inIframe) { + document.getElementById("foot").innerHTML = ""+ibmfoot+""; + } ws.emit("worldmap",{action:"connected"}); }); ws.on('disconnect', function() { console.log("DISCONNECTED"); - document.getElementById("foot").innerHTML = ""+ibmfoot+""; + if (!inIframe) { + document.getElementById("foot").innerHTML = ""+ibmfoot+""; + } setTimeout(function() { ws.connect(); }, 2500); }); ws.on('error', function() { console.log("ERROR"); - document.getElementById("foot").innerHTML = ""+ibmfoot+""; + if (!inIframe) { + document.getElementById("foot").innerHTML = ""+ibmfoot+""; + } setTimeout(function() { ws.connect(); }, 2500); }); @@ -171,6 +179,7 @@ map = new L.map('map').setView(startpos, startzoom); // Move some bits around if in an iframe if (window.self !== window.top) { console.log("IN an iframe"); + inIframe = true; (document.getElementById("topbar").style.display="none"); (document.getElementById("map").style.top="0px"); (document.getElementById("results").style.right="50px"); @@ -181,36 +190,43 @@ if (window.self !== window.top) { (document.getElementById("bars").style.display="none"); (document.getElementById("menu").style.right="8px"); (document.getElementById("menu").style.borderRadius="6px"); - L.easyButton( 'fa-bars fa-lg', function() { toggleMenu(); }, "Toggle menu", "topright").addTo(map); + if (showUserMenu) { + var menuButton = L.easyButton( 'fa-bars fa-lg', function() { toggleMenu(); }, "Toggle menu", "topright").addTo(map); + } } else { console.log("NOT in an iframe") window.onbeforeunload = function(e) { return 'Reloading will delete all the local markers, including any drawing on the "drawing" layer'; }; + if (!showUserMenu) { + document.getElementById("bars").style.display="none"; + } } -// Add the fullscreen button -L.control.fullscreen().addTo(map); +if (!inIframe) { + // Add the fullscreen button + L.control.fullscreen().addTo(map); -// map.on('fullscreenchange', function () { -// if (map.isFullscreen()) { console.log('entered fullscreen') } -// else { console.log('exited fullscreen'); } -// }); + // map.on('fullscreenchange', function () { + // if (map.isFullscreen()) { console.log('entered fullscreen') } + // else { console.log('exited fullscreen'); } + // }); -// Add the locate my position button -L.easyButton( 'fa-crosshairs fa-lg', function() { - map.locate({setView:true, maxZoom:16}); -}, "Locate me").addTo(map); + // Add the locate my position button + L.easyButton( 'fa-crosshairs fa-lg', function() { + map.locate({setView:true, maxZoom:16}); + }, "Locate me").addTo(map); -// Add the measure/ruler button -L.Control.measureControl().addTo(map); + // Add the measure/ruler button + L.Control.measureControl().addTo(map); -// Create the clear heatmap button -var clrHeat = L.easyButton( 'Reset Heatmap', function() { - console.log("reset heatmap"); - heat.setLatLngs([]); -}, "Clears the current heatmap", "bottomright"); + // Create the clear heatmap button + var clrHeat = L.easyButton( 'Reset Heatmap', function() { + console.log("reset heatmap"); + heat.setLatLngs([]); + }, "Clears the current heatmap", "bottomright"); +} // Handle the dialog for popup help var dialog = document.querySelector('dialog'); @@ -511,30 +527,30 @@ basemaps["OSM"] = osm; // Extra Leaflet map layers from http://leaflet-extras.github.io/leaflet-providers/preview/ var Esri_WorldStreetMap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', { - attribution: 'Tiles © Esri — Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012' + attribution: 'Tiles © Esri' }); basemaps["Esri"] = Esri_WorldStreetMap; var Esri_WorldImagery = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { - attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' + attribution: 'Tiles © Esri' }); basemaps["Esri Satellite"] = Esri_WorldImagery; var Esri_WorldShadedRelief = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}', { - attribution: 'Tiles © Esri — Source: Esri', + attribution: 'Tiles © Esri', maxNativeZoom: 13 }); basemaps["Esri Terrain"] = Esri_WorldShadedRelief; var Esri_OceanBasemap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}', { - attribution: 'Tiles © Esri — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri', + attribution: 'Tiles © Esri', maxNativeZoom: 10 }); basemaps["Esri Ocean"] = Esri_OceanBasemap; var OpenMapSurfer_Roads = L.tileLayer('http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}', { maxZoom: 18, - attribution: 'Imagery from GIScience Research Group @ University of Heidelberg — Map data © OpenStreetMap' + attribution: 'Imagery from University of Heidelberg — Map data © OpenStreetMap' }); basemaps["Mapsurfer"] = OpenMapSurfer_Roads; @@ -548,7 +564,7 @@ basemaps["Mapsurfer"] = OpenMapSurfer_Roads; //basemaps["MapQuest OSM"] = MapQuestOpen_OSM; var Esri_NatGeoWorldMap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}', { - attribution: 'Tiles © Esri — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC', + attribution: 'Tiles © Esri', maxNativeZoom: 12 }); basemaps["Nat Geo"] = Esri_NatGeoWorldMap; @@ -563,7 +579,7 @@ var NLS_OS_opendata = L.tileLayer('http://geo.nls.uk/maps/opendata/{z}/{x}/{y}.p basemaps["UK OS Opendata"] = NLS_OS_opendata; var NLS_OS_1919_1947 = L.tileLayer( 'http://nls-{s}.tileserver.com/nls/{z}/{x}/{y}.jpg', { - attribution: 'Historical Maps Layer, 1919-1947 from the NLS Maps API', + attribution: 'Historical Maps Layer, from NLS Maps', bounds: [[49.6, -12], [61.7, 3]], minZoom: 1, maxZoom: 18, @@ -635,7 +651,7 @@ map.on('draw:created', function (e) { overlays["roads"] = L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.{ext}', { type: 'hyb', ext: 'png', - attribution: 'Tiles Courtesy of MapQuest — Map data © OpenStreetMap', + attribution: 'MapQuest — Map data © OpenStreetMap', subdomains: '1234', opacity: 0.9 }); @@ -671,7 +687,9 @@ if ( window.localStorage.hasOwnProperty("lastlayer") ) { basemaps[baselayername].addTo(map); // Add the layers control widget -var layercontrol = L.control.layers(basemaps, overlays).addTo(map); +if (!inIframe) { + var layercontrol = L.control.layers(basemaps, overlays).addTo(map); +} // Layer control based on select box rather than radio buttons. //var layercontrol = L.control.selectLayers(basemaps, overlays).addTo(map); @@ -693,7 +711,7 @@ var delMarker = function(dname) { // the MAIN add something to map function function setMarker(data) { - //console.log(typeof data, data); + console.log(typeof data, data); var ll; var stay = popped; @@ -707,7 +725,9 @@ function setMarker(data) { //zoomToBoundsOnClick:false }).addTo(map); overlays[lay] = layers[lay]; - layercontrol.addOverlay(layers[lay],lay); + if (!inIframe) { + layercontrol.addOverlay(layers[lay],lay); + } } if (typeof markers[data.name] != "undefined") { layers[lay].removeLayer(markers[data.name]); } @@ -927,6 +947,20 @@ function doCommand(cmd) { if (cmd.hasOwnProperty("init") && initialposition) { return; } + if (cmd.hasOwnProperty("panit")) { + if (cmd.panit === "true") { panit = true; } + else { panit = false; } + } + if (cmd.hasOwnProperty("showmenu")) { + if ((cmd.showmenu === "hide") && (showUserMenu === true)) { + showUserMenu = false; + map.removeControl(menuButton); + } + else if ((cmd.showmenu === "show") && (showUserMenu === false)) { + showUserMenu = true; + map.addControl(menuButton); + } + } var existsalready = false; // Add a new base map layer if (cmd.map && cmd.map.hasOwnProperty("name") && cmd.map.hasOwnProperty("url") && cmd.map.hasOwnProperty("opt")) { diff --git a/worldmap/worldmap.appcache b/worldmap/worldmap.appcache index 2c919c3..a935106 100644 --- a/worldmap/worldmap.appcache +++ b/worldmap/worldmap.appcache @@ -1,5 +1,5 @@ CACHE MANIFEST -# date: Nov 11th v1.0.21 +# date: Nov 22nd v1.0.22 CACHE: index.html