UNPKG

maplair

Version:

JavaScript library for mobile-friendly interactive maps

228 lines (227 loc) • 7.72 kB
import { stamp } from "../core/Util.js"; import { Point } from "../geometry/Point.js"; import { off, on } from "../dom/DomEvent.js"; import { create, setPosition } from "../dom/DomUtil.js"; import { Layer } from "./Layer.js"; import { FeatureGroup } from "./FeatureGroup.js"; import { DivOverlay } from "./DivOverlay.js"; //#region src/layer/Tooltip.js var Tooltip = class Tooltip extends DivOverlay { static { this.setDefaultOptions({ pane: "tooltipPane", offset: [0, 0], direction: "auto", permanent: false, sticky: false, opacity: .9 }); } constructor(...args) { super(...args); this.callInitHooks(Tooltip); } onAdd(map) { super.onAdd(map); this.setOpacity(this.options.opacity); map.fire("tooltipopen", { tooltip: this }); if (this._source) { this.addEventParent(this._source); this._source.fire("tooltipopen", { tooltip: this }, true); } } onRemove(map) { super.onRemove(map); map.fire("tooltipclose", { tooltip: this }); if (this._source) { this.removeEventParent(this._source); this._source.fire("tooltipclose", { tooltip: this }, true); } } getEvents() { const events = super.getEvents(); if (!this.options.permanent) events.preclick = this.close; return events; } _initLayout() { const className = `maplair-tooltip ${this.options.className || ""} maplair-zoom-${this._zoomAnimated ? "animated" : "hide"}`; this._contentNode = this._container = create("div", className); this._container.setAttribute("role", "tooltip"); this._container.setAttribute("id", `maplair-tooltip-${stamp(this)}`); } _updateLayout() {} _adjustPan() {} _setPosition(pos) { let subX, subY, direction = this.options.direction; const map = this._map, container = this._container, centerPoint = map.latLngToContainerPoint(map.getCenter()), tooltipPoint = map.layerPointToContainerPoint(pos), tooltipWidth = container.offsetWidth, tooltipHeight = container.offsetHeight, offset = new Point(this.options.offset), anchor = this._getAnchor(); if (direction === "top") { subX = tooltipWidth / 2; subY = tooltipHeight; } else if (direction === "bottom") { subX = tooltipWidth / 2; subY = 0; } else if (direction === "center") { subX = tooltipWidth / 2; subY = tooltipHeight / 2; } else if (direction === "right") { subX = 0; subY = tooltipHeight / 2; } else if (direction === "left") { subX = tooltipWidth; subY = tooltipHeight / 2; } else if (tooltipPoint.x < centerPoint.x) { direction = "right"; subX = 0; subY = tooltipHeight / 2; } else { direction = "left"; subX = tooltipWidth + (offset.x + anchor.x) * 2; subY = tooltipHeight / 2; } pos = pos.subtract(new Point(subX, subY, true)).add(offset).add(anchor); container.classList.remove("maplair-tooltip-right", "maplair-tooltip-left", "maplair-tooltip-top", "maplair-tooltip-bottom"); container.classList.add(`maplair-tooltip-${direction}`); setPosition(container, pos); } _updatePosition() { const pos = this._map.latLngToLayerPoint(this._latlng); this._setPosition(pos); } setOpacity(opacity) { this.options.opacity = opacity; if (this._container) this._container.style.opacity = opacity; } _animateZoom(e) { const pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center); this._setPosition(pos); } _getAnchor() { return new Point(this._source?._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]); } static register(MaplairMap) { MaplairMap.include({ openTooltip(tooltip, latlng, options) { this._initOverlay(Tooltip, tooltip, latlng, options).openOn(this); return this; }, closeTooltip(tooltip) { tooltip.close(); return this; } }); Layer.include({ bindTooltip(content, options) { if (this._tooltip && this.isTooltipOpen()) this.unbindTooltip(); this._tooltip = this._initOverlay(Tooltip, this._tooltip, content, options); this._initTooltipInteractions(); if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) this.openTooltip(); return this; }, unbindTooltip() { if (this._tooltip) { this._initTooltipInteractions(true); this.closeTooltip(); this._tooltip = null; } return this; }, _initTooltipInteractions(remove) { if (!remove && this._tooltipHandlersAdded) return; const onOff = remove ? "off" : "on", events = { remove: this.closeTooltip, move: this._moveTooltip }; if (!this._tooltip.options.permanent) { events.pointerover = this._openTooltip; events.pointerout = this.closeTooltip; events.click = this._openTooltip; if (this._map) this._addFocusListeners(remove); else events.add = () => this._addFocusListeners(remove); } else events.add = this._openTooltip; if (this._tooltip.options.sticky) events.pointermove = this._moveTooltip; this[onOff](events); this._tooltipHandlersAdded = !remove; }, openTooltip(latlng) { if (this._tooltip) { if (!(this instanceof FeatureGroup)) this._tooltip._source = this; if (this._tooltip._prepareOpen(latlng)) { this._tooltip.openOn(this._map); if (this.getElement) this._setAriaDescribedByOnLayer(this); else if (this.eachLayer) this.eachLayer(this._setAriaDescribedByOnLayer, this); } } return this; }, closeTooltip() { if (this._tooltip) return this._tooltip.close(); }, toggleTooltip() { this._tooltip?.toggle(this); return this; }, isTooltipOpen() { return this._tooltip.isOpen(); }, setTooltipContent(content) { this._tooltip?.setContent(content); return this; }, getTooltip() { return this._tooltip; }, _addFocusListeners(remove) { if (this.getElement) this._addFocusListenersOnLayer(this, remove); else if (this.eachLayer) this.eachLayer((layer) => this._addFocusListenersOnLayer(layer, remove), this); }, _addFocusListenersOnLayer(layer, remove) { const el = typeof layer.getElement === "function" && layer.getElement(); if (el) { const toggle = remove ? off : on; if (!remove) { el._maplair_focus_handler && off(el, "focus", el._maplair_focus_handler, this); el._maplair_focus_handler = () => { if (this._tooltip) { this._tooltip._source = layer; this.openTooltip(); } }; } el._maplair_focus_handler && toggle(el, "focus", el._maplair_focus_handler, this); toggle(el, "blur", this.closeTooltip, this); if (remove) delete el._maplair_focus_handler; } }, _setAriaDescribedByOnLayer(layer) { (typeof layer.getElement === "function" && layer.getElement())?.setAttribute?.("aria-describedby", this._tooltip._container.id); }, _openTooltip(e) { if (!this._tooltip || !this._map) return; if (this._map.dragging?.moving()) { if (e.type === "add" && !this._moveEndOpensTooltip) { this._moveEndOpensTooltip = true; this._map.once("moveend", () => { this._moveEndOpensTooltip = false; this._openTooltip(e); }); } return; } this._tooltip._source = e.propagatedFrom ?? e.target; this.openTooltip(this._tooltip.options.sticky ? e.latlng : void 0); }, _moveTooltip(e) { let latlng = e.latlng, containerPoint, layerPoint; if (this._tooltip.options.sticky && e.originalEvent) { containerPoint = this._map.pointerEventToContainerPoint(e.originalEvent); layerPoint = this._map.containerPointToLayerPoint(containerPoint); latlng = this._map.layerPointToLatLng(layerPoint); } this._tooltip.setLatLng(latlng); } }); } }; //#endregion export { Tooltip }; //# sourceMappingURL=Tooltip.js.map