1maps = {}; 2layers = {}; 3 4window.pexLeaflet = { 5 create: function (map, objectReference) { 6 var leafletMap = L.map(map.id, { 7 center: map.center, 8 zoom: map.zoom, 9 zoomControl: map.zoomControl, 10 minZoom: map.minZoom ? map.minZoom : undefined, 11 maxZoom: map.maxZoom ? map.maxZoom : undefined, 12 maxBounds: map.maxBounds && map.maxBounds.item1 && map.maxBounds.item2 ? L.latLngBounds(map.maxBounds.item1, map.maxBounds.item2) : undefined, 13 }); 14 15 connectMapEvents(leafletMap, objectReference); 16 maps[map.id] = leafletMap; 17 layers[map.id] = []; 18 }, 19 dispose: function (mapId) { 20 var map = maps[mapId]; 21 if (map && map.remove) { 22 map.off(); 23 map.remove(); 24 } 25 }, 26 invalidateSize: function (mapId) { 27 var map = maps[mapId]; 28 if (map) { 29 map.invalidateSize(); 30 } 31 }, 32 addTilelayer: function (mapId, tileLayer) { 33 const layer = L.tileLayer(tileLayer.urlTemplate, { 34 attribution: tileLayer.attribution, 35 pane: tileLayer.pane, 36 // --- 37 tileSize: tileLayer.tileSize ? L.point(tileLayer.tileSize.width, tileLayer.tileSize.height) : undefined, 38 opacity: tileLayer.opacity, 39 updateWhenZooming: tileLayer.updateWhenZooming, 40 updateInterval: tileLayer.updateInterval, 41 zIndex: tileLayer.zIndex, 42 bounds: tileLayer.bounds && tileLayer.bounds.item1 && tileLayer.bounds.item2 ? L.latLngBounds(tileLayer.bounds.item1, tileLayer.bounds.item2) : undefined, 43 // --- 44 minZoom: tileLayer.minimumZoom, 45 maxZoom: tileLayer.maximumZoom, 46 subdomains: tileLayer.subdomains, 47 errorTileUrl: tileLayer.errorTileUrl, 48 zoomOffset: tileLayer.zoomOffset, 49 // TMS 50 zoomReverse: tileLayer.isZoomReversed, 51 detectRetina: tileLayer.detectRetina, 52 // crossOrigin 53 }); 54 addLayer(mapId, layer, tileLayer.id); 55 }, 56 addMbTilesLayer: function (mapId, mbTilesLayer, objectReference) { 57 const layer = L.tileLayer.mbTiles(mbTilesLayer.urlTemplate, { 58 attribution: mbTilesLayer.attribution, 59 minZoom: mbTilesLayer.minimumZoom, 60 maxZoom: mbTilesLayer.maximumZoom 61 }); 62 addLayer(mapId, layer, mbTilesLayer.id); 63 }, 64 addShapefileLayer: function (mapId, shapefileLayer, objectReference) { 65 const layer = L.shapefile(shapefileLayer.urlTemplate); 66 addLayer(mapId, layer, shapefileLayer.id); 67 }, 68 addMarker: function (mapId, marker, objectReference) { 69 var options = { 70 ...createInteractiveLayer(marker), 71 keyboard: marker.isKeyboardAccessible, 72 title: marker.title, 73 alt: marker.alt, 74 zIndexOffset: marker.zIndexOffset, 75 opacity: marker.opacity, 76 riseOnHover: marker.riseOnHover, 77 riseOffset: marker.riseOffset, 78 pane: marker.pane, 79 bubblingMouseEvents: marker.isBubblingMouseEvents, 80 draggable: marker.draggable, 81 autoPan: marker.useAutopan, 82 autoPanPadding: marker.autoPanPadding, 83 autoPanSpeed: marker.autoPanSpeed, 84 rotationAngle:marker.rotationAngle 85 }; 86 87 if (marker.icon !== null) { 88 options.icon = createIcon(marker.icon); 89 } 90 const mkr = L.marker(marker.position, options); 91 connectMarkerEvents(mkr, objectReference); 92 addLayer(mapId, mkr, marker.id); 93 setTooltipAndPopupIfDefined(marker, mkr); 94 }, 95 addPolyline: function (mapId, polyline, objectReference) { 96 const layer = L.polyline(shapeToLatLngArray(polyline.shape), createPolyline(polyline)); 97 addLayer(mapId, layer, polyline.id); 98 setTooltipAndPopupIfDefined(polyline, layer); 99 }, 100 updatePolyline: function (mapId, polyline) { 101 let layer = layers[mapId].find(l => l.id === polyline.id); 102 if (layer !== undefined) { 103 layer.setLatLngs(shapeToLatLngArray(polyline.shape)); 104 } 105 }, 106 addPolygon: function (mapId, polygon, objectReference) { 107 const layer = L.polygon(shapeToLatLngArray(polygon.shape), createPolyline(polygon)); 108 addLayer(mapId, layer, polygon.id); 109 setTooltipAndPopupIfDefined(polygon, layer); 110 }, 111 updatePolygon: function (mapId, polygon) { 112 let layer = layers[mapId].find(l => l.id === polygon.id); 113 if (layer !== undefined) { 114 layer.setLatLngs(shapeToLatLngArray(polygon.shape)); 115 } 116 }, 117 addRectangle: function (mapId, rectangle, objectReference) { 118 const layer = L.rectangle([[rectangle.shape.bottom, rectangle.shape.left], [rectangle.shape.top, rectangle.shape.right]], createPolyline(rectangle)); 119 addLayer(mapId, layer, rectangle.id); 120 setTooltipAndPopupIfDefined(rectangle, layer); 121 }, 122 updateRectangle: function (mapId, rectangle) { 123 let layer = layers[mapId].find(l => l.id === rectangle.id); 124 if (layer !== undefined) { 125 layer.setBounds([[rectangle.shape.bottom, rectangle.shape.left], [rectangle.shape.top, rectangle.shape.right]]); 126 } 127 }, 128 addCircle: function (mapId, circle, objectReference) { 129 const layer = L.circle(circle.position, 130 { 131 ...createPath(circle), 132 radius: circle.radius 133 }); 134 addLayer(mapId, layer, circle.id); 135 setTooltipAndPopupIfDefined(circle, layer); 136 }, 137 updateCircle: function (mapId, circle) { 138 let layer = layers[mapId].find(l => l.id === circle.id); 139 if (layer !== undefined) { 140 layer.setRadius(circle.radius); 141 layer.setLatLng(circle.position); 142 } 143 }, 144 addImageLayer: function (mapId, image, objectReference) { 145 const layerOptions = { 146 ...createInteractiveLayer(image), 147 opacity: image.opacity, 148 alt: image.alt, 149 crossOrigin: image.crossOrigin, 150 errorOverlayUrl: image.errorOverlayUrl, 151 zIndex: image.zIndex, 152 className: image.className 153 }; 154 155 const corner1 = L.latLng(image.corner1.x, image.corner1.y); 156 const corner2 = L.latLng(image.corner2.x, image.corner2.y); 157 const bounds = L.latLngBounds(corner1, corner2); 158 159 const imgLayer = L.imageOverlay(image.url, bounds, layerOptions); 160 addLayer(mapId, imgLayer); 161 }, 162 addGeoJsonLayer: function (mapId, geodata, objectReference) { 163 const geoDataObject = JSON.parse(geodata.geoJsonData); 164 var options = { 165 ...createInteractiveLayer(geodata), 166 title: geodata.title, 167 bubblingMouseEvents: geodata.isBubblingMouseEvents, 168 onEachFeature: function onEachFeature(feature, layer) { 169 connectInteractionEvents(layer, objectReference); 170 } 171 }; 172 173 const geoJsonLayer = L.geoJson(geoDataObject, options); 174 addLayer(mapId, geoJsonLayer, geodata.id); 175 }, 176 removeLayer: function (mapId, layerId) { 177 const remainingLayers = layers[mapId].filter((layer) => layer.id !== layerId); 178 const layersToBeRemoved = layers[mapId].filter((layer) => layer.id === layerId); // should be only one ... 179 layers[mapId] = remainingLayers; 180 181 layersToBeRemoved.forEach(m => m.removeFrom(maps[mapId])); 182 }, 183 updatePopupContent: function (mapId, layerId, content) { 184 let layer = layers[mapId].find(l => l.id === layerId); 185 if (layer !== undefined) { 186 var popup = layer.getPopup(); 187 if (popup !== undefined) { 188 popup.setContent(content); 189 } 190 } 191 }, 192 updateTooltipContent: function (mapId, layerId, content) { 193 let layer = layers[mapId].find(l => l.id === layerId); 194 if (layer !== undefined) { 195 var tooltip = layer.getTooltip(); 196 if (tooltip !== undefined) { 197 tooltip.setContent(content); 198 } 199 } 200 }, 201 fitBounds: function (mapId, corner1, corner2, padding, maxZoom) { 202 const corner1LL = L.latLng(corner1.x, corner1.y); 203 const corner2LL = L.latLng(corner2.x, corner2.y); 204 const mapBounds = L.latLngBounds(corner1LL, corner2LL); 205 maps[mapId].fitBounds(mapBounds, { 206 padding: padding == null ? null : L.point(padding.x, padding.y), 207 maxZoom: maxZoom
208 }); 209 }, 210 panTo: function (mapId, position, animate, duration, easeLinearity, noMoveStart) { 211 const pos = L.latLng(position.x, position.y); 212 maps[mapId].panTo(pos, { 213 animate: animate, 214 duration: duration, 215 easeLinearity: easeLinearity, 216 noMoveStart: noMoveStart 217 }); 218 }, 219 setView: function (mapId, position, zoom) { 220 const pos = L.latLng(position.x, position.y); 221 maps[mapId].setView(pos, zoom); 222 }, 223 flyTo: function (mapId, position, zoom) { 224 const pos = L.latLng(position.x, position.y); 225 maps[mapId].flyTo(pos, zoom, { animate: true, duration:1 }); 226 }, 227 getCenter: function (mapId) { 228 return maps[mapId].getCenter(); 229 }, 230 getZoom: function (mapId) { 231 return maps[mapId].getZoom(); 232 }, 233 setZoom: function (mapId, zoomLevel) { 234 maps[mapId].setZoom(zoomLevel); 235 }, 236 getBounds: function (mapId) { 237 var bounds = maps[mapId].getBounds(); 238 return [bounds.getNorthWest(), bounds.getSouthEast()]; 239 }, 240 zoomIn: function (mapId, e) { 241 const map = maps[mapId]; 242 243 if (map.getZoom() < map.getMaxZoom()) { 244 map.zoomIn(map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 245 } 246 }, 247 zoomOut: function (mapId, e) { 248 const map = maps[mapId]; 249 250 if (map.getZoom() > map.getMinZoom()) { 251 map.zoomOut(map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 252 } 253 } 254}; 255 256function createIcon(icon) { 257 return L.icon({ 258 iconUrl: icon.url, 259 iconRetinaUrl: icon.retinaUrl, 260 iconSize: icon.size ? L.point(icon.size.width, icon.size.height) : null, 261 iconAnchor: icon.anchor ? L.point(icon.anchor.x, icon.anchor.y) : null, 262 popupAnchor: L.point(icon.popupAnchor.x, icon.popupAnchor.y), 263 tooltipAnchor: L.point(icon.tooltipAnchor.x, icon.tooltipAnchor.y), 264 shadowUrl: icon.shadowUrl, 265 shadowRetinaUrl: icon.shadowRetinaUrl, 266 shadowSize: icon.shadowSize ? L.point(icon.shadowSize.width, icon.shadowSize.height) : null, 267 shadowSizeAnchor: icon.shadowSizeAnchor ? L.point(icon.shadowSizeAnchor.width, icon.shadowSizeAnchor.height) : null, 268 className: icon.className 269 }) 270} 271 272function shapeToLatLngArray(shape) { 273 var latlngs = []; 274 shape.forEach(pts => { 275 var ll = []; 276 pts.forEach(p => ll.push([p.x, p.y])); 277 latlngs.push(ll); 278 }); 279 280 return latlngs; 281} 282 283function createPolyline(polyline) { 284 return { 285 ...createPath(polyline), 286 smoothFactor: polyline.smoothFactor, 287 noClip: polyline.noClipEnabled 288 }; 289} 290 291function createPath(path) { 292 return { 293 ...createInteractiveLayer(path), 294 stroke: path.drawStroke, 295 color: getColorString(path.strokeColor), 296 weight: path.strokeWidth, 297 opacity: path.strokeOpacity, 298 lineCap: path.lineCap, 299 lineJoin: path.lineJoin, 300 dashArray: path.strokeDashArray, 301 dashOffset: path.strokeDashOffset, 302 fill: path.fill, 303 fillColor: getColorString(path.fillColor), 304 fillOpacity: path.fillOpacity, 305 fillRule: path.fillRule 306 }; 307} 308 309function createInteractiveLayer(layer) { 310 return { 311 ...createLayer(layer), 312 interactive: layer.isInteractive, 313 bubblingMouseEvents: layer.isBubblingMouseEvents 314 }; 315} 316 317function createLayer(obj) { 318 return { 319 id: obj.id, 320 pane: obj.pane, 321 attribution: obj.attribution 322 }; 323} 324 325function getColorString(color) { 326 return "rgb(" + color.r + "," + color.g + "," + color.b + ")"; 327} 328 329function unbindTooltipAndPopupIfDefined(layer) { 330 if (layer.getTooltip()) { 331 layer.unbindTooltip(); 332 } 333 if (layer.getPopup()) { 334 layer.unbindPopup(); 335 } 336} 337 338function setTooltipAndPopupIfDefined(layer, jsLayer) { 339 if (layer.tooltip) { 340 addTooltip(jsLayer, layer.tooltip); 341 } 342 if (layer.popup) { 343 addPopup(jsLayer, layer.popup); 344 } 345} 346 347function addTooltip(layerObj, tooltip) { 348 layerObj.bindTooltip(tooltip.content, 349 { 350 pane: tooltip.pane, 351 offset: L.point(tooltip.offset.x, tooltip.offset.y), 352 direction: tooltip.direction, 353 permanent: tooltip.isPermanent, 354 sticky: tooltip.isSticky, 355 opacity: tooltip.opacity 356 }); 357} 358 359function addPopup(layerObj, popup) { 360 layerObj.bindPopup(popup.content, { 361 pane: popup.pane, 362 className: popup.className, 363 maxWidth: popup.maximumWidth, 364 minWidth: popup.minimumWidth, 365 autoPan: popup.autoPanEnabled, 366 autoPanPaddingTopLeft: popup.autoPanPaddingTopLeft ? L.point(popup.autoPanPaddingTopLeft.x, popup.autoPanPaddingTopLeft.y) : null, 367 autoPanPaddingBottomRight: popup.autoPanPaddingBottomRight ? L.point(popup.autoPanPaddingBottomRight.x, popup.autoPanPaddingBottomRight.y) : null, 368 autoPanPadding: L.point(popup.autoPanPadding.x, popup.autoPanPadding.y), 369 keepInView: popup.keepInView, 370 closeButton: popup.showCloseButton, 371 autoClose: popup.autoClose, 372 closeOnEscapeKey: popup.closeOnEscapeKey, 373 }); 374} 375 376function addLayer(mapId, layer, layerId) { 377 layer.id = layerId; 378 layers[mapId].push(layer); 379 layer.addTo(maps[mapId]); 380} 381 382// #region events 383 384// removes properties that can cause circular references 385function cleanupEventArgsForSerialization(eventArgs) { 386 387 const propertiesToRemove = [ 388 "target", 389 "sourceTarget", 390 "propagatedFrom", 391 "originalEvent", 392 "tooltip", 393 "popup" 394 ]; 395 396 const copy = {}; 397 398 for (let key in eventArgs) { 399 if (!propertiesToRemove.includes(key) && eventArgs.hasOwnProperty(key)) { 400 copy[key] = eventArgs[key]; 401 } 402 } 403 404 return copy; 405} 406 407function mapEvents(mapElement, objectReference, eventHandlerDict) { 408 for (let key in eventHandlerDict) { 409 410 const handlerName = eventHandlerDict[key]; 411 412 mapElement.on(key, function (eventArgs) { 413 objectReference.invokeMethodAsync(handlerName, 414 cleanupEventArgsForSerialization(eventArgs)); 415 }); 416 } 417} 418 419function connectMapEvents(map, objectReference) { 420 421 connectInteractionEvents(map, objectReference); 422 423 mapEvents(map, objectReference, { 424 "zoomlevelschange": "NotifyZoomLevelsChange", 425 "resize": "NotifyResize", 426 "viewreset": "NotifyViewReset", 427 "zoomstart": "NotifyZoomStart", 428 "movestart": "NotifyMoveStart", 429 "zoom": "NotifyZoom", 430 "move": "NotifyMove", 431 "zoomend": "NotifyZoomEnd", 432 "moveend": "NotifyMoveEnd", 433 }); 434} 435 436function connectLayerEvents(layer, objectReference) { 437 mapEvents(layer, objectReference, { 438 "popupopen": "NotifyPopupOpen", 439 "popupclose": "NotifyPopupClose", 440 "tooltipopen": "NotifyTooltipOpen", 441 "tooltipclose": "NotifyTooltipClose", 442 }); 443} 444 445function connectInteractiveLayerEvents(interactiveLayer, objectReference) { 446 447 connectLayerEvents(interactiveLayer, objectReference); 448 connectInteractionEvents(interactiveLayer, objectReference); 449} 450 451function connectMarkerEvents(marker, objectReference) { 452 453 connectInteractiveLayerEvents(marker, objectReference); 454 455 mapEvents(marker, objectReference, { 456 "move": "NotifyMove", 457 "dragstart": "NotifyDragStart", 458 "movestart": "NotifyMoveStart", 459 "drag": "NotifyDrag", 460 "dragend": "NotifyDragEnd", 461 "moveend": "NotifyMoveEnd", 462 }); 463} 464 465function connectInteractionEvents(interactiveObject, objectReference) { 466 467 mapEvents(interactiveObject, objectReference, { 468 "click": "NotifyClick", 469 "dblclick": "NotifyDblClick", 470 "mouseover": "NotifyMouseOver", 471 "mouseout": "NotifyMouseOut", 472 "contextmenu": "NotifyContextMenu", 473 }); 474} 475 476// #endregion
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.