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