node-red-contrib-web-worldmap 2.31.2 → 2.32.0

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,9 @@
1
1
  ### Change Log for Node-RED Worldmap
2
2
 
3
+ - v2.32.0 - Change || to nullish operator ?? to fix numerous dodgy assignments. Issue #219
4
+ Delete marker now also removes from heatmap layer. Issue #218
5
+
6
+ - v2.31.3 - Undo previous fix as while more technically correct - doesn't look so good. Issue #217
3
7
  - v2.31.2 = Fix more antimeridian crossing wrinkles. Issue #216
4
8
  - v2.31.1 - Fix missing type property for drawings, and pass back feedback value. Add route distance. Issue #213, Issue #212, PR #215
5
9
  - v2.31.0 - Better handling of KML files. Issue #211
package/README.md CHANGED
@@ -11,6 +11,9 @@ map web page for plotting "things" on.
11
11
 
12
12
  ### Updates
13
13
 
14
+ - v2.32.0 - Change || to nullish operator ?? to fix numerous dodgy assignments. Issue #219
15
+ Delete marker now also removes from heatmap layer. Issue #218
16
+ - v2.31.3 - Undo previous fix as while more technically correct - doesn't look so good. Issue #217
14
17
  - v2.31.2 = Fix more antimeridian crossing wrinkles. Issue #216
15
18
  - v2.31.1 - Fix missing type property for drawings, and pass back feedback value. Add route distance. Issue #213, Issue #212, PR #215
16
19
  - v2.31.0 - Better handling of KML files. Issue #211
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-web-worldmap",
3
- "version": "2.31.2",
3
+ "version": "2.32.0",
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": "~6.5.0",
@@ -266,11 +266,11 @@ var errRing;
266
266
  function onLocationFound(e) {
267
267
  if (followState === true) { map.panTo(e.latlng); }
268
268
  if (followMode.icon) {
269
- var self = {name:followMode.name || "self", lat:e.latlng.lat, lon:e.latlng.lng, hdg:e.heading, speed:(e.speed*3.6 || undefined), layer:followMode.layer, icon:followMode.icon, iconColor:followMode.iconColor || "#910000" };
269
+ var self = {name:followMode.name || "self", lat:e.latlng.lat, lon:e.latlng.lng, hdg:e.heading, speed:(e.speed*3.6 ?? undefined), layer:followMode.layer, icon:followMode.icon, iconColor:followMode.iconColor ?? "#910000" };
270
270
  setMarker(self);
271
271
  }
272
272
  if (followMode.accuracy) {
273
- errRing = L.circle(e.latlng, e.accuracy, {color:followMode.color || "cyan", weight:3, opacity:0.6, fill:false, clickable:false});
273
+ errRing = L.circle(e.latlng, e.accuracy, {color:followMode.color ?? "cyan", weight:3, opacity:0.6, fill:false, clickable:false});
274
274
  errRing.addTo(map);
275
275
  // if (e.hasOwnProperty("heading")) {
276
276
  // var lengthAsDegrees = e.speed * 60 / 110540;
@@ -280,7 +280,7 @@ function onLocationFound(e) {
280
280
  // L.polygon([ e.latlng, lla ], {color:"cyan", weight:3, opacity:0.5, clickable:false}).addTo(map);
281
281
  // }
282
282
  }
283
- ws.send(JSON.stringify({action:"point", lat:e.latlng.lat.toFixed(5), lon:e.latlng.lng.toFixed(5), point:"self", hdg:e.heading, speed:(e.speed*3.6 || undefined)}));
283
+ ws.send(JSON.stringify({action:"point", lat:e.latlng.lat.toFixed(5), lon:e.latlng.lng.toFixed(5), point:"self", hdg:e.heading, speed:(e.speed*3.6 ?? undefined)}));
284
284
  }
285
285
 
286
286
  function onLocationError(e) { console.log(e.message); }
@@ -702,7 +702,7 @@ var addThing = function() {
702
702
  var bits = thing.split(",");
703
703
  var icon = (bits[1] || "circle").trim();
704
704
  var lay = (bits[2] || "_drawing").trim();
705
- var colo = (bits[3] || "#910000").trim();
705
+ var colo = (bits[3] ?? "#910000").trim();
706
706
  var hdg = parseFloat(bits[4] || 0);
707
707
  var drag = true;
708
708
  var regi = /^[S,G,E,I,O][A-Z]{3}.*/i; // if it looks like a SIDC code
@@ -1214,9 +1214,13 @@ var addOverlays = function(overlist) {
1214
1214
  });
1215
1215
  }
1216
1216
 
1217
- // Add the heatmap layer
1217
+ // Add the heatmap layer (and add delete LatLng function)
1218
1218
  if (overlist.indexOf("HM")!==-1) {
1219
1219
  heat = L.heatLayer([], {radius:60, gradient:{0.2:'blue', 0.4:'lime', 0.6:'red', 0.8:'yellow', 1:'white'}});
1220
+ heat.delLatLng = function(ll) {
1221
+ heat._latlngs = heat._latlngs.filter(v => { return v != ll; } );
1222
+ heat._redraw();
1223
+ }
1220
1224
  layers["_heat"] = new L.LayerGroup().addLayer(heat);
1221
1225
  overlays["heatmap"] = layers["_heat"];
1222
1226
  }
@@ -1276,6 +1280,9 @@ var delMarker = function(dname,note) {
1276
1280
  delete polygons[dname+"_"];
1277
1281
  }
1278
1282
  if (typeof markers[dname] != "undefined") {
1283
+ if (heat && markers[dname].hasOwnProperty("_latlng")) {
1284
+ heat.delLatLng(markers[dname]._latlng);
1285
+ }
1279
1286
  layers[markers[dname].lay].removeLayer(markers[dname]);
1280
1287
  map.removeLayer(markers[dname]);
1281
1288
  delete markers[dname];
@@ -1325,7 +1332,7 @@ var rangerings = function(latlng, options) {
1325
1332
  radius: options.ranges[i],
1326
1333
  fill: false,
1327
1334
  color: options.color,
1328
- weight: options.weight || 1
1335
+ weight: options.weight ?? 1
1329
1336
  }).setDirection(options.pan, options.fov).addTo(rings);
1330
1337
  }
1331
1338
  return rings;
@@ -1333,7 +1340,6 @@ var rangerings = function(latlng, options) {
1333
1340
 
1334
1341
  // the MAIN add something to map function
1335
1342
  function setMarker(data) {
1336
-
1337
1343
  var rightmenu = function(m) {
1338
1344
  // customise right click context menu
1339
1345
  var rightcontext = "";
@@ -1376,8 +1382,8 @@ function setMarker(data) {
1376
1382
  var ll;
1377
1383
  var lli = null;
1378
1384
  var opt = {};
1379
- opt.color = data.color || data.lineColor || "#910000";
1380
- opt.fillColor = data.fillColor || "#910000";
1385
+ opt.color = data.color ?? data.lineColor ?? "#910000";
1386
+ opt.fillColor = data.fillColor ?? "#910000";
1381
1387
  opt.stroke = (data.hasOwnProperty("stroke")) ? data.stroke : true;
1382
1388
  opt.weight = data.weight;
1383
1389
  opt.opacity = data.opacity;
@@ -1407,7 +1413,7 @@ function setMarker(data) {
1407
1413
  if (markers.hasOwnProperty(data.name) && markers[data.name].hasOwnProperty("lay")) {
1408
1414
  lll = markers[data.name].lay;
1409
1415
  }
1410
- var lay = data.layer || lll;
1416
+ var lay = data.layer ?? lll;
1411
1417
  if (!data.hasOwnProperty("action") || data.action.indexOf("layer") === -1) {
1412
1418
  if (typeof layers[lay] == "undefined") { // add layer if if doesn't exist
1413
1419
  if (clusterAt > 0) {
@@ -1475,11 +1481,7 @@ function setMarker(data) {
1475
1481
  if (!data.hasOwnProperty("weight")) { opt.weight = 3; } //Standard settings different for lines
1476
1482
  if (!data.hasOwnProperty("opacity")) { opt.opacity = 0.8; }
1477
1483
  var greatc = L.Polyline.Arc(data.greatcircle[0], data.greatcircle[1], opt);
1478
- var gcp = greatc._latlngs.map(function(x) {
1479
- if (x.lng > 180) { x.lng -= 360; }
1480
- return x;
1481
- });
1482
- var aml = new L.Wrapped.Polyline(gcp, opt);
1484
+ var aml = new L.Wrapped.Polyline(greatc._latlngs, opt);
1483
1485
 
1484
1486
  polygons[data.name] = rightmenu(aml);
1485
1487
  if (data.hasOwnProperty("fit") && data.fit === true) {
@@ -1568,11 +1570,11 @@ function setMarker(data) {
1568
1570
  if (data.draggable === true) { drag = true; }
1569
1571
 
1570
1572
  if (data.hasOwnProperty("icon")) {
1571
- var dir = parseFloat(data.hdg || data.heading || data.bearing || "0");
1573
+ var dir = parseFloat(data.hdg ?? data.heading ?? data.bearing ?? "0");
1572
1574
  if (data.icon === "ship") {
1573
1575
  marker = L.boatMarker(ll, {
1574
1576
  title: data.name,
1575
- color: (data.iconColor || "blue")
1577
+ color: (data.iconColor ?? "blue")
1576
1578
  });
1577
1579
  marker.setHeading(dir);
1578
1580
  q = 'https://www.bing.com/images/search?q='+data.icon+'%20%2B"'+encodeURIComponent(data.name)+'"';
@@ -1596,7 +1598,7 @@ function setMarker(data) {
1596
1598
  marker = L.marker(ll, {title:data.name, icon:myMarker, draggable:drag});
1597
1599
  }
1598
1600
  else if (data.icon === "smallplane") {
1599
- data.iconColor = data.iconColor || "black";
1601
+ data.iconColor = data.iconColor ?? "black";
1600
1602
  icon = '<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="20" height="20">';
1601
1603
  icon += '<path d="M15.388 4.781c.068.068.061.154-.171.656-.028.06-.18.277-.18.277s.102.113.13.14c.054.055.078.175.056.27-.068.295-.89 1.47-1.35 1.93-.285.286-.432.481-.422.56.009.068.117.356.24.64.219.5.3.599 2.762 3.339 1.95 2.169 2.546 2.87 2.582 3.028.098.439-.282.847-1.264 1.356l-.507.263-7.389-5.29-4.43 3.365.102.18c.056.099.519.676 1.029 1.283.51.607.933 1.161.94 1.232.026.284-1.111 1.177-1.282 1.006-.27-.27-1.399-1.131-1.494-1.14-.068-.007-1.04-.747-1.37-1.077-.329-.33-1.07-1.301-1.076-1.37-.01-.094-.871-1.224-1.14-1.493-.171-.171.722-1.308 1.006-1.282.07.007.625.43 1.231.94.607.51 1.185.973 1.283 1.029l.18.101 3.365-4.43-5.29-7.388.263-.507c.51-.982.918-1.362 1.357-1.264.158.035.859.632 3.028 2.581 2.74 2.462 2.838 2.544 3.339 2.762.284.124.572.232.639.24.08.01.274-.136.56-.422.46-.46 1.635-1.282 1.93-1.35.095-.022.216.003.27.057.028.028.139.129.139.129s.217-.153.277-.18c.502-.233.59-.238.657-.17z" fill="'+data.iconColor+'"/></svg>';
1602
1604
  var svgplane = "data:image/svg+xml;base64," + btoa(icon);
@@ -1611,7 +1613,7 @@ function setMarker(data) {
1611
1613
  dir = dir - 90;
1612
1614
  var sc = 1;
1613
1615
  if (dir < -90 || dir >= 90) { sc = -1; }
1614
- data.iconColor = data.iconColor || "#910000";
1616
+ data.iconColor = data.iconColor ?? "#910000";
1615
1617
  var p = "m595.5 97.332-30.898-68.199c-11.141-24.223-35.344-39.762-62.004-39.801h-443.3c-32.738 0.035157-59.266 26.562-59.301 59.305v148.2c0 17.949 14.551 32.5 32.5 32.5h48.5c4.7344 23.309 25.219 40.051 49 40.051s44.266-16.742 49-40.051h242c4.7344 23.309 25.219 40.051 49 40.051s44.266-16.742 49-40.051h53.203c12.348-0.003906 23.219-8.1484 26.699-20 0.72266-2.5391 1.0898-5.1602 1.0977-7.7969v-83.5c-0.003906-7.1445-1.5391-14.203-4.5-20.703zm-545.5 12c-5.5234 0-10-4.4766-10-10v-80c0-5.5195 4.4766-10 10-10h70c5.5234 0 10 4.4805 10 10v80c0 5.5234-4.4766 10-10 10zm80 140c-16.566 0-30-13.43-30-30 0-16.566 13.434-30 30-30s30 13.434 30 30c-0.046875 16.551-13.453 29.953-30 30zm110-150c0 5.5234-4.4766 10-10 10h-70c-5.5234 0-10-4.4766-10-10v-80c0-5.5195 4.4766-10 10-10h70c5.5234 0 10 4.4805 10 10zm110 0c0 5.5234-4.4766 10-10 10h-70c-5.5234 0-10-4.4766-10-10v-80c0-5.5195 4.4766-10 10-10h70c5.5234 0 10 4.4805 10 10zm30 10c-5.5234 0-10-4.4766-10-10v-80c0-5.5195 4.4766-10 10-10h70c5.5234 0 10 4.4805 10 10v80c0 5.5234-4.4766 10-10 10zm90 140c-16.566 0-30-13.43-30-30 0-16.566 13.434-30 30-30s30 13.434 30 30c-0.046875 16.551-13.453 29.953-30 30zm19.199-140c-5.1836-0.46094-9.168-4.793-9.1992-10v-80.086c0-5.4727 4.4375-9.9141 9.9141-9.9141h12.684c18.824 0.050781 35.914 11.012 43.805 28.102l30.898 68.199c1.6133 3.5547 2.5 7.3984 2.6016 11.297z";
1616
1618
  icon = '<svg width="640pt" height="640pt" viewBox="-20 -180 640 640" xmlns="http://www.w3.org/2000/svg">';
1617
1619
  icon += '<path d="'+p+'" fill="'+data.iconColor+'"/></svg>';
@@ -1624,7 +1626,7 @@ function setMarker(data) {
1624
1626
  marker = L.marker(ll, {title:data.name, icon:myMarker, draggable:drag});
1625
1627
  }
1626
1628
  else if (data.icon === "helicopter") {
1627
- data.iconColor = data.iconColor || "black";
1629
+ data.iconColor = data.iconColor ?? "black";
1628
1630
  if (data.hasOwnProperty("squawk")) {
1629
1631
  if (data.squawk == 7500 || data.squawk == 7600 || data.squawk == 7700) {
1630
1632
  data.iconColor = "red";
@@ -1776,7 +1778,7 @@ function setMarker(data) {
1776
1778
  }
1777
1779
  else if (data.icon.match(/^:.*:$/g)) {
1778
1780
  var em = emojify(data.icon);
1779
- var col = data.iconColor || "#910000";
1781
+ var col = data.iconColor ?? "#910000";
1780
1782
  myMarker = L.divIcon({
1781
1783
  className:"emicon",
1782
1784
  html: '<center><span style="font-size:2em; color:'+col+'">'+em+'</span></center>',
@@ -1786,7 +1788,7 @@ function setMarker(data) {
1786
1788
  labelOffset = [12,-4];
1787
1789
  }
1788
1790
  else if (data.icon.match(/^https?:.*$/)) {
1789
- var sz = data.iconSize || 32;
1791
+ var sz = data.iconSize ?? 32;
1790
1792
  myMarker = L.icon({
1791
1793
  iconUrl: data.icon,
1792
1794
  iconSize: [sz, sz],
@@ -1798,7 +1800,7 @@ function setMarker(data) {
1798
1800
  delete data.iconSize;
1799
1801
  }
1800
1802
  else if (data.icon.substr(0,3) === "fa-") {
1801
- var col = data.iconColor || "#910000";
1803
+ var col = data.iconColor ?? "#910000";
1802
1804
  var imod = "";
1803
1805
  if (data.icon.indexOf(" ") === -1) { imod = "fa-2x "; }
1804
1806
  myMarker = L.divIcon({
@@ -1812,7 +1814,7 @@ function setMarker(data) {
1812
1814
  labelOffset = [8,-8];
1813
1815
  }
1814
1816
  else if (data.icon.substr(0,3) === "wi-") {
1815
- var col = data.iconColor || "#910000";
1817
+ var col = data.iconColor ?? "#910000";
1816
1818
  var imod = "";
1817
1819
  if (data.icon.indexOf(" ") === -1) { imod = "wi-2x "; }
1818
1820
  myMarker = L.divIcon({
@@ -1827,8 +1829,8 @@ function setMarker(data) {
1827
1829
  }
1828
1830
  else {
1829
1831
  myMarker = L.VectorMarkers.icon({
1830
- icon: data.icon || "circle",
1831
- markerColor: (data.iconColor || "#910000"),
1832
+ icon: data.icon ?? "circle",
1833
+ markerColor: (data.iconColor ?? "#910000"),
1832
1834
  prefix: 'fa',
1833
1835
  iconColor: 'white'
1834
1836
  });
@@ -1867,7 +1869,7 @@ function setMarker(data) {
1867
1869
  else {
1868
1870
  myMarker = L.VectorMarkers.icon({
1869
1871
  icon: "circle",
1870
- markerColor: (data.iconColor || "#910000"),
1872
+ markerColor: (data.iconColor ?? "#910000"),
1871
1873
  prefix: 'fa',
1872
1874
  iconColor: 'white'
1873
1875
  });
@@ -2455,7 +2457,7 @@ function doCommand(cmd) {
2455
2457
  }
2456
2458
 
2457
2459
  var custIco = function() {
2458
- var col = cmd.map.iconColor || "#910000";
2460
+ var col = cmd.map.iconColor ?? "#910000";
2459
2461
  var myMarker = L.VectorMarkers.icon({
2460
2462
  icon: "circle",
2461
2463
  markerColor: col,
@@ -2696,17 +2698,17 @@ function doCommand(cmd) {
2696
2698
  // handle any incoming GEOJSON directly - may style badly
2697
2699
  function doGeojson(n,g,l,o) {
2698
2700
  //console.log("GEOJSON",n,g,l,o)
2699
- var lay = l || g.name || "unknown";
2701
+ var lay = l ?? g.name ?? "unknown";
2700
2702
  // if (!basemaps[lay]) {
2701
2703
  var opt = { style: function(feature) {
2702
2704
  var st = { stroke:true, color:"#910000", weight:1, fill:true, fillColor:"#910000", fillOpacity:0.15 };
2703
2705
  st = Object.assign(st,o);
2704
2706
  if (feature.hasOwnProperty("properties")) {
2705
2707
  //console.log("GPROPS", feature.properties)
2706
- st.color = feature.properties["stroke"] || st.color;
2707
- st.weight = feature.properties["stroke-width"] || st.weight;
2708
- st.fillColor = feature.properties["fill-color"] || feature.properties["fill"] || st.fillColor;
2709
- st.fillOpacity = feature.properties["fill-opacity"] || st.fillOpacity;
2708
+ st.color = feature.properties["stroke"] ?? st.color;
2709
+ st.weight = feature.properties["stroke-width"] ?? st.weight;
2710
+ st.fillColor = feature.properties["fill-color"] ?? feature.properties["fill"] ?? st.fillColor;
2711
+ st.fillOpacity = feature.properties["fill-opacity"] ?? st.fillOpacity;
2710
2712
  delete feature.properties["stroke"];
2711
2713
  delete feature.properties["stroke-width"];
2712
2714
  delete feature.properties["fill-color"];
@@ -2716,10 +2718,10 @@ function doGeojson(n,g,l,o) {
2716
2718
  }
2717
2719
  if (feature.hasOwnProperty("style")) {
2718
2720
  //console.log("GSTYLE", feature.style)
2719
- st.color = feature.style["stroke"] || st.color;
2720
- st.weight = feature.style["stroke-width"] || st.weight;
2721
- st.fillColor = feature.style["fill-color"] || feature.style["fill"] || st.fillColor;
2722
- st.fillOpacity = feature.style["fill-opacity"] || st.fillOpacity;
2721
+ st.color = feature.style["stroke"] ?? st.color;
2722
+ st.weight = feature.style["stroke-width"] ?? st.weight;
2723
+ st.fillColor = feature.style["fill-color"] ?? feature.style["fill"] ?? st.fillColor;
2724
+ st.fillOpacity = feature.style["fill-opacity"] ?? st.fillOpacity;
2723
2725
  }
2724
2726
  if (feature.hasOwnProperty("geometry") && feature.geometry.hasOwnProperty("type") && (feature.geometry.type === "LineString" || feature.geometry.type === "MultiLineString") ) {
2725
2727
  st.fill = false;
@@ -2755,8 +2757,8 @@ function doGeojson(n,g,l,o) {
2755
2757
  }
2756
2758
  else {
2757
2759
  myMarker = L.VectorMarkers.icon({
2758
- icon: feature.properties["marker-symbol"] || "circle",
2759
- markerColor: (feature.properties["marker-color"] || "#910000"),
2760
+ icon: feature.properties["marker-symbol"] ?? "circle",
2761
+ markerColor: (feature.properties["marker-color"] ?? "#910000"),
2760
2762
  prefix: 'fa',
2761
2763
  iconColor: 'white'
2762
2764
  });
@@ -2772,7 +2774,7 @@ function doGeojson(n,g,l,o) {
2772
2774
  delete feature.properties["marker-size"];
2773
2775
  var nf = {title:feature.properties.title, name:feature.properties.name};
2774
2776
  feature.properties = Object.assign(nf, feature.properties);
2775
- return L.marker(latlng, {title:feature.properties.title || "", icon:myMarker});
2777
+ return L.marker(latlng, {title:feature.properties.title ?? "", icon:myMarker});
2776
2778
  }
2777
2779
  opt.onEachFeature = function (f,l) {
2778
2780
  if (f.properties && Object.keys(f.properties).length > 0) {