aboutsummaryrefslogtreecommitdiff
path: root/js/selection.js
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-08-03 14:31:25 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-08-03 14:31:25 +0200
commit6839831af54cd9302119bcc3bffafe10475958d4 (patch)
tree12a1c1fbd864e9579cb9c3a09d4bf4686a280b73 /js/selection.js
parentfccb70cbd876785f6833dfe6efc10ec9e445556d (diff)
downloadbycs-sol-6839831af54cd9302119bcc3bffafe10475958d4.tar.gz
bycs-sol-6839831af54cd9302119bcc3bffafe10475958d4.zip
refactor project structure
* merge sites into single project root * fix name of mass-graduation site * enable typescript support
Diffstat (limited to 'js/selection.js')
-rw-r--r--js/selection.js170
1 files changed, 0 insertions, 170 deletions
diff --git a/js/selection.js b/js/selection.js
deleted file mode 100644
index eda20ae..0000000
--- a/js/selection.js
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Initialises a selection based on existing HTML elements.
- * For HTML elements are required:
- * - A text input with id $idPrefix
- * - A list with id ${idPrefix}-list
- * - An element shown if no results are available with id ${idPrefix}-noresults
- * - A button to clear the input with id ${idPrefix}-clear
- *
- * @param {string} idPrefix - The id prefix of the four HTML elements.
- * @param {async function} fetchCandidates - The async function to retrieve the selectable candidates.
- * @param {function} fmtCandidate - The function to format the displayed HTML for each candidate.
- * @param {function} onSelection - The function to call when a candidate is selected.
- */
-async function initSelection(idPrefix, fetchCandidates, fmtCandidate, onSelection) {
- const sel = document.getElementById(idPrefix);
- const list = document.getElementById(`${idPrefix}-list`);
- const noResults = document.getElementById(`${idPrefix}-noresults`);
- const clearBtn = document.getElementById(`${idPrefix}-clear`);
- const loader = document.getElementById(`${idPrefix}-loader`);
-
- loader.style.display = "unset";
- const candidates = await fetchCandidates();
- loader.style.display = "none";
-
- let items = [];
-
- let currentFocus = -1;
- let visibleItems = [];
- function setActive() {
- visibleItems.forEach(item => item.classList.remove("active"));
- if (currentFocus >= 0 && visibleItems[currentFocus]) {
- visibleItems[currentFocus].classList.add("active");
- }
- }
-
- for (const candidate of candidates) {
- let item = document.createElement("li");
- item.candidate = candidate;
- item.innerHTML = fmtCandidate(candidate);
- item.style.display = 'none';
-
- item.addEventListener('click', function() {
- sel.value = "";
- sel.dispatchEvent(new Event('keyup'));
- onSelection(candidate);
- });
-
- list.appendChild(item);
- items.push(item);
- }
-
- sel.addEventListener('keyup', function(e) {
- if ((["ArrowDown", "ArrowUp", "Enter"]).includes(e.key))
- return;
-
- const filter = sel.value.toLowerCase();
- visibleItems = [];
- for (const item of items) {
- const itemText = item.textContent.trim().toLowerCase();
-
- if (itemText.indexOf(filter) > -1 && filter !== "") {
- item.style.display = "";
- visibleItems.push(item);
-
- // Highlight matched text
- const regex = new RegExp(`(${filter})`, 'gi');
- item.innerHTML = item.textContent.replace(
- regex,
- "<u class='student-selection-list-highlight'>$1</u>"
- );
- } else {
- item.style.display = "none";
- }
- }
-
- // Show the clear button if there is an input
- clearBtn.style.display = sel.value ? "block" : "none";
-
- // Select the first or none if there are no items visible
- currentFocus = visibleItems.length ? 0 : -1;
- setActive(visibleItems);
- noResults.style.display = visibleItems.length || filter === "" ? "none" : "block";
- });
-
- clearBtn.addEventListener('click', function() {
- sel.value = "";
- sel.dispatchEvent(new Event('keyup')); // reset list
- sel.focus();
- });
-
- sel.addEventListener('keydown', function(e) {
- if (e.key === "ArrowDown" || e.key === "ArrowUp") {
- if(e.key === "ArrowDown")
- currentFocus = (currentFocus + 1) % visibleItems.length;
- else
- currentFocus = (currentFocus - 1 + visibleItems.length) % visibleItems.length;
- setActive();
- e.preventDefault();
- } else if (e.key === "Enter") {
- if (currentFocus > -1 && visibleItems[currentFocus]) {
-
- const visibleItem = visibleItems[currentFocus];
- sel.value = "";
- sel.dispatchEvent(new Event('keyup'));
- onSelection(visibleItem.candidate);
- }
- e.preventDefault();
- }
- });
-}
-
-function pointClickHandler(color) {
- const textareaDiv = document.getElementById("student-info-point-reason-container");
- const textarea = document.getElementById("student-info-point-reason");
- const submitBtn = document.getElementById("student-info-point-reason-submit");
-
- // TODO(muhq): Prefill the textarea with common reasons
- switch (color) {
- case "green":
- textarea.style.background = "rgb(from green r g b / 20%)"
- textarea.value = "";
- break;
- case "orange":
- textarea.style.background = "rgb(from orange r g b / 20%)"
- textarea.value = "";
- break;
- case "red":
- textarea.style.background = "rgb(from red r g b / 20%)"
- textarea.value = "";
- break;
- }
- textareaDiv.style.display = "block";
- textarea.focus();
-
- // Can not use string interpolation because of Moodle's firstname filter.
- const coach = firstname + " " + lastname;
-
- let submit = function() {
- let change;
- switch (color) {
- case "green":
- change = GraduationChange.newGreenPointChange(student, textarea.value, coach);
- break;
- case "orange":
- change = GraduationChange.newOrangePointChange(student, textarea.value, coach);
- break;
- case "red":
- change = GraduationChange.newRedPointChange(student, textarea.value, coach);
- break;
- default:
- alert("Invalid color");
- break;
- }
- submitGraduationChange(student, change);
- textareaDiv.style.display = "none";
- updateStudentInfo();
- }
- // Use onEVENT to override any previous handler
- textarea.onkeydown = function(e) {
- if (e.shiftKey && e.key === "Enter") {
- submit();
- }
- if (e.key === "Escape") {
- textareaDiv.style.display = "none";
- }
- };
- submitBtn.onclick = submit;
-}
-
-export { initSelection };