modules/behavior/tail.js (71 lines of code) (raw):

import { event as d3_event, select as d3_select } from 'd3-selection'; import { utilSetTransform } from '../util'; import { utilGetDimensions } from '../util/dimensions'; export function behaviorTail() { var container; var xmargin = 25; var tooltipSize = [0, 0]; var selectionSize = [0, 0]; var _text; function behavior(selection) { if (!_text) return; d3_select(window) .on('resize.tail', function() { selectionSize = utilGetDimensions(selection); }); container = d3_select(document.body) .append('div') .style('display', 'none') .attr('class', 'tail tooltip-inner'); container.append('div') .text(_text); selection .on('mousemove.tail', mousemove) .on('mouseenter.tail', mouseenter) .on('mouseleave.tail', mouseleave); container .on('mousemove.tail', mousemove); tooltipSize = utilGetDimensions(container); selectionSize = utilGetDimensions(selection); function show() { container.style('display', 'block'); tooltipSize = utilGetDimensions(container); } function mousemove() { if (container.style('display') === 'none') show(); var xoffset = ((d3_event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ? -tooltipSize[0] - xmargin : xmargin; container.classed('left', xoffset > 0); utilSetTransform(container, d3_event.clientX + xoffset, d3_event.clientY); } function mouseleave() { if (d3_event.relatedTarget !== container.node()) { container.style('display', 'none'); } } function mouseenter() { if (d3_event.relatedTarget !== container.node()) { show(); } } } behavior.off = function(selection) { if (!_text) return; container .on('mousemove.tail', null) .remove(); selection .on('mousemove.tail', null) .on('mouseenter.tail', null) .on('mouseleave.tail', null); d3_select(window) .on('resize.tail', null); }; behavior.text = function(val) { if (!arguments.length) return _text; _text = val; return behavior; }; return behavior; }