'use strict'; var m = require('mithril'); var isFunction = require('lodash/lang/isFunction'); var assign = require('lodash/object/assign'); var minMax = require('client/utils').minMax; var content, targetDimensions, options, showTimer, isVisible; function px(value) { return value + 'px'; } function show(_content, _options) { var wrapInRedraw = require('client/utils/viewhelper').wrapInRedraw; return function(event) { targetDimensions = event.currentTarget.getBoundingClientRect(); options = assign({ position: 'bottom', delay: 500 }, _options); content = _content; showTimer = setTimeout(wrapInRedraw(function() { isVisible = true; }), options.delay); }; } function hide() { clearTimeout(showTimer); isVisible = false; } function withTooltip(el, content, options) { el.attrs.onmouseenter = show(content, assign({ position: 'bottom', delay: 500 }, options)); el.attrs.onmouseout = hide; return el; } function view() { var classy = require('client/utils/viewhelper').classy; if (!content) { return; } var classes = { 'tooltip-hidden': !isVisible, 'tooltip-dark': options.dark }; classes['tooltip-' + options.position] = true; return m('.tooltip', { className: classy(classes), config: function(element) { var contentDimensions = element.getBoundingClientRect(); var targetVerticalCenter = targetDimensions.top + targetDimensions.height/2; var targetHorizontalCenter = targetDimensions.left + targetDimensions.width/2; // ensure that bubble is on screen if (targetHorizontalCenter + contentDimensions.width / 2 > window.innerWidth) { options.position = 'left'; } if (targetHorizontalCenter - contentDimensions.width / 2 < 0) { options.position = 'right'; } if (targetVerticalCenter - contentDimensions.height / 2 < 0) { options.position = 'bottom'; } if (targetVerticalCenter + contentDimensions.height / 2 > window.innerHeight) { options.position = 'top'; } // default bottom var left = targetHorizontalCenter - contentDimensions.width/2; var top = targetDimensions.bottom; if (options.position === 'right') { left = targetDimensions.right; top = targetVerticalCenter - contentDimensions.height/2; } else if (options.position === 'top') { left = targetHorizontalCenter - contentDimensions.width/2; top = targetDimensions.top - contentDimensions.height; } else if (options.position === 'left') { left = targetDimensions.left - contentDimensions.width; top = targetVerticalCenter - contentDimensions.height/2; } // again ensure that bubble is on screen in case it's in one of the screen edges left = minMax(0, left, window.innerWidth - contentDimensions.width); top = minMax(0, top, window.innerHeight - contentDimensions.height); element.style.left = px(Math.floor(window.scrollX + left)); element.style.top = px(Math.floor(window.scrollY + top)); } }, isFunction(content) ? content() : content); } module.exports = { show: show, hide: hide, view: view, withTooltip: withTooltip };