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 const geoJsonSource = new ol.source.Vector({ 320 url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.geojsonfile, 321 format: new ol.format.GeoJSON(), 322 }); 323 overlayGroup.getLayers().push(new ol.layer.Vector({ 324 title: 'GeoJSON file', visible: true, source: geoJsonSource, 325 // TODO 326 // style: { 327 // strokeColor: "#FF00FF", 328 // strokeWidth: 3, 329 // strokeOpacity: 0.7, 330 // pointRadius: 4, 331 // fillColor: "#FF99FF", 332 // fillOpacity: 0.7 333 // } 334 })); 335 336 if (mapOpts.autozoom) { 337 geoJsonSource.once('change', function () { 338 extent = ol.extent.extend(extent, geoJsonSource.getExtent()); 339 map.getView().fit(extent); 340 }); 341 } 342 } catch (e) { 343 console.error(e); 344 } 345 } 346 347 if (mapOpts.gpxfile.length > 0) { 348 try { 349 const gpxSource = new ol.source.Vector({ 350 url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.gpxfile, 351 format: new ol.format.GPX(), 352 }); 353 overlayGroup.getLayers().push(new ol.layer.Vector({ 354 title: 'GPS track', visible: true, source: gpxSource, 355 // TODO 356 // style: { 357 // strokeColor: "#0000FF", 358 // strokeWidth: 3, 359 // strokeOpacity: 0.7, 360 // pointRadius: 4, 361 // fillColor: "#0099FF", 362 // fillOpacity: 0.7 363 // } 364 })); 365 366 if (mapOpts.autozoom) { 367 gpxSource.once('change', function () { 368 extent = ol.extent.extend(extent, gpxSource.getExtent()); 369 map.getView().fit(extent); 370 }); 371 } 372 } catch (e) { 373 console.error(e); 374 } 375 } 376 377 const container = document.getElementById('popup'); 378 const content = document.getElementById('popup-content'); 379 const closer = document.getElementById('popup-closer'); 380 381 const overlay = new ol.Overlay({ 382 element: container, autoPan: true, autoPanAnimation: { 383 duration: 250, 384 }, //stopEvent: false, 385 }); 386 map.addOverlay(overlay); 387 388 /** 389 * Add a click handler to hide the popup. 390 * @return {boolean} Don't follow the href. 391 */ 392 closer.onclick = function () { 393 overlay.setPosition(undefined); 394 closer.blur(); 395 return false; 396 }; 397 398 // display popup on click 399 map.on('singleclick', function (evt) { 400 const selFeature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { 401 return feature; 402 }); 403 if (selFeature) { 404 overlay.setPosition(evt.coordinate); 405 406 let pContent = '<div class="spacer"> </div>'; 407 let locDesc = ''; 408 409 if (selFeature.get('rowId') !== undefined) { 410 pContent += '<span class="rowId">' + selFeature.get('rowId') + ': </span>'; 411 } 412 if (selFeature.get('name') !== undefined) { 413 pContent += '<span class="txt">' + selFeature.get('name') + '</span>'; 414 locDesc = selFeature.get('name'); 415 // TODO strip <p> tag from locDesc 416 // locDesc = selFeature.get('name').split(/\s+/).slice(0,2).join('+'); 417 } 418 if (selFeature.get('ele') !== undefined) { 419 pContent += '<div class="ele">elevation: ' + selFeature.get('ele') + '</div>'; 420 } 421 if (selFeature.get('type') !== undefined) { 422 pContent += '<div>' + selFeature.get('type') + '</div>'; 423 } 424 if (selFeature.get('time') !== undefined) { 425 pContent += '<div class="time">time: ' + selFeature.get('time') + '</div>'; 426 } 427 if (selFeature.get('description') !== undefined) { 428 pContent += '<div class="desc">' + selFeature.get('description') + '</div>'; 429 } 430 if (selFeature.get('img') !== undefined) { 431 pContent += '<div class="coord" title="lat;lon">' + 432 '<img alt="" src="' + DOKU_BASE + 'lib/plugins/openlayersmap/icons/' + selFeature.get('img') + 433 '" width="16" height="16" ' + 'style="transform:rotate(' + selFeature.get('angle') + 'deg)" /> ' + 434 '<a href="geo:' + selFeature.get('lat') + ',' + selFeature.get('lon') + '?q=' + selFeature.get('lat') + 435 ',' + selFeature.get('lon') + '(' + selFeature.get('alt') + ')" title="Open in navigation app">' + 436 ol.coordinate.format([selFeature.get('lon'), selFeature.get('lat')], '{x}º; {y}º', 4) + '</a></div>'; 437 } 438 content.innerHTML = pContent; 439 } else { 440 // do nothing... 441 } 442 }); 443 444 // change mouse cursor when over marker 445 map.on('pointermove', function (e) { 446 const pixel = map.getEventPixel(e.originalEvent); 447 const hit = map.hasFeatureAtPixel(pixel); 448 map.getTarget().style.cursor = hit ? 'pointer' : ''; 449 }); 450 451 return map; 452} 453 454/** 455 * add layers to the map based on the olMapOverlays object. 456 */ 457function olovAddToMap() { 458 for (const key in olMapOverlays) { 459 const overlay = olMapOverlays[key]; 460 const m = olMaps[overlay.id]; 461 462 switch (overlay.type) { 463 case 'osm': 464 m.addLayer(new ol.layer.Tile({ 465 title: overlay.name, 466 visible: (overlay.visible).toLowerCase() === 'true', 467 opacity: parseFloat(overlay.opacity), 468 source: new ol.source.OSM({ 469 url: overlay.url, 470 crossOrigin: 'Anonymous', 471 attributions: overlay.attribution 472 }) 473 })); 474 break; 475 case 'wms': 476 m.addLayer(new ol.layer.Image({ 477 title: overlay.name, 478 opacity: parseFloat(overlay.opacity), 479 visible: (overlay.visible).toLowerCase() === 'true', 480 source: new ol.source.ImageWMS({ 481 url: overlay.url, 482 params: { 483 'LAYERS': overlay.layers, 484 'VERSION': overlay.version, 485 'TRANSPARENT': overlay.transparent, 486 'FORMAT': overlay.format 487 }, 488 ratio: 1, 489 crossOrigin: 'Anonymous', 490 attributions: overlay.attribution 491 }) 492 })); 493 break; 494 case 'ags': 495 m.addLayer(new ol.layer.Image({ 496 title: overlay.name, 497 opacity: parseFloat(overlay.opacity), 498 visible: (overlay.visible).toLowerCase() === 'true', 499 source: new ol.source.ImageArcGISRest({ 500 url: overlay.url, 501 params: { 502 'LAYERS': overlay.layers, 503 'TRANSPARENT': overlay.transparent, 504 'FORMAT': overlay.format 505 }, 506 ratio: 1, 507 crossOrigin: 'Anonymous', 508 attributions: overlay.attribution 509 }) 510 })); 511 break; 512 // case 'mapillary': 513 // var mUrl = 'http://api.mapillary.com/v1/im/search?'; 514 // if (overlay.skey !== '') { 515 // mUrl = 'http://api.mapillary.com/v1/im/sequence?'; 516 // } 517 // var mLyr = new OpenLayers.Layer.Vector( 518 // "Mapillary", { 519 // projection: new OpenLayers.Projection("EPSG:4326"), 520 // strategies: [new OpenLayers.Strategy.BBOX({ 521 // ratio: 1.1, 522 // resFactor: 1.5 523 // }) /* ,new OpenLayers.Strategy.Cluster({}) */], 524 // protocol: new OpenLayers.Protocol.HTTP({ 525 // url: mUrl, 526 // format: new OpenLayers.Format.GeoJSON(), 527 // params: { 528 // // default to max. 250 locations 529 // 'max-results': 250, 530 // 'geojson': true, 531 // 'skey': overlay.skey 532 // }, 533 // filterToParams: function (filter, params) { 534 // if (filter.type === OpenLayers.Filter.Spatial.BBOX) { 535 // // override the bbox serialization of 536 // // the filter to give the Mapillary 537 // // specific bounds 538 // params['min-lat'] = filter.value.bottom; 539 // params['max-lat'] = filter.value.top; 540 // params['min-lon'] = filter.value.left; 541 // params['max-lon'] = filter.value.right; 542 // // if the width of our bbox width is 543 // // less than 0.15 degrees drop the max 544 // // results 545 // if (filter.value.top - filter.value.bottom < .15) { 546 // OpenLayers.Console.debug('dropping max-results parameter, width is: ', 547 // filter.value.top - filter.value.bottom); 548 // params['max-results'] = null; 549 // } 550 // } 551 // return params; 552 // } 553 // }), 554 // styleMap: new OpenLayers.StyleMap({ 555 // 'default': { 556 // cursor: 'help', 557 // rotation: '${ca}', 558 // externalGraphic: DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20.png', 559 // graphicHeight: 20, 560 // graphicWidth: 20, 561 // }, 562 // 'select': { 563 // externalGraphic: DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20-select.png', 564 // label: '${location}', 565 // fontSize: '1em', 566 // fontFamily: 'monospace', 567 // labelXOffset: '0.5', 568 // labelYOffset: '0.5', 569 // labelAlign: 'lb', 570 // } 571 // }), 572 // attribution: '<a href="http://www.mapillary.com/legal.html">' + 573 // '<img src="http://mapillary.com/favicon.ico" ' + 574 // 'alt="Mapillary" height="16" width="16" />Mapillary (CC-BY-SA)', 575 // visibility: (overlay.visible).toLowerCase() == 'true', 576 // }); 577 // m.addLayer(mLyr); 578 // selectControl.addLayer(mLyr); 579 // break; 580 // case 'search': 581 // m.addLayer(new OpenLayers.Layer.Vector( 582 // overlay.name, 583 // overlay.url, 584 // { 585 // layers: overlay.layers, 586 // version: overlay.version, 587 // transparent: overlay.transparent, 588 // format: overlay.format 589 // }, { 590 // opacity: parseFloat(overlay.opacity), 591 // visibility: (overlay.visible).toLowerCase() == 'true', 592 // isBaseLayer: !1, 593 // attribution: overlay.attribution 594 // } 595 // )); 596 // break; 597 } 598 } 599} 600 601/** init. */ 602function olInit() { 603 if (olEnable) { 604 // add info window to DOM 605 const frag = document.createDocumentFragment(), 606 temp = document.createElement('div'); 607 temp.innerHTML = '<div id="popup" class="olPopup"><a href="#" id="popup-closer" class="olPopupCloseBox"></a><div id="popup-content"></div></div>'; 608 while (temp.firstChild) { 609 frag.appendChild(temp.firstChild); 610 } 611 document.body.appendChild(frag); 612 613 let _i = 0; 614 // create the maps in the page 615 for (_i = 0; _i < olMapData.length; _i++) { 616 var _id = olMapData[_i].mapOpts.id; 617 olMaps[_id] = createMap(olMapData[_i].mapOpts, olMapData[_i].poi); 618 619 // set max-width on help pop-over 620 jQuery('#' + _id).parent().parent().find('.olMapHelp').css('max-width', olMapData[_i].mapOpts.width); 621 622 // shrink the map width to fit inside page container 623 var _w = jQuery('#' + _id + '-olContainer').parent().innerWidth(); 624 if (parseInt(olMapData[_i].mapOpts.width) > _w) { 625 jQuery('#' + _id).width(_w); 626 jQuery('#' + _id).parent().parent().find('.olMapHelp').width(_w); 627 olMaps[_id].updateSize(); 628 } 629 } 630 631 // add overlays 632 olovAddToMap(); 633 634 let resizeTimer; 635 jQuery(window).on('resize', function (e) { 636 clearTimeout(resizeTimer); 637 resizeTimer = setTimeout(function () { 638 for (_i = 0; _i < olMapData.length; _i++) { 639 var _id = olMapData[_i].mapOpts.id; 640 var _w = jQuery('#' + _id + '-olContainer').parent().innerWidth(); 641 if (parseInt(olMapData[_i].mapOpts.width) > _w) { 642 jQuery('#' + _id).width(_w); 643 jQuery('#' + _id).parent().parent().find('.olMapHelp').width(_w); 644 olMaps[_id].updateSize(); 645 } 646 } 647 }, 250); 648 }); 649 650 // hide the table(s) with POI by giving it a print-only style 651 jQuery('.olPOItableSpan').addClass('olPrintOnly'); 652 // hide the static map image(s) by giving it a print only style 653 jQuery('.olStaticMap').addClass('olPrintOnly'); 654 // add help button with toggle. 655 jQuery('.olWebOnly > .olMap') 656 .prepend( 657 '<div class="olMapHelpButtonDiv">' 658 + '<button onclick="jQuery(\'.olMapHelp\').toggle(500);" class="olMapHelpButton olHasTooltip"><span>' 659 + 'Show or hide help</span>?</button></div>'); 660 // toggle to switch dynamic vs. static map 661 jQuery('.olMapHelp').before( 662 '<div class="a11y"><button onclick="jQuery(\'.olPrintOnly\').toggle();jQuery(\'.olWebOnly\').toggle();">' 663 + 'Hide or show the dynamic map</button></div>'); 664 } 665} 666 667/** 668 * CSS support flag. 669 * 670 * @type {Boolean} 671 */ 672let olCSSEnable = true; 673 674/* register olInit to run with onload event. */ 675jQuery(olInit); 676