diff --git a/Compass QoL Enhancer.user.js b/Compass QoL Enhancer.user.js index 1633096..f035418 100644 --- a/Compass QoL Enhancer.user.js +++ b/Compass QoL Enhancer.user.js @@ -2,7 +2,7 @@ // @name Compass QoL Enhancer // @namespace blankie-scripts // @match http*://*.compass.education/* -// @version 1.1.1 +// @version 1.2.0 // @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 // @inject-into page @@ -11,6 +11,41 @@ "use strict"; +let qolTabOpened = false; +// needed because .toString() adds a trailing = for empty values +function serializeURLSearchParams(query) { + let out = ""; + for (let [key, value] of query) { + if (out) { + out += "&"; + } + // required for session/... or activity/... + out += encodeURIComponent(key).replaceAll("%2F", "/"); + if (value) { + out += `=${encodeURIComponent(value)}`; + } + } + return out; +} +function getPanelItemHash(panelId, isDefault) { + if (window.location.pathname === "/Organise/Activities/Activity.aspx") { + let query = new URLSearchParams(window.location.hash.substring(1)); + if (panelId === "learningtasks") { + query.delete("qol_open_tab"); + query.set("openLearningTaskTab", ""); + } else if (isDefault) { + query.delete("qol_open_tab"); + query.delete("openLearningTaskTab"); + } else { + query.set("qol_open_tab", panelId); + query.delete("openLearningTaskTab"); + } + return `#${serializeURLSearchParams(query)}`; + } + + return `#${encodeURIComponent(panelId)}`; +} + let observer = new MutationObserver(function(mutations) { for (let mutation of mutations) { if (mutation.type !== "childList") { @@ -35,11 +70,15 @@ function handleNewNode(node) { for (let element of node.querySelectorAll("div.ext-cal-evt")) { handleNewCalendarEvent(element); } - } else if (window.location.pathname === "/Organise/Activities/Activity.aspx" && node.classList.contains("activityPage__tabPanel")) { - for (let tab of node.querySelectorAll(".x-tab")) { - tab.addEventListener("click", function() { - handleActivityTabClick(tab); - }, {passive: true}); + } else if (!qolTabOpened && node.classList.contains("x-panel")) { + qolTabOpened = true; + let tabToOpen = window.location.hash.substring(1); + 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); } } } @@ -73,7 +112,7 @@ function handleNewCalendarEvent(element) { if (a.classList.contains("activity-type-1")) { // Add a link for activities/"standard classes" // missing targetUserId parameter, shouldn't matter too much if you're a student - let eventId = / calendar-event-(\d+) /.exec(a.className)[1]; + let eventId = /\bcalendar-event-(\d+)\b/.exec(a.className)[1]; a.href = `/Organise/Activities/Activity.aspx#session/${eventId}`; preventCompassHandler = true; } else if (a.classList.contains("activity-type-10")) { @@ -94,21 +133,34 @@ function handleNewCalendarEvent(element) { element.replaceWith(a); } -function handleActivityTabClick(element) { - // Automatically add or remove &openLearningTaskTab when a tab is clicked - let matches = /^(#(?:session|activity)\/\d+)(?:&openLearningTaskTab)?$/.exec(window.location.hash); - if (!matches) { - return; +function handlePanelItem(panel, panelItem, isDefault, tabToOpen) { + let panelId = panelItem.itemId || panelItem.id; + // i don't know why but dashboard is dsh + if (window.location.pathname === "/Records/User.aspx" && panelId === "dashboard") { + panelId = "dsh"; } - let newHash = matches[1]; - if (element.classList.contains("sel-learning-tasks-tab")) { - newHash += "&openLearningTaskTab"; + // Automatically open tab specified in fragment + if (panelId === tabToOpen) { + panel.setActiveTab(panelItem); } - if (newHash !== window.location.hash) { - history.pushState("", "", newHash); - } + panelItem.tab.preventDefault = false; + let panelItemHash = getPanelItemHash(panelId, isDefault); + panelItem.tab.el.dom.href = panelItemHash; + + panelItem.tab.el.dom.addEventListener("click", function(event) { + if (event.ctrlKey) { + event.stopImmediatePropagation(); + return; + } + // prevent the browser from scrolling to the body + event.preventDefault(); + if (panelItemHash !== window.location.hash) { + // Automatically add a reference to the tab when it is clicked + history.pushState("", "", panelItemHash); + } + }); } // Suppress that annoying barebones context menu that only has Copy diff --git a/README.md b/README.md index db0f4b3..4292e56 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ Hacky script to disable the client-side file limit per tab A userscript that adds small but useful features for Compass. Features include: - The ability to close windows by clicking on the background -- Calendar events being links (they work with [Link Hints](https://lydell.github.io/LinkHints/) +- Calendar events are now links (they work with [Link Hints](https://lydell.github.io/LinkHints/) now! you can also ctrl+click on "standard classes" and learning tasks) -- `&openLearningTaskTab` is automatically added whenever you go to the Learning - Tasks tab and removed whenever you go to another tab +- Tabs are now links (you can refresh pages and the tab will automatically + open. you can also ctrl+click on them) - The context menu that only says "Copy" is now suppressed - The option to remember logins is unchecked by default