Skip to content

Instantly share code, notes, and snippets.

@jacobio
Last active December 22, 2021 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacobio/bb845d272d244231cc078a7f0085b759 to your computer and use it in GitHub Desktop.
Save jacobio/bb845d272d244231cc078a7f0085b759 to your computer and use it in GitHub Desktop.
/** Global Vars **/
var PREVIEW_ELEM_NAME = "preview";
var PREVIEW_ELEM_ID = `#${PREVIEW_ELEM_NAME}`;
var SHOW_PREVIEW = true;
/**
*
**/
function loadExternalJS(srcUrl)
{
var script = null;
if (srcUrl) {
// Create the script element
script = document.createElement('script');
script.src = srcUrl;
script.type = "text/javascript";
// Add the script element to the DOM's <head> element
document.head.insertAdjacentElement('beforeend', script);
}
return script
}
/**
*
**/
function addDivElement(container, id)
{
var prev = null;
if (container && id) {
prev = document.createElement('div');
prev.id = id;
container.insertAdjacentElement('beforeend', prev);
}
return prev
}
/**
*
**/
function hideElementOnBlur(elem)
{
window.addEventListener("blur", () => {
elem.style.display = "none";
});
}
/**
*
**/
function isVisible(el)
{
var rect = el.getBoundingClientRect();
var elemTop = rect.top;
var elemBottom = rect.bottom;
// Only completely visible elements return true:
var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
return isVisible;
}
/**
*
**/
function renderPreview(linkElem, mdText)
{
// Only preview MD files that start with an h1
if (mdText.startsWith("# ") && SHOW_PREVIEW) {
var md = new Remarkable();
html = md.render(mdText);
var prev = document.querySelector(PREVIEW_ELEM_ID);
// Parse the text
var parser = new DOMParser();
var doc = parser.parseFromString(html, "text/html");
var content = doc.querySelector('body').innerHTML;
prev.innerHTML = content;
// First try displaying the popover below the the link
var top = linkElem.offsetTop + 30;
var left = Math.max(30, linkElem.offsetLeft - (prev.clientWidth / 2));
// If the popover is off the right-side of the page,
// pull it to the left
if ((left + prev.clientWidth) > document.body.clientWidth)
left = document.body.clientWidth - prev.clientWidth - 30;
prev.style.transform = `translate3d(${left}px, ${top}px, 0)`;
// If the popover is not visible, place it above the link
if (!isVisible(prev)) {
top = linkElem.offsetTop - prev.clientHeight - 30;
prev.style.transform = `translate3d(${left}px, ${top}px, 0)`;
}
prev.style.display = "block";
}
}
/**
*
**/
function showPreview(event)
{
var elem = event.target;
// Don't preview links to the current page
if (!elem.href.startsWith(window.location.href)) {
SHOW_PREVIEW = true;
setTimeout( () =>
fetch(elem.href, {
headers: { 'Content-Type': 'text/html; charset=UTF-8', }
}).then(function(response) {
return response.text().then(function(text) {
renderPreview(elem, text);
});
}), 250);
}
}
/**
*
**/
function hidePreview(event)
{
SHOW_PREVIEW = false;
document.querySelector(PREVIEW_ELEM_ID).style.display = "none";
}
/**
*
**/
function enablePreview(link)
{
// Show preview
link.addEventListener('mouseover', showPreview);
link.addEventListener("mouseenter", showPreview);
link.addEventListener("focus", showPreview);
// Hide preview
link.addEventListener("mouseout", hidePreview);
link.addEventListener("mouseleave", hidePreview);
link.addEventListener("focusout", hidePreview);
}
/**
*
**/
function makeLinksPreviewable()
{
// Get internal and/or relative links only
let links = document.querySelectorAll(
'a:not([href^="https://"]):not([href^="http://"]):not([href^="#"])');
links.forEach(function(link){
enablePreview(link);
});
}
// Load the Remarkable Markdown parser for creating MD HTML previews
loadExternalJS("https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.4/remarkable.min.js")
// Wait for the DOM to load before processing elements
document.addEventListener("DOMContentLoaded", function () {
// Add the preview DOM element
let prev = addDivElement(document.body, PREVIEW_ELEM_NAME);
// Add page previews when internal links are moused over
makeLinksPreviewable();
// Also hide previews when the window loses focus
hideElementOnBlur(prev);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment