node-red-contrib-web-worldmap 5.0.6 → 5.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ### Change Log for Node-RED Worldmap
2
2
 
3
+ - v5.0.8 - Fix flag handling for SIDC 2525D, add example.
4
+ - v5.0.7 - Allow Tooltip options (see new example). #PR295.
3
5
  - v5.0.6 - Tweak SIDC flag handling slightly to show direction if available and moving.
4
6
  - v5.0.4 - Tweak CoT handling slightly.
5
7
  - v5.0.3 - Add great context menu example flow. PR#290. Bump express lib. PR#291.
package/README.md CHANGED
@@ -13,32 +13,34 @@ Feel free to [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%
13
13
 
14
14
  ### Updates
15
15
 
16
- - v5.0.6 - Tweak SIDC flag handling slightly to show direction if available and moving.
17
- - v5.0.4 - Tweak CoT handling slightly.
18
- - v5.0.3 - Add great context menu example flow. PR#290. Bump express lib. PR#291.
19
- - v5.0.2 - Fix sidcEdgeIcon docs PR#289.
20
- - v5.0.1 - Fix isArray error PR #288.
21
- - v5.0.0 - v5.0.0 - Feedback cleanup PR#281, edgeicons option PR#287, bump libs for vuln fixes.
22
- - v4.9.0 - If payload.flag is two char ISO code replace it with flag emoji. Revert part of PR #271
23
- - v4.8.1 - Slight tidy of some of the geojson handling
24
- - v4.8.0 - Merged PR for feedback functionality cleanup and example. PR #271 and #272
25
- - v4.7.0 - Update pmtiles library, fix feedback function inconsistency. Issue #270
26
- - v4.6.5 - Let geojson allow for generic overrides with .icon and .layer.
27
- - v4.6.4 - Fix deletion of layers logic to actually fully remove points.
28
- - v4.6.3 - Fix sending of layer events when not wanted. Issue #262
29
- - v4.6.2 - Fix multiple use of contextmenu feedback. Issue #259
30
- - v4.6.1 - Let default pmtiles be light/dark or monocolored.
31
- - v4.5.2 - Tidy up when pmtiles removed.
32
- - v4.5.0 - Fix pmtiles to look for maps in userdir rather than modules
33
- - v4.4.0 - Add quad(copter) drone icon.
34
- - v4.3.3 - Fix for objects changing layers.
35
- - v4.3.2 - Fix geojson popup missing label name.
36
- - v4.3.1 - Small fix to icon transparency, and routing detail.
37
- - v4.3.0 - Add support for PMtiles files.
38
- - v4.2.1 - Revert use of optional chaining to extend life slightly. Issue #252
39
- - v4.2.0 - Let icons also be inline images data:image...
40
- - v4.1.0 - Add optional SOG, COG, altft, altm input properties.
41
- - v4.0.0 - Breaking - Better context menu variable substitution and retention
16
+ - v5.0.8 - Fix flag handling for SIDC 2525D, add example.
17
+ - v5.0.7 - Allow Tooltip options (see new example). #PR295.
18
+ - v5.0.6 - Tweak SIDC flag handling slightly to show direction if available and moving.
19
+ - v5.0.4 - Tweak CoT handling slightly.
20
+ - v5.0.3 - Add great context menu example flow. PR#290. Bump express lib. PR#291.
21
+ - v5.0.2 - Fix sidcEdgeIcon docs PR#289.
22
+ - v5.0.1 - Fix isArray error PR #288.
23
+ - v5.0.0 - v5.0.0 - Feedback cleanup PR#281, edgeicons option PR#287, bump libs for vuln fixes.
24
+ - v4.9.0 - If payload.flag is two char ISO code replace it with flag emoji. Revert part of PR #271
25
+ - v4.8.1 - Slight tidy of some of the geojson handling
26
+ - v4.8.0 - Merged PR for feedback functionality cleanup and example. PR #271 and #272
27
+ - v4.7.0 - Update pmtiles library, fix feedback function inconsistency. Issue #270
28
+ - v4.6.5 - Let geojson allow for generic overrides with .icon and .layer.
29
+ - v4.6.4 - Fix deletion of layers logic to actually fully remove points.
30
+ - v4.6.3 - Fix sending of layer events when not wanted. Issue #262
31
+ - v4.6.2 - Fix multiple use of contextmenu feedback. Issue #259
32
+ - v4.6.1 - Let default pmtiles be light/dark or monocolored.
33
+ - v4.5.2 - Tidy up when pmtiles removed.
34
+ - v4.5.0 - Fix pmtiles to look for maps in userdir rather than modules
35
+ - v4.4.0 - Add quad(copter) drone icon.
36
+ - v4.3.3 - Fix for objects changing layers.
37
+ - v4.3.2 - Fix geojson popup missing label name.
38
+ - v4.3.1 - Small fix to icon transparency, and routing detail.
39
+ - v4.3.0 - Add support for PMtiles files.
40
+ - v4.2.1 - Revert use of optional chaining to extend life slightly. Issue #252
41
+ - v4.2.0 - Let icons also be inline images data:image...
42
+ - v4.1.0 - Add optional SOG, COG, altft, altm input properties.
43
+ - v4.0.0 - Breaking - Better context menu variable substitution and retention
42
44
  Now uses ${name} syntax rather than $name so we can handle user defined variables in context menus.
43
45
 
44
46
  - see [CHANGELOG](https://github.com/dceejay/RedMap/blob/master/CHANGELOG.md) for full list of changes.
@@ -88,6 +90,7 @@ Optional properties for **msg.payload** include
88
90
  - **popup** : html to fill the popup if you don't want the automatic default of the properties list. Using this overrides photourl, videourl and weblink options.
89
91
  - **label** : displays the contents as a permanent label next to the marker, or
90
92
  - **tooltip** : displays the contents when you hover over the marker. (Mutually exclusive with label. Label has priority)
93
+ - **tooltipOptions** : custom tooltip/label options (offset, direction, permanent, sticky, interactive, opacity, className) )
91
94
  - **contextmenu** : an html fragment to display on right click of marker - defaults to delete marker. You can specify `${name}` to substitute in the name of the marker. Set to `""` to disable just this instance.
92
95
 
93
96
  Any other `msg.payload` properties will be added to the icon popup text box. This can be
@@ -142,6 +145,10 @@ SIDC codes can be generated using the online tool - https://www.spatialillusions
142
145
 
143
146
  There are lots of extra options you can specify as `msg.payload.options` - see the <a href="https://spatialillusions.com/milsymbol/documentation.html" target="mapinfo">milsymbol docs here</a>.
144
147
 
148
+ Note: If the SIDC code is a 2525C 15 characters long, where chars 13 and 14 are a country code - then the country flag emoji is added to the staffComments field of the icon. If it's a 20 char 2525D code then the options:country property will be used to create the flag.
149
+
150
+ Note: Not all browsers/OS support unicode emoji - if you can see the Swiss flag here (🇨🇭) then you may be OK.
151
+
145
152
  #### TAK Visualisation
146
153
 
147
154
  Users of [TAK](https://tak.gov) can use the [TAK ingest node](https://flows.nodered.org/node/node-red-contrib-tak-registration) to create a JSON formatted TAK event object, received from a TAK server. This can be fed directly into the worldmap node.
@@ -0,0 +1,83 @@
1
+ [
2
+ {
3
+ "id": "ec9da974.051b48",
4
+ "type": "inject",
5
+ "z": "f6f2187d.f17ca8",
6
+ "name": "",
7
+ "repeat": "",
8
+ "crontab": "",
9
+ "once": false,
10
+ "topic": "",
11
+ "payload": "",
12
+ "payloadType": "str",
13
+ "x": 1010,
14
+ "y": 560,
15
+ "wires": [
16
+ [
17
+ "f77a7ed4.f955d"
18
+ ]
19
+ ]
20
+ },
21
+ {
22
+ "id": "f77a7ed4.f955d",
23
+ "type": "function",
24
+ "z": "f6f2187d.f17ca8",
25
+ "name": "Car + Label",
26
+ "func": "var thing = {\n name:\"Jason Isaacs\", \n lat:51, \n lon:-1.45,\n icon:\"car\",\n iconColor:\"darkred\",\n extrainfo:\"Hello to Jason Isaacs\",\n label:\"This is a custom label\",\n tooltipOptions: {\"offset\" : [-100,-100], \"permanent\" : true, \"opacity\" : 1, \"direction\" : \"top\", \"className\" : \"tooltip\"}\n};\nmsg.payload = thing;\nreturn msg;",
27
+ "outputs": 1,
28
+ "timeout": "",
29
+ "noerr": 0,
30
+ "initialize": "",
31
+ "finalize": "",
32
+ "libs": [],
33
+ "x": 1230,
34
+ "y": 560,
35
+ "wires": [
36
+ [
37
+ "f83930ff.b21488"
38
+ ]
39
+ ]
40
+ },
41
+ {
42
+ "id": "cd09f7be.079518",
43
+ "type": "comment",
44
+ "z": "f6f2187d.f17ca8",
45
+ "name": "Simple map - click inject to send info to map.",
46
+ "info": "Adds a map at http://(your-server-ip):1880/worldmap. \n\nThe `function` node creates an object with some basic properties required to add to a map.",
47
+ "x": 1170,
48
+ "y": 500,
49
+ "wires": []
50
+ },
51
+ {
52
+ "id": "f83930ff.b21488",
53
+ "type": "worldmap",
54
+ "z": "f6f2187d.f17ca8",
55
+ "name": "",
56
+ "lat": "",
57
+ "lon": "",
58
+ "zoom": "",
59
+ "layer": "OSMG",
60
+ "cluster": "",
61
+ "maxage": "",
62
+ "usermenu": "show",
63
+ "layers": "show",
64
+ "panit": "false",
65
+ "panlock": "false",
66
+ "zoomlock": "false",
67
+ "hiderightclick": "false",
68
+ "coords": "none",
69
+ "showgrid": "false",
70
+ "showruler": "true",
71
+ "allowFileDrop": "false",
72
+ "path": "/worldmap",
73
+ "overlist": "DR,CO,RA,DN,HM",
74
+ "maplist": "OSMG,OSMC,EsriC,EsriS,EsriT,EsriO,EsriDG,NatGeo,UKOS,OpTop",
75
+ "mapname": "",
76
+ "mapurl": "",
77
+ "mapopt": "",
78
+ "mapwms": false,
79
+ "x": 1400,
80
+ "y": 560,
81
+ "wires": []
82
+ }
83
+ ]
@@ -0,0 +1 @@
1
+ [{"id":"2e5fb67b7383373a","type":"worldmap","z":"51335a8bc38f387c","name":"","lat":"","lon":"","zoom":"","layer":"","cluster":"","maxage":"","usermenu":"show","layers":"show","panit":"false","panlock":"false","zoomlock":"false","hiderightclick":"false","coords":"false","showgrid":"false","showruler":"false","allowFileDrop":"false","path":"/worldmap","overlist":"DR,CO,RA,DN","maplist":"OSMG,OSMC,EsriC,EsriS,UKOS","mapname":"","mapurl":"","mapopt":"","mapwms":false,"x":740,"y":120,"wires":[]},{"id":"a43cf3b6fb5c779a","type":"inject","z":"51335a8bc38f387c","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":120,"wires":[["814986215a0adc67"]]},{"id":"814986215a0adc67","type":"function","z":"51335a8bc38f387c","name":"2525C with country","func":"msg.payload = {\n name: \"Dave\",\n lat: 51.0,\n lon: -1.20,\n SIDC: \"SFAPC-------GBR\",\n options:{\n staffComments: \"Comment A\",\n direction:220,\n speed:\"111\",\n targetNumber:\"AB1234\",\n additionalInformation:\"some more info\",\n commonIdentifier:\"Hawk\",\n type:\"Some Type\"\n }\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":120,"wires":[["2e5fb67b7383373a"]]},{"id":"22188e4b94786964","type":"inject","z":"51335a8bc38f387c","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":180,"wires":[["b33a82ee22d45a25"]]},{"id":"b33a82ee22d45a25","type":"function","z":"51335a8bc38f387c","name":"2525D with flag","func":"msg.payload = {\n name: \"Jon\",\n lat: 51.1,\n lon: -1.20,\n SIDC: \"10061500351105000000\",\n flag: \"DE\",\n options: {\n staffComments: \"Comment B\",\n direction: 300,\n speed: \"110\",\n additionalInformation: \"some more info\",\n }\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":180,"wires":[["2e5fb67b7383373a"]]},{"id":"a505c3cbe0ae507a","type":"inject","z":"51335a8bc38f387c","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":240,"wires":[["a75fc8cb90ab6b1b"]]},{"id":"a75fc8cb90ab6b1b","type":"function","z":"51335a8bc38f387c","name":"2525D with country","func":"msg.payload = {\n name: \"Mike\",\n lat: 51.0,\n lon: -1.50,\n SIDC: \"10032700000000000000\",\n options: {\n staffComments: \"Comment C\",\n direction: 120,\n country: \"FR\",\n additionalInformation: \"yet more info\",\n }\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":240,"wires":[["2e5fb67b7383373a"]]},{"id":"84429b6fce72a6e1","type":"inject","z":"51335a8bc38f387c","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":60,"wires":[["374f2d903bb3dc01"]]},{"id":"374f2d903bb3dc01","type":"function","z":"51335a8bc38f387c","name":"2525C with flag","func":"msg.payload = {\n name: \"Joe\",\n lat: 51.1,\n lon: -1.5,\n SIDC: \"SUGPUCATM---\",\n flag: \"CH\",\n options:{\n staffComments: \"Comment D\",\n direction:60,\n speed:\"111\"\n }\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":60,"wires":[["2e5fb67b7383373a"]]}]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-web-worldmap",
3
- "version": "5.0.6",
3
+ "version": "5.0.8",
4
4
  "description": "A Node-RED node to provide a web page of a world map for plotting things on.",
5
5
  "dependencies": {
6
6
  "@turf/bezier-spline": "~7.1.0",
@@ -2123,13 +2123,28 @@ function setMarker(data) {
2123
2123
  }
2124
2124
  opts.size = opts.size || sz;
2125
2125
  opts.size = opts.size * (opts.scale || 1);
2126
- if (data.SIDC.length > 12 && data.SIDC.substr(12,2) !== "**") {
2126
+ if (data.SIDC.length > 12 && /^[A-Za-z]{2}$/gm.test(data.SIDC.substr(12,2))) {
2127
2127
  var cc = data.SIDC.substr(12,2).toLowerCase();
2128
2128
  opts.country = cc.toUpperCase();
2129
2129
  opts.staffComments = emojify(":flag-"+cc+":") + " " + (opts?.staffComments || "");
2130
- data.flag = emojify(":flag-"+cc+":");
2130
+ data.flag = opts.country.toUpperCase() + " " + emojify(":flag-"+cc+":");
2131
2131
  }
2132
- if (data?.speed) { opts.direction = data?.bearing || data?.hdg || data?.COG }
2132
+ if (data.SIDC.length == 12 && data?.flag && data.flag.length == 2) {
2133
+ opts.staffComments = emojify(":flag-"+data.flag.toLowerCase()+":") + " " + (opts?.staffComments || "");
2134
+ }
2135
+ if (data.SIDC.length == 20) {
2136
+ if (opts?.country && opts.country.length == 2) {
2137
+ data.flag = opts.country.toUpperCase() + " " + emojify(":flag-"+opts.country.toLowerCase()+":");
2138
+ opts.country = data.flag;
2139
+ }
2140
+ else if (data?.flag && data.flag.length == 2) {
2141
+ opts.country = data.flag.toUpperCase() + " " + emojify(":flag-"+data.flag.toLowerCase()+":");
2142
+ }
2143
+ }
2144
+ console.log("OPTS",opts)
2145
+ data.speed = opts?.speed || data?.speed; // If SIDC then options.speed can override the speed.
2146
+ if (data?.speed && !opts?.direction) { opts.direction = data?.track || data?.hdg || data?.heading || data?.COG || data?.bearing }
2147
+ if (data.speed == undefined) { delete data.speed; }
2133
2148
  // escape out any isocodes eg flag symbols
2134
2149
  var optfields = ["additionalInformation","higherFormation","specialHeadquarters","staffComments","type","uniqueDesignation","speed","country"];
2135
2150
  //const regex = /\p{Extended_Pictographic}/ug;
@@ -2229,8 +2244,10 @@ function setMarker(data) {
2229
2244
  // data.flag = mmsiToCountry(data.MMSI)
2230
2245
  // }
2231
2246
  if (data?.flag && data.flag.length == 2) {
2232
- const tflg = emojify(":flag-"+data.flag.toLowerCase()+":");
2233
- if (!tflg.includes("flag-")) { data.flag = tflg; }
2247
+ const tflg = data.flag.toUpperCase() + " " + emojify(":flag-"+data.flag.toLowerCase()+":")
2248
+ if (!tflg.includes("flag-")) {
2249
+ data.flag = tflg;
2250
+ }
2234
2251
  }
2235
2252
  if (data.hasOwnProperty("photourl")) {
2236
2253
  words += "<img src=\"" + data.photourl + "\" style=\"max-width:100%; max-height:250px; margin-top:10px;\"><br/>";
@@ -2289,10 +2306,10 @@ function setMarker(data) {
2289
2306
  // If .label then use that rather than name tooltip
2290
2307
  if (data.label) {
2291
2308
  if (typeof data.label === "boolean" && data.label === true) {
2292
- marker.bindTooltip(data["name"], { permanent:true, direction:"right", offset:labelOffset });
2309
+ marker.bindTooltip(data["name"], data.tooltipOptions || { permanent:true, direction:"right", offset:labelOffset });
2293
2310
  }
2294
2311
  else if (typeof data.label === "string" && data.label.length > 0) {
2295
- marker.bindTooltip(data.label, { permanent:true, direction:"right", offset:labelOffset });
2312
+ marker.bindTooltip(data.label, data.tooltipOptions || { permanent:true, direction:"right", offset:labelOffset });
2296
2313
  }
2297
2314
  delete marker.options.title;
2298
2315
  delete data.label;
@@ -2300,7 +2317,7 @@ function setMarker(data) {
2300
2317
  // otherwise check for .tooltip then use that rather than name tooltip
2301
2318
  else if (data.tooltip) {
2302
2319
  if (typeof data.tooltip === "string" && data.tooltip.length > 0) {
2303
- marker.bindTooltip(data.tooltip, { direction:"bottom", offset:[0,4] });
2320
+ marker.bindTooltip(data.tooltip, data.tooltipOptions || { direction:"bottom", offset:[0,4] });
2304
2321
  delete marker.options.title;
2305
2322
  delete data.tooltip;
2306
2323
  }
@@ -2308,7 +2325,6 @@ function setMarker(data) {
2308
2325
 
2309
2326
  // Add right click contextmenu
2310
2327
  marker = rightmenu(marker);
2311
-
2312
2328
  // Delete more already handled properties
2313
2329
  var llc = data.lineColor ?? data.color;
2314
2330
  delete data.lat;
@@ -2387,7 +2403,7 @@ function setMarker(data) {
2387
2403
  var track = data.track ?? data.COG ?? data.cog ?? data.hdg ?? data.heading ?? data.bearing;
2388
2404
  if (track != undefined) { // if there is a heading
2389
2405
  // Speed is in m/s
2390
- if (data.speed != null && data.length === undefined) { // and a speed - lets convert to a leader length
2406
+ if (data.speed != null && data.length === undefined && !data?.SIDC) { // and a speed - lets convert to a leader length
2391
2407
  data.length = parseFloat(data.speed || "0") * 60;
2392
2408
  var re1 = new RegExp('kn|knot|kt|kts','i');
2393
2409
  var re2 = new RegExp('kph|kmh','i');
@@ -3320,15 +3336,15 @@ function doTAKjson(p) {
3320
3336
  d.lon = Number(p.point.lon);
3321
3337
  d.layer = "TAK";
3322
3338
  if (p.type.indexOf('a') === 0) {
3323
- d.hdg = p.detail?.track?.course;
3339
+ d.track = p.detail?.track?.course;
3340
+ if (d.track && d.track == 9999999) { delete d.track; }
3341
+ if (d?.track) { d.track = Math.round(d.track * 100)/100; }
3324
3342
  if (p.detail?.track?.speed) {
3325
3343
  d.speed = Number(p.detail?.track?.speed);
3326
3344
  if (d.speed == 9999999 || d.speed == 0) { delete d.speed; }
3327
3345
  else {
3328
3346
  d.speed = d.speed + " m/s";
3329
- delete d.hdg;
3330
- d.course = p.detail?.track?.course;
3331
- d.options = { direction: d.course };
3347
+ if (d?.track) { d.options = { direction: d.track } };
3332
3348
  }
3333
3349
  }
3334
3350
  if (p.detail?.__group?.name) {
@@ -3355,7 +3371,6 @@ function doTAKjson(p) {
3355
3371
  d.alt = Number(p.point.hae) || 9999999;
3356
3372
  if (d?.alt && parseInt(d.alt) == 9999999) { delete d.alt; }
3357
3373
  else { d.alt = d.alt + "m"; }
3358
- if (d?.hdg && parseInt(d.hdg) == 9999999) { delete d.hdg; }
3359
3374
  setMarker(d);
3360
3375
  }
3361
3376
  else {
@@ -3379,15 +3394,15 @@ function doTAKMCjson(p) {
3379
3394
  d.type = p.type;
3380
3395
  d.uid = p.uid;
3381
3396
  d.name = p.detail?.contact?.callsign || p.uid;
3382
- d.hdg = p.detail?.track?.course;
3397
+ d.track = p.detail?.track?.course;
3398
+ if (d?.track && d.track == 9999999) { delete d.track; }
3399
+ if (d?.track) { d.track = Math.round(d.track * 100)/100; }
3383
3400
  if (p.detail?.track?.speed) {
3384
3401
  d.speed = Number(p.detail?.track?.speed);
3385
3402
  if (d.speed == 9999999 || d.speed == 0) { delete d.speed; }
3386
3403
  else {
3387
3404
  d.speed = d.speed + " m/s";
3388
- delete d.hdg;
3389
- d.course = p.detail?.track?.course;
3390
- d.options = { direction: d.course };
3405
+ if (d?.track) { d.options = { direction: d.track } };
3391
3406
  }
3392
3407
  }
3393
3408
  try {
@@ -3399,7 +3414,6 @@ function doTAKMCjson(p) {
3399
3414
  d.alt = p.hae || 9999999;
3400
3415
  if (d.alt && d.alt == 9999999) { delete d.alt; }
3401
3416
  else { d.alt = d.alt + "m"; }
3402
- if (d.hdg && d.hdg == 9999999) { delete d.hdg; }
3403
3417
  setMarker(d);
3404
3418
  }
3405
3419
  else {