/* leaflet.responsive.popup 0.6.4 (c) 2019 https://github.com/yafred */ L.ResponsivePopup = L.Popup.extend({ options: { hasTip: true, /* * Inherited from L.Popup * * - offset * * - autoPanPadding * - autoPanPaddingTopLeft * - autoPanPaddingBottomRight */ }, /** * Overrides https://github.com/Leaflet/Leaflet/blob/v1.3.4/src/layer/Popup.js#L176 * This is to add hasTip option */ _initLayout: function () { var prefix = "leaflet-rrose", container = (this._container = L.DomUtil.create( "div", prefix + " " + (this.options.className || "") + " leaflet-zoom-animated", )); var wrapper = (this._wrapper = L.DomUtil.create( "div", prefix + "-content-wrapper", container, )); this._contentNode = L.DomUtil.create("div", prefix + "-content", wrapper); L.DomEvent.disableClickPropagation(wrapper); L.DomEvent.disableScrollPropagation(this._contentNode); L.DomEvent.on(wrapper, "contextmenu", L.DomEvent.stopPropagation); this._tipContainer = L.DomUtil.create( "div", prefix + "-tip-container", container, ); if (!this.options.hasTip) { this._tipContainer.style.visibility = "hidden"; } this._tip = L.DomUtil.create("div", prefix + "-tip", this._tipContainer); if (this.options.closeButton) { var closeButton = (this._closeButton = L.DomUtil.create( "a", prefix + "-close-button", container, )); closeButton.href = "#close"; closeButton.innerHTML = "×"; L.DomEvent.on(closeButton, "click", this._onCloseButtonClick, this); } }, /** * Overrides https://github.com/Leaflet/Leaflet/blob/v1.3.4/src/layer/DivOverlay.js#L178 */ _updatePosition: function () { if (!this._map) { return; } var pos = this._map.latLngToLayerPoint(this._latlng), basePoint = this._map.layerPointToContainerPoint(pos), containerWidth = this._container.offsetWidth, containerHeight = this._container.offsetHeight, padding = L.point(this.options.autoPanPadding), paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), mapSize = this._map.getSize(), anchor = this._getAnchor(), // popup anchor offset = L.point(this.options.offset); // offset relative to anchor (option from L.DivOverlay. We only use absolute values). // Leaflet default dimensions (should not be hard coded in the future) var tipHeight = 11; //px var tipWidth = 22; //px var containerRadius = 12; //px // Tweak offset to include tip dimensions var offsetX = Math.abs(offset.x); var offsetY = Math.abs(offset.y); if (this.options.hasTip) { offsetX += tipHeight; offsetY += tipHeight; // clear CSS L.DomUtil.removeClass(this._container, "leaflet-resp-popup-north"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-south"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-east"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-west"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-north-east"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-north-west"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-south-east"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-south-west"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-east-north"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-east-south"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-west-north"); L.DomUtil.removeClass(this._container, "leaflet-resp-popup-west-south"); // this._container.style.display = 'initial'; // this does not work } // Where can we fit the popup ? var canGoTop = true, canGoBottom = true, canGoLeft = true, canGoRight = true, containerPos = false; if ( basePoint.y + anchor.y - offsetY - containerHeight - Math.abs(paddingTL.y) < 0 ) { canGoTop = false; } if ( basePoint.y + anchor.y + offsetY + containerHeight + Math.abs(paddingBR.y) > mapSize.y ) { canGoBottom = false; } if ( basePoint.x + anchor.x - offsetX - containerWidth - Math.abs(paddingTL.x) < 0 ) { canGoLeft = false; } if ( basePoint.x + anchor.x + offsetX + containerWidth + Math.abs(paddingBR.x) > mapSize.x ) { canGoRight = false; } // manage overflows var subtractX = containerWidth / 2 - anchor.x, subtractY = containerHeight / 2 - anchor.y; if (canGoTop || canGoBottom) { var containerLeft = basePoint.x + anchor.x - containerWidth / 2; var containerRight = basePoint.x + anchor.x + containerWidth / 2; if (containerLeft < Math.abs(paddingTL.x)) { // left overflow subtractX = containerWidth / 2 - anchor.x - Math.abs(paddingTL.x) + containerLeft; } if (containerRight > mapSize.x - Math.abs(paddingBR.x)) { // right overflow subtractX = containerWidth / 2 - anchor.x + containerRight - mapSize.x + Math.abs(paddingBR.x); } } if (canGoLeft || canGoRight) { var containerTop = basePoint.y + anchor.y - containerHeight / 2; var containerBottom = basePoint.y + anchor.y + containerHeight / 2; if (containerTop < Math.abs(paddingTL.y)) { // top overflow subtractY = containerHeight / 2 - anchor.y - Math.abs(paddingTL.y) + containerTop; } if (containerBottom > mapSize.y - Math.abs(paddingBR.y)) { // bottom overflow subtractY = containerHeight / 2 - anchor.y + containerBottom - mapSize.y + Math.abs(paddingBR.y); } } // position the popup (order of preference is: top, left, bottom, right, centerOnMap) if (canGoTop) { containerPos = pos.subtract( L.point(subtractX, -anchor.y + containerHeight + offsetY, true), ); if (this.options.hasTip) { if ( basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth / 2 ) { containerPos.x = pos.x + anchor.x; L.DomUtil.addClass(this._container, "leaflet-resp-popup-north-east"); this._tipContainer.style.top = containerHeight + "px"; this._tipContainer.style.left = "0px"; } else if ( basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth / 2 ) { containerPos.x = pos.x + anchor.x - containerWidth; L.DomUtil.addClass(this._container, "leaflet-resp-popup-north-west"); this._tipContainer.style.top = containerHeight + "px"; this._tipContainer.style.left = containerWidth + "px"; } else { L.DomUtil.addClass(this._container, "leaflet-resp-popup-north"); this._tipContainer.style.top = containerHeight + "px"; this._tipContainer.style.left = pos.x + anchor.x - containerPos.x + "px"; } } } else if (canGoLeft) { containerPos = pos.subtract( L.point(-anchor.x + containerWidth + offsetX, subtractY, true), ); if (this.options.hasTip) { if ( basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth / 2 ) { containerPos.y = pos.y + anchor.y; L.DomUtil.addClass(this._container, "leaflet-resp-popup-west-south"); this._tipContainer.style.top = "0px"; this._tipContainer.style.left = containerWidth + "px"; } else if ( basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth / 2 ) { containerPos.y = pos.y + anchor.y - containerHeight; L.DomUtil.addClass(this._container, "leaflet-resp-popup-west-north"); this._tipContainer.style.top = containerHeight + "px"; this._tipContainer.style.left = containerWidth + "px"; } else { L.DomUtil.addClass(this._container, "leaflet-resp-popup-west"); this._tipContainer.style.top = pos.y + anchor.y - containerPos.y + "px"; this._tipContainer.style.left = containerWidth + "px"; } } } else if (canGoBottom) { containerPos = pos.subtract( L.point(subtractX, -anchor.y - offsetY, true), ); if (this.options.hasTip) { if ( basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth / 2 ) { containerPos.x = pos.x + anchor.x; L.DomUtil.addClass(this._container, "leaflet-resp-popup-south-east"); this._tipContainer.style.top = "1px"; this._tipContainer.style.left = "0px"; } else if ( basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth / 2 ) { containerPos.x = pos.x + anchor.x - containerWidth; L.DomUtil.addClass(this._container, "leaflet-resp-popup-south-west"); this._tipContainer.style.top = "0px"; this._tipContainer.style.left = containerWidth + "px"; } else { L.DomUtil.addClass(this._container, "leaflet-resp-popup-south"); this._tipContainer.style.top = "2px"; this._tipContainer.style.left = pos.x + anchor.x - containerPos.x + "px"; } } } else if (canGoRight) { containerPos = pos.subtract( L.point(-anchor.x - offsetX, subtractY, true), ); if (this.options.hasTip) { if ( basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth / 2 ) { containerPos.y = pos.y + anchor.y; L.DomUtil.addClass(this._container, "leaflet-resp-popup-east-south"); this._tipContainer.style.top = "0px"; this._tipContainer.style.left = "0px"; } else if ( basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth / 2 ) { containerPos.y = pos.y + anchor.y - containerHeight; L.DomUtil.addClass(this._container, "leaflet-resp-popup-east-north"); this._tipContainer.style.top = containerHeight + "px"; this._tipContainer.style.left = "0px"; } else { L.DomUtil.addClass(this._container, "leaflet-resp-popup-east"); this._tipContainer.style.top = pos.y + anchor.y - containerPos.y + "px"; this._tipContainer.style.left = "4px"; } } } else { var pos = this._map.latLngToLayerPoint(this._map.getCenter()); containerPos = pos.subtract( L.point(containerWidth / 2, containerHeight / 2), ); if (this.options.hasTip) { // this._tipContainer.style.display = 'none'; // this does not work } } // if point is not visible, just hide the popup if ( basePoint.x < 0 || basePoint.y < 0 || basePoint.x > mapSize.x || basePoint.y > mapSize.y ) { // this._container.style.display = 'none'; // this does not work } // if container is too big, just hide the popup if ( containerWidth - Math.abs(paddingTL.x) - Math.abs(paddingBR.x) > mapSize.x || containerHeight - Math.abs(paddingTL.y) - Math.abs(paddingBR.y) > mapSize.y ) { // this._container.style.display = 'none'; // this does not work } L.DomUtil.setPosition(this._container, containerPos); }, }); //Instantiates a `ResponsivePopup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers. L.responsivePopup = function (options, source) { return new L.ResponsivePopup(options, source); }; //Adds Angular support if (typeof exports === "object" && typeof module !== "undefined") { exports.responsivePopup = L.responsivePopup; exports.ResponsivePopup = L.ResponsivePopup; }