function isObj(obj) {
|
return (obj && typeof obj === 'object' && obj !== null) ? true : false;
|
}
|
|
function createEl(element = 'div') {
|
return document.createElement(element);
|
}
|
|
function emptyEl(el) {
|
while(el.firstChild)
|
el.removeChild(el.firstChild);
|
}
|
|
function elem(selector, parent = document){
|
let elem = isObj(parent) ? parent.querySelector(selector) : false;
|
return elem ? elem : false;
|
}
|
|
function elems(selector, parent = document) {
|
let elems = isObj(parent) ?parent.querySelectorAll(selector) : [];
|
return elems.length ? elems : false;
|
}
|
|
function pushClass(el, targetClass) {
|
if (isObj(el) && targetClass) {
|
let elClass = el.classList;
|
elClass.contains(targetClass) ? false : elClass.add(targetClass);
|
}
|
}
|
|
function deleteClass(el, targetClass) {
|
if (isObj(el) && targetClass) {
|
let elClass = el.classList;
|
elClass.contains(targetClass) ? elClass.remove(targetClass) : false;
|
}
|
}
|
|
function modifyClass(el, targetClass) {
|
if (isObj(el) && targetClass) {
|
const elClass = el.classList;
|
elClass.contains(targetClass) ? elClass.remove(targetClass) : elClass.add(targetClass);
|
}
|
}
|
|
function containsClass(el, targetClass) {
|
if (isObj(el) && targetClass && el !== document ) {
|
return el.classList.contains(targetClass) ? true : false;
|
}
|
}
|
|
function isChild(node, parentClass) {
|
let objectsAreValid = isObj(node) && parentClass && typeof parentClass == 'string';
|
return (objectsAreValid && node.closest(parentClass)) ? true : false;
|
}
|
|
function elemAttribute(elem, attr, value = null) {
|
if (value) {
|
elem.setAttribute(attr, value);
|
} else {
|
value = elem.getAttribute(attr);
|
return value ? value : false;
|
}
|
}
|
|
function deleteChars(str, subs) {
|
let newStr = str;
|
if (Array.isArray(subs)) {
|
for (let i = 0; i < subs.length; i++) {
|
newStr = newStr.replace(subs[i], '');
|
}
|
} else {
|
newStr = newStr.replace(subs, '');
|
}
|
return newStr;
|
}
|
|
function isBlank(str) {
|
return (!str || str.trim().length === 0);
|
}
|
|
function isMatch(element, selectors) {
|
if(isObj(element)) {
|
if(selectors.isArray) {
|
let matching = selectors.map(function(selector){
|
return element.matches(selector)
|
})
|
return matching.includes(true);
|
}
|
return element.matches(selectors)
|
}
|
}
|
|
function closestInt(goal, collection) {
|
const closest = collection.reduce(function(prev, curr) {
|
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
|
});
|
return closest
|
}
|
|
function hasClasses(el) {
|
if(isObj(el)) {
|
const classes = el.classList;
|
return classes.length
|
}
|
}
|
|
(function markInlineCodeTags(){
|
const codeBlocks = elems('code');
|
if(codeBlocks) {
|
codeBlocks.forEach(function(codeBlock){
|
if(!hasClasses(codeBlock)) {
|
codeBlock.children.length ? false : pushClass(codeBlock, 'noClass');
|
}
|
});
|
}
|
})();
|
|
function activeHeading(position, listLinks) {
|
let active = 'active';
|
|
let linksToModify = Object.create(null);
|
linksToModify.active = listLinks.filter(function(link) {
|
return containsClass(link, active);
|
})[0];
|
|
// activeTocLink ? deleteClass
|
|
linksToModify.new = listLinks.filter(function(link){
|
return parseInt(link.dataset.position) === position
|
})[0];
|
|
if (linksToModify.active != linksToModify.new) {
|
linksToModify.active ? deleteClass(linksToModify.active, active): false;
|
pushClass(linksToModify.new, active);
|
}
|
};
|
|
function loadActions() {
|
|
const parentURL = '{{ absURL "" }}';
|
const doc = document.documentElement;
|
|
(function updateDate() {
|
const date = new Date();
|
const year = date.getFullYear();
|
const yearEl = elem('.year');
|
yearEl ? year.innerHTML = year : false;
|
})();
|
|
(function customizeSidebar(){
|
const tocActive = 'toc_active';
|
const aside = elem('aside');
|
const tocs = elems('nav', aside);
|
if(tocs) {
|
tocs.forEach(function(toc){
|
toc.id = "";
|
pushClass(toc, 'toc');
|
if(toc.children.length >= 1) {
|
const tocItems = Array.from(toc.children[0].children);
|
|
const previousHeading = toc.previousElementSibling;
|
previousHeading.matches('.active') ? pushClass(toc, tocActive) : false;
|
|
tocItems.forEach(function(item){
|
pushClass(item, 'toc_item');
|
pushClass(item.firstElementChild, 'toc_link');
|
})
|
}
|
});
|
|
const currentToc = elem(`.${tocActive}`);
|
|
if(currentToc) {
|
const pageInternalLinks = Array.from(elems('a', currentToc));
|
|
const pageIds = pageInternalLinks.map(function(link){
|
return link.hash;
|
});
|
|
const linkPositions = pageIds.map(function(id){
|
const heading = elem(id);
|
const position = heading.offsetTop;
|
return position;
|
});
|
|
pageInternalLinks.forEach(function(link, index){
|
link.dataset.position = linkPositions[index]
|
});
|
|
window.addEventListener('scroll', function(e) {
|
// this.setTimeout(function(){
|
let position = window.scrollY;
|
let active = closestInt(position, linkPositions);
|
activeHeading(active, pageInternalLinks);
|
// }, 1500)
|
});
|
}
|
}
|
})();
|
|
function searchResults(results=[], order =[]) {
|
let resultsFragment = new DocumentFragment();
|
let showResults = elem('.search_results');
|
emptyEl(showResults);
|
let index = 0
|
results.forEach(function(result){
|
let item = createEl('a');
|
item.href = result.link;
|
item.className = 'search_result';
|
item.textContent = result.title;
|
item.style.order = order[index];
|
resultsFragment.appendChild(item);
|
index += 1
|
});
|
|
showResults.appendChild(resultsFragment);
|
}
|
|
(function search(){
|
const searchField = elem('.search_field');
|
|
if (searchField) {
|
searchField.addEventListener('input', function() {
|
let rawResults = idx.search(`${ this.value }`).slice(0,6);
|
let refs = rawResults.map(function(ref){
|
// return id and score in a single string
|
return `${ref.ref}:${ref.score}`;
|
});
|
|
let ids = refs.map(function(id){
|
let positionOfSeparator = id.indexOf(":");
|
id = id.substring(0,positionOfSeparator)
|
return Number(id);
|
});
|
|
let scores = refs.map(function(score){
|
let positionOfSeparator = score.indexOf(":");
|
score = score.substring((positionOfSeparator + 1), (score.length - 1));
|
return (parseFloat(score) * 50).toFixed(0);
|
});
|
|
let matchedDocuments = simpleIndex.filter(function(doc){
|
return ids.includes(doc.id);
|
});
|
|
matchedDocuments.length >= 1 ? searchResults(matchedDocuments, scores) : false;
|
});
|
}
|
|
})();
|
|
(function makeExternalLinks(){
|
let links = elems('a');
|
if(links) {
|
Array.from(links).forEach(function(link){
|
let target, rel, blank, noopener, attr1, attr2, url, isExternal;
|
url = elemAttribute(link, 'href');
|
isExternal = (url && typeof url == 'string' && url.startsWith('http')) && !url.startsWith(parentURL) ? true : false;
|
if(isExternal) {
|
target = 'target';
|
rel = 'rel';
|
blank = '_blank';
|
noopener = 'noopener';
|
attr1 = elemAttribute(link, target);
|
attr2 = elemAttribute(link, noopener);
|
|
attr1 ? false : elemAttribute(link, target, blank);
|
attr2 ? false : elemAttribute(link, rel, noopener);
|
}
|
});
|
}
|
})();
|
|
let headingNodes = [], results, link, icon, current, id,
|
tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
|
|
current = document.URL;
|
|
tags.forEach(function(tag){
|
results = document.getElementsByTagName(tag);
|
Array.prototype.push.apply(headingNodes, results);
|
});
|
|
function sanitizeURL(url) {
|
// removes any existing id on url
|
const hash = '#';
|
const positionOfHash = url.indexOf(hash);
|
if(positionOfHash > -1 ) {
|
const id = url.substr(positionOfHash, url.length - 1);
|
url = url.replace(id, '');
|
}
|
return url
|
}
|
|
headingNodes.forEach(function(node){
|
link = createEl('a');
|
icon = createEl('img');
|
icon.src = '{{ absURL "icons/link.svg" }}';
|
link.className = 'link icon';
|
link.appendChild(icon);
|
id = node.getAttribute('id');
|
if(id) {
|
link.href = `${sanitizeURL(current)}#${id}`;
|
node.appendChild(link);
|
pushClass(node, 'link_owner');
|
}
|
});
|
|
const copyToClipboard = str => {
|
let copy, selection, selected;
|
copy = createEl('textarea');
|
copy.value = str;
|
copy.setAttribute('readonly', '');
|
copy.style.position = 'absolute';
|
copy.style.left = '-9999px';
|
selection = document.getSelection();
|
doc.appendChild(copy);
|
// check if there is any selected content
|
selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
|
copy.select();
|
document.execCommand('copy');
|
doc.removeChild(copy);
|
if (selected) { // if a selection existed before copying
|
selection.removeAllRanges(); // unselect existing selection
|
selection.addRange(selected); // restore the original selection
|
}
|
}
|
|
|
function copyFeedback(parent) {
|
const copyText = document.createElement('div');
|
const yanked = 'link_yanked';
|
copyText.classList.add(yanked);
|
copyText.innerText = 'Link Copied';
|
if(!elem(`.${yanked}`, parent)) {
|
parent.appendChild(copyText);
|
setTimeout(function() {
|
// parent.removeChild(copyText)
|
}, 3000);
|
}
|
}
|
|
(function copyHeadingLink() {
|
let deeplink, deeplinks, newLink, parent, target;
|
deeplink = 'link';
|
deeplinks = elems(`.${deeplink}`);
|
if(deeplinks) {
|
document.addEventListener('click', function(event)
|
{
|
target = event.target;
|
parent = target.parentNode;
|
if (target && containsClass(target, deeplink) || containsClass(parent, deeplink)) {
|
event.preventDefault();
|
newLink = target.href != undefined ? target.href : target.parentNode.href;
|
copyToClipboard(newLink);
|
target.href != undefined ? copyFeedback(target) : copyFeedback(target.parentNode);
|
}
|
});
|
}
|
})();
|
}
|
|
window.addEventListener('load', loadActions());
|