practical-cl-beautified/js/main.js

176 lines
4.8 KiB
JavaScript
Raw Normal View History

2019-01-01 20:10:17 +01:00
// Create Table of Contents
let chapters = [];
// get chapter for navigation
function loadChapters(callback) {
2019-06-26 11:32:28 +02:00
let sending = browser.runtime.sendMessage({
msg: "getChapters"
});
return sending;
2019-01-01 20:10:17 +01:00
}
// Inject the Table of Contents
function createTOC() {
let TOC = document.getElementById('toc') || document.createElement('nav'),
2019-06-26 11:32:28 +02:00
headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
2019-01-01 20:10:17 +01:00
// fix headings
for(let heading of headings) {
2019-06-26 11:32:28 +02:00
heading.id = heading.parentNode.getAttribute('name');
2019-01-01 20:10:17 +01:00
}
2019-06-26 11:32:28 +02:00
2019-01-01 20:10:17 +01:00
TOC.id = 'toc';
TOC.classList.add('toc', 'toc-right');
TOC.innerHTML = '';
document.body.insertBefore(TOC, document.body.childNodes[0]);
tocbot.init({
2019-06-26 11:32:28 +02:00
// Where to render the table of contents.
tocSelector: '#toc',
// Where to grab the headings to build the table of contents.
contentSelector: 'body',
// Which headings to grab inside of the contentSelector element.
headingSelector: 'h2, h3',
// smooth it out
scrollSmooth: true
2019-01-01 20:10:17 +01:00
});
}
2019-01-01 21:10:21 +01:00
function wrapInner(parent, wrapper, className) {
if (typeof wrapper === "string")
wrapper = document.createElement(wrapper);
wrapper.classList.add(className);
var div = parent.appendChild(wrapper);
2019-01-01 20:10:17 +01:00
2019-01-01 21:10:21 +01:00
while(parent.firstChild !== wrapper)
wrapper.appendChild(parent.firstChild);
}
2019-01-01 20:10:17 +01:00
function wrapPre() {
for(let el of document.querySelectorAll('pre')) {
2019-06-26 11:32:28 +02:00
wrapInner(el, 'code', 'lisp');
2019-01-01 20:10:17 +01:00
}
}
// get the index of the currently viewed chapter
function findCurrentChapter() {
let file = document.URL.split('/').pop().replace(/\#.*$/, '');
let currentChapter = -1;
for(let chapter in chapters) {
2019-06-26 11:32:28 +02:00
if(chapters[chapter].url === file)
currentChapter = chapter;
2019-01-01 20:10:17 +01:00
}
return parseInt(currentChapter);
}
// go to previous chapter
function goToPrevious() {
if(!chapters) return;
let currentChapter = findCurrentChapter();
if(currentChapter > 0) {
2019-06-26 11:32:28 +02:00
document.location.href = chapters[currentChapter-1].url;
2019-01-01 20:10:17 +01:00
}
}
// go to next chapter
function gotoNext() {
if(!chapters) return;
let currentChapter = findCurrentChapter();
if(currentChapter < chapters.length - 1) {
2019-06-26 11:32:28 +02:00
document.location.href = chapters[currentChapter+1].url;
2019-01-01 20:10:17 +01:00
}
}
// set up the navigation shortcuts
function setUpNav() {
document.addEventListener('keypress', (event) => {
2019-06-26 11:39:45 +02:00
switch(event.key) {
case 'p':
2019-06-26 11:32:28 +02:00
goToPrevious();
break;
2019-06-26 11:39:45 +02:00
case 'n':
2019-06-26 11:32:28 +02:00
gotoNext();
break;
2019-06-26 11:39:45 +02:00
case 'h':
2019-06-26 11:32:28 +02:00
document.location.href = 'index.html';
break;
}
2019-01-01 20:10:17 +01:00
});
}
2019-01-05 11:44:50 +01:00
function setUpNumbering() {
let chapter = findCurrentChapter();
if (chapter >= 0) {
2019-06-26 11:32:28 +02:00
document.documentElement.style['counter-reset'] = 'chapter ' + (chapter + 1);
2019-01-05 11:44:50 +01:00
}
};
2019-01-01 20:10:17 +01:00
2019-01-11 11:03:46 +01:00
function collectFootnotes() {
let footMap = [];
// collect al footnotes into pairs
for(let note of document.querySelectorAll('sup')) {
2019-06-26 11:32:28 +02:00
let index = parseInt(note.innerText) - 1;
// JS forces me to do that!
if(!footMap[index])
footMap[index] = {};
footMap[index][note.parentElement.parentElement.classList.contains('notes') ?
'target' : 'origin'] = note;
2019-01-11 11:03:46 +01:00
}
return footMap;
}
function linkFootnotes() {
function identifyAndLink(index, originid, targetid, origin, target) {
2019-06-26 11:32:28 +02:00
origin.id = `foot${index}${originid}`;
let link = document.createElement('a');
target.id = `foot${index}${targetid}`;
link.href = '#' + target.id;
link.innerText = (index + 1);
origin.innerHTML = '';
origin.appendChild(link);
2019-01-11 11:03:46 +01:00
};
2019-01-11 12:43:44 +01:00
function createPopover(index, origin, target) {
2019-06-26 11:32:28 +02:00
let content = target.parentElement.innerHTML;
content = content.substring(`<sup>${index+1}</sup>`.length);
if(target.parentElement && target.parentElement.nextSibling && target.parentElement.nextSibling.tagName !== 'P')
content += '&hellip;';
tippy(origin, { content, animateFill: false, animation: 'fade', theme: 'pcl'});
2019-01-11 12:43:44 +01:00
}
2019-06-26 11:32:28 +02:00
2019-01-11 11:03:46 +01:00
let footMap = collectFootnotes();
for(let index in footMap) {
2019-06-26 11:32:28 +02:00
index = parseInt(index); // I love you JavaScript :/
let pair = footMap[index];
if(pair && 'origin' in pair && 'target' in pair) {
let origin = pair.origin;
let target = pair.target;
createPopover(index, origin, target);
identifyAndLink(index, 1, 2, origin, target);
identifyAndLink(index, 2, 1, target, origin);
}
2019-01-11 11:03:46 +01:00
}
}
2019-01-05 11:44:50 +01:00
// Let's apply that stuff.
2019-01-01 20:10:17 +01:00
loadChapters().then(newChapters => {
chapters = newChapters;
2019-01-05 11:44:50 +01:00
setUpNumbering();
2019-01-01 20:10:17 +01:00
});
2019-01-11 13:39:10 +01:00
linkFootnotes();
2019-01-01 20:10:17 +01:00
wrapPre();
HighlightLisp.highlight_auto();
HighlightLisp.paren_match();
createTOC();
setUpNav();