diff options
Diffstat (limited to 'Info/9/3/Planet/templates/add-glossary-item.js')
| -rw-r--r-- | Info/9/3/Planet/templates/add-glossary-item.js | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/Info/9/3/Planet/templates/add-glossary-item.js b/Info/9/3/Planet/templates/add-glossary-item.js new file mode 100644 index 00000000..8d9eb33b --- /dev/null +++ b/Info/9/3/Planet/templates/add-glossary-item.js @@ -0,0 +1,117 @@ +// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later +// Copyright (C) 2026 Florian Fischer + +// Get the id to this course's glossary activity +const activityAutoLinkDiv = document.getElementById("glossary-autolink"); +const activityLinkNode = activityAutoLinkDiv.querySelector("a.autolink"); +const glossaryUrl = activityLinkNode.href; +const glossaryId = (/id=(\d+)/).exec(glossaryUrl)[1]; +// Remove the dummy autolink +activityLinkNode.remove(); + +class GlossaryPost { + constructor(eid, showurl, concept) { + this.eid = eid; + this.showurl = showurl; + this.concept = concept; + } +} + +function autoLinkHTML(post) { + const a = document.createElement("a"); + a.classList.add("glossary", "autolink", "concept", `glossaryid${post.eid}`); + a.dataset.entryid=post.eid; + a.href = post.showurl; + a.innerHTML = post.concept; + return a.outerHTML; +} + +function replaceAllText(node, pattern, newHTML) { + var walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT); + + const found = []; + + while (walker.nextNode()) { + const node = walker.currentNode; + if (node.nodeValue.trim() && !(["SCRIPT", "STYLE"]).includes(node.parentNode.nodeName) ) { + + if (node.nodeValue.includes(pattern)) + found.push(node.parentNode); + } + } + + for (const node of found) { + node.innerHTML = node.innerHTML.replace(pattern, newHTML); + } +} + +const termsAlreadyAdded = new Map(); + +async function autoLink() { + const glRes = await fetch(glossaryUrl + "&hook=ALL"); + const glDoc = new DOMParser().parseFromString(await glRes.text(), "text/html"); + + glDoc.querySelectorAll(".glossarypost.dictionary").forEach((post) => { + const concept = post.querySelector(".entry > .concept").innerText; + const showurl = post.querySelector('.commands > a.icon[title*="Eingabelink"]').href; + const eid = (/eid=(\d+)/).exec(showurl)[1]; + + termsAlreadyAdded.set(concept, new GlossaryPost(eid, showurl, concept)); + }); + + const page = document.querySelector('div[role="main"]'); + for (const post of termsAlreadyAdded.values()) { + replaceAllText(page, post.concept, autoLinkHTML(post)); + } +} + +async function addGlossaryItems() { + const itemsToAdd = document.querySelectorAll(".glossary-item-toadd"); + for (const item of itemsToAdd) { + if (termsAlreadyAdded.has(item.dataset.term)) { + item.classList.remove("glossary-item-toadd"); + continue; + } + + item.addEventListener("click", async function() { + const editFormData = new FormData(); + + editFormData.set("cmid", glossaryId); + editFormData.set("sesskey", M.cfg.sesskey); + + const editRes = await fetch("/mod/glossary/edit.php", { + method: "POST", + body: editFormData, + }); + + const editDoc = new DOMParser().parseFromString(await editRes.text(), "text/html"); + const form = editDoc.querySelector('div[role="main"] > form'); + const formData = new FormData(form); + + formData.set("concept", item.dataset.term ? item.dataset.term: item.textContent); + formData.set("definition_editor[text]", item.dataset.definition); + formData.set("usedynalink", "1"); + formData.set("submitbutton", "Änderung speichern"); + + const addRes = await fetch("/mod/glossary/edit.php", { + method: "POST", + body: formData, + }); + const showAddedPostUrl = addRes.url; + + item.classList.remove("glossary-item-toadd"); + + const eid = (/hook=(\d+)/).exec(showAddedPostUrl)[1]; + const showurl = `/mod/glossary/showentry.php?eid=${eid}&displayformat=dictionary`; + const post = new GlossaryPost(eid, showurl, item.dataset.term) + item.innerHTML = autoLinkHTML(post); + + // Link to all occurrences of the added term + const page = document.querySelector('div[role="main"]'); + replaceAllText(page, post.concept, autoLinkHTML(post)); + }, { once: true }); + } +} + +autoLink().then( addGlossaryItems ); +// @license-end |
