node-red-contrib-web-worldmap 2.42.3 → 3.1.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.
@@ -18,7 +18,7 @@ var menuOpen = false;
18
18
  var clusterAt = 0;
19
19
  var maxage = 900; // default max age of icons on map in seconds - cleared after 10 mins
20
20
  var baselayername = "OSM grey"; // Default base layer OSM but uniform grey
21
- var pagefoot = " © DCJ 2023"
21
+ var pagefoot = " © DCJ 2023";
22
22
  var inIframe = false;
23
23
  var showUserMenu = true;
24
24
  var showLayerMenu = true;
@@ -28,7 +28,7 @@ var heat;
28
28
  var minimap;
29
29
  var sidebyside;
30
30
  var layercontrol;
31
- var drawControl;
31
+ // var drawControl;
32
32
  var drawingColour = "#910000";
33
33
  var sendDrawing;
34
34
  var colorControl;
@@ -54,6 +54,8 @@ var iconSz = {
54
54
  "Command": 44
55
55
  };
56
56
 
57
+ // L.PM.setOptIn(true);
58
+
57
59
  // Create the socket
58
60
  var connect = function() {
59
61
  // var transports = ["websocket", "xhr-streaming", "xhr-polling"],
@@ -79,10 +81,10 @@ var connect = function() {
79
81
  if (data.hasOwnProperty("type") && data.hasOwnProperty("data") && data.type === "Buffer") { data = data.data.toString(); }
80
82
  handleData(data);
81
83
  }
82
- catch (e) { if (data) { console.log("BAD DATA",data); } }
84
+ catch (e) { if (data) { console.log("BAD DATA",data); console.log(e); } }
83
85
  // console.log("DATA",typeof data,data);
84
86
  };
85
- }
87
+ };
86
88
  console.log("CONNECT TO",location.pathname + 'socket');
87
89
 
88
90
  var handleData = function(data) {
@@ -189,7 +191,14 @@ if (inIframe === true) {
189
191
  // }
190
192
 
191
193
  // Create the Initial Map object.
192
- map = new L.map('map',{zoomSnap: 0.1}).setView(startpos, startzoom);
194
+ map = new L.map('map',{
195
+ zoomSnap: 0.1,
196
+ rotate: true,
197
+ rotateControl: {
198
+ closeOnZeroBearing: true,
199
+ position: 'topleft'
200
+ },
201
+ bearing: 0}).setView(startpos, startzoom);
193
202
  map.whenReady(function() {
194
203
  connect();
195
204
  });
@@ -301,6 +310,7 @@ function onLocationFound(e) {
301
310
  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" };
302
311
  setMarker(self);
303
312
  }
313
+ if (e.heading !== null) { map.setBearing(e.heading); }
304
314
  if (followMode.accuracy) {
305
315
  errRing = L.circle(e.latlng, e.accuracy, {color:followMode.color ?? "#00ffff", weight:3, opacity:0.6, fill:false, clickable:false});
306
316
  errRing.addTo(map);
@@ -696,8 +706,8 @@ map.on('overlayadd', function(e) {
696
706
  }
697
707
  if (e.name == "drawing") {
698
708
  overlays["drawing"].bringToFront();
709
+ map.pm.toggleControls();
699
710
  map.addControl(colorControl);
700
- map.addControl(drawControl);
701
711
  }
702
712
  ws.send(JSON.stringify({action:"addlayer", name:e.name}));
703
713
  });
@@ -710,7 +720,7 @@ map.on('overlayremove', function(e) {
710
720
  layers["_daynight"].clearLayers();
711
721
  }
712
722
  if (e.name == "drawing") {
713
- map.removeControl(drawControl);
723
+ map.pm.toggleControls()
714
724
  map.removeControl(colorControl);
715
725
  }
716
726
  ws.send(JSON.stringify({action:"dellayer", name:e.name}));
@@ -793,7 +803,6 @@ const colorKeywordToRGB = (colorKeyword) => {
793
803
  document.body.appendChild(el);
794
804
  let rgbValue = window.getComputedStyle(el).color;
795
805
  document.body.removeChild(el);
796
- console.log(rgbValue);
797
806
  return rgba2hex(rgbValue);
798
807
  }
799
808
 
@@ -1077,46 +1086,37 @@ var addOverlays = function(overlist) {
1077
1086
 
1078
1087
  layers["_drawing"] = new L.FeatureGroup();
1079
1088
  overlays["drawing"] = layers["_drawing"];
1080
- map.options.drawControlTooltips = false;
1081
1089
  var drawCount = 0;
1082
- drawControl = new L.Control.Draw({
1083
- draw: {
1084
- polyline: { shapeOptions: { clickable:true } },
1085
- marker: false,
1086
- //circle: false,
1087
- circle: { shapeOptions: { clickable:true } },
1088
- circlemarker: false,
1089
- rectangle: { shapeOptions: { clickable:true } },
1090
- polygon: { shapeOptions: { clickable:true } }
1091
- }
1092
- //edit: none
1093
- // {
1094
- // featureGroup: layers["_drawing"],
1095
- // remove: true,
1096
- // edit: true
1097
- // }
1090
+ map.pm.addControls({
1091
+ position: 'topleft',
1092
+ drawMarker: false,
1093
+ drawCircleMarker: false,
1094
+ drawText: false,
1095
+ editControls: false
1098
1096
  });
1097
+ map.pm.toggleControls();
1098
+
1099
1099
  var changeDrawColour = function(col) {
1100
1100
  drawingColour = col;
1101
- // console.log("COLOR",col)
1102
- drawControl.setDrawingOptions({
1103
- polyline: { shapeOptions: { color:drawingColour } },
1104
- circle: { shapeOptions: { color:drawingColour } },
1105
- rectangle: { shapeOptions: { color:drawingColour } },
1106
- polygon: { shapeOptions: { color:drawingColour } }
1107
- });
1101
+ map.pm.setPathOptions({
1102
+ color: drawingColour,
1103
+ fillColor: drawingColour,
1104
+ fillOpacity: 0.4
1105
+ });
1108
1106
  }
1107
+
1109
1108
  var shape;
1110
- map.on('draw:created', function (e) {
1111
- var name = e.layerType + drawCount;
1109
+ map.on("pm:create", (e) => {
1110
+ var name = e.shape + drawCount;
1112
1111
  drawCount = drawCount + 1;
1113
1112
 
1114
1113
  e.layer.on('contextmenu', function(e) {
1115
1114
  L.DomEvent.stopPropagation(e);
1116
1115
  var rmen = L.popup({offset:[0,-12]}).setLatLng(e.latlng);
1117
- rmen.setContent("<input type='text' autofocus value='"+e.target.name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+e.target.name+"\",true);'>Edit points</button><button onclick='delMarker(\""+e.target.name+"\",true);'>Delete</button><button onclick='sendDrawing();'>OK</button>");
1116
+ rmen.setContent("<input type='text' value='"+e.target.name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+e.target.name+"\");'>Edit points</button><button onclick='editPoly(\""+e.target.name+"\",\"drag\");'>Drag</button><button onclick='editPoly(\""+e.target.name+"\",\"rot\");'>Rotate</button><button onclick='delMarker(\""+e.target.name+"\",true);'>Delete</button><button onclick='sendDrawing();'>OK</button>");
1118
1117
  map.openPopup(rmen);
1119
1118
  });
1119
+ e.layer.bindPopup(name);
1120
1120
 
1121
1121
  var la, lo, cent;
1122
1122
  if (e.layer.hasOwnProperty("_latlng")) {
@@ -1127,7 +1127,7 @@ var addOverlays = function(overlist) {
1127
1127
  else {
1128
1128
  cent = e.layer.getBounds().getCenter();
1129
1129
  }
1130
- var m = {action:"draw", name:name, type:e.layerType, layer:"_drawing", options:e.layer.options, radius:e.layer._mRadius, lat:la, lon:lo};
1130
+ var m = {action:"draw", name:name, type:e.shape, layer:"_drawing", options:e.layer.options, radius:e.layer._mRadius, lat:la, lon:lo};
1131
1131
  if (e.layer.hasOwnProperty("_latlngs")) {
1132
1132
  if (e.layer.options.fill === false) { m.line = e.layer._latlngs; }
1133
1133
  else { m.area = e.layer._latlngs[0]; }
@@ -1139,9 +1139,9 @@ var addOverlays = function(overlist) {
1139
1139
  polygons[name].name = name;
1140
1140
  layers["_drawing"].addLayer(shape.layer);
1141
1141
 
1142
- var rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\",true);'>Edit points</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
1142
+ var rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\");'>Edit points</button><button onclick='editPoly(\""+name+"\",\"drag\");'>Drag</button><button onclick='editPoly(\""+name+"\",\"rot\");'>Rotate</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
1143
1143
  if (e.layer.options.fill === false && navigator.onLine) {
1144
- rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\",true);'>Edit points</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendRoute(\""+name+"\");'>Route</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
1144
+ rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\");'>Edit points</button><button onclick='editPoly(\""+name+"\",\"drag\");'>Drag</button><button onclick='editPoly(\""+name+"\",\"rot\");'>Rotate</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendRoute(\""+name+"\");'>Route</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
1145
1145
  }
1146
1146
  rightmenuMarker.setLatLng(cent);
1147
1147
  setTimeout(function() {map.openPopup(rightmenuMarker)},25);
@@ -1151,6 +1151,7 @@ var addOverlays = function(overlist) {
1151
1151
  var thing = document.getElementById('dinput').value;
1152
1152
  map.closePopup();
1153
1153
  shape.m.name = thing;
1154
+ shape.layer.bindPopup(thing);
1154
1155
  delMarker(n,true);
1155
1156
 
1156
1157
  polygons[thing] = shape.layer;
@@ -1378,7 +1379,7 @@ helpText += '<p><i class="fa fa-globe fa-lg fa-fw"></i> <b>Heatmap all layers</b
1378
1379
  helpText += 'all layers whether hidden or not will contribute to the heatmap.';
1379
1380
  helpText += 'The default is that only visible layers add to the heatmap.</p>';
1380
1381
 
1381
- // Delete a marker (and notify websocket)
1382
+ // Delete a marker or shape (and notify websocket)
1382
1383
  var delMarker = function(dname,note) {
1383
1384
  if (note) { map.closePopup(); }
1384
1385
  if (typeof polygons[dname] != "undefined") {
@@ -1402,16 +1403,15 @@ var delMarker = function(dname,note) {
1402
1403
  if (note) { ws.send(JSON.stringify({action:"delete", name:dname, deleted:true})); }
1403
1404
  }
1404
1405
 
1405
- var editPoly = function(pname) {
1406
+ var editPoly = function(pname,fun) {
1406
1407
  map.closePopup();
1407
- editFeatureGroup = L.featureGroup();
1408
- editToolbar = new L.EditToolbar({ featureGroup:editFeatureGroup });
1409
- editHandler = editToolbar.getModeHandlers()[0].handler;
1410
- editHandler._map = map;
1408
+ if (fun === "rot") { polygons[pname].pm.enableRotate(); }
1409
+ else if (fun === "drag") { polygons[pname].pm.enableLayerDrag(); }
1410
+ else { polygons[pname].pm.enable(); }
1411
1411
  polygons[pname].on("dblclick", function(e) {
1412
- editHandler.disable();
1413
- editFeatureGroup.removeLayer(polygons[pname]);
1414
- polygons[pname].off("dblclick");
1412
+ if (fun === "rot") { polygons[pname].pm.disableRotate(); }
1413
+ else if (fun === "drag") { polygons[pname].pm.disableLayerDrag(); }
1414
+ else { polygons[pname].pm.disable(); }
1415
1415
  L.DomEvent.stopPropagation(e);
1416
1416
  var la, lo;
1417
1417
  if (e.target.hasOwnProperty("_latlng")) {
@@ -1425,10 +1425,9 @@ var editPoly = function(pname) {
1425
1425
  }
1426
1426
  ws.send(JSON.stringify(m));
1427
1427
  })
1428
- editFeatureGroup.addLayer(polygons[pname]);
1429
- editHandler.enable();
1430
1428
  }
1431
1429
 
1430
+
1432
1431
  var rangerings = function(latlng, options) {
1433
1432
  options = L.extend({
1434
1433
  ranges: [250,500,750,1000],
@@ -1463,7 +1462,7 @@ function setMarker(data) {
1463
1462
  rightcontext = "<button id='delbutton' onclick='delMarker(\""+data.name+"\",true);'>Delete</button>";
1464
1463
  //}
1465
1464
  if (data.editable) {
1466
- rightcontext = "<button onclick='editPoly(\""+data.name+"\",true);'>Edit</button><button onclick='delMarker(\""+data.name+"\",true);'>Delete</button>";
1465
+ rightcontext = "<button onclick='editPoly(\""+data.name+"\");'>Edit</button><button onclick='delMarker(\""+data.name+"\",true);'>Delete</button>";
1467
1466
  }
1468
1467
  if ((data.contextmenu !== undefined) && (typeof data.contextmenu === "string")) {
1469
1468
  rightcontext = data.contextmenu.replace(/\$name/g,'"'+data.name+'"');
@@ -2468,57 +2467,69 @@ function doCommand(cmd) {
2468
2467
  }
2469
2468
  }
2470
2469
  // Add a new geojson overlay layer
2471
- if (cmd.map && cmd.map.hasOwnProperty("overlay") && cmd.map.hasOwnProperty("geojson") ) {
2470
+ if (cmd.map && cmd.map.hasOwnProperty("overlay") && cmd.map.hasOwnProperty("geojson")) {
2472
2471
  if (overlays.hasOwnProperty(cmd.map.overlay)) {
2473
2472
  map.removeLayer(overlays[cmd.map.overlay]);
2474
2473
  existsalready = true;
2475
2474
  }
2476
- var opt = cmd.map.opt || { style:function(feature) {
2477
- var st = { stroke:true, weight:2, fill:true };
2478
- if (feature.hasOwnProperty("properties")) {
2479
- st.color = feature.properties.color||feature.properties.roofColor||"black";
2480
- if (feature.properties.hasOwnProperty("color")) { delete feature.properties.color; }
2481
- if (feature.properties.hasOwnProperty("roofColor")) { delete feature.properties.roofColor; }
2475
+ try {
2476
+ var opt = cmd.map.opt || {};
2477
+ if (opt.hasOwnProperty("style")) { opt.style = new Function('return ' + opt.style)(); }
2478
+ else {
2479
+ opt.style = function(feature) {
2480
+ var st = { stroke:true, weight:2, fill:true };
2481
+ if (feature.hasOwnProperty("properties")) {
2482
+ st.color = feature.properties.color||feature.properties.roofColor||"black";
2483
+ if (feature.properties.hasOwnProperty("color")) { delete feature.properties.color; }
2484
+ if (feature.properties.hasOwnProperty("roofColor")) { delete feature.properties.roofColor; }
2485
+ }
2486
+ if (feature.hasOwnProperty("properties") && feature.properties.hasOwnProperty('style')) {
2487
+ if (feature.properties.style.hasOwnProperty('stroke')) {
2488
+ st.color = feature.properties.style.stroke;
2489
+ }
2490
+ if (feature.properties.style.hasOwnProperty('stroke-width')) {
2491
+ st.weight = feature.properties.style["stroke-width"];
2492
+ }
2493
+ if (feature.properties.style.hasOwnProperty('stroke-opacity')) {
2494
+ st.opacity = feature.properties.style["stroke-opacity"];
2495
+ }
2496
+ if (feature.properties.style.hasOwnProperty('fill')) {
2497
+ if (feature.properties.style.fill == "none") { st.fill = false; }
2498
+ else { st.fillColor = feature.properties.style.fill; }
2499
+ }
2500
+ if (feature.properties.style.hasOwnProperty('fill-opacity')) {
2501
+ st.fillOpacity = feature.properties.style["fill-opacity"];
2502
+ }
2503
+ }
2504
+ delete feature.properties.style;
2505
+ return st;
2506
+ };
2482
2507
  }
2483
- if (feature.hasOwnProperty("properties") && feature.properties.hasOwnProperty('style')) {
2484
- if (feature.properties.style.hasOwnProperty('stroke')) {
2485
- st.color = feature.properties.style.stroke;
2486
- }
2487
- if (feature.properties.style.hasOwnProperty('stroke-width')) {
2488
- st.weight = feature.properties.style["stroke-width"];
2489
- }
2490
- if (feature.properties.style.hasOwnProperty('stroke-opacity')) {
2491
- st.opacity = feature.properties.style["stroke-opacity"];
2492
- }
2493
- if (feature.properties.style.hasOwnProperty('fill')) {
2494
- if (feature.properties.style.fill == "none") { st.fill = false; }
2495
- else { st.fillColor = feature.properties.style.fill; }
2496
- }
2497
- if (feature.properties.style.hasOwnProperty('fill-opacity')) {
2498
- st.fillOpacity = feature.properties.style["fill-opacity"];
2508
+ if (opt.hasOwnProperty("pointToLayer")) { opt.pointToLayer = new Function('return ' + opt.pointToLayer)(); }
2509
+ if (opt.hasOwnProperty("filter")) { opt.filter = new Function('return ' + opt.filter)(); }
2510
+ if (opt.hasOwnProperty("onEachFeature")) { opt.onEachFeature = new Function('return ' + opt.onEachFeature)(); }
2511
+ else {
2512
+ opt.onEachFeature = function (f,l) {
2513
+ var pw = '<pre>'+JSON.stringify(f.properties,null,' ').replace(/[\{\}"]/g,'')+'</pre>';
2514
+ if (pw.length > 11) { l.bindPopup(pw); }
2515
+ if (cmd.map.hasOwnProperty("clickable") && cmd.map.clickable === true) {
2516
+ l.on('click', function (e) {
2517
+ ws.send(JSON.stringify({action:"clickgeo",name:cmd.map.overlay,type:f.type,properties:f.properties,geometry:f.geometry}));
2518
+ });
2519
+ }
2499
2520
  }
2500
2521
  }
2501
- delete feature.properties.style;
2502
- return st;
2503
- }};
2504
- opt.onEachFeature = function (f,l) {
2505
- var pw = '<pre>'+JSON.stringify(f.properties,null,' ').replace(/[\{\}"]/g,'')+'</pre>';
2506
- if (pw.length > 11) { l.bindPopup(pw); }
2507
- if (cmd.map.hasOwnProperty("clickable") && cmd.map.clickable === true) {
2508
- l.on('click', function (e) {
2509
- ws.send(JSON.stringify({action:"clickgeo",name:cmd.map.overlay,type:f.type,properties:f.properties,geometry:f.geometry}));
2510
- });
2522
+ overlays[cmd.map.overlay] = L.geoJson(cmd.map.geojson,opt);
2523
+ if (!existsalready) {
2524
+ layercontrol.addOverlay(overlays[cmd.map.overlay],cmd.map.overlay);
2511
2525
  }
2512
- }
2513
- overlays[cmd.map.overlay] = L.geoJson(cmd.map.geojson,opt);
2514
- if (!existsalready) {
2515
- layercontrol.addOverlay(overlays[cmd.map.overlay],cmd.map.overlay);
2516
- }
2517
- if (!cmd.map.hasOwnProperty("visible") || (cmd.map.visible != false)) {
2518
- map.addLayer(overlays[cmd.map.overlay]);
2519
- }
2520
- if (cmd.map.hasOwnProperty("fly") && (cmd.map.fly === true)) { map.flyToBounds(overlays[cmd.map.overlay].getBounds()); }
2521
- else if (cmd.map.hasOwnProperty("fit") && (cmd.map.fit === true)) { map.fitBounds(overlays[cmd.map.overlay].getBounds()); }
2526
+ if (!cmd.map.hasOwnProperty("visible") || (cmd.map.visible != false)) {
2527
+ map.addLayer(overlays[cmd.map.overlay]);
2528
+ }
2529
+ if (cmd.map.hasOwnProperty("fly") && (cmd.map.fly === true)) { map.flyToBounds(overlays[cmd.map.overlay].getBounds()); }
2530
+ else if (cmd.map.hasOwnProperty("fit") && (cmd.map.fit === true)) { map.fitBounds(overlays[cmd.map.overlay].getBounds()); }
2531
+ }
2532
+ catch(e) { console.log(e); }
2522
2533
  }
2523
2534
  // Add a new NVG XML overlay layer
2524
2535
  if (cmd.map && cmd.map.hasOwnProperty("overlay") && cmd.map.hasOwnProperty("nvg") ) {
@@ -2661,6 +2672,29 @@ function doCommand(cmd) {
2661
2672
  if (cmd.map.hasOwnProperty("fly") && cmd.map.fly === true) { map.flyToBounds(overlays[cmd.map.overlay].getBounds()); }
2662
2673
  else if (cmd.map.hasOwnProperty("fit") && cmd.map.fit === true) { map.fitBounds(overlays[cmd.map.overlay].getBounds()); }
2663
2674
  }
2675
+ // Add a new ESRI feature layer
2676
+ if (cmd.map && cmd.map.hasOwnProperty("overlay") && cmd.map.hasOwnProperty("esri") ) {
2677
+ try {
2678
+ if (overlays.hasOwnProperty(cmd.map.overlay)) {
2679
+ overlays[cmd.map.overlay].removeFrom(map);
2680
+ existsalready = true;
2681
+ }
2682
+ var opt = {};
2683
+ if (cmd.map.hasOwnProperty("opt")) { opt = cmd.map.opt; }
2684
+ if (opt.hasOwnProperty("style")) { opt.style = new Function('return ' + opt.style)(); }
2685
+ if (opt.hasOwnProperty("pointToLayer")) { opt.pointToLayer = new Function('return ' + opt.pointToLayer)(); }
2686
+ if (opt.hasOwnProperty("onEachFeature")) { opt.onEachFeature = new Function('return ' + opt.onEachFeature)(); }
2687
+ opt.url = cmd.map.esri;
2688
+ overlays[cmd.map.overlay] = L.esri.featureLayer(opt);
2689
+ if (!existsalready) {
2690
+ layercontrol.addOverlay(overlays[cmd.map.overlay],cmd.map.overlay);
2691
+ }
2692
+ if (!cmd.map.hasOwnProperty("visible") || (cmd.map.visible != false)) {
2693
+ overlays[cmd.map.overlay].addTo(map);
2694
+ }
2695
+ // NOTE can't fit or fly to bounds as they keep reloading
2696
+ } catch(e) { console.log(e); }
2697
+ }
2664
2698
  // Add a new TOPOJSON overlay layer
2665
2699
  if (cmd.map && cmd.map.hasOwnProperty("overlay") && cmd.map.hasOwnProperty("topojson") ) {
2666
2700
  if (overlays.hasOwnProperty(cmd.map.overlay)) {
@@ -2812,7 +2846,7 @@ function doCommand(cmd) {
2812
2846
  else { lockit = false; doLock(false); }
2813
2847
  document.getElementById("lockit").checked = lockit;
2814
2848
  }
2815
- // move to a new position
2849
+ // Move to a new position
2816
2850
  var clat = map.getCenter().lat;
2817
2851
  var clon = map.getCenter().lng;
2818
2852
  var czoom = map.getZoom();
@@ -2821,6 +2855,9 @@ function doCommand(cmd) {
2821
2855
  if (cmd.hasOwnProperty("zoom")) { czoom = cmd.zoom; }
2822
2856
  map.setView([clat,clon],czoom);
2823
2857
 
2858
+ // Set rotation of map
2859
+ if (cmd.hasOwnProperty("rotation") && !isNaN(cmd.rotation)) { map.setBearing(-cmd.rotation); }
2860
+
2824
2861
  if (cmd.hasOwnProperty("cluster")) {
2825
2862
  clusterAt = cmd.cluster;
2826
2863
  document.getElementById("setclus").value = cmd.cluster;
@@ -2865,8 +2902,7 @@ function doCommand(cmd) {
2865
2902
  }
2866
2903
 
2867
2904
  // handle any incoming GEOJSON directly - may style badly
2868
- function doGeojson(n,g,l,o) {
2869
- // console.log("GEOJSON",n,g,l,o) // name,geojson,layer,options
2905
+ function doGeojson(n,g,l,o) { // name, geojson, layer, options
2870
2906
  var lay = l ?? g.name ?? "unknown";
2871
2907
  // if (!basemaps[lay]) {
2872
2908
  var opt = { style: function(feature) {
@@ -2961,10 +2997,12 @@ function doGeojson(n,g,l,o) {
2961
2997
  delete tx["marker-color"];
2962
2998
  delete tx["marker-size"];
2963
2999
  delete tx["coordinateProperties"];
2964
- delete tx["_gpxType"]
3000
+ delete tx["_gpxType"];
3001
+ var n = tx["name"];
3002
+ delete tx["name"];
2965
3003
  tx = JSON.stringify(tx,null,' ');
2966
3004
  if ( tx !== "{}") {
2967
- l.bindPopup('<pre style="overflow-x: scroll">'+tx.replace(/[\{\}"]/g,'')+'</pre>');
3005
+ l.bindPopup('<b>'+n+'</b><pre style="overflow-x:scroll">'+tx.replace(/[\{\}"]/g,'')+'</pre>');
2968
3006
  }
2969
3007
  }
2970
3008
  if (o && o.hasOwnProperty("clickable") && o.clickable === true) {
@@ -2972,6 +3010,16 @@ function doGeojson(n,g,l,o) {
2972
3010
  ws.send(JSON.stringify({action:"clickgeo",name:n,type:f.type,properties:f.properties,geometry:f.geometry}));
2973
3011
  });
2974
3012
  }
3013
+ if (f.geometry.type === "MultiLineString") {
3014
+ l.on('contextmenu', function(e) {
3015
+ L.DomEvent.stopPropagation(e);
3016
+ var rmen = L.popup({offset:[0,-12]}).setLatLng(e.latlng);
3017
+ rmen.setContent("<b>"+n+"</b><br/><button onclick='editPoly(\""+n+"\");'>Edit points</button><button onclick='delMarker(\""+n+"\",true);'>Delete</button><button onclick='sendDrawing();'>OK</button>");
3018
+ map.openPopup(rmen);
3019
+ });
3020
+ polygons[n] = l;
3021
+ polygons[n].lay = lay;
3022
+ }
2975
3023
  }
2976
3024
  markers[n] = L.geoJson(g,opt);
2977
3025
  markers[n].lay = lay;
package/worldmap.html CHANGED
@@ -380,8 +380,8 @@ If <i>Web Path</i> is left empty, then by default <code>⌘⇧m</code> - <code>c
380
380
  showruler: {value:"false"},
381
381
  allowFileDrop: {value:"false"},
382
382
  path: {value:"/worldmap"},
383
- overlist: {value:"DR,CO,RA,DN,HM"},
384
- maplist: {value:"OSMG,OSMC,EsriC,EsriS,EsriT,EsriDG,UKOS"},
383
+ overlist: {value:"DR,CO,RA,DN"},
384
+ maplist: {value:"OSMG,OSMC,EsriC,EsriS,UKOS"},
385
385
  mapname: {value:""},
386
386
  mapurl: {value:""},
387
387
  mapopt: {value:"", validate:function(v) {try{ v.length===0 || JSON.parse(v); return true;} catch(e) {return false;}}},
package/worldmap.js CHANGED
@@ -40,8 +40,8 @@ module.exports = function(RED) {
40
40
  node.mapurl = n.mapurl || "";
41
41
  node.mapopt = n.mapopt || "";
42
42
  node.mapwms = n.mapwms || false;
43
- if (n.maplist === undefined) { node.maplist = "OSMG,OSMC,EsriC,EsriS,EsriT,EsriDG,UKOS,SW"; }
44
- if (n.overlist === undefined) { node.overlist = "DR,CO,RA,DN,HM"; }
43
+ if (n.maplist === undefined) { node.maplist = "OSMG,OSMC,EsriC,EsriS,UKOS"; }
44
+ if (n.overlist === undefined) { node.overlist = "DR,CO,RA,DN"; }
45
45
  try { node.mapopt2 = JSON.parse(node.mapopt); }
46
46
  catch(e) { node.mapopt2 = null; }
47
47
 
@@ -1,10 +0,0 @@
1
- .leaflet-draw-section{position:relative}.leaflet-draw-toolbar{margin-top:12px}.leaflet-draw-toolbar-top{margin-top:0}.leaflet-draw-toolbar-notop a:first-child{border-top-right-radius:0}.leaflet-draw-toolbar-nobottom a:last-child{border-bottom-right-radius:0}.leaflet-draw-toolbar a{background-image:url('images/spritesheet.png');background-image:linear-gradient(transparent,transparent),url('images/spritesheet.svg');background-repeat:no-repeat;background-size:300px 30px;background-clip:padding-box}.leaflet-retina .leaflet-draw-toolbar a{background-image:url('images/spritesheet-2x.png');background-image:linear-gradient(transparent,transparent),url('images/spritesheet.svg')}
2
- .leaflet-draw a{display:block;text-align:center;text-decoration:none}.leaflet-draw a .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.leaflet-draw-actions{display:none;list-style:none;margin:0;padding:0;position:absolute;left:26px;top:0;white-space:nowrap}.leaflet-touch .leaflet-draw-actions{left:32px}.leaflet-right .leaflet-draw-actions{right:26px;left:auto}.leaflet-touch .leaflet-right .leaflet-draw-actions{right:32px;left:auto}.leaflet-draw-actions li{display:inline-block}
3
- .leaflet-draw-actions li:first-child a{border-left:0}.leaflet-draw-actions li:last-child a{-webkit-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.leaflet-right .leaflet-draw-actions li:last-child a{-webkit-border-radius:0;border-radius:0}.leaflet-right .leaflet-draw-actions li:first-child a{-webkit-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.leaflet-draw-actions a{background-color:#919187;border-left:1px solid #AAA;color:#FFF;font:11px/19px "Helvetica Neue",Arial,Helvetica,sans-serif;line-height:28px;text-decoration:none;padding-left:10px;padding-right:10px;height:28px}
4
- .leaflet-touch .leaflet-draw-actions a{font-size:12px;line-height:30px;height:30px}.leaflet-draw-actions-bottom{margin-top:0}.leaflet-draw-actions-top{margin-top:1px}.leaflet-draw-actions-top a,.leaflet-draw-actions-bottom a{height:27px;line-height:27px}.leaflet-draw-actions a:hover{background-color:#a0a098}.leaflet-draw-actions-top.leaflet-draw-actions-bottom a{height:26px;line-height:26px}.leaflet-draw-toolbar .leaflet-draw-draw-polyline{background-position:-2px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-polyline{background-position:0 -1px}
5
- .leaflet-draw-toolbar .leaflet-draw-draw-polygon{background-position:-31px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-polygon{background-position:-29px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-rectangle{background-position:-62px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-rectangle{background-position:-60px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-circle{background-position:-92px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-circle{background-position:-90px -1px}
6
- .leaflet-draw-toolbar .leaflet-draw-draw-marker{background-position:-122px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-marker{background-position:-120px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-circlemarker{background-position:-273px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-circlemarker{background-position:-271px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-edit{background-position:-152px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-edit{background-position:-150px -1px}
7
- .leaflet-draw-toolbar .leaflet-draw-edit-remove{background-position:-182px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-remove{background-position:-180px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled{background-position:-212px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled{background-position:-210px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled{background-position:-242px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled{background-position:-240px -2px}
8
- .leaflet-mouse-marker{background-color:#fff;cursor:crosshair}.leaflet-draw-tooltip{background:#363636;background:rgba(0,0,0,0.5);border:1px solid transparent;-webkit-border-radius:4px;border-radius:4px;color:#fff;font:12px/18px "Helvetica Neue",Arial,Helvetica,sans-serif;margin-left:20px;margin-top:-21px;padding:4px 8px;position:absolute;visibility:hidden;white-space:nowrap;z-index:6}.leaflet-draw-tooltip:before{border-right:6px solid black;border-right-color:rgba(0,0,0,0.5);border-top:6px solid transparent;border-bottom:6px solid transparent;content:"";position:absolute;top:7px;left:-7px}
9
- .leaflet-error-draw-tooltip{background-color:#f2dede;border:1px solid #e6b6bd;color:#b94a48}.leaflet-error-draw-tooltip:before{border-right-color:#e6b6bd}.leaflet-draw-tooltip-single{margin-top:-12px}.leaflet-draw-tooltip-subtext{color:#f8d5e4}.leaflet-draw-guide-dash{font-size:1%;opacity:.6;position:absolute;width:5px;height:5px}.leaflet-edit-marker-selected{background-color:rgba(254,87,161,0.1);border:4px dashed rgba(254,87,161,0.6);-webkit-border-radius:4px;border-radius:4px;box-sizing:content-box}
10
- .leaflet-edit-move{cursor:move}.leaflet-edit-resize{cursor:pointer}.leaflet-oldie .leaflet-draw-toolbar{border:1px solid #999}