Unterstützung für /course/show und Refactoring

- Seitenrouting auf /course/show korrigiert (/course/list leitet um)
- Planungsgruppen-Dropdown (planningGroupIds[]) für /course/show ergänzt
- Funktionsblöcke je Seite eingeführt (courseList_*, planningGroupList_*)
- MutationObserver + Polling für zuverlässiges Timing beim Seitenladen
- .gitignore ergänzt
This commit is contained in:
2026-04-28 09:37:17 +02:00
parent 194c3e70e8
commit 1771382287
2 changed files with 101 additions and 34 deletions
+98 -34
View File
@@ -1,8 +1,8 @@
// ==UserScript==
// @name academyFIVE::AddSelectBox
// @namespace dakp/academyfive
// @version 2026.03.001
// @description Füge Selectbox für Kohorten hinzu
// @version 2026.04.007
// @description Füge Selectbox für Kohorten/Planungsgruppen hinzu
// @author Dims Akpan
// @match https://a5.fhdw-hannover.de/*
// @match https://a5.fhdw.de/*
@@ -14,34 +14,35 @@
(function() {
'use strict';
function addSelectButtons() {
// Prüfe ob wir auf der richtigen Seite sind
if (!window.location.href.includes('/course/planning-group/list')) {
return;
const LOG = '[A5-SelectBox]';
// ─── Gemeinsame Hilfsfunktionen ───────────────────────────────────────────
function insertSelectButtons(selectSelector) {
const select = document.querySelector(selectSelector);
if (!select) {
console.log(LOG, 'select nicht gefunden:', selectSelector);
return false;
}
const cohortsDropdown = document.querySelector('select[name="cohort-ids[]"]');
if (!cohortsDropdown) {
console.log('Kohorten-Dropdown nicht gefunden');
return;
const dropdownContainer = select.closest('.btn-group.bootstrap-select');
if (!dropdownContainer) {
console.log(LOG, 'closest(.btn-group.bootstrap-select) nicht gefunden');
return false;
}
const dropdownContainer = cohortsDropdown.closest('.btn-group.bootstrap-select');
const searchBox = dropdownContainer?.querySelector('.bs-searchbox');
const searchBox = dropdownContainer.querySelector('.bs-searchbox');
if (!searchBox) {
console.log('Searchbox nicht gefunden');
return;
console.log(LOG, '.bs-searchbox nicht gefunden im Container');
return false;
}
// Prüfe ob schon vorhanden
if (searchBox.nextElementSibling?.classList.contains('bs-actionsbox')) {
console.log('Select/Deselect Buttons bereits vorhanden');
return;
console.log(LOG, 'Buttons bereits vorhanden, überspringe');
return true;
}
// Füge die Buttons hinzu
const actionsBox = document.createElement('div');
actionsBox.className = 'bs-actionsbox';
actionsBox.innerHTML = `
@@ -50,17 +51,80 @@
<button type="button" class="actions-btn bs-deselect-all btn btn-default">Nichts auswählen</button>
</div>
`;
searchBox.insertAdjacentElement('afterend', actionsBox);
console.log('Select/Deselect Buttons erfolgreich eingefügt');
console.log(LOG, 'Buttons erfolgreich eingefügt für:', selectSelector);
return true;
}
// Versuche es direkt
addSelectButtons();
// Falls das Element noch nicht da ist, warte auf DOMContentLoaded
function waitAndInsert(tryFn) {
console.log(LOG, 'waitAndInsert gestartet | readyState:', document.readyState, '| URL:', window.location.href);
if (tryFn()) return;
console.log(LOG, 'Erster Versuch fehlgeschlagen, starte Observer + Polling');
const observer = new MutationObserver(() => {
if (tryFn()) {
console.log(LOG, 'Observer: Buttons eingefügt, Observer beendet');
observer.disconnect();
}
});
observer.observe(document.body, { childList: true, subtree: true });
let attempts = 0;
const poll = setInterval(() => {
attempts++;
if (tryFn()) {
console.log(LOG, 'Polling: Buttons eingefügt nach', attempts, 'Versuchen');
clearInterval(poll);
} else if (attempts >= 50) {
console.log(LOG, 'Polling: Timeout nach 50 Versuchen');
clearInterval(poll);
observer.disconnect();
}
}, 100);
}
// ─── /course/list ─────────────────────────────────────────────────────────
function courseList_tryInsert() {
return insertSelectButtons('select[name="planningGroupIds[]"]');
}
function courseList_init() {
waitAndInsert(courseList_tryInsert);
}
// ─── /course/planning-group/list ──────────────────────────────────────────
function planningGroupList_tryInsert() {
return insertSelectButtons('select[name="cohort-ids[]"]');
}
function planningGroupList_init() {
waitAndInsert(planningGroupList_tryInsert);
}
// ─── Routing ──────────────────────────────────────────────────────────────
function init() {
const url = window.location.href;
console.log(LOG, 'init() | URL:', url);
if (url.includes('/course/planning-group/list')) {
planningGroupList_init();
} else if (url.includes('/course/show')) {
courseList_init();
} else {
console.log(LOG, 'URL passt zu keiner bekannten Seite, Script inaktiv');
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', addSelectButtons);
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
})();