aboutsummaryrefslogtreecommitdiff
path: root/Info/9/3/Planet/templates/add-glossary-item.js
blob: f2f32b3888d3944edc97dccba6d49bc50838b8fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// @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, concept) {
		this.eid = eid;
		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 = `/mod/glossary/showentry.php?eid=${post.eid}&displayformat=dictionary`;
	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 editurl = post.querySelector('.commands > a.icon[title*="Bearbeiten"]').href;
		const eid = (/&id=(\d+)/).exec(editurl)[1];

		termsAlreadyAdded.set(concept, new GlossaryPost(eid, 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.def);
			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 post = new GlossaryPost(eid, 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