Move a map to a seperate window.
Move a map to a seperate window.
import 'ol/ol.css';
import Map from 'ol/Map';
import OSM from 'ol/source/OSM';
import TileLayer from 'ol/layer/Tile';
import View from 'ol/View';
import {
Control,
FullScreen,
defaults as defaultControls,
} from 'ol/control';
import {fromLonLat} from 'ol/proj';
class UnusableMask extends Control {
constructor() {
super({
element: document.createElement('div'),
});
this.element.setAttribute('hidden', 'hidden');
this.element.className = 'ol-mask';
this.element.innerHTML = '<div>Map not usable</div>';
}
}
const localMapTarget = document.getElementById('map');
const map = new Map({
target: localMapTarget,
controls: defaultControls().extend([new FullScreen(), new UnusableMask()]),
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
center: fromLonLat([37.41, 8.82]),
zoom: 4,
}),
});
let mapWindow;
function closeMapWindow() {
if (mapWindow) {
mapWindow.close();
mapWindow = undefined;
}
}
// Close external window in case the main page is closed or reloaded
window.addEventListener('pagehide', closeMapWindow);
const button = document.getElementById('external-map-button');
function resetMapTarget() {
localMapTarget.style.height = '';
map.setTarget(localMapTarget);
button.disabled = false;
}
function updateOverlay() {
if (!mapWindow) {
return;
}
const externalMapTarget = mapWindow.document.getElementById('map');
if (!externalMapTarget) {
return;
}
if (document.visibilityState === 'visible') {
// Show controls and enable keyboard input
externalMapTarget.classList.remove('unusable');
externalMapTarget.setAttribute('tabindex', '0');
externalMapTarget.focus();
} else {
// Hide all controls and disable keyboard input
externalMapTarget.removeAttribute('tabindex');
externalMapTarget.classList.add('unusable');
}
}
window.addEventListener('visibilitychange', updateOverlay);
button.addEventListener('click', function () {
const blockerNotice = document.getElementById('blocker-notice');
blockerNotice.setAttribute('hidden', 'hidden');
button.disabled = true;
// Reset button and map target in case window did not load or open
let timeoutKey = setTimeout(function () {
closeMapWindow();
resetMapTarget();
blockerNotice.removeAttribute('hidden');
timeoutKey = undefined;
}, 3000);
mapWindow = window.open(
'resources/external-map-map.html',
'MapWindow',
'toolbar=0,location=0,menubar=0,width=800,height=600'
);
mapWindow.addEventListener('DOMContentLoaded', function () {
const externalMapTarget = mapWindow.document.getElementById('map');
localMapTarget.style.height = '0px';
map.setTarget(externalMapTarget);
if (timeoutKey) {
timeoutKey = clearTimeout(timeoutKey);
}
mapWindow.addEventListener('pagehide', function () {
resetMapTarget();
// Close window in case user does a page reload
closeMapWindow();
});
updateOverlay();
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>External map</title>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep"></script>
<!-- The lines below are only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,TextDecoder"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.3/minified.js"></script>
<style>
.map {
width: 100%;
height:400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<input id="external-map-button" type="button" value="Open external map"></input>
<span id="blocker-notice" hidden>Could not open map in external window. If you are using a popup or ad blocker you may need to disable it for this example.</span>
<script src="main.js"></script>
</body>
</html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<style>
body {
margin: 0;
}
.map {
height: 100%;
}
.map.unusable .ol-mask {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
background-color: rgba(0, 0, 0, .7);
color: white;
font: bold 3rem 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.map.unusable .ol-control {
display: none;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
</body>
</html>
{
"name": "external-map",
"dependencies": {
"ol": "6.12.0"
},
"devDependencies": {
"parcel": "^2.0.0"
},
"scripts": {
"start": "parcel index.html",
"build": "parcel build --public-url . index.html"
}
}