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