1/* 2 * Copyright (c) 2008-2022 Mark C. Prins <mprins@users.sf.net> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 18/** 19 * Test for css support in the browser by sniffing for a css class we added 20 * using javascript added by the action plugin; this is an edge case because 21 * browsers that support javascript generally support css as well. 22 * 23 * @returns {Boolean} true when the browser supports css (and implicitly 24 * javascript) 25 */ 26function olTestCSSsupport() { 27 return (jQuery('.olCSSsupported').length > 0); 28} 29 30/** 31 * Creates a DocumentFragment to insert into the dom. 32 * 33 * @param mapid 34 * id for the map div 35 * @param width 36 * width for the map div 37 * @param height 38 * height for the map div 39 * @returns a {DocumentFragment} element that can be injected into the dom 40 */ 41function olCreateMaptag(mapid, width, height) { 42 const // fragment 43 frag = document.createDocumentFragment(), 44 // temp node 45 temp = document.createElement('div'); 46 temp.innerHTML = '<div id="' + mapid + '-olContainer" class="olContainer olWebOnly">' 47 // map 48 + '<div id="' + mapid + '" tabindex="0" style="width:' + width + ';height:' + height + ';" class="olMap"></div>' 49 + '</div>'; 50 while (temp.firstChild) { 51 frag.appendChild(temp.firstChild); 52 } 53 return frag; 54} 55 56/** 57 * Create the map based on the params given. 58 * 59 * @param mapOpts {Object} 60 * mapOpts MapOptions hash {id:'olmap', width:500px, height:500px, 61 * lat:6710200, lon:506500, zoom:13, controls:1, 62 * baselyr:'', kmlfile:'', gpxfile:'', geojsonfile, 63 * summary:''} 64 * @param poi {Array} 65 * OLmapPOI array with POI's [ {lat:6710300,lon:506000,txt:'instap 66 * punt',angle:180,opacity:.9,img:'', rowId:n},... ]); 67 * 68 * @return {ol.Map} the created map 69 */ 70function createMap(mapOpts, poi) { 71 72 // const mapOpts = olMapData[0].mapOpts; 73 // const poi = olMapData[0].poi; 74 const autoZoom_options = {padding: [16, 16, 16, 16]}; 75 76 if (!olEnable) { 77 return null; 78 } 79 if (!olTestCSSsupport()) { 80 olEnable = false; 81 return null; 82 } 83 84 // find map element location 85 const cleartag = document.getElementById(mapOpts.id + '-clearer'); 86 if (cleartag === null) { 87 return null; 88 } 89 // create map element and add to document 90 const fragment = olCreateMaptag(mapOpts.id, mapOpts.width, mapOpts.height); 91 cleartag.parentNode.insertBefore(fragment, cleartag); 92 93 /** dynamic map extent. */ 94 let extent = ol.extent.createEmpty(); 95 let overlayGroup = new ol.layer.Group({title: 'Overlays', fold: 'open', layers: []}); 96 const baseLyrGroup = new ol.layer.Group({'title': 'Base maps', layers: []}); 97 98 const map = new ol.Map({ 99 target: document.getElementById(mapOpts.id), 100 layers: [baseLyrGroup, overlayGroup], 101 view: new ol.View({ 102 center: ol.proj.transform([mapOpts.lon, mapOpts.lat], 'EPSG:4326', 'EPSG:3857'), 103 zoom: mapOpts.zoom, 104 projection: 'EPSG:3857' 105 }), 106 controls: [ 107 new ol.control.Attribution({ 108 collapsible: true, 109 collapsed: true 110 }) 111 ] 112 }); 113 114 if (osmEnable) { 115 baseLyrGroup.getLayers().push( 116 new ol.layer.Tile({ 117 visible: true, 118 title: 'OSM', 119 type: 'base', 120 source: new ol.source.OSM() 121 })); 122 123 baseLyrGroup.getLayers().push( 124 new ol.layer.Tile({ 125 visible: mapOpts.baselyr === "opentopomap", 126 title: 'opentopomap', 127 type: 'base', 128 source: new ol.source.OSM({ 129 url: 'https://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png', 130 attributions: 'Data ©ODbL <a href="https://openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>, ' 131 + '<a href="http://viewfinderpanoramas.org" target="_blank">SRTM</a>, ' 132 + 'style ©<a href="https://opentopomap.org/" target="_blank">OpenTopoMap</a>' 133 + '(<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)' 134 }) 135 })); 136 137 baseLyrGroup.getLayers().push( 138 new ol.layer.Tile({ 139 visible: mapOpts.baselyr === "cycle map", 140 title: 'cycle map', 141 type: 'base', 142 source: new ol.source.OSM({ 143 url: 'https://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=' + tfApiKey, 144 attributions: 'Data ©ODbL <a href="https://openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>, ' 145 + 'Tiles ©<a href="https://www.thunderforest.com/" target="_blank">Thunderforest</a>' 146 + '<img src="https://www.thunderforest.com/favicon.ico" alt="Thunderforest logo"/>' 147 }) 148 })); 149 150 baseLyrGroup.getLayers().push( 151 new ol.layer.Tile({ 152 visible: mapOpts.baselyr === "transport", 153 title: 'transport', 154 type: 'base', 155 source: new ol.source.OSM({ 156 url: 'https://{a-c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=' + tfApiKey, 157 attributions: 'Data ©ODbL <a href="https://openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>, ' 158 + 'Tiles ©<a href="https://www.thunderforest.com/" target="_blank">Thunderforest</a>' 159 + '<img src="https://www.thunderforest.com/favicon.ico" alt="Thunderforest logo"/>' 160 }) 161 })); 162 163 baseLyrGroup.getLayers().push( 164 new ol.layer.Tile({ 165 visible: mapOpts.baselyr === "landscape", 166 title: 'landscape', 167 type: 'base', 168 source: new ol.source.OSM({ 169 url: 'https://{a-c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey=' + tfApiKey, 170 attributions: 'Data ©ODbL <a href="https://openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>, ' 171 + 'Tiles ©<a href="https://www.thunderforest.com/" target="_blank">Thunderforest</a>' 172 + '<img src="https://www.thunderforest.com/favicon.ico" alt="Thunderforest logo"/>' 173 }) 174 })); 175 176 baseLyrGroup.getLayers().push( 177 new ol.layer.Tile({ 178 visible: mapOpts.baselyr === "outdoors", 179 title: 'outdoors', 180 type: 'base', 181 source: new ol.source.OSM({ 182 url: 'https://{a-c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=' + tfApiKey, 183 attributions: 'Data ©ODbL <a href="https://openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>, ' 184 + 'Tiles ©<a href="https://www.thunderforest.com/" target="_blank">Thunderforest</a>' 185 + '<img src="https://www.thunderforest.com/favicon.ico" alt="Thunderforest logo"/>' 186 }) 187 })); 188 } 189 190 if (bEnable && bApiKey !== '') { 191 baseLyrGroup.getLayers().push( 192 new ol.layer.Tile({ 193 visible: mapOpts.baselyr === "bing road", 194 title: 'bing road', 195 type: 'base', 196 source: new ol.source.BingMaps({ 197 key: bApiKey, 198 imagerySet: 'Road' 199 }) 200 })); 201 202 baseLyrGroup.getLayers().push( 203 new ol.layer.Tile({ 204 visible: mapOpts.baselyr === "bing sat", 205 title: 'bing sat', 206 type: 'base', 207 source: new ol.source.BingMaps({ 208 key: bApiKey, 209 imagerySet: 'Aerial' 210 }) 211 })); 212 213 baseLyrGroup.getLayers().push( 214 new ol.layer.Tile({ 215 visible: mapOpts.baselyr === "bing hybrid", 216 title: 'bing hybrid', 217 type: 'base', 218 source: new ol.source.BingMaps({ 219 key: bApiKey, 220 imagerySet: 'AerialWithLabels' 221 }) 222 })); 223 } 224 225 if (stamenEnable) { 226 baseLyrGroup.getLayers().push( 227 new ol.layer.Tile({ 228 visible: mapOpts.baselyr === "toner", 229 type: 'base', 230 title: 'toner', 231 source: new ol.source.Stamen({layer: 'toner'}) 232 }) 233 ); 234 235 baseLyrGroup.getLayers().push( 236 new ol.layer.Tile({ 237 visible: mapOpts.baselyr === "terrain", 238 type: 'base', 239 title: 'terrain', 240 source: new ol.source.Stamen({layer: 'terrain'}) 241 }) 242 ); 243 } 244 245 extent = ol.extent.extend(extent, map.getView().calculateExtent()); 246 247 const iconScale = window.devicePixelRatio ?? 1.0; 248 const vectorSource = new ol.source.Vector(); 249 poi.forEach((p) => { 250 const f = new ol.Feature({ 251 geometry: new ol.geom.Point(ol.proj.fromLonLat([p.lon, p.lat])), 252 description: p.txt, 253 img: p.img, 254 rowId: p.rowId, 255 lat: p.lat, 256 lon: p.lon, 257 angle: p.angle, 258 opacity: p.opacity, 259 alt: p.img.substring(0, p.img.lastIndexOf(".")) 260 }); 261 f.setId(p.rowId); 262 vectorSource.addFeature(f); 263 }); 264 265 const vectorLayer = new ol.layer.Vector({ 266 title: 'POI', 267 visible: true, 268 source: vectorSource, 269 style(feature, resolution) { 270 const img = feature.get('img'); 271 const opacity = feature.get('opacity'); 272 const angle = feature.get('angle'); 273 const text = feature.get('rowId'); 274 275 return new ol.style.Style({ 276 image: new ol.style.Icon({ 277 src: `${DOKU_BASE}lib/plugins/openlayersmap/icons/${img}`, 278 crossOrigin: '', 279 opacity: opacity, 280 scale: iconScale, 281 rotation: angle * Math.PI / 180, 282 // width/height were added in OpenLayers 7.2.2 283 // see https://github.com/openlayers/openlayers/pull/14364 284 }), 285 text: new ol.style.Text({ 286 text: `${text}`, 287 textAlign: 'center', 288 textBaseline: 'middle', 289 offsetX: (8 + 4 + 2) * iconScale, 290 offsetY: -8 * iconScale, 291 scale: iconScale, 292 fill: new ol.style.Fill({color: 'rgb(0,0,0)'}), 293 font: 'bold 16px monospace', 294 stroke: new ol.style.Stroke({color: 'rgba(255,255,255,.4)', width: 5}), 295 }) 296 }); 297 } 298 }); 299 overlayGroup.getLayers().push(vectorLayer); 300 if (mapOpts.autozoom) { 301 extent = ol.extent.extend(extent, vectorSource.getExtent()); 302 map.getView().fit(extent, autoZoom_options); 303 } 304 305 if (mapOpts.controls === 1) { 306 map.addControl(new ol.control.Zoom()); 307 map.addControl(new ol.control.ScaleLine({bar: true, text: true})); 308 map.addControl(new ol.control.MousePosition({ 309 coordinateFormat: ol.coordinate.createStringXY(4), projection: 'EPSG:4326', 310 })); 311 map.addControl(new ol.control.FullScreen({ 312 label: '✈' 313 })); 314 map.addControl(new ol.control.OverviewMap({ 315 label: '+', 316 layers: [new ol.layer.Tile({ 317 source: new ol.source.OSM() 318 })] 319 })); 320 map.addControl(new ol.control.LayerSwitcher({ 321 activationMode: 'click', 322 label: '\u2630', 323 collapseLabel: '\u00BB', 324 })); 325 } 326 327 if (mapOpts.kmlfile.length > 0) { 328 try { 329 const kmlSource = new ol.source.Vector({ 330 url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.kmlfile, 331 format: new ol.format.KML(), 332 }); 333 overlayGroup.getLayers().push(new ol.layer.Vector({title: 'KML file', visible: true, source: kmlSource})); 334 335 if (mapOpts.autozoom) { 336 kmlSource.once('change', function () { 337 extent = ol.extent.extend(extent, kmlSource.getExtent()); 338 map.getView().fit(extent, autoZoom_options); 339 }); 340 } 341 } catch (e) { 342 console.error(e); 343 } 344 } 345 346 if (mapOpts.geojsonfile.length > 0) { 347 try { 348 // these are the same colour as in StaticMap#drawJSON() 349 const geoJsonStyle = { 350 'Point': new ol.style.Style({ 351 image: new ol.style.Circle({ 352 fill: new ol.style.Fill({ 353 color: 'rgba(255,0,255,0.4)', 354 }), 355 radius: 5, 356 stroke: new ol.style.Stroke({ 357 color: 'rgba(255,0,255,0.9)', 358 width: 1, 359 }), 360 }), 361 }), 362 'LineString': new ol.style.Style({ 363 stroke: new ol.style.Stroke({ 364 color: 'rgba(255,0,255,0.9)', 365 width: 3, 366 }), 367 }), 368 'MultiLineString': new ol.style.Style({ 369 stroke: new ol.style.Stroke({ 370 color: 'rgba(255,0,255,0.9)', 371 width: 3, 372 }), 373 }), 374 'Polygon': new ol.style.Style({ 375 stroke: new ol.style.Stroke({ 376 color: 'rgba(255,0,255,0.9)', 377 width: 3, 378 }), 379 fill: new ol.style.Fill({ 380 color: 'rgba(255,0,255,0.4)', 381 }), 382 }), 383 'MultiPolygon': new ol.style.Style({ 384 stroke: new ol.style.Stroke({ 385 color: 'rgba(255,0,255,0.9)', 386 width: 3, 387 }), 388 fill: new ol.style.Fill({ 389 color: 'rgba(255,0,255,0.4)', 390 }), 391 }), 392 }; 393 const geoJsonSource = new ol.source.Vector({ 394 url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.geojsonfile, 395 format: new ol.format.GeoJSON(), 396 }); 397 overlayGroup.getLayers().push(new ol.layer.Vector({ 398 title: 'GeoJSON file', visible: true, source: geoJsonSource, 399 style: function (feature) { 400 return geoJsonStyle[feature.getGeometry().getType()]; 401 }, 402 })); 403 404 if (mapOpts.autozoom) { 405 geoJsonSource.once('change', function () { 406 extent = ol.extent.extend(extent, geoJsonSource.getExtent()); 407 map.getView().fit(extent, autoZoom_options); 408 }); 409 } 410 } catch (e) { 411 console.error(e); 412 } 413 } 414 415 if (mapOpts.gpxfile.length > 0) { 416 try { 417 // these are the same colour as in StaticMap#drawGPX() 418 const gpxJsonStyle = { 419 'Point': new ol.style.Style({ 420 image: new ol.style.Circle({ 421 fill: new ol.style.Fill({ 422 color: 'rgba(0,0,255,0.4)', 423 }), 424 radius: 5, 425 stroke: new ol.style.Stroke({ 426 color: 'rgba(0,0,255,0.9)', 427 width: 1, 428 }), 429 }), 430 }), 431 'LineString': new ol.style.Style({ 432 stroke: new ol.style.Stroke({ 433 color: 'rgba(0,0,255,0.9)', 434 width: 3, 435 }), 436 }), 437 'MultiLineString': new ol.style.Style({ 438 stroke: new ol.style.Stroke({ 439 color: 'rgba(0,0,255,0.9)', 440 width: 3, 441 }), 442 }), 443 }; 444 const gpxSource = new ol.source.Vector({ 445 url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.gpxfile, 446 format: new ol.format.GPX(), 447 }); 448 overlayGroup.getLayers().push(new ol.layer.Vector({ 449 title: 'GPS track', visible: true, source: gpxSource, 450 style: function (feature) { 451 return gpxJsonStyle[feature.getGeometry().getType()]; 452 }, 453 })); 454 455 if (mapOpts.autozoom) { 456 gpxSource.once('change', function () { 457 extent = ol.extent.extend(extent, gpxSource.getExtent()); 458 map.getView().fit(extent, autoZoom_options); 459 }); 460 } 461 } catch (e) { 462 console.error(e); 463 } 464 } 465 466 const container = document.getElementById('popup'); 467 const content = document.getElementById('popup-content'); 468 const closer = document.getElementById('popup-closer'); 469 470 const overlay = new ol.Overlay({ 471 element: container, 472 positioning: 'center-center', 473 stopEvent: true, 474 autoPan: { 475 animation: { 476 duration: 250, 477 } 478 }, 479 }); 480 map.addOverlay(overlay); 481 482 /** 483 * Add a click handler to hide the popup. 484 * @return {boolean} Don't follow the href. 485 */ 486 closer.onclick = function () { 487 overlay.setPosition(undefined); 488 closer.blur(); 489 return false; 490 }; 491 492 // display popup on click 493 map.on('singleclick', function (evt) { 494 const selFeature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { 495 return feature; 496 }); 497 if (selFeature) { 498 overlay.setPosition(evt.coordinate); 499 500 let pContent = '<div class="spacer"> </div>'; 501 // let locDesc = ''; 502 503 if (selFeature.get('rowId') !== undefined) { 504 pContent += '<span class="rowId">' + selFeature.get('rowId') + ': </span>'; 505 } 506 if (selFeature.get('name') !== undefined) { 507 pContent += '<span class="txt">' + selFeature.get('name') + '</span>'; 508 // locDesc = selFeature.get('name'); 509 // TODO strip <p> tag from locDesc 510 // locDesc = selFeature.get('name').split(/\s+/).slice(0,2).join('+'); 511 } 512 if (selFeature.get('ele') !== undefined) { 513 pContent += '<div class="ele">elevation: ' + selFeature.get('ele') + '</div>'; 514 } 515 if (selFeature.get('type') !== undefined) { 516 pContent += '<div>' + selFeature.get('type') + '</div>'; 517 } 518 if (selFeature.get('time') !== undefined) { 519 pContent += '<div class="time">time: ' + selFeature.get('time') + '</div>'; 520 } 521 if (selFeature.get('description') !== undefined) { 522 pContent += '<div class="desc">' + selFeature.get('description') + '</div>'; 523 } 524 if (selFeature.get('img') !== undefined) { 525 const _alt = selFeature.get('alt'); 526 pContent += '<div class="coord" title="lat;lon">' + 527 '<img alt="' + _alt + '" src="' + DOKU_BASE + 'lib/plugins/openlayersmap/icons/' + selFeature.get('img') + 528 '" width="16" height="16" ' + 'style="transform:rotate(' + selFeature.get('angle') + 'deg)" /> ' + 529 '<a href="geo:' + selFeature.get('lat') + ',' + selFeature.get('lon') + '?q=' + selFeature.get('lat') + 530 ',' + selFeature.get('lon') + '(' + selFeature.get('alt') + ')" title="Open in navigation app">' + 531 ol.coordinate.format([selFeature.get('lon'), selFeature.get('lat')], '{x}º; {y}º', 4) + '</a></div>'; 532 } 533 content.innerHTML = pContent; 534 } else { 535 // do nothing... 536 } 537 }); 538 539 // change mouse cursor when over marker 540 map.on('pointermove', function (e) { 541 const pixel = map.getEventPixel(e.originalEvent); 542 const hit = map.hasFeatureAtPixel(pixel); 543 map.getTarget().style.cursor = hit ? 'pointer' : ''; 544 }); 545 546 return map; 547} 548 549/** 550 * add layers to the map based on the olMapOverlays object. 551 */ 552function olovAddToMap() { 553 for (const key in olMapOverlays) { 554 const overlay = olMapOverlays[key]; 555 const m = olMaps[overlay.id]; 556 557 switch (overlay.type) { 558 case 'osm': 559 m.addLayer(new ol.layer.Tile({ 560 title: overlay.name, 561 visible: (overlay.visible).toLowerCase() === 'true', 562 opacity: parseFloat(overlay.opacity), 563 source: new ol.source.OSM({ 564 url: overlay.url, 565 crossOrigin: 'Anonymous', 566 attributions: overlay.attribution 567 }) 568 })); 569 break; 570 case 'wms': 571 m.addLayer(new ol.layer.Image({ 572 title: overlay.name, 573 opacity: parseFloat(overlay.opacity), 574 visible: (overlay.visible).toLowerCase() === 'true', 575 source: new ol.source.ImageWMS({ 576 url: overlay.url, 577 params: { 578 'LAYERS': overlay.layers, 579 'VERSION': overlay.version, 580 'TRANSPARENT': overlay.transparent, 581 'FORMAT': overlay.format 582 }, 583 ratio: 1, 584 crossOrigin: 'Anonymous', 585 attributions: overlay.attribution 586 }) 587 })); 588 break; 589 case 'ags': 590 m.addLayer(new ol.layer.Image({ 591 title: overlay.name, 592 opacity: parseFloat(overlay.opacity), 593 visible: (overlay.visible).toLowerCase() === 'true', 594 source: new ol.source.ImageArcGISRest({ 595 url: overlay.url, 596 params: { 597 'LAYERS': overlay.layers, 598 'TRANSPARENT': overlay.transparent, 599 'FORMAT': overlay.format 600 }, 601 ratio: 1, 602 crossOrigin: 'Anonymous', 603 attributions: overlay.attribution 604 }) 605 })); 606 break; 607 // case 'mapillary': 608 // var mUrl = 'http://api.mapillary.com/v1/im/search?'; 609 // if (overlay.skey !== '') { 610 // mUrl = 'http://api.mapillary.com/v1/im/sequence?'; 611 // } 612 // var mLyr = new OpenLayers.Layer.Vector( 613 // "Mapillary", { 614 // projection: new OpenLayers.Projection("EPSG:4326"), 615 // strategies: [new OpenLayers.Strategy.BBOX({ 616 // ratio: 1.1, 617 // resFactor: 1.5 618 // }) /* ,new OpenLayers.Strategy.Cluster({}) */], 619 // protocol: new OpenLayers.Protocol.HTTP({ 620 // url: mUrl, 621 // format: new OpenLayers.Format.GeoJSON(), 622 // params: { 623 // // default to max. 250 locations 624 // 'max-results': 250, 625 // 'geojson': true, 626 // 'skey': overlay.skey 627 // }, 628 // filterToParams: function (filter, params) { 629 // if (filter.type === OpenLayers.Filter.Spatial.BBOX) { 630 // // override the bbox serialization of 631 // // the filter to give the Mapillary 632 // // specific bounds 633 // params['min-lat'] = filter.value.bottom; 634 // params['max-lat'] = filter.value.top; 635 // params['min-lon'] = filter.value.left; 636 // params['max-lon'] = filter.value.right; 637 // // if the width of our bbox width is 638 // // less than 0.15 degrees drop the max 639 // // results 640 // if (filter.value.top - filter.value.bottom < .15) { 641 // OpenLayers.Console.debug('dropping max-results parameter, width is: ', 642 // filter.value.top - filter.value.bottom); 643 // params['max-results'] = null; 644 // } 645 // } 646 // return params; 647 // } 648 // }), 649 // styleMap: new OpenLayers.StyleMap({ 650 // 'default': { 651 // cursor: 'help', 652 // rotation: '${ca}', 653 // externalGraphic: DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20.png', 654 // graphicHeight: 20, 655 // graphicWidth: 20, 656 // }, 657 // 'select': { 658 // externalGraphic: DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20-select.png', 659 // label: '${location}', 660 // fontSize: '1em', 661 // fontFamily: 'monospace', 662 // labelXOffset: '0.5', 663 // labelYOffset: '0.5', 664 // labelAlign: 'lb', 665 // } 666 // }), 667 // attribution: '<a href="http://www.mapillary.com/legal.html">' + 668 // '<img src="http://mapillary.com/favicon.ico" ' + 669 // 'alt="Mapillary" height="16" width="16" />Mapillary (CC-BY-SA)', 670 // visibility: (overlay.visible).toLowerCase() == 'true', 671 // }); 672 // m.addLayer(mLyr); 673 // selectControl.addLayer(mLyr); 674 // break; 675 // case 'search': 676 // m.addLayer(new OpenLayers.Layer.Vector( 677 // overlay.name, 678 // overlay.url, 679 // { 680 // layers: overlay.layers, 681 // version: overlay.version, 682 // transparent: overlay.transparent, 683 // format: overlay.format 684 // }, { 685 // opacity: parseFloat(overlay.opacity), 686 // visibility: (overlay.visible).toLowerCase() == 'true', 687 // isBaseLayer: !1, 688 // attribution: overlay.attribution 689 // } 690 // )); 691 // break; 692 } 693 } 694} 695 696/** init. */ 697function olInit() { 698 if (typeof olEnable !== 'undefined' && olEnable) { 699 // add info window to DOM 700 const frag = document.createDocumentFragment(), 701 temp = document.createElement('div'); 702 temp.innerHTML = '<div id="popup" class="olPopup"><a href="#" id="popup-closer" class="olPopupCloseBox"></a><div id="popup-content"></div></div>'; 703 while (temp.firstChild) { 704 frag.appendChild(temp.firstChild); 705 } 706 document.body.appendChild(frag); 707 708 let _i = 0; 709 // create the maps in the page 710 for (_i = 0; _i < olMapData.length; _i++) { 711 const _id = olMapData[_i].mapOpts.id; 712 olMaps[_id] = createMap(olMapData[_i].mapOpts, olMapData[_i].poi); 713 714 // set max-width on help pop-over 715 jQuery('#' + _id).parent().parent().find('.olMapHelp').css('max-width', olMapData[_i].mapOpts.width); 716 717 // shrink the map width to fit inside page container 718 const _w = jQuery('#' + _id + '-olContainer').parent().innerWidth(); 719 if (parseInt(olMapData[_i].mapOpts.width) > _w) { 720 jQuery('#' + _id).width(_w); 721 jQuery('#' + _id).parent().parent().find('.olMapHelp').width(_w); 722 olMaps[_id].updateSize(); 723 } 724 } 725 726 // add overlays 727 olovAddToMap(); 728 729 let resizeTimer; 730 jQuery(window).on('resize', function (e) { 731 clearTimeout(resizeTimer); 732 resizeTimer = setTimeout(function () { 733 for (_i = 0; _i < olMapData.length; _i++) { 734 const _id = olMapData[_i].mapOpts.id; 735 const _w = jQuery('#' + _id + '-olContainer').parent().innerWidth(); 736 if (parseInt(olMapData[_i].mapOpts.width) > _w) { 737 jQuery('#' + _id).width(_w); 738 jQuery('#' + _id).parent().parent().find('.olMapHelp').width(_w); 739 olMaps[_id].updateSize(); 740 } 741 } 742 }, 250); 743 }); 744 745 // hide the table(s) with POI by giving it a print-only style 746 jQuery('.olPOItableSpan').addClass('olPrintOnly'); 747 // hide the static map image(s) by giving it a print only style 748 jQuery('.olStaticMap').addClass('olPrintOnly'); 749 // add help button with toggle. 750 jQuery('.olWebOnly > .olMap') 751 .prepend( 752 '<div class="olMapHelpButtonDiv">' 753 + '<button onclick="jQuery(\'.olMapHelp\').toggle(500);" class="olMapHelpButton olHasTooltip"><span>' 754 + 'Show or hide help</span>?</button></div>'); 755 // toggle to switch dynamic vs. static map 756 jQuery('.olMapHelp').before( 757 '<div class="a11y"><button onclick="jQuery(\'.olPrintOnly\').toggle();jQuery(\'.olWebOnly\').toggle();">' 758 + 'Hide or show the dynamic map</button></div>'); 759 } 760} 761 762/** 763 * CSS support flag. 764 * 765 * @type {Boolean} 766 */ 767let olCSSEnable = true; 768 769/* register olInit to run with onload event. */ 770jQuery(olInit); 771