Last active
February 27, 2025 13:30
-
-
Save dcdunkan/37a5d23ceccfb42084de917eeec1538c to your computer and use it in GitHub Desktop.
"Focus for Etlab" UserScript for TKMCE Etlab, which declutters the dashboard and gives focus to most frequently used items.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Focus for Etlab | |
// @namespace Utilities for Etlab | |
// @match https://tkmce.etlab.in/user/dashboard* | |
// @include https://tkmce.etlab.in/ | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @version 0.3 | |
// @run-at document-end | |
// @author Dunkan <https://github.com/dcdunkan> | |
// @description "Focus for Etlab" UserScript for TKMCE Etlab, which declutters the dashboard and gives focus to most frequently used items. | |
// @homepageURL https://gist.github.com/dcdunkan/37a5d23ceccfb42084de917eeec1538c | |
// @downloadURL https://gist.githubusercontent.com/dcdunkan/37a5d23ceccfb42084de917eeec1538c/raw/etlab-focus.userscript.js | |
// ==/UserScript== | |
const pathSegments = window.location.pathname | |
.split("/").slice(1) | |
.filter((segment) => segment.length > 0); | |
const WORK_ITEM_TITLES = ["Assignments", "Homeworks", "Tutorials"]; | |
const DATA_ITEM_TITLES = ["My Profile", "Results", "Attendance"]; | |
(function () { | |
if ( | |
pathSegments.length > 0 && | |
(pathSegments[0] !== "user" || pathSegments[1] !== "dashboard") | |
) return; | |
console.info("Focs for Etlab is active"); | |
const hasNotified = GM_getValue("hasNotified", false); | |
if (!hasNotified) { | |
window.alert("Focus for Etlab is now active. This will re-arrange the dashboard. Click on the focus button to enable it"); | |
GM_setValue("hasNotified", true); | |
} | |
const mainContent = document.getElementById("breadcrumb").nextElementSibling; | |
const focusToggleButton = document.createElement("button"); | |
focusToggleButton.onclick = function () { | |
let current = localStorage.getItem("focusEnabled") === "true"; | |
localStorage.setItem("focusEnabled", String(!current)); | |
focusToggleButton.innerHTML = current ? "Focus" : "Unfocus"; | |
if (!current) startFocusing(); | |
else window.location.reload(); | |
} | |
mainContent.prepend(focusToggleButton); | |
let shouldFocus = localStorage.getItem("focusEnabled") === "true"; | |
focusToggleButton.innerHTML = shouldFocus ? "Unfocus" : "Focus"; | |
if (shouldFocus) { | |
startFocusing(); | |
} | |
})(); | |
function startFocusing() { | |
console.log("Focus was enabled."); | |
// Declutter the paragraphs, that no one cares for. | |
const uselessSections = [ | |
document.evaluate("//h3[contains(., 'Vision of the College')]", document, null, XPathResult.ANY_TYPE, null).iterateNext(), | |
document.evaluate("//h3[contains(., 'Mission of the College')]", document, null, XPathResult.ANY_TYPE, null).iterateNext(), | |
].filter((section) => section != null); | |
for (const section of uselessSections) { | |
if (section.parentNode != null) { | |
const target = section.parentNode.parentNode; | |
if (target == null) continue; | |
if (target.nodeName != "DIV") return; | |
target.remove(); | |
} | |
} | |
const shortcuts = document.getElementsByClassName("shortcuts").item("div"); | |
const workTitle = createTitle("WORK RELATED"); | |
const workContainer = document.createElement("div"); | |
workContainer.classList.add("shortcuts"); | |
const dataTitle = createTitle("IMPORTANT DATA"); | |
const dataContainer = document.createElement("div"); | |
dataContainer.classList.add("shortcuts"); | |
for (const shortcut of shortcuts.childNodes) { | |
if (shortcut.nodeName !== "A") continue; | |
if (!shortcut.classList.contains("shortcut")) continue; | |
let title = ""; | |
for (const child of shortcut.childNodes) { | |
if (child.nodeName !== "SPAN") continue; | |
if (!child.classList.contains("shortcut-label")) continue; | |
title = child.textContent.trim(); | |
} | |
if (title == "") continue; | |
if (WORK_ITEM_TITLES.includes(title)) { | |
workContainer.appendChild(shortcuts.removeChild(shortcut)); | |
} else if (DATA_ITEM_TITLES.includes(title)) { | |
dataContainer.appendChild(shortcuts.removeChild(shortcut)); | |
} | |
} | |
if (workContainer.childNodes.length !== WORK_ITEM_TITLES.length) { | |
console.warn("FOCUS: Failed to find all the work items."); | |
} | |
if (dataContainer.childNodes.length !== DATA_ITEM_TITLES.length) { | |
console.warn("FOCUS: Failed to find all the data items."); | |
} | |
if (workContainer.childNodes.length > 0) { | |
shortcuts.before(workTitle); | |
workTitle.after(workContainer); | |
} | |
if (dataContainer.childNodes.length > 0) { | |
shortcuts.before(dataTitle); | |
dataTitle.after(dataContainer); | |
} | |
if (workContainer.childNodes.length > 0 || dataContainer.childNodes.length > 0) { | |
const uselessTitle = createTitle("USELESS FOR MOST OF THE TIME (click to expand)"); | |
const details = document.createElement("details"); | |
const summary = document.createElement("summary"); | |
summary.appendChild(uselessTitle); | |
details.appendChild(summary); | |
details.appendChild(shortcuts.parentNode.removeChild(shortcuts)); | |
const lastContainer = dataContainer.childNodes.length > 0 ? dataContainer : workContainer; | |
lastContainer.after(details); | |
} | |
console.log("Finished decluttering"); | |
} | |
function createTitle(title) { | |
const element = document.createElement("center"); | |
element.textContent = title; | |
element.style.padding = "10px"; | |
element.style.fontWeight = "900"; | |
element.style.fontSize = "large"; | |
return element; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment