Worldmap - Working with Markers example

What this example provides:

  • Save markers you create on the map between deployments, restarts, page refreshes.
  • Warns user if marker name is already used and does not overwrite marker.
  • Outlines step by step how to add a marker with name, layer, icon, and icon colour.

First import this flow

[{"id":"150b582b.3e6d68","type":"tab","label":"worldmap-markers","disabled":false,"info":""},{"id":"f1e92b11.aa1ed","type":"worldmap","z":"150b582b.3e6d68","name":"","lat":"","lon":"","zoom":"","layer":"","cluster":"","maxage":"","usermenu":"show","layers":"show","panit":"false","panlock":"false","zoomlock":"false","hiderightclick":"false","coords":"none","showgrid":"false","allowFileDrop":"false","path":"/worldmap-markers","x":1050,"y":340,"wires":[]},{"id":"15d68878.b3108","type":"worldmap in","z":"150b582b.3e6d68","name":"","path":"/worldmap-markers","events":"all","x":130,"y":200,"wires":[["c4730cf6.3bec6","81c551e3.fc3ad","1e17eaea.c0ee2d"]]},{"id":"a8132d83.b93f38","type":"inject","z":"150b582b.3e6d68","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":100,"wires":[["958ce24.30041a"]]},{"id":"958ce24.30041a","type":"file in","z":"150b582b.3e6d68","name":"","filename":"worldmap-icon-example.dat","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":340,"y":100,"wires":[["bcde3220.4f3c78"]]},{"id":"322bc938.180706","type":"debug","z":"150b582b.3e6d68","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":970,"y":100,"wires":[]},{"id":"4cd1ebe4.0a6564","type":"comment","z":"150b582b.3e6d68","name":"Load stored Markers from file to flow.markers, We only want to call on the file once at start/deploy of node-red","info":"","x":410,"y":60,"wires":[]},{"id":"bcde3220.4f3c78","type":"json","z":"150b582b.3e6d68","name":"","property":"payload","action":"obj","pretty":false,"x":550,"y":100,"wires":[["b6ed23f0.2c9f9"]]},{"id":"b6ed23f0.2c9f9","type":"change","z":"150b582b.3e6d68","name":"set flow.markers to msg.payload","rules":[{"t":"set","p":"markers","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":100,"wires":[["322bc938.180706"]]},{"id":"13bc8399.64440c","type":"function","z":"150b582b.3e6d68","name":"","func":"//Check if stored markers in MarkersObjectArray exists, if not create it\nvar flowMarkersObjectArray = flow.get('MarkersObjectArray')||[];\n//Send the markers to msg payload to be processed by split node\nmsg.payload = flowMarkersObjectArray;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":200,"wires":[["bfe6d785.17955"]]},{"id":"c4730cf6.3bec6","type":"switch","z":"150b582b.3e6d68","name":"connected?","property":"payload.action","propertyType":"msg","rules":[{"t":"eq","v":"connected","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":330,"y":200,"wires":[["13bc8399.64440c"]]},{"id":"bfe6d785.17955","type":"split","z":"150b582b.3e6d68","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":770,"y":200,"wires":[["f1e92b11.aa1ed"]]},{"id":"81c551e3.fc3ad","type":"switch","z":"150b582b.3e6d68","name":"point?","property":"payload.action","propertyType":"msg","rules":[{"t":"eq","v":"point","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":340,"wires":[["e722ddbe.766658"]]},{"id":"e722ddbe.766658","type":"function","z":"150b582b.3e6d68","name":"","func":"//Check if stored markers in MarkersObjectArray exists, if not create it\nvar flowMarkersObjectArray = flow.get('MarkersObjectArray')||[];\n\n//Check if marker name is already used\nif (flowMarkersObjectArray.some(element => element.name === msg.payload.name)) {\n    //flowMarkersObjectArray contains msg.payload.name value that is already in use\n    //warn user and don't add it to the flowMarkersObjectArray\n    node.warn(\"Marker name: \" + msg.payload.name + \" is already used. Please use a diffrent name or Delete current marker with that name\");\n    \n    //send msg\n    msg.payload = flowMarkersObjectArray;\n    return msg;\n}\n\nelse {\n    //append new marker object to flowMarkersObjectArray\n    var newMarker = {\n        \"name\" : msg.payload.name, \n        \"layer\": msg.payload.layer, \n        \"lat\" : msg.payload.lat, \n        \"lon\" : msg.payload.lon, \n        \"icon\" : msg.payload.icon, \n        \"iconColor\" : msg.payload.iconColor\n        };\n    // append new value to the array\n    flowMarkersObjectArray.push(newMarker);\n\n    //update the flow.MarkersObjectArray\n    flow.set('MarkersObjectArray',flowMarkersObjectArray);\n\n    //send msg\n    msg.payload = flowMarkersObjectArray;\n    return msg;\n}\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":340,"wires":[["3dc01673.533fda","9ae27151.fa55e8"]]},{"id":"3dc01673.533fda","type":"split","z":"150b582b.3e6d68","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":770,"y":340,"wires":[["f1e92b11.aa1ed","21336764.52b88"]]},{"id":"9ae27151.fa55e8","type":"json","z":"150b582b.3e6d68","name":"","property":"payload","action":"str","pretty":false,"x":490,"y":300,"wires":[["bff4167b.e46ae"]]},{"id":"bff4167b.e46ae","type":"file","z":"150b582b.3e6d68","name":"","filename":"worldmap-icon-example.dat","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":700,"y":300,"wires":[[]]},{"id":"1e17eaea.c0ee2d","type":"switch","z":"150b582b.3e6d68","name":"delete?","property":"payload.action","propertyType":"msg","rules":[{"t":"eq","v":"delete","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":320,"y":480,"wires":[["3c3a9b96.199ff4"]]},{"id":"3c3a9b96.199ff4","type":"function","z":"150b582b.3e6d68","name":"","func":"//Check if stored markers in MarkersObjectArray exists, if not create it\nvar flowMarkersObjectArray = flow.get('MarkersObjectArray')||[];\n\n//Get the index in the array that the marker name is located\nvar index = flowMarkersObjectArray.findIndex(element => element.name === msg.payload.name);\n\n//Delete marker from flowMarkersObjectArray if its in the array\nif (index > -1) {\n    flowMarkersObjectArray.splice(index, 1);\n    //update the flow.MarkersObjectArray\n    flow.set('MarkersObjectArray',flowMarkersObjectArray);\n\n    //send msg\n    msg.payload = flowMarkersObjectArray;\n    return msg;\n}\n\n\nelse {\n    //warn user and don't add it to the flowMarkersObjectArray\n    node.warn(\"Unable to Delete Marker name: \" + msg.payload.name + \"as it was not found in the MarkersObjectArray\");\n    \n    //send msg\n    msg.payload = flowMarkersObjectArray;\n    return msg;\n}\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":480,"wires":[["db529cfe.9b6cf8","3de0a07.f2989e"]]},{"id":"db529cfe.9b6cf8","type":"json","z":"150b582b.3e6d68","name":"","property":"payload","action":"str","pretty":false,"x":490,"y":440,"wires":[["97808541.30ee5"]]},{"id":"97808541.30ee5","type":"file","z":"150b582b.3e6d68","name":"","filename":"worldmap-icon-example.dat","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":700,"y":440,"wires":[[]]},{"id":"3de0a07.f2989e","type":"split","z":"150b582b.3e6d68","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":770,"y":480,"wires":[["f1e92b11.aa1ed"]]},{"id":"b1ca1413.bc4ff8","type":"comment","z":"150b582b.3e6d68","name":"Load Markers from flow","info":"","x":540,"y":160,"wires":[]},{"id":"42dcf03.e0cf01","type":"comment","z":"150b582b.3e6d68","name":"Add a new marker to the map/flow/storage","info":"","x":600,"y":260,"wires":[]},{"id":"38b479c0.72e1b6","type":"comment","z":"150b582b.3e6d68","name":"Delete marker from the map/flow/storage","info":"","x":600,"y":400,"wires":[]},{"id":"21336764.52b88","type":"debug","z":"150b582b.3e6d68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1010,"y":260,"wires":[]}]

Open a new browser tab and goto http://your_ip_address:1880/worldmap-markers/

Right Click on the map. you should get Add marker.
01mp

You need to ender a value for the name at minimum but lets change the default layer, icon, the icon colour, and even add a headding.

test-01,fa-at,testlayer,green,90.3

test-01 is the name.
fa-at is the icon we chose.
testlayer is the layer on the map we will use.
green is the color of the icon we want.
90.3 is the heading if the marker is for somting in motion.

You can play around with these values if you like.
For icons see - Font Awesome Icons
For color see - 147 Colors | CSS Color Names

02mp

After pressing enter you should see a @ symble in the color green on the map.
Also you should see the new layer we created. By enabling and disabling the layer you can control the markers you add by layer name.

03mp

By right clicking on the marker you can delete it.

04mp

All of the above is just a over view. The function nodes in the flow are what allows all this to be stored and used later.

Take a look at the functions and how they work so you can build on it and create something for your needs.

Nice - are you going to add it to flows.nodered.og as well ? Thanks

Good Idea - Did not think of doing that. I'll get around to it ......

Curently working on the dashboard version of Guide:
Allow user to create / edit / delete marker with drop downs to select things like colour, icon, etc.

What do you think would be the next best guide. What is your most common worldmap question by users that could be solved by some photos and a step by step howto ?

Well the default addMarker right click context menu could be improved along the lines you suggest as a start - so then the guide may be unnecessary :slight_smile:

Not really sure re common questions - don't get too many... (it IS almost perfect after all :wink:
sometimes - how do I use my own icons ?