Skip to content

Instantly share code, notes, and snippets.

@StephanHoyer
Created January 4, 2016 08:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StephanHoyer/f34c685cfc1b31534039 to your computer and use it in GitHub Desktop.
Save StephanHoyer/f34c685cfc1b31534039 to your computer and use it in GitHub Desktop.
'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
};
.tooltip
font-size: 0.8rem
text-align: center
z-index: zIndexTooltip
transition: opacity 0.3s ease-in-out
opacity: 1
position: absolute
display: block
max-width: 17rem
line-height: 1rem
.tooltip-hidden
transition: none
pointer-events: none
opacity: 0
.tooltip-dark
.icon svg
fill: white
color: white
.tooltip-right
margin-left: triangleSize
&.tooltip-dark
bubble: left center rgba(black, 0.8)
&:not(.tooltip-dark)
bubble: left center white defaultBorderColor
.tooltip-bottom
margin-top: triangleSize
&.tooltip-dark
bubble: top center rgba(black, 0.8)
&:not(.tooltip-dark)
bubble: top center white defaultBorderColor
.tooltip-top
margin-top: - triangleSize
&.tooltip-dark
bubble: bottom center rgba(black, 0.8)
&:not(.tooltip-dark)
bubble: bottom center white defaultBorderColor
.tooltip-left
margin-left: - triangleSize
&.tooltip-dark
bubble: right center rgba(black, 0.8)
&:not(.tooltip-dark)
bubble: right center white defaultBorderColor
@StephanHoyer
Copy link
Author

usage:

Some in a base view

  var tooltip = require('./tooltip');
  tooltip.view();
var withTooltip = require('./tooltip').withTooltip;
withTooltip(m('div.that-should-have-tooltip'), 'Content of tooltip', tooltipOptions));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment