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);