Last active
December 22, 2021 19:34
-
-
Save jacobio/bb845d272d244231cc078a7f0085b759 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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