Skip to content

Instantly share code, notes, and snippets.

@Steve-Tech
Last active March 25, 2024 05:27
Show Gist options
  • Save Steve-Tech/35462ed4eb2580c8d604f595aee580cf to your computer and use it in GitHub Desktop.
Save Steve-Tech/35462ed4eb2580c8d604f595aee580cf to your computer and use it in GitHub Desktop.
Enhancements to the QUT Canvas, may work on other instances of Canvas by Instructure. Re-sorts the 'Courses' menu by semester & changes the course link to the modules page.
// ==UserScript==
// @name QUT Canvas++
// @namespace https://stevetech.me/
// @version 0.3
// @description Enhancements to the QUT Canvas, may work on other instances of Canvas by Instructure.
// @author Steve-Tech
// @match https://canvas.qut.edu.au/*
// @icon https://instructure-uploads-apse2.s3.ap-southeast-2.amazonaws.com/account_218620000000000001/attachments/792/favicon.ico
// @grant none
// @run-at document-idle
// @updateURL https://gist.githubusercontent.com/Steve-Tech/35462ed4eb2580c8d604f595aee580cf/raw/QUT%2520Canvas++.js
// @downloadURL https://gist.githubusercontent.com/Steve-Tech/35462ed4eb2580c8d604f595aee580cf/raw/QUT%2520Canvas++.js
// @supportURL https://gist.github.com/Steve-Tech/35462ed4eb2580c8d604f595aee580cf
// ==/UserScript==
(function () {
'use strict';
function startTrayObserver(targetNode = document.getElementById("nav-tray-portal")) {
trayObserver.observe(targetNode, { childList: true, subtree: true });
}
// Wait for #nav-tray-portal to load
const bodyObserver = new MutationObserver((mutationsList, observer) => {
const targetNode = document.getElementById("nav-tray-portal");
if (targetNode != null) {
observer.disconnect();
startTrayObserver(targetNode);
}
});
const trayObserver = new MutationObserver((mutationsList, observer) => {
let courses_elem = document.querySelector("div.navigation-tray-container.courses-tray > div.tray-with-space-for-global-nav > div > ul > li > ul")
if (courses_elem != null && !["Loading", ""].includes(courses_elem.innerText) && !courses_elem.dataset?.sorted) {
// Set flag to reduce looping
courses_elem.dataset.sorted = true;
// Get all courses
let courses = {};
for (const course of courses_elem.children) {
const key = course.querySelector("div")?.innerText;
if (!(key in courses)) {
courses[key] = [];
}
let new_node = course.cloneNode(true);
new_node.firstChild.href += "/modules" // Add "/modules" to the URL
courses[key].push(new_node);
}
// Put newest courses first
let keys = Object.keys(courses);
keys.sort((a, b) => {
let a_match = a.match("^([0-9]{4}) SEM-([12])$");
let b_match = b.match("^([0-9]{4}) SEM-([12])$");
if (a_match != null && b_match != null) {
// Compare year
if (a_match[1] != b_match[1]) {
return b_match[1] - a_match[1];
}
// Compare semester
if (a_match[2] != b_match[2]) {
return b_match[2] - a_match[2];
}
}
// Use default sort
return 0;
});
let new_children = [];
for (const key of keys) {
new_children.push(...courses[key]);
}
observer.disconnect(); // Disconnect observer to reduce looping when mutating children
courses_elem.replaceChildren(...new_children);
startTrayObserver();
}
});
bodyObserver.observe(document.body, { childList: true });
// Use the whole screen when there's an iframe tool
if (document.querySelector("iframe.tool_launch")) {
document.querySelector("body:not(.full-width):not(.outcomes):not(.body--login-confirmation) .ic-Layout-wrapper").style.maxWidth = "none";
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment