From f337cba627a55e5955f52936c9d28dd07a21cec7 Mon Sep 17 00:00:00 2001 From: platinorum <69057107+platinorum@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:39:29 +0100 Subject: [PATCH 1/5] New TUWEL enhancer This userscript enhances TUWEL with various features such as added LVA abbreviations, a 'Select All' button for checkboxes and auto-ticking the "this is my own work" statement required by some submissions. --- tuwel-plus.user.js | 179 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 tuwel-plus.user.js diff --git a/tuwel-plus.user.js b/tuwel-plus.user.js new file mode 100644 index 0000000..89d1e4f --- /dev/null +++ b/tuwel-plus.user.js @@ -0,0 +1,179 @@ +// ==UserScript== +// @name TUWEL+ +// @namespace https://fsinf.at/ +// @match https://tuwel.tuwien.ac.at/* +// @grant none +// @version 1.0 +// @author - +// @description Various small improvements to TUWEL including LVA-abbreviations and "Select All" for Kreuzerl +// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js +// ==/UserScript== + +this.$ = this.jQuery = jQuery.noConflict(true); + +const DictLVA = { // keyword : abbreviation + "Algebra und Diskrete Mathematik": "ADM", + "Grundzüge digitaler Systeme": "GDS", + "Angleichungskurs Mathematik": "AKMath", + "Einführung in die Programmierung 1": "EP1", + "Einführung in die Programmierung 2": "EP2", + "Denkweisen der Informatik": "Denki", + "Mathematisches Arbeiten": "MathArb", + "Orientierung Informatik": "Ori", + "Algorithmen und Datenstrukturen": "AlgoDat", +} + +const seperator = " » " + + +const courseTileSelector = 'a.coursename[href*="https://tuwel.tuwien.ac.at/course/view.php?id="] > span.multiline > span[aria-hidden="true"]'; +const courseListSelector = 'a.coursename[href*="https://tuwel.tuwien.ac.at/course/view.php?id="]' +const courseTitleSelector = 'h1.h2.mb-0' +const courseDropdownMenuItemSelector = 'div.carousel-inner > a.dropdown-item[role="menuitem"][href*="https://tuwel.tuwien.ac.at/course/view.php?id="]'; +const breadcrumbSelector = 'li.breadcrumb-item:first > a'; + + +// prepend the LVA abbreviation for a selected element +function editGeneric (selector) { + $(selector).each(function() { + + //get text of selected element, excluding it's decendents + const fullName = $(this).clone().children().remove().end().text(); + + if (fullName) { + // if the LVA-name has a specified abbreviation in DictLVA, use it + for (LVA in DictLVA) { + if (fullName.includes(LVA)) { + shortName = DictLVA[LVA]; + + // set the new text in the menu item + var newName = "" + shortName + "" + seperator + fullName; + $(this).html(newName); + } + } + } + }); +} + + + +// edit the breadcrumb to contain a readable abbreviation of the LVA name +function editBreadcrumb(selector) { + const fullName = $(selector).attr("title"); + + if (fullName) { + + const match = fullName.match(/^([a-zA-Z]).{8}/); + + // set the shortName to a truncated version (…) of fullName for now + if (match) { + var shortName = match[0] + "…"; + } + + // if the LVA-name has a specified abbreviation in DictLVA, use it + for (LVA in DictLVA) { + if (fullName.includes(LVA)) { + shortName = DictLVA[LVA]; + } + } + + // set the new text in the breadcrumb (shortName + semester) + var newName = "" + shortName + "" + seperator + fullName.match(/.{5}$/)[0]; + $("li.breadcrumb-item:first > a").html(newName); + } +} + + +// highlight quiz result + +function highlightQuizResult() { + gradeCell = "table.quizreviewsummary tr:contains('Bewertung') > td" + + if ($(gradeCell).text().includes("100%")) { + $(gradeCell).css("background-color", "lightgreen"); + } else { + $(gradeCell).css("background-color", "pink"); + } + +} + +function addtickAllKreuzerlButton() { + $("#fgroup_id_buttonar > div > div > div").append('') + document.querySelector("#select-all-button").addEventListener("click", tickAllKreuzerl); + checkboxes = $("div.checkboxgroup1 input.checkboxgroup1"); +} + + + +function tickAllKreuzerl() { + checkboxes.each(function() { + (this).checked = true; + }) + + document.querySelector("#select-all-button").removeEventListener("click", tickAllKreuzerl); + document.querySelector("#select-all-button").value = "Keine auswählen"; + document.querySelector("#select-all-button").addEventListener("click", untickAllKreuzerl); + +} +function untickAllKreuzerl() { + checkboxes.each(function() { + (this).checked = false; + }) + + document.querySelector("#select-all-button").removeEventListener("click", untickAllKreuzerl); + document.querySelector("#select-all-button").value = "Alle auswählen"; + document.querySelector("#select-all-button").addEventListener("click", tickAllKreuzerl); + +} + + +function tickSubmissionStatement() { + $("input#id_submissionstatement").prop('checked', true); +} + + + +function init() { + const pathname = window.location.pathname; + + editGeneric(courseDropdownMenuItemSelector); + //set dropdown text to blue color to stand out more (OG TUWEL blue: #006699, no contrast on hover) + $(courseDropdownMenuItemSelector + " b.shortLvaName").css("color", "#013d5b"); + + editBreadcrumb(breadcrumbSelector); + + //if "my courses" page is open + if (pathname.startsWith("/my")) { + // wait for content to load on "my courses" + setTimeout(() => { editGeneric(courseTileSelector) }, 1600); + setTimeout(() => { editGeneric(courseListSelector) }, 1600); + } + + //if course main page is open + if (pathname.startsWith("/course/view.php?id=")) { + editGeneric(courseTitleSelector); + } + + if (pathname.startsWith("/mod/quiz/review.php")) { + highlightQuizResult(); + } + + if (pathname.startsWith("/mod/checkmark")) { + addtickAllKreuzerlButton(); + } + + if (pathname.startsWith("/mod/assign/view.php")) { + tickSubmissionStatement(); + } + +} + + + +$(document).ready(function() { + init(); +}); + + + + From 0558b70e2472e6d764d8af851ea5e0736b48c6e0 Mon Sep 17 00:00:00 2001 From: platinorum <69057107+platinorum@users.noreply.github.com> Date: Thu, 27 Nov 2025 20:34:02 +0100 Subject: [PATCH 2/5] Update version to 1.1 and improve URL checks --- tuwel-plus.user.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tuwel-plus.user.js b/tuwel-plus.user.js index 89d1e4f..ac956d4 100644 --- a/tuwel-plus.user.js +++ b/tuwel-plus.user.js @@ -3,8 +3,8 @@ // @namespace https://fsinf.at/ // @match https://tuwel.tuwien.ac.at/* // @grant none -// @version 1.0 -// @author - +// @version 1.1 +// @icon https://i.imgur.com/gJ9tqWL.png // @description Various small improvements to TUWEL including LVA-abbreviations and "Select All" for Kreuzerl // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js // ==/UserScript== @@ -28,6 +28,7 @@ const seperator = " » " const courseTileSelector = 'a.coursename[href*="https://tuwel.tuwien.ac.at/course/view.php?id="] > span.multiline > span[aria-hidden="true"]'; const courseListSelector = 'a.coursename[href*="https://tuwel.tuwien.ac.at/course/view.php?id="]' +const mobileDrawerSelector = 'div.drawer a.list-group-item[href*="https://tuwel.tuwien.ac.at/course/view.php?id="]' const courseTitleSelector = 'h1.h2.mb-0' const courseDropdownMenuItemSelector = 'div.carousel-inner > a.dropdown-item[role="menuitem"][href*="https://tuwel.tuwien.ac.at/course/view.php?id="]'; const breadcrumbSelector = 'li.breadcrumb-item:first > a'; @@ -134,8 +135,9 @@ function tickSubmissionStatement() { function init() { - const pathname = window.location.pathname; + const href = window.location.href; + editGeneric(mobileDrawerSelector); editGeneric(courseDropdownMenuItemSelector); //set dropdown text to blue color to stand out more (OG TUWEL blue: #006699, no contrast on hover) $(courseDropdownMenuItemSelector + " b.shortLvaName").css("color", "#013d5b"); @@ -143,26 +145,28 @@ function init() { editBreadcrumb(breadcrumbSelector); //if "my courses" page is open - if (pathname.startsWith("/my")) { + if (href.contains("/my")) { // wait for content to load on "my courses" setTimeout(() => { editGeneric(courseTileSelector) }, 1600); setTimeout(() => { editGeneric(courseListSelector) }, 1600); } + console.log(pathname); //if course main page is open - if (pathname.startsWith("/course/view.php?id=")) { + if (href.contains("/course/view.php?id=")) { editGeneric(courseTitleSelector); + console.log("AAA"); } - if (pathname.startsWith("/mod/quiz/review.php")) { + if (href.contains("/mod/quiz/review.php")) { highlightQuizResult(); } - if (pathname.startsWith("/mod/checkmark")) { + if (href.contains("/mod/checkmark")) { addtickAllKreuzerlButton(); } - if (pathname.startsWith("/mod/assign/view.php")) { + if (href.contains("/mod/assign/view.php")) { tickSubmissionStatement(); } From 9e67d97e566a0f0f80f8f657a34b1f5ac7869100 Mon Sep 17 00:00:00 2001 From: platinorum <69057107+platinorum@users.noreply.github.com> Date: Thu, 27 Nov 2025 20:38:37 +0100 Subject: [PATCH 3/5] 1.2 --- tuwel-plus.user.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tuwel-plus.user.js b/tuwel-plus.user.js index ac956d4..a7a6f96 100644 --- a/tuwel-plus.user.js +++ b/tuwel-plus.user.js @@ -3,7 +3,7 @@ // @namespace https://fsinf.at/ // @match https://tuwel.tuwien.ac.at/* // @grant none -// @version 1.1 +// @version 1.2 // @icon https://i.imgur.com/gJ9tqWL.png // @description Various small improvements to TUWEL including LVA-abbreviations and "Select All" for Kreuzerl // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js @@ -88,7 +88,7 @@ function editBreadcrumb(selector) { // highlight quiz result function highlightQuizResult() { - gradeCell = "table.quizreviewsummary tr:contains('Bewertung') > td" + gradeCell = "table.quizreviewsummary tr:includes('Bewertung') > td" if ($(gradeCell).text().includes("100%")) { $(gradeCell).css("background-color", "lightgreen"); @@ -145,28 +145,26 @@ function init() { editBreadcrumb(breadcrumbSelector); //if "my courses" page is open - if (href.contains("/my")) { + if (href.includes("/my")) { // wait for content to load on "my courses" setTimeout(() => { editGeneric(courseTileSelector) }, 1600); setTimeout(() => { editGeneric(courseListSelector) }, 1600); } - console.log(pathname); //if course main page is open - if (href.contains("/course/view.php?id=")) { + if (href.includes("/course/view.php?id=")) { editGeneric(courseTitleSelector); - console.log("AAA"); } - if (href.contains("/mod/quiz/review.php")) { + if (href.includes("/mod/quiz/review.php")) { highlightQuizResult(); } - if (href.contains("/mod/checkmark")) { + if (href.includes("/mod/checkmark")) { addtickAllKreuzerlButton(); } - if (href.contains("/mod/assign/view.php")) { + if (href.includes("/mod/assign/view.php")) { tickSubmissionStatement(); } From a164bfd344839e1ddabf6c62d6fa0b50c37e2ca4 Mon Sep 17 00:00:00 2001 From: platinorum <69057107+platinorum@users.noreply.github.com> Date: Thu, 27 Nov 2025 20:59:12 +0100 Subject: [PATCH 4/5] 1.3: smaller edit button Updated version number to 1.3 and smaller edit button in header bar. --- tuwel-plus.user.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tuwel-plus.user.js b/tuwel-plus.user.js index a7a6f96..d8a7fe0 100644 --- a/tuwel-plus.user.js +++ b/tuwel-plus.user.js @@ -3,7 +3,7 @@ // @namespace https://fsinf.at/ // @match https://tuwel.tuwien.ac.at/* // @grant none -// @version 1.2 +// @version 1.3 // @icon https://i.imgur.com/gJ9tqWL.png // @description Various small improvements to TUWEL including LVA-abbreviations and "Select All" for Kreuzerl // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js @@ -132,11 +132,16 @@ function tickSubmissionStatement() { $("input#id_submissionstatement").prop('checked', true); } +function smallerEditButton() { + $("label[for$='-editingswitch']").replaceWith(""); +} function init() { const href = window.location.href; + smallerEditButton(); + editGeneric(mobileDrawerSelector); editGeneric(courseDropdownMenuItemSelector); //set dropdown text to blue color to stand out more (OG TUWEL blue: #006699, no contrast on hover) From d2a8d2ff0361597cfe6f0800a80e442e8a7b24e5 Mon Sep 17 00:00:00 2001 From: platinorum <69057107+platinorum@users.noreply.github.com> Date: Thu, 27 Nov 2025 21:00:54 +0100 Subject: [PATCH 5/5] 1.4: smaller edit button only on dashboard --- tuwel-plus.user.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tuwel-plus.user.js b/tuwel-plus.user.js index d8a7fe0..af67226 100644 --- a/tuwel-plus.user.js +++ b/tuwel-plus.user.js @@ -3,7 +3,7 @@ // @namespace https://fsinf.at/ // @match https://tuwel.tuwien.ac.at/* // @grant none -// @version 1.3 +// @version 1.4 // @icon https://i.imgur.com/gJ9tqWL.png // @description Various small improvements to TUWEL including LVA-abbreviations and "Select All" for Kreuzerl // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js @@ -140,9 +140,9 @@ function smallerEditButton() { function init() { const href = window.location.href; - smallerEditButton(); editGeneric(mobileDrawerSelector); + editGeneric(courseDropdownMenuItemSelector); //set dropdown text to blue color to stand out more (OG TUWEL blue: #006699, no contrast on hover) $(courseDropdownMenuItemSelector + " b.shortLvaName").css("color", "#013d5b"); @@ -151,6 +151,7 @@ function init() { //if "my courses" page is open if (href.includes("/my")) { + smallerEditButton(); // wait for content to load on "my courses" setTimeout(() => { editGeneric(courseTileSelector) }, 1600); setTimeout(() => { editGeneric(courseListSelector) }, 1600);