Skip to content

Instantly share code, notes, and snippets.

@karreiro
Last active January 17, 2021 17:35
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 karreiro/cb205a2eba404210e01cf3465e75687c to your computer and use it in GitHub Desktop.
Save karreiro/cb205a2eba404210e01cf3465e75687c to your computer and use it in GitHub Desktop.

Simple tooltip system

2021-01-17 16 24 55

<div class=" preview tooltip">
<div class=" preview tooltip-content"></div>
</div>
<iframe src="" class=" preview tooltip-iframe"></iframe>
<script src="/assets/js/preview-tooltip.js"></script>
(function () {
var showTooltipTimeout, opacityTimeout, contentTimeout;
var ENABLED_CSS_CLASS = "enabled";
var DELAY_TO_SHOW = 750;
var OPACITY_DURATION = 100;
var tooltip = document.querySelector(".preview.tooltip");
var tooltipContent = document.querySelector(".preview.tooltip-content");
var tooltipIframe = document.querySelector(".preview.tooltip-iframe");
var linkElements = document.querySelectorAll(".wiki a");
function showTooltip() {
setTimeout(function () {
tooltip.classList.add(ENABLED_CSS_CLASS);
}, 1);
}
function hideTooltip() {
function clearTooltipContent() {
contentTimeout = setTimeout(function () {
tooltipContent.innerHTML = "";
}, OPACITY_DURATION + 1);
}
clearTimeout(showTooltipTimeout);
opacityTimeout = setTimeout(function () {
tooltip.classList.remove(ENABLED_CSS_CLASS);
clearTooltipContent();
}, OPACITY_DURATION);
}
function getTooltipDocument() {
return tooltipIframe.contentWindow.document;
}
function getTooltipIframeTitle() {
return getTooltipDocument().querySelector("h1").textContent;
}
function getTooltipIframeContent() {
var content = getTooltipDocument().querySelector(".content");
content.querySelectorAll("img").forEach(function (img) {
var rawSrc = img.getAttribute("src");
var prefix = tooltipIframe.src.replace(/\/$/, "");
img.src = prefix + "/" + rawSrc;
});
return content.innerHTML.trim();
}
function updateTooltipContent() {
var html = "";
html += '<div class="title">' + getTooltipIframeTitle() + "</div>";
html += getTooltipIframeContent() || "Empty page.";
tooltipContent.innerHTML = html;
}
function setTooltipContent(event) {
tooltipIframe.src = event.target.href;
tooltipIframe.onload = function () {
updateTooltipContent();
showTooltip();
};
}
function setTooltipPosition(event) {
var link = event.target;
var linkRect = link.getBoundingClientRect();
var visibleHeight = window.innerHeight;
var tooltipHeight = 225;
var isVisiableBelow =
linkRect.y + linkRect.height + tooltipHeight < visibleHeight;
if (isVisiableBelow) {
tooltip.style.top = linkRect.y + linkRect.height + 5 + "px";
} else {
tooltip.style.top = linkRect.y - tooltipHeight - 5 + "px";
}
tooltip.style.left = linkRect.x + "px";
}
function enableTooltip(event) {
if (event.target.host !== window.location.host) {
return;
}
clearTimeout(showTooltipTimeout);
showTooltipTimeout = setTimeout(function () {
clearHideTooltipTimeouts();
setTooltipPosition(event);
setTooltipContent(event);
}, DELAY_TO_SHOW);
}
function clearHideTooltipTimeouts() {
clearTimeout(opacityTimeout);
clearTimeout(contentTimeout);
}
function setupLinkElement(linkElement) {
linkElement.addEventListener("mouseleave", hideTooltip);
linkElement.addEventListener("mouseenter", enableTooltip);
}
function setupTooltipElement() {
tooltip.addEventListener("mouseleave", hideTooltip);
}
function setupLinkElements() {
linkElements.forEach(setupLinkElement);
}
setupLinkElements();
setupTooltipElement();
})();
// Preview
// ––––––––––––––––––––––––––––––––––––––––––––––––––
.preview
&.tooltip,
&.tooltip-iframe
pointer-events: none
&.tooltip-iframe
display: none
height: 0
width: 0
&.tooltip
pointer-events: none
opacity: 0
margin-top: 1rem
background: #ffffff
padding: 1em
overflow: hidden
position: fixed
border: 1px solid #eeeeee
box-shadow: 0 8px 18px rgba(0, 0, 0, .15)
transition: opacity 100ms, margin 100ms
transform: translateZ(0)
z-index: 1
filter: grayscale(.9)
top: 0
left: 0
width: 0
height: 0
&::after
content: ""
position: absolute
z-index: 1
bottom: 0
left: 0
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 90%)
width: 100%
height: 50px
&.enabled
width: 350px
height: 225px
opacity: 1
margin-top: 0
& > div
zoom: .7
.title
zoom: 1.4
font-weight: bold
margin-bottom: .5rem
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment