Update Compass QoL Enhancer to 1.5.0

- Make links inside lesson plans open in the parent instead of a new tab
- Rearrange the code a little bit
This commit is contained in:
blankie 2023-08-03 21:25:19 +10:00
parent 7e87996b41
commit 7bef678880
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
2 changed files with 89 additions and 60 deletions

View File

@ -2,7 +2,7 @@
// @name Compass QoL Enhancer // @name Compass QoL Enhancer
// @namespace blankie-scripts // @namespace blankie-scripts
// @match http*://*.compass.education/* // @match http*://*.compass.education/*
// @version 1.4.0 // @version 1.5.0
// @author blankie // @author blankie
// @description A userscript that adds small but useful features for Compass, such as the ability to close windows by clicking on the background // @description A userscript that adds small but useful features for Compass, such as the ability to close windows by clicking on the background
// @inject-into page // @inject-into page
@ -12,6 +12,9 @@
"use strict"; "use strict";
let qolTabOpened = false; let qolTabOpened = false;
// we make a copy of window.location.hash because the dashboard tab on a user's page would set the fragment to #dsh for some reason
let hashCopy = window.location.hash;
// needed because .toString() adds a trailing = for empty values // needed because .toString() adds a trailing = for empty values
function serializeURLSearchParams(query) { function serializeURLSearchParams(query) {
let out = ""; let out = "";
@ -46,65 +49,6 @@ function getPanelItemHash(panelId, isDefault) {
return `#${encodeURIComponent(panelId)}`; return `#${encodeURIComponent(panelId)}`;
} }
let observer = new MutationObserver(function(mutations) {
for (let mutation of mutations) {
if (mutation.type !== "childList") {
continue;
}
for (let node of mutation.addedNodes) {
handleNewNode(node);
}
}
});
observer.observe(document.body, {childList: true, subtree: true});
// we make a copy of window.location.hash because the dashboard tab on a user's page would set the fragment to #dsh for some reason
let hashCopy = window.location.hash;
function handleNewNode(node) {
if (node.nodeType !== 1) {
return;
}
if (node.parentElement && (node.classList.contains("ext-cal-hd-ct") || node.classList.contains("ext-cal-bg-tbl") || node.classList.contains("ext-cal-inner-ct"))) {
for (let element of node.querySelectorAll("div.ext-cal-evt")) {
handleNewCalendarEvent(element);
}
} else if (!qolTabOpened && node.classList.contains("x-panel")) {
qolTabOpened = true;
let tabToOpen = hashCopy.substring(1) || null;
if (window.location.pathname === "/Organise/Activities/Activity.aspx") {
tabToOpen = (new URLSearchParams(tabToOpen)).get("qol_open_tab");
}
let panel = unsafeWindow.Ext.getCmp(node.id);
for (let i = 0; i < panel.items.items.length; i++) {
handlePanelItem(panel, panel.items.items[i], i === 0, tabToOpen);
}
} else if (node.closest("[id^='wikibrowserpanel-'], #CompassWidgetsWikiBrowserPanel")) {
// Make files and folders in wiki/resources clickable for Link Hints
if (node.localName === "td") {
node.setAttribute("role", "button");
}
for (let element of node.querySelectorAll("td, .x-tree-expander")) {
element.setAttribute("role", "button");
}
}
}
document.body.addEventListener("click", function(event) {
// Add the ability to close windows by clicking on the background
if (!event.target.classList.contains("x-mask")) {
return;
}
let maskZIndex = BigInt(event.target.style.zIndex);
for (let maskMsg of document.querySelectorAll(".x-mask-msg")) {
if (BigInt(maskMsg.style.zIndex) >= maskZIndex && maskMsg.style.display !== "none") {
return;
}
}
document.querySelector(".x-window-closable.x-window-active .x-tool-close").click();
}, {passive: true});
function handleNewCalendarEvent(element) { function handleNewCalendarEvent(element) {
// Turn each calendar event into a link so that Link Hints can recognize it // Turn each calendar event into a link so that Link Hints can recognize it
let a = document.createElement("a"); let a = document.createElement("a");
@ -189,6 +133,89 @@ function handlePanelItem(panel, panelItem, isDefault, tabToOpen) {
}); });
} }
function handleCKEditor(instance) {
instance.on("contentDom", function() {
let editable = instance.editable();
for (let element of editable.$.querySelectorAll("a")) {
handleCKEditorLink(element);
}
observer.observe(editable.$, {childList: true, subtree: true});
});
}
function handleCKEditorLink(element) {
// Make links inside lesson plans open in the parent instead of a new tab
if (element.target !== "_blank" && element.target) {
return;
}
element.target = "_parent";
element.addEventListener("click", function(event) {
event.stopImmediatePropagation();
}, {passive: true});
}
function handleNewNode(node, observer) {
if (node.nodeType !== 1) {
return;
}
if (node.parentElement && (node.classList.contains("ext-cal-hd-ct") || node.classList.contains("ext-cal-bg-tbl") || node.classList.contains("ext-cal-inner-ct"))) {
for (let element of node.querySelectorAll("div.ext-cal-evt")) {
handleNewCalendarEvent(element);
}
} else if (!qolTabOpened && node.classList.contains("x-panel")) {
qolTabOpened = true;
let tabToOpen = hashCopy.substring(1) || null;
if (window.location.pathname === "/Organise/Activities/Activity.aspx") {
tabToOpen = (new URLSearchParams(tabToOpen)).get("qol_open_tab");
}
let panel = unsafeWindow.Ext.getCmp(node.id);
for (let i = 0; i < panel.items.items.length; i++) {
handlePanelItem(panel, panel.items.items[i], i === 0, tabToOpen);
}
} else if (node.closest("[id^='wikibrowserpanel-'], #CompassWidgetsWikiBrowserPanel")) {
// Make files and folders in wiki/resources clickable for Link Hints
if (node.localName === "td") {
node.setAttribute("role", "button");
}
for (let element of node.querySelectorAll("td, .x-tree-expander")) {
element.setAttribute("role", "button");
}
} else if (node.classList.contains("cke")) {
let instance = unsafeWindow.CKEDITOR.instances[node.id.substring(4)];
handleCKEditor(instance);
} else if (node.localName === "a" && /\bcke_/.test(node.closest("body").className)) {
handleCKEditorLink(node);
}
}
let observer = new MutationObserver(function(mutations, observer) {
for (let mutation of mutations) {
if (mutation.type !== "childList") {
continue;
}
for (let node of mutation.addedNodes) {
handleNewNode(node, observer);
}
}
});
observer.observe(document.body, {childList: true, subtree: true});
document.body.addEventListener("click", function(event) {
// Add the ability to close windows by clicking on the background
if (!event.target.classList.contains("x-mask")) {
return;
}
let maskZIndex = BigInt(event.target.style.zIndex);
for (let maskMsg of document.querySelectorAll(".x-mask-msg")) {
if (BigInt(maskMsg.style.zIndex) >= maskZIndex && maskMsg.style.display !== "none") {
return;
}
}
document.querySelector(".x-window-closable.x-window-active .x-tool-close").click();
}, {passive: true});
// Suppress that annoying barebones context menu that only has Copy // Suppress that annoying barebones context menu that only has Copy
// why is it not obvious that you can just hold ctrl or shift to suppress it??? // why is it not obvious that you can just hold ctrl or shift to suppress it???
// i know it's compass' fault but i'm still frustrated // i know it's compass' fault but i'm still frustrated

View File

@ -27,6 +27,8 @@ A userscript that adds small but useful features for Compass. Features include:
open. you can also ctrl+click on them) open. you can also ctrl+click on them)
- Files and folders in Resources is now marked clickable ([Link Hints] can now - Files and folders in Resources is now marked clickable ([Link Hints] can now
open them!) open them!)
- Links inside lesson plans now open in the parent tab by default instead of
creating a new tab
- The context menu that only says "Copy" is now suppressed - The context menu that only says "Copy" is now suppressed
- The option to remember logins is unchecked by default - The option to remember logins is unchecked by default