UNPKG

npmap.js

Version:

A JavaScript web mapping library, built as a Leaflet plugin, for the National Park Service.

223 lines (193 loc) 8.31 kB
/* global L */ /* TODO: - Detect if map is in an iframe - If map is in an iframe, detect if it is cross-domain - If it is, detect if window.postMessage is supported - If it is, enable it (this may work, but what if there are multiple maps on a page? the parent page may need to know which map has called fullscreen,, and there is no way to do this currently) - If it isn't, disable the tool - If it isn't, try to bubble up and set necessary CSS styles on window.parent window.postMessage should always be called for 'enterfullscreen' and 'exitfullscreen' You should provide a library that makes it easy to hook up to these postMessage calls */ 'use strict'; var util = require('../util/util'); var FullscreenControl = L.Control.extend({ initialize: function(options) { this._frame = null; this._supported = true; if ((window.self !== window.top) && document.referrer !== '') { // The map is in an iframe. if (util.parseDomainFromUrl(document.referrer) === util.parseDomainFromUrl(window.location.href)) { try { this._frame = window.frameElement; if (this._frame) { this._frameBody = this._getParentDocumentBody(this._frame); } } catch (exception) { this._supported = false; } } else { this._supported = false; } } // TODO: Also add ARIA attributes. this._li = L.DomUtil.create('li', ''); this._button = L.DomUtil.create('button', 'fullscreen enter', this._li); this._button.title = 'Enter fullscreen'; L.DomEvent.addListener(this._button, 'click', this.fullscreen, this); return this; }, _onKeyUp: function(e) { if (!e) { e = window.event; } if (this._isFullscreen === true && e.keyCode === 27) { this.fullscreen(); } }, addTo: function(map) { var toolbar = util.getChildElementsByClassName(map.getContainer().parentNode.parentNode, 'npmap-toolbar')[0]; toolbar.childNodes[1].appendChild(this._li); toolbar.style.display = 'block'; this._container = toolbar.parentNode.parentNode; this._isFullscreen = false; this._map = map; util.getChildElementsByClassName(this._container.parentNode, 'npmap-map-wrapper')[0].style.top = '26px'; return this; }, _getParentDocumentBody: function(el) { while (el.parentNode) { el = el.parentNode; if (el.tagName.toLowerCase() === 'body') { return el; } } return null; }, fullscreen: function() { if (this._supported) { var body = document.body, utils; if (this._isFullscreen) { if (this._frame) { this._frameBody.style.height = this._frameBodyHeight; this._frameBody.style.margin = this._frameBodyMargin; this._frameBody.style.overflow = this._frameBodyOverflow; this._frameBody.style.padding = this._frameBodyPadding; this._frameBody.style.width = this._frameBodyWidth; this._frame.height = this._frameHeight; this._frame.style.height = this._frameHeightStyle; this._frame.style.left = this._frameLeft; this._frame.style.margin = this._frameMargin; this._frame.style.padding = this._framePadding; this._frame.style.position = this._framePosition; this._frame.style.top = this._frameTop; this._frame.style.width = this._frameWidthStyle; this._frame.style.zIndex = this._frameZindex; this._frame.width = this._frameWidth; } body.style.margin = this._bodyMargin; body.style.overflow = this._bodyOverflow; body.style.padding = this._bodyPadding; this._container.style.left = this._containerLeft; this._container.style.position = this._containerPosition; this._container.style.top = this._containerTop; L.DomEvent.removeListener(document, 'keyup', this._onKeyUp); this._isFullscreen = false; L.DomUtil.removeClass(this._button, 'exit'); L.DomUtil.addClass(this._button, 'enter'); this._button.title = 'Enter fullscreen'; this._map.fire('exitfullscreen'); if (this._frame && window.postMessage) { parent.postMessage('exitfullscreen', '*'); if (this._frameBody) { utils = window.parent.NPMapUtils; if (utils && utils.fullscreenControl && utils.fullscreenControl.listeners && typeof utils.fullscreenControl.listeners.exitfullscreen === 'function') { utils.fullscreenControl.listeners.exitfullscreen(); } } } } else { // TODO: You should probably capture each margin and padding side individually (e.g. padding-left). if (this._frame) { this._frameBodyHeight = this._frameBody.style.height; this._frameBodyMargin = this._frameBody.style.margin; this._frameBodyOverflow = this._frameBody.style.overflow; this._frameBodyPadding = this._frameBody.style.padding; this._frameBodyWidth = this._frameBody.style.width; this._frameBody.style.height = '100%'; this._frameBody.style.margin = '0'; this._frameBody.style.overflow = 'hidden'; this._frameBody.style.padding = '0'; this._frameBody.style.width = '100%'; this._frameHeight = this._frame.height; this._frameHeightStyle = this._frame.style.height; this._frameLeft = this._frame.style.left; this._frameMargin = this._frame.style.margin; this._framePadding = this._frame.style.padding; this._framePosition = this._frame.style.position; this._frameTop = this._frame.style.top; this._frameWidth = this._frame.width; this._frameWidthStyle = this._frame.style.width; this._frameZindex = this._frame.style.zIndex; this._frame.height = '100%'; this._frame.style.height = '100%'; this._frame.style.left = '0'; this._frame.style.margin = '0'; this._frame.style.padding = '0'; this._frame.style.position = 'fixed'; this._frame.style.top = '0'; this._frame.style.width = '100%'; this._frame.style.zIndex = 9999999999; this._frame.width = '100%'; } this._bodyMargin = body.style.margin; this._bodyOverflow = body.style.overflow; this._bodyPadding = body.style.padding; body.style.margin = '0'; body.style.overflow = 'hidden'; body.style.padding = '0'; this._containerLeft = this._container.style.left; this._containerPosition = this._container.style.position; this._containerTop = this._container.style.top; this._container.style.left = '0'; this._container.style.position = 'fixed'; this._container.style.top = '0'; L.DomEvent.addListener(document, 'keyup', this._onKeyUp, this); this._isFullscreen = true; L.DomUtil.removeClass(this._button, 'enter'); L.DomUtil.addClass(this._button, 'exit'); this._button.title = 'Exit fullscreen'; this._map.fire('enterfullscreen'); if (this._frame && window.postMessage) { parent.postMessage('enterfullscreen', '*'); if (this._frameBody) { utils = window.parent.NPMapUtils; if (utils && utils.fullscreenControl && utils.fullscreenControl.listeners && typeof utils.fullscreenControl.listeners.enterfullscreen === 'function') { utils.fullscreenControl.listeners.enterfullscreen(); } } } } this._map.invalidateSize(); } else { window.alert('Sorry, but the fullscreen tool does not work for maps that are loaded in an iframe hosted from another domain.'); } } }); L.Map.mergeOptions({ fullscreenControl: false }); L.Map.addInitHook(function() { if (this.options.fullscreenControl) { var options = {}; if (typeof this.options.fullscreenControl === 'object') { options = this.options.fullscreenControl; } this.fullscreenControl = L.npmap.control.fullscreen(options).addTo(this); } }); module.exports = function(options) { return new FullscreenControl(options); };