Files
BetterSEQTA-Plus/src/seqta/utils/seqtaMenuColourPatch.js
T

222 lines
6.3 KiB
JavaScript

/**
* PAGE context — patches broken menu.update.colours and removes stuck colour-dialog layers.
*/
(function () {
if (window.__bsplusMenuColoursPatched) return;
var MENU_UPDATE_COLOURS = "menu.update.colours";
var SUBJECT_PREFIX = "timetable.subject.colour.";
var TUTOR_PREFIX = "timetable.tutor.";
var CLEANUP_FOLLOWUP_MS = 300;
var cleanupFollowup = null;
function isTesStyling() {
var el = document.getElementById("logo-style");
return el && el.textContent.indexOf("tesSeqta") !== -1;
}
function dismissStaleDialogs(forceColour) {
var slide = 0;
var panes = document.querySelectorAll(".uiSlidePane");
for (var i = 0; i < panes.length; i++) {
var p = panes[i];
if (p.querySelector(".pane.colourChooser")) {
p.remove();
slide++;
continue;
}
if (!forceColour && p.classList.contains("shown")) continue;
if (!p.classList.contains("shown")) {
p.remove();
slide++;
}
}
var modal = 0;
var containers = document.querySelectorAll(".modaliser-container");
for (var j = 0; j < containers.length; j++) {
var c = containers[j];
var m = c.querySelector(".modaliser");
if (!m || !m.childElementCount || !c.classList.contains("visible")) {
c.remove();
modal++;
}
}
document.body.classList.remove("clr-open");
document.documentElement.classList.remove("clr-open");
return { slideRemoved: slide, modalRemoved: modal };
}
function scheduleCleanup() {
dismissStaleDialogs(true);
if (cleanupFollowup) clearTimeout(cleanupFollowup);
cleanupFollowup = setTimeout(function () {
cleanupFollowup = null;
dismissStaleDialogs(true);
}, CLEANUP_FOLLOWUP_MS);
}
function applyMenuColours() {
if (!window.user) return;
var def = isTesStyling() ? "#2b3547" : "#dddddd";
var items = document.querySelectorAll("#menu li[data-colour]");
for (var i = 0; i < items.length; i++) {
var item = items[i];
var prefName = item.getAttribute("data-colour");
if (!prefName) continue;
var pref = window.user.getPreference(prefName);
item.style.setProperty("--item-colour", (pref && pref.value) || def);
}
}
function reconcileQuickbars() {
var fixed = 0;
var quickbars = document.querySelectorAll(".timetablepage .quickbar.visible");
for (var i = 0; i < quickbars.length; i++) {
var qb = quickbars[i];
var w = qb.querySelector(".wrapper");
if (!w || !w.childElementCount) {
qb.classList.remove("visible");
fixed++;
}
}
if (fixed) {
try {
window.msg.send("calendar.quickbar.hide");
} catch (err) {
/* ignore */
}
}
return fixed;
}
function findEntry(calendarId, code) {
if (calendarId) {
var byId = document.querySelector(
".timetablepage .entry[data-calendarid=\"" + calendarId + "\"]",
);
if (byId) return byId;
}
if (!code) return null;
var entries = document.querySelectorAll(".timetablepage .entry.class");
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
var titleEl = entry.querySelector(".title");
var title =
titleEl && titleEl.textContent ? titleEl.textContent.trim() : "";
if (title && title.indexOf(code) !== -1) return entry;
}
return null;
}
function normalizeQuickbarContext(contents) {
if (!contents) return contents;
reconcileQuickbars();
var element = contents.element;
var calendarId =
(element && element.getAttribute && element.getAttribute("data-calendarid")) ||
(contents.data && contents.data.calendarid);
var code = contents.data && contents.data.code;
var connected =
element &&
element.isConnected &&
typeof document.contains === "function" &&
document.contains(element);
if (!connected) {
var replacement = findEntry(calendarId, code);
if (replacement) contents.element = replacement;
}
return contents;
}
function isColourPref(handle) {
return (
typeof handle === "string" &&
(handle.indexOf(SUBJECT_PREFIX) === 0 || handle.indexOf(TUTOR_PREFIX) === 0)
);
}
function onMenuColourUpdate() {
try {
applyMenuColours();
} catch (err) {
console.error("[BetterSEQTA+] menu.update.colours failed:", err);
}
scheduleCleanup();
reconcileQuickbars();
}
function neutralizeBrokenListeners(msg) {
var listeners = msg.listeners && msg.listeners[MENU_UPDATE_COLOURS];
if (!listeners) return;
for (var i = 0; i < listeners.length; i++) {
if (listeners[i]) listeners[i].fn = onMenuColourUpdate;
}
}
function patchMsg(msg) {
if (!msg || msg.__bsplusPatched) return;
var send = msg.send.bind(msg);
var register = msg.register.bind(msg);
msg.send = function (handle, contents, suppressLogs, noRecord) {
if (handle === MENU_UPDATE_COLOURS) {
onMenuColourUpdate();
return;
}
if (isColourPref(handle)) {
var result = send(handle, contents, suppressLogs, noRecord);
scheduleCleanup();
reconcileQuickbars();
return result;
}
if (handle === "calendar.quickbar.class") {
return send(
handle,
normalizeQuickbarContext(contents),
suppressLogs,
noRecord,
);
}
return send(handle, contents, suppressLogs, noRecord);
};
msg.register = function (handle, callback, clear, ignoreHistory) {
if (handle === MENU_UPDATE_COLOURS) {
return register(handle, onMenuColourUpdate, clear, ignoreHistory);
}
return register(handle, callback, clear, ignoreHistory);
};
neutralizeBrokenListeners(msg);
msg.__bsplusPatched = true;
}
function tryPatch() {
if (window.__bsplusMenuColoursPatched) return true;
if (!window.msg || !window.msg.send) return false;
patchMsg(window.msg);
window.__bsplusMenuColoursPatched = true;
return true;
}
if (!tryPatch()) {
var interval = setInterval(function () {
if (tryPatch()) {
clearInterval(interval);
} else if (window.msg) {
neutralizeBrokenListeners(window.msg);
}
}, 25);
setTimeout(function () {
clearInterval(interval);
}, 120000);
}
})();