in modules/ui/curtain.js [69:235]
curtain.reveal = function(box, html, options) {
options = options || {};
if (typeof box === 'string') {
box = d3_select(box).node();
}
if (box && box.getBoundingClientRect) {
box = copyBox(box.getBoundingClientRect());
var containerRect = containerNode.getBoundingClientRect();
box.top -= containerRect.top;
box.left -= containerRect.left;
}
if (box && options.padding) {
box.top -= options.padding;
box.left -= options.padding;
box.bottom += options.padding;
box.right += options.padding;
box.height += options.padding * 2;
box.width += options.padding * 2;
}
var tooltipBox;
if (options.tooltipBox) {
tooltipBox = options.tooltipBox;
if (typeof tooltipBox === 'string') {
tooltipBox = d3_select(tooltipBox).node();
}
if (tooltipBox && tooltipBox.getBoundingClientRect) {
tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
}
} else {
tooltipBox = box;
}
if (tooltipBox && html) {
if (html.indexOf('**') !== -1) {
if (html.indexOf('<span') === 0) {
html = html.replace(/^(<span.*?>)(.+?)(\*\*)/, '$1<span>$2</span>$3');
} else {
html = html.replace(/^(.+?)(\*\*)/, '<span>$1</span>$2');
}
// pseudo markdown bold text for the instruction section..
html = html.replace(/\*\*(.*?)\*\*/g, '<span class="instruction">$1</span>');
}
html = html.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
html = html.replace(/\{br\}/g, '<br/><br/>'); // linebreak
if (options.buttonText && options.buttonCallback) {
html += '<div class="button-section">' +
'<button href="#" class="button action">' + options.buttonText + '</button></div>';
}
var classes = 'curtain-tooltip popover tooltip arrowed in ' + (options.tooltipClass || '');
tooltip
.classed(classes, true)
.selectAll('.popover-inner')
.html(html);
if (options.buttonText && options.buttonCallback) {
var button = tooltip.selectAll('.button-section .button.action');
button
.on('click', function(d3_event) {
d3_event.preventDefault();
options.buttonCallback();
});
}
var tip = copyBox(tooltip.node().getBoundingClientRect()),
w = containerNode.clientWidth,
h = containerNode.clientHeight,
tooltipWidth = 200,
tooltipArrow = 5,
side, pos;
// hack: this will have bottom placement,
// so need to reserve extra space for the tooltip illustration.
if (options.tooltipClass === 'intro-mouse') {
tip.height += 80;
}
// trim box dimensions to just the portion that fits in the container..
if (tooltipBox.top + tooltipBox.height > h) {
tooltipBox.height -= (tooltipBox.top + tooltipBox.height - h);
}
if (tooltipBox.left + tooltipBox.width > w) {
tooltipBox.width -= (tooltipBox.left + tooltipBox.width - w);
}
// determine tooltip placement..
if (tooltipBox.top + tooltipBox.height < 100) {
// tooltip below box..
side = 'bottom';
pos = [
tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
tooltipBox.top + tooltipBox.height
];
} else if (tooltipBox.top > h - 140) {
// tooltip above box..
side = 'top';
pos = [
tooltipBox.left + tooltipBox.width / 2 - tip.width / 2,
tooltipBox.top - tip.height
];
} else {
// tooltip to the side of the tooltipBox..
var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
if (localizer.textDirection() === 'rtl') {
if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
side = 'right';
pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
} else {
side = 'left';
pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
}
} else {
if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
side = 'left';
pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
} else {
side = 'right';
pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
}
}
}
if (options.duration !== 0 || !tooltip.classed(side)) {
tooltip.call(uiToggle(true));
}
tooltip
.style('top', pos[1] + 'px')
.style('left', pos[0] + 'px')
.attr('class', classes + ' ' + side);
// shift popover-inner if it is very close to the top or bottom edge
// (doesn't affect the placement of the popover-arrow)
var shiftY = 0;
if (side === 'left' || side === 'right') {
if (pos[1] < 60) {
shiftY = 60 - pos[1];
} else if (pos[1] + tip.height > h - 100) {
shiftY = h - pos[1] - tip.height - 100;
}
}
tooltip.selectAll('.popover-inner')
.style('top', shiftY + 'px');
} else {
tooltip
.classed('in', false)
.call(uiToggle(false));
}
curtain.cut(box, options.duration);
return tooltip;
};