aboutsummaryrefslogtreecommitdiff
path: root/Info/9/3/Planet/templates
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-08-12 18:05:41 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-08-12 18:05:41 +0200
commit52a4aa583ea522afb1aba9a529f434666f3be776 (patch)
tree970a8b3bd56657f6f1daac5e016d4ecc3fb3ebb5 /Info/9/3/Planet/templates
parent37779aebcb9f859866e6458afef5ab406b5607fd (diff)
downloadunterricht-52a4aa583ea522afb1aba9a529f434666f3be776.tar.gz
unterricht-52a4aa583ea522afb1aba9a529f434666f3be776.zip
planet: add collectable glossary entries
Diffstat (limited to 'Info/9/3/Planet/templates')
-rw-r--r--Info/9/3/Planet/templates/add-glossary-item.js117
-rw-r--r--Info/9/3/Planet/templates/planet-mebis-page-template.css24
-rw-r--r--Info/9/3/Planet/templates/planet-mebis-page-template.html3
3 files changed, 144 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
diff --git a/Info/9/3/Planet/templates/planet-mebis-page-template.css b/Info/9/3/Planet/templates/planet-mebis-page-template.css
index 0a10283d..f9ac9791 100644
--- a/Info/9/3/Planet/templates/planet-mebis-page-template.css
+++ b/Info/9/3/Planet/templates/planet-mebis-page-template.css
@@ -310,3 +310,27 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; }
opacity:0;
}
}
+
+.glossary-item-toadd {
+ cursor: pointer;
+ display: inline-block;
+ border-radius: 5;
+ animation: glossary-item-glow 1s infinite alternate;
+}
+
+@keyframes glossary-item-glow {
+ from {
+ box-shadow: 0 0 10px -10px #aef4af;
+ }
+ to {
+ box-shadow: 0 0 10px 10px #aef4af;
+ }
+}
+
+@media print {
+ .glossary-item-toadd {
+ background-color: none;
+ animation: none;
+ }
+}
+
diff --git a/Info/9/3/Planet/templates/planet-mebis-page-template.html b/Info/9/3/Planet/templates/planet-mebis-page-template.html
index 70c1e3b7..7c78d921 100644
--- a/Info/9/3/Planet/templates/planet-mebis-page-template.html
+++ b/Info/9/3/Planet/templates/planet-mebis-page-template.html
@@ -13,6 +13,8 @@ $for(include-before)$
$include-before$
$endfor$
+<div id="glossary-autolink">Glossar</div>
+
$body$
$for(include-after)$
@@ -21,6 +23,7 @@ $endfor$
<script>
$js/h5p-autoembed.js()$
+$js/add-glossary-item.js()$
</script>
</body>
</html>