UNPKG

vega-tooltip

Version:

A tooltip plugin for Vega-Lite and Vega visualizations.

94 lines (78 loc) 2.81 kB
import {TooltipHandler} from 'vega-typings'; import {createDefaultStyle, DEFAULT_OPTIONS, Options} from './defaults.js'; import {calculatePositionRelativeToCursor, calculatePositionRelativeToMark} from './position.js'; /** * The tooltip handler class. */ export class Handler { /** * The handler function. We bind this to this function in the constructor. */ public call: TooltipHandler; /** * Complete tooltip options. */ private options: Required<Options>; /** * The tooltip html element. */ private el: HTMLElement | null; /** * Create the tooltip handler and initialize the element and style. * * @param options Tooltip Options */ constructor(options?: Options) { this.options = {...DEFAULT_OPTIONS, ...options}; const elementId = this.options.id; this.el = null; // bind this to call this.call = this.tooltipHandler.bind(this); // prepend a default stylesheet for tooltips to the head if (!this.options.disableDefaultStyle && !document.getElementById(this.options.styleId)) { const style = document.createElement('style'); style.setAttribute('id', this.options.styleId); style.innerHTML = createDefaultStyle(elementId); const head = document.head; if (head.childNodes.length > 0) { head.insertBefore(style, head.childNodes[0]); } else { head.appendChild(style); } } } /** * The tooltip handler function. */ private tooltipHandler(handler: any, event: MouseEvent, item: any, value: any) { // append a div element that we use as a tooltip unless it already exists this.el = document.getElementById(this.options.id); if (!this.el) { this.el = document.createElement('div'); this.el.setAttribute('id', this.options.id); this.el.classList.add('vg-tooltip'); const tooltipContainer = document.fullscreenElement ?? document.body; tooltipContainer.appendChild(this.el); } // hide tooltip for null, undefined, or empty string values if (value == null || value === '') { this.el.classList.remove('visible', `${this.options.theme}-theme`); return; } // set the tooltip content this.el.innerHTML = this.options.formatTooltip( value, this.options.sanitize, this.options.maxDepth, this.options.baseURL, ); // make the tooltip visible this.el.classList.add('visible', `${this.options.theme}-theme`); const {x, y} = this.options.anchor === 'mark' ? calculatePositionRelativeToMark(handler, event, item, this.el.getBoundingClientRect(), this.options) : calculatePositionRelativeToCursor(event, this.el.getBoundingClientRect(), this.options); this.el.style.top = `${y}px`; this.el.style.left = `${x}px`; } }