Poznámka: Aby sa zmeny prejavili, po uložení musíte vymazať vyrovnávaciu pamäť vášho prehliadača.
- Mozilla Firefox / Safari: Držte stlačený Shift a kliknite na Reload alebo stlačte buď Ctrl-F5 alebo Ctrl-R (⌘-R na Mac)
- Google Chrome: Stlačte Ctrl-Shift-R (⌘-Shift-R na Mac)
- Internet Explorer: Držte Ctrl a kliknite na Refresh alebo stlačte Ctrl-F5
- Opera: Stlačte Ctrl-F5.
(function () {
const tippyInstancia = tippy(document.createElement("div"));
/**
* Vytvorí JSON pojmovej mapy z obsahu stránky.
*
* @param {HTMLElement} poznamkyElement Element, ktorý obsahuje poznámky.
* @returns {object} JSON reprezentácia pojmovej mapy.
**/
function vytvoritDataMapy(poznamkyElement) {
const nadpisy = poznamkyElement.querySelectorAll(
"h1, h2, h3, h4, h5, h6"
);
let mapa = { vrcholy: [], hrany: [] };
// Zoznam, ktorý uchováva posledný nadpis na každej úrovni
let posledneNadpisy = [];
for (let i = 0; i < nadpisy.length; i++) {
const nadpis = nadpisy[i];
const aktualnyLevel = ziskatLevelNadpisu(nadpis);
const idVrchola = i + 1;
const nazov = nadpis.querySelector(".mw-headline").innerText.slice(2);
const idRodica = posledneNadpisy[aktualnyLevel - 1] || 1;
mapa.vrcholy.push({
id: idVrchola,
label: nazov,
color: generovatFarbu(idRodica * aktualnyLevel),
tooltip: obsahNadpisu(nadpis),
});
if (aktualnyLevel > 1) {
mapa.hrany.push({
from: idRodica,
to: idVrchola,
});
}
// Aktualizujte posledný nadpis na úrovni
posledneNadpisy[aktualnyLevel] = idVrchola;
// Vymažte všetky nadpisy na vyšších úrovniach
for (let j = aktualnyLevel + 1; j < posledneNadpisy.length; j++) {
delete posledneNadpisy[j];
}
}
return mapa;
}
/**
* Získa obsah nadpisu a všetkých nasledujúcich elementov, ktoré nie sú nadpisy.
* Obsah je v HTML formáte.
*
* @param {HTMLElement} nadpisElement HTML element nadpisu.
* @returns {string} Obsah nadpisu a všetkých nasledujúcich elementov, ktoré nie sú nadpisy.
**/
function obsahNadpisu(nadpisElement) {
let obsah = "";
let element = nadpisElement.nextElementSibling;
while (
element &&
!["H1", "H2", "H3", "H4", "H5", "H6"].includes(element.tagName)
) {
obsah += element.outerHTML;
element = element.nextElementSibling;
}
return obsah;
}
/**
* Vygeneruje zobrazenie pojmovej mapy.
*
* @param {HTMLElement} elementMapy Element, do ktorého sa vloží zobrazenie pojmovej mapy.
* @param {object} jsonMapy JSON reprezentácia pojmovej mapy.
* @returns {object} Objekt pojmovej mapy (vis-network).
**/
function vykreslitMapu(elementMapy, jsonMapy) {
const sirkaZobrazenia = window.innerWidth;
const jeSirokeZobrazenie = sirkaZobrazenia > 768;
const dataSiete = {
nodes: new vis.DataSet(jsonMapy.vrcholy),
edges: new vis.DataSet(jsonMapy.hrany),
};
const nastavenia = {
interaction: {
hover: true,
keyboard: {
enabled: true,
bindToWindow: false,
autoFocus: false,
},
},
nodes: {
shape: "box",
widthConstraint: {
maximum: 200,
},
margin: 10,
labelHighlightBold: false,
},
edges: {
smooth: {
type: "dynamic",
roundness: 0.5,
},
width: 0.75,
arrows: {
to: {
enabled: true,
},
},
},
layout: {
hierarchical: {
enabled: true,
direction: jeSirokeZobrazenie ? "UD" : "LR",
sortMethod: "directed",
nodeSpacing: jeSirokeZobrazenie ? 220 : 100,
levelSeparation: jeSirokeZobrazenie ? 100 : 250,
shakeTowards: "roots",
},
},
physics: false,
};
pojmova_mapa = new vis.Network(elementMapy, dataSiete, nastavenia);
pojmova_mapa.on("hoverNode", (parametre) => {
const obsah = jsonMapy.vrcholy.find(
(vrchol) => vrchol.id === parametre.node
).tooltip;
if (!parametre.node || !obsah) return;
tippyInstancia.setProps({
triggerTarget: elementMapy,
maxWidth: "90vw",
allowHTML: true,
getReferenceClientRect: () => ({
width: 0,
height: 0,
left: window.innerWidth / 2,
right: window.innerWidth / 2,
top: window.innerHeight - 10,
}),
interact: true,
});
tippyInstancia.setContent(
`<div style="padding: 1rem 0.5rem; font-size: 12px;">${obsah}</div>`
);
tippyInstancia.show();
MathJax.typesetPromise([tippyInstancia.popper]);
});
pojmova_mapa.on("blurNode", () => {
tippyInstancia.hide();
});
return pojmova_mapa;
}
/**
* Získa úroveň nadpisu (h1, h2, atď.).
*
* @param {HTMLElement} nadpis HTML element nadpisu.
* @returns {number} Číselná reprezentácia úrovne nadpisu.
**/
function ziskatLevelNadpisu(nadpis) {
return parseInt(nadpis.tagName.substring(1), 10);
}
/**
* Generuje náhodné číslo z čísla (seed). Rovnaký seed vždy vygeneruje rovnaké "náhodné" číslo v určenom rozsahu.
*
* https://stackoverflow.com/a/63599906
*
* @param {number} seed Číslo, z ktorého sa generuje náhodné číslo.
* @param {number[]} rozsah Rozsah, v ktorom sa náhodné číslo generuje.
* @returns {number} Náhodné číslo.
**/
function nahodneCislo(seed, rozsah = [0, 255]) {
seed = String(seed)
.split("")
.reduce((c, n) => (n != 0 ? c * n : c * c));
let od = rozsah[0];
let po = rozsah[1];
while (seed < rozsah[0] || seed > rozsah[1]) {
if (seed > rozsah[1]) seed = Math.floor(seed / po--);
if (seed < rozsah[0]) seed = Math.floor(seed * od++);
}
return seed;
}
/**
* Generuje náhodnú farbu z čísla. Rovnaké číslo vždy vygeneruje rovnakú farbu.
*
* @param {number} cislo Číslo, z ktorého sa generuje farba.
* @returns {string} Farba v RBG formáte.
**/
function generovatFarbu(seed = 1, svetla = true) {
let od = svetla ? 125 : 0;
let po = svetla ? 255 : 125;
r = nahodneCislo(seed + 11, [od, po]);
g = nahodneCislo(seed + 12, [od, po]);
b = nahodneCislo(seed + 13, [od, po]);
return `rgb(${r}, ${g}, ${b})`;
}
// ----------------------------------------------------------------
const poznamkyElement = document.getElementById("#mw-content-text .mw-parser-output");
const elementMapy = document.getElementById("mapa");
if (elementMapy !== null && poznamkyElement !== null) {
const jsonMapy = vytvoritDataMapy(poznamkyElement);
vykreslitMapu(elementMapy, jsonMapy);
}
})();