// TODO Optimalisatie: De huidige lijst meegeven en controleren tijdens het opstellen zodat er gestopt wordt vanaf er een titel gevonden is // Initialiseer de webpagina const taal = document.getElementById('taal'); const start = document.getElementById('start'); const einde = document.getElementById('einde'); const toevoegKnop = document.getElementById('toevoegKnop'); const visualisatie = document.getElementById('visualisatie'); const logo = document.getElementById('logo'); const waarschuwing = document.getElementById('waarschuwing'); let huidigeTaal; let huidigeDoel; let timer; let rotatie; refreshTree(); /** * Zoek een pad met python backend en voeg deze toe in de lijst. */ function zoek() { // Schakel de knop 'toevoegen' uit zolang het zoekproces bezig is, zodat er geen meerdere // paden tegelijk toegevoegd kunnen worden. toggleZoeken(false); refreshTree(); const verzoek = { // Standaardwaarden gebruiken indien het veld leeg is. taal: getOrDefault(taal), start: getOrDefault(start), einde: getOrDefault(einde) }; fetch(`cgi-bin/init.py?data=${JSON.stringify(verzoek)}`) .then(antwoord => antwoord.json()) .then(data => voegToe(data)) .catch(reason => alert('‼ ' + reason)) .finally(() => toggleZoeken()); // Herstel de knop. Ook als er ondertussen iets mis ging. } function voegToe(data) { if (data.hasOwnProperty('error')) { alert('↯ ' + data.error); } else { let pad = data.pad; // Locatie van invoegen bepalen. let moeder = visualisatie; let kinderen = visualisatie.getElementsByTagName('li'); let kindernamen = Array.from(kinderen).map(item => item.getAttribute('item')); let i = 0; while (moeder === visualisatie && i < pad.length) { if (kindernamen.indexOf(pad[i]) !== -1) { moeder = kinderen[kindernamen.indexOf(pad[i])]; } i += 1; } // Alleen nog die elementen toevoegen die nog niet op het pad staan. pad = pad.slice(0, i - 1); // Nieuw element creëren (zonder toe te voegen aan het DOM). for (let item of pad.reverse()) { moeder = maakIn(item, moeder); } } } /** * Maakt een element aan binnen een ander element, en geeft het nieuwste (diepste) element terug. */ function maakIn(titel, moeder, id) { let wrap = document.createElement('ul'); let nieuw = document.createElement('li'); nieuw.innerHTML = titel; nieuw.setAttribute('item', titel); wrap.appendChild(nieuw); if (id !== undefined) { wrap.id = id; } moeder.appendChild(wrap); return nieuw; } /** * Probeer of de huidige boom verwijderd moet worden en voeg de bestemming reeds toe aan de nieuwe boom. */ function refreshTree() { if (huidigeDoel !== getOrDefault(einde) || huidigeTaal !== getOrDefault(taal)) { huidigeTaal = getOrDefault(taal); huidigeDoel = getOrDefault(einde); visualisatie.innerHTML = ''; maakIn(huidigeDoel, visualisatie, 'wortel'); inputWaarschuwing(); } } /** * Toon of verberg een speciale waarschuwing die zegt of de huidige boom verwijderd zal worden * bij een nieuwe toevoeging. */ function inputWaarschuwing() { waarschuwing.hidden = (huidigeTaal === getOrDefault(taal) && huidigeDoel === getOrDefault(einde)); } function getOrDefault(element) { return element.value === '' ? element.getAttribute('placeholder') : element.value; } /** * Toggle tussen de zoek-status en de wacht-op-input-status. Dit heeft invloed op zowel de indienkop als op het * roterende logo. Standaardaanroep zal alles stoppen, om überveel animaties te vermijden bij fout gebruik. */ function toggleZoeken(stop = true) { toevoegKnop.disabled = !stop; rotatie = 0; if (stop) { clearInterval(timer); logo.style.transform = 'rotate(0)'; } else { timer = setInterval(draai, 24); } } function draai() { rotatie += 5; logo.style.transform = `rotate(${rotatie % 360}deg`; }