NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name BombManual.com Tab Title and TOC
// @downloadURL https://openuserjs.org/install/dperelman/BombManual.com_Tab_Title_and_TOC.user.js
// @updateURL https://openuserjs.org/meta/dperelman/BombManual.com_Tab_Title_and_TOC.meta.js
// @version 0.1
// @description Update tab title while scrolling and show a table of contents.
// @author Daniel Perelman <perelman@aweirdimagination.net>
// @license MIT
// @match https://www.bombmanual.com/web/*
// @match https://bombmanual.com/web/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
window.addEventListener("load", (event) => {
const pages = document.getElementsByClassName('page');
const visiblePages = new Map();
function titleFor(el) {
let title = el.id;
const titles = el.getElementsByClassName('page-header-section-title');
const h2 = el.querySelector('h2');
if (titles.length && !el.id.startsWith("Appendix")) {
title = titles[0].innerText;
} else if (h2) {
title = h2.innerText;
}
if (title == "www.keeptalkinggame.com") {
title = "Title Page";
} else if (title == "Keypads") {
title = "Symbols";
} else if (title.startsWith("Appendix")) {
title = title.substring(9);
}
return title;
}
function updateTitleFor(el) {
const title = titleFor(el);
document.title = title + " - Keep Talking and Nobody Explodes - Bomb Defusal Manual - en - v1";
}
const toc = document.createElement('ul');
for (const page of pages) {
if (page.id) {
const link = document.createElement('a');
link.href = '#' + page.id;
link.innerText = titleFor(page);
const item = document.createElement('li');
item.appendChild(link);
toc.appendChild(item);
}
}
pages[1].querySelector(".page-content").appendChild(toc);
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
visiblePages.set(entry.target, entry.intersectionRatio);
} else {
visiblePages.delete(entry.target);
}
});
let max = -1;
for (const page of pages) {
const intersectionRatio = visiblePages.get(page);
if (intersectionRatio && intersectionRatio > max) {
max = intersectionRatio;
updateTitleFor(page);
}
}
}, {
threshold: [0, 0.1, 0.25, 0.5, 0.75, 0.9, 1],
});
for (const page of pages) {
observer.observe(page);
}
});
})();