const ShortcutLinks = require('./seqta/content/links.json'); var MenuitemSVGKey = require('./seqta/content/MenuItemSVGKey.json'); var isChrome = window.chrome; var SettingsClicked = false var MenuOptionsOpen = false; var UserInitalCode = ''; var currentSelectedDate = new Date(); var WhatsNewOpen = false; var LessonInterval; function stringToHTML (str, styles=false) { var parser = new DOMParser(); var str = DOMPurify.sanitize(str, { ADD_ATTR: ['onclick']}); var doc = parser.parseFromString(str, "text/html"); if(styles){doc.body.style.cssText = "height: auto; overflow: scroll; margin: 0px; background: var(--background-primary);"} return doc.body; }; function loading() { loadinghtml = stringToHTML( `
v${chrome.runtime.getManifest().version}
` ); var html = document.getElementsByTagName("html")[0]; html.append(loadinghtml.firstChild); } function AppendLoadingSymbol(givenID, position) { loadingsymbol = stringToHTML(`
`).firstChild document.querySelector(position).appendChild(loadingsymbol) } function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function SetDisplayNone(ElementName) { return `li[data-key=${ElementName}]{display:var(--menuHidden) !important; transition: 1s;}`; } function ApplyCSSToHiddenMenuItems() { var stylesheetInnerText = ""; chrome.storage.local.get(null, function (result) { for (let i = 0; i < Object.keys(result.menuitems).length; i++) { if (!Object.values(result.menuitems)[i].toggle) { stylesheetInnerText += SetDisplayNone(Object.keys(result.menuitems)[i]); console.log( `[Even BetterSEQTA] Hiding ${Object.keys(result.menuitems)[i]} menu item` ); } } MenuItemStyle = document.createElement("style"); MenuItemStyle.innerText = stylesheetInnerText; document.head.appendChild(MenuItemStyle); }); } function OpenWhatsNewPopup() { const background = document.createElement('div'); background.id = "whatsnewbk"; background.classList.add('whatsnewBackground'); const container = document.createElement('div'); container.classList.add('whatsnewContainer'); var header = stringToHTML(`

What's New

Even BetterSEQTA V${chrome.runtime.getManifest().version}

`).firstChild; imagecont = document.createElement('div'); imagecont.classList.add('whatsnewImgContainer'); var image = document.createElement('img'); image.src = chrome.runtime.getURL('icons/betterseqta-dark-icon.png'); image.classList.add('whatsnewImg') imagecont.append(image); textcontainer = document.createElement('div'); textcontainer.classList.add('whatsnewTextContainer'); textheader = stringToHTML('

DESIGN OVERHAUL

').firstChild; textcontainer.append(textheader); text = stringToHTML( `

3.0.0 - Even BetterSEQTA *Complete Overhaul*

  • Redesigned appearance
  • Upgraded to manifest V3 (longer support)
  • Fixed transitional glitches
  • Under the hood improvements
  • Fixed News Feed
  • 2.0.7 - Added support to other domains + Minor bug fixes

  • Fixed Even BetterSEQTA not loading on some pages
  • Fixed text colour of notices being unreadable
  • Fixed pages not reloading when saving changes
  • 2.0.2 - Minor bug fixes

  • Fixed indicator for current lesson
  • Fixed text colour for DM messages list in Light mode
  • Fixed user info text colour
  • Sleek New Layout

  • Updated with a new font and presentation, Even BetterSEQTA has never looked better.
  • New Updated Sidebar

  • Condensed appearance with new updated icons.
  • Independent Light Mode and Dark Mode

  • Dark mode and Light mode are now available to pick alongside your chosen Theme Colour. Your Theme Colour will now become an accent colour for the page. Light/Dark mode can be toggled with the new button, found in the top-right of the menu bar.
  • Create Custom Shortcuts

  • Found in the Even BetterSEQTA Settings menu, custom shortcuts can now be created with a name and URL of your choice.
  • ` ).firstChild; footer = stringToHTML(`
    Report bugs and feedback:
    `).firstChild exitbutton = document.createElement('div') exitbutton.innerText = 'x'; exitbutton.id = 'whatsnewclosebutton'; container.append(header); container.append(imagecont); container.append(textcontainer); container.append(text); container.append(footer); container.append(exitbutton); document.getElementById('container').append(background); document.getElementById('container').append(container); chrome.storage.local.remove(["justupdated"]); var bkelement = document.getElementById('whatsnewbk'); bkelement.addEventListener('click', function () { DeleteWhatsNew(); WhatsNewOpen = false; }) var closeelement = document.getElementById('whatsnewclosebutton'); closeelement.addEventListener('click', function (e) { DeleteWhatsNew(); WhatsNewOpen = false; }) } async function finishLoad() { try { var loadingbk = document.getElementById("loading"); loadingbk.style.opacity = "0"; await delay(501); loadingbk.remove(); } catch(err) { console.log(err); } chrome.storage.local.get(["justupdated"], function (result) { if (result.justupdated) { WhatsNewOpen = true; OpenWhatsNewPopup(); } }) } async function DeleteWhatsNew() { var bkelement = document.getElementById('whatsnewbk'); var popup = document.getElementsByClassName("whatsnewContainer")[0]; bkelement.classList.add('whatsnewfadeout'); popup.classList.add('whatsnewzoomout'); await delay(500); bkelement.remove(); popup.remove(); } function CreateBackground() { // Creating and inserting 3 divs containing the background applied to the pages var bklocation = document.getElementById("container"); var menu = document.getElementById("menu"); var bk = document.createElement("div"); bk.classList.add("bg"); bklocation.insertBefore(bk, menu); var bk2 = document.createElement("div"); bk2.classList.add("bg"); bk2.classList.add("bg2"); bklocation.insertBefore(bk2, menu); var bk3 = document.createElement("div"); bk3.classList.add("bg"); bk3.classList.add("bg3"); bklocation.insertBefore(bk3, menu); } function waitForElm(selector) { return new Promise((resolve) => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver((mutations) => { if (document.querySelector(selector)) { resolve(document.querySelector(selector)); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true, }); }); } var LoadingDone = false; async function RunColourCheck(element) { if (typeof element.contentDocument.documentElement.childNodes[1] == 'undefined') { await delay(1000); RunColourCheck(element); } else { element.contentDocument.documentElement.childNodes[1].style.color = "white"; } } function GetiFrameCSSElement() { var cssFile = chrome.runtime.getURL("inject/iframe.css"); var fileref = document.createElement("link"); fileref.setAttribute("rel", "stylesheet"); fileref.setAttribute("type", "text/css"); fileref.setAttribute("href", cssFile); return fileref; } function CheckiFrameItems() { // Injecting CSS File to the webpage to overwrite iFrame default CSS fileref = GetiFrameCSSElement(); const observer = new MutationObserver(function (mutations_list) { mutations_list.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { if (added_node.tagName == "IFRAME") { chrome.storage.local.get(["DarkMode"], function (result) { DarkModeResult = result.DarkMode if (DarkModeResult) { RunColourCheck(added_node); if (added_node.contentDocument.documentElement.childNodes[1].style.color != "white") { added_node.contentDocument.documentElement.childNodes[1].style.color = "white"; } if ( !added_node.contentDocument.documentElement.firstChild.innerHTML.includes( "iframe.css" ) ) { added_node.contentDocument.documentElement.firstChild.appendChild( fileref ); } added_node.addEventListener("load", function () { if (added_node.contentDocument.documentElement.childNodes[1].style.color != "white") { added_node.contentDocument.documentElement.childNodes[1].style.color = "white"; } if ( !added_node.contentDocument.documentElement.firstChild.innerHTML.includes( "iframe.css" ) ) { added_node.contentDocument.documentElement.firstChild.appendChild( fileref ); } }); } }); } }); }); }); observer.observe(document.body, { subtree: true, childList: true, }); } function SortMessagePageItems(messagesParentElement) { filterbutton = document.createElement('div'); filterbutton.classList.add("messages-filterbutton"); filterbutton.innerText = "Filter"; header = document.getElementsByClassName('MessageList__MessageList___3DxoC')[0].firstChild; header.append(filterbutton); const observer = new MutationObserver(function (mutations_list) { mutations_list.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { if (added_node.dataset.message) { // Check if added_node.firstChild.title is in block list } }); }); }); observer.observe(messagesParentElement, { subtree: true, childList: true, }); } function LoadPageElements() { AddBetterSEQTAElements(true); var sublink = window.location.href.split("/")[4]; switch (sublink) { case "news": console.log("[Even BetterSEQTA] Started Init"); chrome.storage.local.get(null, function (result) { if (result.onoff) { SendNewsPage(); // Sends similar HTTP Post Request for the notices chrome.storage.local.get(null, function (result) { if (result.notificationcollector) { var xhr3 = new XMLHttpRequest(); xhr3.open( "POST", `${location.origin}/seqta/student/heartbeat?`, true ); xhr3.setRequestHeader( "Content-Type", "application/json; charset=utf-8" ); xhr3.onreadystatechange = function () { if (xhr3.readyState === 4) { var Notifications = JSON.parse(xhr3.response); var alertdiv = document.getElementsByClassName( "notifications__bubble___1EkSQ" )[0]; if (typeof alertdiv == 'undefined') { console.log("[Even BetterSEQTA] No notifications currently") } else { alertdiv.textContent = Notifications.payload.notifications.length; } } }; xhr3.send( JSON.stringify({ timestamp: "1970-01-01 00:00:00.0", hash: "#?page=/home", }) ); } }); finishLoad(); } }); break; case "home": window.location.replace(`${location.origin}/#?page=/home`); LoadInit(); break; case undefined: window.location.replace(`${location.origin}/#?page=/home`); LoadInit(); break; default: finishLoad(); // Sends similar HTTP Post Request for the notices chrome.storage.local.get(null, function (result) { if (result.notificationcollector) { var xhr3 = new XMLHttpRequest(); xhr3.open( "POST", `${location.origin}/seqta/student/heartbeat?`, true ); xhr3.setRequestHeader( "Content-Type", "application/json; charset=utf-8" ); xhr3.onreadystatechange = function () { if (xhr3.readyState === 4) { var Notifications = JSON.parse(xhr3.response); var alertdiv = document.getElementsByClassName( "notifications__bubble___1EkSQ" )[0]; if (typeof alertdiv == 'undefined') { console.log("[Even BetterSEQTA] No notifications currently") } else { alertdiv.textContent = Notifications.payload.notifications.length; } } }; xhr3.send( JSON.stringify({ timestamp: "1970-01-01 00:00:00.0", hash: "#?page=/home", }) ); } }); break; } const observer = new MutationObserver(function (mutations_list) { mutations_list.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { if (added_node.classList.contains('messages')) { element = document.getElementById('title').firstChild; element.innerText = "Direct Messages"; document.title = "Direct Messages ― SEQTA Learn"; SortMessagePageItems(added_node); } else if (added_node.classList.contains('notices')) { CheckNoticeTextColour(added_node); } }); }); }); observer.observe(document.querySelector('#main'), { subtree: false, childList: true, }); } function CheckNoticeTextColour(notice) { const observer = new MutationObserver(function (mutations_list) { mutations_list.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { chrome.storage.local.get(['DarkMode'], function (result) { Darkmode = result.DarkMode; if (added_node.classList.contains('notice')) { var hex = added_node.style.cssText.split(' ')[1]; var threshold = GetThresholdofHex(hex); if (Darkmode && threshold < 100) { added_node.style.cssText = "--color: undefined;"; } } }) }); }); }); observer.observe(notice, { subtree: true, childList: true, }); } function tryLoad() { waitForElm(".login").then((elm) => { LoadingDone = true; finishLoad(); }); waitForElm(".day-container").then((elm) => { LoadingDone = true; finishLoad(); }); waitForElm("[data-key=welcome]").then((elm) => { elm.classList.remove('active') }); waitForElm(".code").then((elm) => { if (!elm.innerText.includes("BetterSEQTA")) LoadPageElements(); }); // Waits for page to call on load, run scripts document.addEventListener( "load", function () { CheckiFrameItems(); }, true ); } function ChangeMenuItemPositions(storage) { menuorder = storage; var menuList = document.querySelector('#menu').firstChild.childNodes; listorder = [] for (let i = 0; i < menuList.length; i++) { namevalue = menuList[i].dataset.key a = menuorder.indexOf(menuList[i].dataset.key) listorder.push(a) } var newArr = [] for (var i = 0; i < listorder.length; i++) { newArr[listorder[i]] = menuList[i] } listItemsDOM = document.getElementById('menu').firstChild for (let i = 0; i < newArr.length; i++) { const element = newArr[i]; if (element) { element.setAttribute('data-checked', 'true') listItemsDOM.appendChild(element); } } } async function ObserveMenuItemPosition() { chrome.storage.local.get(null, function (result) { menuorder = result.menuorder if (menuorder && result.onoff) { const observer = new MutationObserver(function (mutations_list) { mutations_list.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { if (!added_node?.dataset?.checked && !MenuOptionsOpen) { if (MenuitemSVGKey[added_node?.dataset?.key]) { ReplaceMenuSVG(added_node, MenuitemSVGKey[added_node.dataset.key]) } ChangeMenuItemPositions(menuorder); } }); }); }); observer.observe(document.querySelector('#menu').firstChild, { subtree: true, childList: true, }); } }) } function AppendElementsToDisabledPage() { AddBetterSEQTAElements(false); settingsStyle = document.createElement('style') settingsStyle.innerText = ` .addedButton { position: absolute !important; right: 50px; width: 35px; height: 35px; padding: 6px !important; overflow: unset !important; border-radius: 50%; margin: 7px !important; cursor: pointer; color: white !important; } .addedButton svg { margin: 6px; } .outside-container { top: 48px !important; } ` document.head.append(settingsStyle) } function lightenAndPaleColor(hexColor, lightenFactor = 0.75, paleFactor = 0.55) { // Convert a RGB value to HSL function rgbToHsl(r, g, b) { r /= 255, g /= 255, b /= 255; let max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max === min) { h = s = 0; } else { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; } // Convert an HSL value to RGB function hslToRgb(h, s, l) { function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1/6) return p + (q - p) * 6 * t; if (t < 1/2) return q; if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; return p; } let r, g, b; if (s === 0) { r = g = b = l; } else { let q = l < 0.5 ? l * (1 + s) : l + s - l * s; let p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } return [r * 255, g * 255, b * 255]; } // Extract the red, green, and blue components from hex let r = parseInt(hexColor.substr(1, 2), 16); let g = parseInt(hexColor.substr(3, 2), 16); let b = parseInt(hexColor.substr(5, 2), 16); // Convert RGB to HSL let [h, s, l] = rgbToHsl(r, g, b); // Adjust saturation and lightness s -= s * paleFactor; l += (1 - l) * lightenFactor; // Convert HSL back to RGB [r, g, b] = hslToRgb(h, s, l); // Convert RGB to hex r = Math.round(r).toString(16).padStart(2, '0'); g = Math.round(g).toString(16).padStart(2, '0'); b = Math.round(b).toString(16).padStart(2, '0'); return '#' + r + g + b; } function ColorLuminance(hex, lum) { // validate hex string hex = String(hex).replace(/[^0-9a-f]/gi, ''); if (hex.length < 6) { hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } lum = lum || 0; // convert to decimal and change luminosity var rgb = "#", c, i; for (i = 0; i < 3; i++) { c = parseInt(hex.substr(i * 2, 2), 16); c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); rgb += ("00" + c).substring(c.length); } return rgb; } chrome.storage.onChanged.addListener(function (changes) { if (changes.selectedColor) { try { document.documentElement.style.setProperty('--better-pale', lightenAndPaleColor(changes.selectedColor.newValue)); } catch(err) { console.log(err) } rbg = GetThresholdofHex(changes.selectedColor.newValue) if (rbg > 210) { document.documentElement.style.setProperty('--text-color', 'black'); document.documentElement.style.setProperty('--betterseqta-logo', `url(${chrome.runtime.getURL('icons/betterseqta-dark-full.png')})`); } else { document.documentElement.style.setProperty('--text-color', 'white'); document.documentElement.style.setProperty('--betterseqta-logo', `url(${chrome.runtime.getURL('icons/betterseqta-light-full.png')})`); } document.documentElement.style.setProperty('--better-main', changes.selectedColor.newValue); // document.documentElement.style.setProperty('--better-sub', ColorLuminance(changes.selectedColor.newValue, -0.15)); if (changes.selectedColor.newValue == '#ffffff') { document.documentElement.style.setProperty('--better-light', '#b7b7b7'); } else { document.documentElement.style.setProperty('--better-light', ColorLuminance(changes.selectedColor.newValue, 0.99)); } } if (changes?.customshortcuts?.newValue) { if (changes.customshortcuts.oldValue.length > 0) { CreateCustomShortcutDiv(changes.customshortcuts.newValue[(changes.customshortcuts.oldValue.length)]); } else { CreateCustomShortcutDiv(changes.customshortcuts.newValue[0]); } } }) var PageLoaded = false; async function CheckLoadOnPeriods() { if (!PageLoaded) { await delay(1000); var code = document.getElementsByClassName('code')[0]; if (code && !UserInitalCode) { LoadPageElements(); finishLoad(); PageLoaded = true; } if (!code) { CheckLoadOnPeriods(); } } } function RunFunctionOnTrue(storedSetting) { // If the option is 'on', open BetterSEQTA if (typeof storedSetting.onoff == 'undefined') { chrome.runtime.sendMessage({ type: "setDefaultStorage" }); } if (storedSetting.onoff) { console.log("[Even BetterSEQTA] Enabled"); // Injecting CSS File to the webpage to overwrite SEQTA's default CSS var cssFile = chrome.runtime.getURL("inject/injected.css"); var fileref = document.createElement("link"); fileref.setAttribute("rel", "stylesheet"); fileref.setAttribute("type", "text/css"); fileref.setAttribute("href", cssFile); document.head.appendChild(fileref); document.getElementsByTagName("html")[0].appendChild(fileref); document.documentElement.style.setProperty('--better-sub', "#161616"); document.documentElement.style.setProperty('--better-alert-highlight', "#c61851"); if (storedSetting.DarkMode) { document.documentElement.style.setProperty('--background-primary', "#232323"); document.documentElement.style.setProperty('--background-secondary', "#1a1a1a"); document.documentElement.style.setProperty('--text-primary', "white"); } else { try { document.documentElement.style.setProperty('--better-pale', lightenAndPaleColor(storedSetting.selectedColor)); } catch(err) { console.log(err) } document.documentElement.style.setProperty('--background-primary', "#ffffff"); document.documentElement.style.setProperty('--background-secondary', "#e5e7eb"); document.documentElement.style.setProperty('--text-primary', "black"); } document.querySelector('link[rel*="icon"]').href = chrome.runtime.getURL("icons/icon-48.png"); rbg = GetThresholdofHex(storedSetting.selectedColor); if (rbg > 210) { document.documentElement.style.setProperty('--text-color', 'black'); document.documentElement.style.setProperty('--betterseqta-logo', `url(${chrome.runtime.getURL('icons/betterseqta-dark-full.png')})`); } else { document.documentElement.style.setProperty('--text-color', 'white'); document.documentElement.style.setProperty('--betterseqta-logo', `url(${chrome.runtime.getURL('icons/betterseqta-light-full.png')})`); } document.documentElement.style.setProperty('--better-main', storedSetting.selectedColor); // document.documentElement.style.setProperty('--better-sub', ColorLuminance(storedSetting.selectedColor, -0.15)); if (storedSetting.selectedColor == '#ffffff') { document.documentElement.style.setProperty('--better-light', '#b7b7b7'); } else { document.documentElement.style.setProperty('--better-light', ColorLuminance(storedSetting.selectedColor, 0.95)); } ApplyCSSToHiddenMenuItems(); loading(); CheckLoadOnPeriods(); if (!isChrome || isChrome == "undefined") { tryLoad(); } window.addEventListener("load", function () { tryLoad(); }); } else { if (!isChrome || isChrome == "undefined") { waitForElm(".code").then((elm) => { AppendElementsToDisabledPage(); }); } window.addEventListener("load", function () { waitForElm(".code").then((elm) => { AppendElementsToDisabledPage(); }); }); }; } async function CheckForMenuList() { if (!MenuItemMutation) { try { if (document.getElementById('menu').firstChild) { ObserveMenuItemPosition(); MenuItemMutation = true; } } catch (error) { return; } } } var MenuItemMutation = false; var NonSEQTAPage = false; var IsSEQTAPage = false; document.addEventListener( "load", function () { CheckForMenuList(); var weblink = window.location.origin if (document.childNodes[1].textContent?.includes("Copyright (c) SEQTA Software") && document.title.includes("SEQTA Learn") && !IsSEQTAPage) { IsSEQTAPage = true; console.log("[BetterSEQTA] Verified SEQTA Page"); var link = document.createElement("link"); link.href = chrome.runtime.getURL("inject/documentload.css"); link.type = "text/css"; link.rel = "stylesheet"; document.getElementsByTagName("html")[0].appendChild(link); chrome.storage.local.get(null, function (items) { RunFunctionOnTrue(items); }); } if ( !document.childNodes[1].textContent?.includes("SEQTA") && !NonSEQTAPage ) { NonSEQTAPage = true; } }, true ); function RunExtensionSettingsJS() { const whatsnewsettings = document.getElementById('whatsnewsettings'); whatsnewsettings.addEventListener('click', function () { if (!WhatsNewOpen) { WhatsNewOpen = true; OpenWhatsNewPopup(); } }); const onoffselection = document.querySelector("#onoff"); const notificationcollector = document.querySelector("#notification"); const lessonalert = document.querySelector("#lessonalert"); const aboutsection = document.querySelector("#aboutsection"); const shortcutsection = document.querySelector("#shortcutsection"); const miscsection = document.querySelector('#miscsection'); const mainpage = document.querySelector("#mainpage"); const colorpicker = document.querySelector("#colorpicker"); const animatedbk = document.querySelector('#animatedbk'); const customshortcutbutton = document.getElementsByClassName('custom-shortcuts-button')[0]; const customshortcutdiv = document.getElementsByClassName('custom-shortcuts-container')[0]; const customshortcutsubmit = document.getElementsByClassName('custom-shortcuts-submit')[0]; const customshortcutinputname = document.querySelector('#shortcutname'); const customshortcutinputurl = document.querySelector('#shortcuturl'); const shortcutmenuitemselection = document.getElementsByClassName('menushortcut')[0]; const applybutton = document.querySelector('#applychanges') const navbuttons = document.getElementsByClassName("navitem"); const menupages = document.getElementsByClassName("menu-page") const allinputs = document.getElementsByTagName('input'); const menupage = document.querySelector("#menupage"); const shortcutpage = document.querySelector("#shortcutpage"); const miscpage = document.querySelector('#miscpage'); var shortcutbuttons = document.getElementsByClassName("shortcutitem"); var validURL = false; var validName = false; const github = document.getElementById("github"); function openGithub() { chrome.runtime.sendMessage({ type: "githubTab" }); } function resetActive() { for (let i = 0; i < navbuttons.length; i++) { navbuttons[i].classList.remove('activenav'); } for (let i = 0; i < menupages.length; i++) { menupages[i].classList.add('hiddenmenu'); } } function FindSEQTATab() { chrome.runtime.sendMessage({ type: "reloadTabs", }); } /* Store the currently selected settings using chrome.storage.local. */ function storeSettings() { chrome.storage.local.set({ onoff: onoffselection.checked }, function () { FindSEQTATab(); }); } function storeNotificationSettings() { chrome.storage.local.set( { notificationcollector: notificationcollector.checked }); chrome.storage.local.set({ lessonalert: lessonalert.checked }); chrome.storage.local.set({ animatedbk: animatedbk.checked }); } function StoreAllSettings() { chrome.storage.local.get(["shortcuts"], function (result) { var shortcuts = Object.values(result)[0]; for (var i = 0; i < shortcutbuttons.length; i++) { shortcuts[i].enabled = shortcutbuttons[i].checked; } chrome.storage.local.set({ shortcuts: shortcuts }); }); FindSEQTATab(); } /* Update the options UI with the settings values retrieved from storage, or the default settings if the stored settings are empty. */ function updateUI(restoredSettings) { if (typeof restoredSettings.onoff == 'undefined') { chrome.runtime.sendMessage({ type: "setDefaultStorage" }); chrome.storage.local.get(null, function (result) { updateUI(result); }); } else { onoffselection.checked = restoredSettings.onoff; notificationcollector.checked = restoredSettings.notificationcollector; lessonalert.checked = restoredSettings.lessonalert; animatedbk.checked = restoredSettings.animatedbk; chrome.storage.local.get(["shortcuts"], function (result) { var shortcuts = Object.values(result)[0]; for (var i = 0; i < shortcutbuttons.length; i++) { shortcutbuttons[i].checked = shortcuts[i].enabled; } chrome.storage.local.set({ shortcuts: shortcuts }); }); } } function CreateShortcutDiv(name) { div = stringtoHTML(` `).firstChild; shortcutmenuitemselection.append(div); const deletebutton = document.getElementById(`delete-${name}`); deletebutton.addEventListener('click', function () { DeleteCustomShortcut(name); applybutton.style.left = "4px"; }); } function AddCustomShortcuts() { chrome.storage.local.get(["customshortcuts"], function (result) { var customshortcuts = Object.values(result)[0]; for (let i = 0; i < customshortcuts.length; i++) { const element = customshortcuts[i]; CreateShortcutDiv( element.name, ) } }); } function DeleteCustomShortcut(name) { item = document.querySelector(`[data-customshortcut="${name}"]`); item.remove(); chrome.storage.local.get(["customshortcuts"], function (result) { var customshortcuts = Object.values(result)[0]; for (let i = 0; i < customshortcuts.length; i++) { if (customshortcuts[i].name == name) { customshortcuts.splice(i, 1); } } chrome.storage.local.set({ customshortcuts: customshortcuts }); }); } function CustomShortcutMenu() { customshortcutinputname.value = ''; customshortcutinputurl.value = ''; validURL = false; validName = false; customshortcutsubmit.classList.remove("customshortcut-submit-valid"); if (customshortcutdiv.classList.contains('custom-shortcuts-container-shown')) { customshortcutdiv.classList.remove('custom-shortcuts-container-shown') } else { customshortcutdiv.classList.add('custom-shortcuts-container-shown') }; } function CreateCustomShortcut() { const shortcutname = customshortcutinputname.value; var shortcuturl = customshortcutinputurl.value; if (!(shortcuturl.includes('http'))) { shortcuturl = "https://" + shortcuturl; } chrome.storage.local.get(["customshortcuts"], function (result) { var customshortcuts = Object.values(result)[0]; customshortcuts.push({ name: shortcutname, url: shortcuturl, icon: (shortcutname[0]).toUpperCase() }); chrome.storage.local.set({ customshortcuts: customshortcuts }); }); CreateShortcutDiv( shortcutname ); document.getElementsByClassName("shortcut-container")[0].style.display = "block"; } function onError(e) { console.error(e); } chrome.storage.local.get(null, function (result) { document.getElementsByClassName('clr-field')[0].style.color = result.selectedColor; colorpicker.value = result.selectedColor; updateUI(result); }); github.addEventListener("click", openGithub); aboutsection.addEventListener("click", () => { resetActive(); aboutsection.classList.add('activenav'); menupage.classList.remove('hiddenmenu') }); shortcutsection.addEventListener("click", () => { resetActive(); shortcutsection.classList.add('activenav'); shortcutpage.classList.remove('hiddenmenu') }); miscsection.addEventListener("click", () => { resetActive(); miscsection.classList.add('activenav'); miscpage.classList.remove('hiddenmenu') }); customshortcutbutton.addEventListener("click", () => { CustomShortcutMenu(); }) customshortcutsubmit.addEventListener("click", () => { if (validName && validURL) { CreateCustomShortcut(); CustomShortcutMenu() } }); var sameName = false; customshortcutinputname.addEventListener("input", function () { sameName = false; chrome.storage.local.get(["customshortcuts"], function (result) { var customshortcuts = Object.values(result)[0]; for (let i = 0; i < customshortcuts.length; i++) { if (customshortcuts[i].name == customshortcutinputname.value) { sameName = true; } } if (customshortcutinputname.value.length > 0 && customshortcutinputname.value.length < 22 && !sameName) { validName = true; } else { validName = false; } if (validName && validURL) { customshortcutsubmit.classList.add("customshortcut-submit-valid"); } else { customshortcutsubmit.classList.remove("customshortcut-submit-valid"); } }); }); customshortcutinputurl.addEventListener("input", function () { if (customshortcutinputurl.value.length > 0 && customshortcutinputurl.value.includes('.')) { validURL = true; } else { validURL = false; } if (validName && validURL) { customshortcutsubmit.classList.add("customshortcut-submit-valid"); } else { customshortcutsubmit.classList.remove("customshortcut-submit-valid"); } }) AddCustomShortcuts(); onoffselection.addEventListener("change", storeSettings); notificationcollector.addEventListener( "change", storeNotificationSettings ); lessonalert.addEventListener("change", storeNotificationSettings) animatedbk.addEventListener("change", storeNotificationSettings) for (let i = 0; i < allinputs.length; i++) { if (allinputs[i].id != 'colorpicker' && allinputs[i].id != "shortcuturl" && allinputs[i].id != "shortcutname") { allinputs[i].addEventListener("change", () => { applybutton.style.left = "4px" }) } } applybutton.addEventListener('click', () => { StoreAllSettings(); applybutton.style.left = "-150px" }) colorpicker.addEventListener("input", function () { var colorPreview = document.querySelector('#clr-color-preview') if (colorPreview.style.color) { var hex = colorPreview.style.color.split("(")[1].split(")")[0]; hex = hex.split(","); var b = hex.map(function (x) { //For each array element x = parseInt(x).toString(16); //Convert to a base16 string return (x.length == 1) ? "0" + x : x; //Add zero if we get only one character }) b = "#" + b.join(""); chrome.storage.local.set({ selectedColor: b }) } }) } function CallExtensionSettings() { // Injecting CSS File to the webpage to overwrite iFrame default CSS var cssFile = chrome.runtime.getURL("popup/info.css"); var fileref = document.createElement("link"); fileref.setAttribute("rel", "stylesheet"); fileref.setAttribute("type", "text/css"); fileref.setAttribute("href", cssFile); document.head.append(fileref); var jsFile = chrome.runtime.getURL("popup/coloris.js"); var fileref = document.createElement("script"); fileref.setAttribute("src", jsFile); document.head.append(fileref); var cssFile = chrome.runtime.getURL("popup/coloris.css"); var fileref = document.createElement("link"); fileref.setAttribute("rel", "stylesheet"); fileref.setAttribute("type", "text/css"); fileref.setAttribute("href", cssFile); document.head.append(fileref); NextPageImage = chrome.runtime.getURL('popup/page.png') Settings = stringToHTML(``) document.body.append(Settings.firstChild) var container = document.getElementById('container'); var extensionsettings = document.getElementById('ExtensionPopup'); container.onclick = function () { if (!SettingsClicked) { extensionsettings.classList.add('hidden'); } SettingsClicked = false } } function ApplyDraggableFunctions() { var listItens = document.querySelectorAll('.draggable'); [].forEach.call(listItens, function (item) { addEventsDragAndDrop(item); }); } // Code By Webdevtrick ( https://webdevtrick.com ) var remove = document.querySelector('.draggable'); function dragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML); }; function dragEnter(e) { this.classList.add('over'); } function dragLeave(e) { e.stopPropagation(); this.classList.remove('over'); } function dragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; return false; } function dragDrop(e) { if (dragSrcEl != this) { const parentA = this.parentNode; const siblingA = this.nextSibling === dragSrcEl ? this : this.nextSibling; // Move `this` to before the `dragSrcEl` dragSrcEl.parentNode.insertBefore(this, dragSrcEl); // Move `dragSrcEl` to before the sibling of `this` parentA.insertBefore(dragSrcEl, siblingA); // Save position of all menu items children = parentA.childNodes; // console.log(children) listorder = [] for (let i = 0; i < children.length; i++) { const elm = children[i] listorder.push(elm.dataset.key) } chrome.storage.local.set({ menuorder: listorder }) } return false; } function dragEnd(e) { var listItens = document.querySelectorAll('.draggable'); [].forEach.call(listItens, function (item) { item.classList.remove('over'); }); this.style.opacity = '1'; } function addEventsDragAndDrop(el) { el.addEventListener('dragstart', dragStart, false); el.addEventListener('dragenter', dragEnter, false); el.addEventListener('dragover', dragOver, false); el.addEventListener('dragleave', dragLeave, false); el.addEventListener('drop', dragDrop, false); el.addEventListener('dragend', dragEnd, false); } function cloneAttributes(target, source) { [...source.attributes].forEach(attr => { target.setAttribute(attr.nodeName, attr.nodeValue) }) } function OpenMenuOptions() { chrome.storage.local.get(null, function (result) { var container = document.getElementById('container'); var menu = document.getElementById('menu'); if (result.defaultmenuorder.length == '0') { childnodes = menu.firstChild.childNodes; newdefaultmenuorder = []; for (let i = 0; i < childnodes.length; i++) { const element = childnodes[i]; newdefaultmenuorder.push(element.dataset.key) chrome.storage.local.set({ defaultmenuorder: newdefaultmenuorder }) } } childnodes = menu.firstChild.childNodes; if (result.defaultmenuorder.length != childnodes.length) { for (let i = 0; i < childnodes.length; i++) { const element = childnodes[i]; if (!result.defaultmenuorder.indexOf(element.dataset.key)) { newdefaultmenuorder = result.defaultmenuorder; newdefaultmenuorder.push(element.dataset.key); chrome.storage.local.set({ defaultmenuorder: newdefaultmenuorder }) } } } MenuOptionsOpen = true; cover = document.createElement('div'); cover.classList.add('notMenuCover'); menu.style.zIndex = '20'; menu.style.setProperty('--menuHidden', 'flex'); container.append(cover); menusettings = document.createElement('div'); menusettings.classList.add('editmenuoption-container'); defaultbutton = document.createElement('div'); defaultbutton.classList.add('editmenuoption'); defaultbutton.innerText = 'Restore Default'; defaultbutton.id = 'restoredefaultoption'; savebutton = document.createElement('div'); savebutton.classList.add('editmenuoption'); savebutton.innerText = 'Save'; savebutton.id = 'restoredefaultoption'; menusettings.appendChild(defaultbutton); menusettings.appendChild(savebutton); menu.appendChild(menusettings); ListItems = menu.firstChild.childNodes; for (let i = 0; i < ListItems.length; i++) { const element = ListItems[i]; element.classList.add('draggable'); element.setAttribute('draggable', true) if (element.classList.contains('hasChildren')) { element.classList.remove('active'); menu.firstChild.classList.remove('noscroll'); } MenuItemToggle = stringToHTML(`
    `).firstChild element.append(MenuItemToggle); if (!element.dataset.betterseqta) { var a = document.createElement('section'); a.innerHTML = element.innerHTML; cloneAttributes(a, element); menu.firstChild.insertBefore(a, element); element.remove(); } } if (Object.keys(result.menuitems).length == 0) { menubuttons = menu.firstChild.childNodes; var menuItems = {}; for (var i = 0; i < menubuttons.length; i++) { var id = menubuttons[i].dataset.key; const element = {} element.toggle = true; menuItems[id] = element; } chrome.storage.local.set({ menuitems: menuItems }); } var menubuttons = document.getElementsByClassName('menuitem'); chrome.storage.local.get(["menuitems"], function (result) { var menuItems = result.menuitems; buttons = document.getElementsByClassName('menuitem'); for (var i = 0; i < buttons.length; i++) { var id = buttons[i].id; if (menuItems[id]) { buttons[i].checked = menuItems[id].toggle; } if (!menuItems[id]) { buttons[i].checked = true; } } }); ApplyDraggableFunctions(); function StoreMenuSettings() { chrome.storage.local.get(["menuitems"], function (result) { var menuItems = {}; menubuttons = menu.firstChild.childNodes; button = document.getElementsByClassName('menuitem'); for (var i = 0; i < menubuttons.length; i++) { var id = menubuttons[i].dataset.key; const element = {} element.toggle = button[i].checked; menuItems[id] = element; } chrome.storage.local.set({ menuitems: menuItems }); }); } function changeDisplayProperty(element) { if (!element.checked) { element.parentNode.parentNode.style.display = 'var(--menuHidden)'; } if (element.checked) { element.parentNode.parentNode.style.setProperty('display', 'flex', 'important'); } } for (let i = 0; i < menubuttons.length; i++) { const element = menubuttons[i]; element.addEventListener('change', () => { StoreMenuSettings(); changeDisplayProperty(element); }) } function closeAll() { ListItems = menu.firstChild.childNodes; menusettings.remove(); cover.remove(); MenuOptionsOpen = false; menu.style.setProperty('--menuHidden', 'none'); for (let i = 0; i < ListItems.length; i++) { const element = ListItems[i]; element.classList.remove('draggable'); element.setAttribute('draggable', false) if (!element.dataset.betterseqta) { var a = document.createElement('li'); a.innerHTML = element.innerHTML; cloneAttributes(a, element); menu.firstChild.insertBefore(a, element); element.remove(); } } switches = menu.querySelectorAll('.onoffswitch') for (let i = 0; i < switches.length; i++) { switches[i].remove() } StoreMenuSettings(); } cover.addEventListener('click', closeAll) savebutton.addEventListener('click', closeAll) defaultbutton.addEventListener('click', function () { chrome.storage.local.get(null, function (response) { const options = response.defaultmenuorder chrome.storage.local.set({ menuorder: options }) ChangeMenuItemPositions(options); for (let i = 0; i < menubuttons.length; i++) { const element = menubuttons[i]; element.checked = true; element.parentNode.parentNode.style.setProperty('display', 'flex', 'important'); } StoreMenuSettings(); }) }) }) } function ReplaceMenuSVG(element, svg) { item = element.firstChild; item.firstChild.remove(); if (element.dataset.key == "messages") { element.firstChild.innerText = "Direct Messages"; } newsvg = stringToHTML(svg).firstChild; item.insertBefore(newsvg, item.firstChild); } function AddBetterSEQTAElements(toggle) { var code = document.getElementsByClassName("code")[0]; // Replaces students code with the version of BetterSEQTA if (code != null) { if (!code.innerHTML.includes("BetterSEQTA")) { UserInitalCode = code.innerText; code.innerText = `BetterSEQTA v${chrome.runtime.getManifest().version}`; code.setAttribute('data-hover', 'Click for user code'); code.addEventListener('click', function () { var code = document.getElementsByClassName("code")[0]; if (code.innerText.includes('BetterSEQTA')) { code.innerText = UserInitalCode; code.setAttribute('data-hover', 'Click for BetterSEQTA version') } else { code.innerText = `BetterSEQTA v${chrome.runtime.getManifest().version}` code.setAttribute('data-hover', 'Click for user code'); } }) if (toggle) { // Creates Home menu button and appends it as the first child of the list chrome.storage.local.get(['animatedbk'], function (result) { if (result.animatedbk) { CreateBackground(); } else { document.getElementById('container').style.background = "var(--background-secondary)"; } }) var titlebar = document.createElement('div'); titlebar.classList.add("titlebar"); container = document.getElementById('content'); container.append(titlebar); var NewButtonStr = `
  • `; var NewButton = stringToHTML(NewButtonStr); var menu = document.getElementById("menu"); var List = menu.firstChild; List.insertBefore(NewButton.firstChild, List.firstChild); fetch(`${location.origin}/seqta/student/login`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({ "mode": "normal", "query": null, "redirect_url": location.origin }) }) .then((result) => result.json()) .then((response) => { info = response.payload; var titlebar = document.getElementsByClassName('titlebar')[0]; titlebar.append(stringToHTML(`
    `).firstChild) var userinfostr = `

    ${info.userDesc}

    ${UserInitalCode}

    ` var userinfo = stringToHTML(userinfostr).firstChild titlebar.append(userinfo) var logoutbutton = document.getElementsByClassName('logout')[0]; var userInfosvgdiv = document.getElementById('logouttooltip'); userInfosvgdiv.appendChild(logoutbutton); fetch(`${location.origin}/seqta/student/load/message/people`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({ "mode": "student" }) }) .then((result) => result.json()) .then((response) => { students = response.payload; var index = students.findIndex(function (person) { return person.firstname == (info.userDesc.split(' ')[0]) && person.surname == (info.userDesc.split(' ')[1]) }); houseelement = document.getElementsByClassName("userInfohouse")[0]; if (students[index]?.house) { houseelement.style.background = students[index].house_colour; try { colorresult = GetThresholdofHex(students[index]?.house_colour); if (colorresult > 300) { houseelement.style.color = "black"; } else { houseelement.style.color = "white"; } houseelement.innerText = students[index].year + students[index].house; } catch {} } else { houseelement.innerText = students[index].year; } }) }) var NewsButtonStr = `
  • `; var NewsButton = stringToHTML(NewsButtonStr); List.appendChild(NewsButton.firstChild) editmenu = document.createElement('div'); editmenu.classList.add('editmenu'); svg = stringToHTML('') editmenu.append(svg.firstChild) menu.appendChild(editmenu); a = document.createElement('div'); a.classList.add('icon-cover'); a.id = 'icon-cover'; menu.appendChild(a); var editmenu = document.querySelector("#editmenu"); editmenu.addEventListener("click", function () { if (!MenuOptionsOpen) { OpenMenuOptions(); } }) var menuCover = document.querySelector("#icon-cover"); menuCover.addEventListener("click", function () { location.href = '../#?page=/home' SendHomePage(); document.getElementById('menu').firstChild.classList.remove('noscroll'); }) // Creates the home container when the menu button is pressed var homebutton = document.getElementById("homebutton"); homebutton.addEventListener("click", function () { if (!MenuOptionsOpen) { SendHomePage(); } }); // Creates the news container when the menu button is pressed var newsbutton = document.getElementById("newsbutton"); newsbutton.addEventListener("click", function () { if (!MenuOptionsOpen) { SendNewsPage(); } }); } CallExtensionSettings(); RunExtensionSettingsJS(); if (toggle) { // Creates settings and dashboard buttons next to alerts var SettingsButton = stringToHTML( `` ); var ContentDiv = document.getElementById("content"); ContentDiv.append(SettingsButton.firstChild); chrome.storage.local.get(['DarkMode'], function (result) { Darkmode = result.DarkMode; tooltipstring = GetLightDarkModeString(Darkmode); var LightDarkModeButton = stringToHTML(``); ContentDiv.append(LightDarkModeButton.firstChild); LightDarkModeElement = document.getElementById('LightDarkModeButton'); if (Darkmode) { LightDarkModeElement.firstChild.innerHTML = `` document.documentElement.style.removeProperty('--better-pale'); } else { LightDarkModeElement.firstChild.innerHTML = `` try { chrome.storage.local.get(null, function (result) { document.documentElement.style.setProperty('--better-pale', lightenAndPaleColor(result.selectedColor)); // TODO: Make this variable referencable }); } catch(err) { console.log(err) } } darklightText = document.getElementById('darklighttooliptext'); LightDarkModeElement.addEventListener('click', function () { chrome.storage.local.get(['DarkMode'], function (result) { alliframes = document.getElementsByTagName('iframe'); fileref = GetiFrameCSSElement(); if (!result.DarkMode) { document.documentElement.style.setProperty('--background-primary', "#232323"); document.documentElement.style.setProperty('--background-secondary', "#1a1a1a"); document.documentElement.style.setProperty('--text-primary', "white"); document.documentElement.style.removeProperty('--better-pale'); LightDarkModeElement.firstChild.innerHTML = `` for (let i = 0; i < alliframes.length; i++) { const element = alliframes[i]; element.contentDocument.documentElement.childNodes[1].style.color = "white"; element.contentDocument.documentElement.firstChild.appendChild(fileref); } } else { document.documentElement.style.setProperty('--background-primary', "#ffffff"); document.documentElement.style.setProperty('--background-secondary', "#e5e7eb"); document.documentElement.style.setProperty('--text-primary', "black"); try { chrome.storage.local.get(null, function (result) { document.documentElement.style.setProperty('--better-pale', lightenAndPaleColor(result.selectedColor)); // TODO: Make this variable referencable }); } catch(err) { console.log(err) } LightDarkModeElement.firstChild.innerHTML = `` for (let i = 0; i < alliframes.length; i++) { const element = alliframes[i]; element.contentDocument.documentElement.childNodes[1].style.color = "black"; element.contentDocument.documentElement.firstChild.lastChild.remove(); } } tooltipstring = GetLightDarkModeString(!result.DarkMode); darklightText.innerText = tooltipstring; chrome.storage.local.set({ DarkMode: !result.DarkMode }); }); }); }); } else { // Creates settings and dashboard buttons next to alerts var SettingsButton = stringToHTML( `` ); var ContentDiv = document.getElementById("content"); ContentDiv.append(SettingsButton.firstChild); } var AddedSettings = document.getElementById("AddedSettings"); var extensionsettings = document.getElementById("ExtensionPopup") AddedSettings.addEventListener("click", function () { extensionsettings.classList.toggle('hidden'); SettingsClicked = true }); } } } function GetLightDarkModeString(darkmodetoggle) { if (darkmodetoggle) { tooltipstring = "Switch to light theme"; } else { tooltipstring = "Switch to dark theme"; } return tooltipstring; } function ChangeCurrentPage(newpage) { window.location.replace(`${location.origin}"/#?page=/" + ${newpage}`); } function CheckCurrentLesson(lesson, num) { var startTime = lesson.from; var endTime = lesson.until; // Gets current time currentDate = new Date(); // Takes start time of current lesson and makes it into a Date function for comparison startDate = new Date(currentDate.getTime()); startDate.setHours(startTime.split(":")[0]); startDate.setMinutes(startTime.split(":")[1]); startDate.setSeconds("00"); // Takes end time of current lesson and makes it into a Date function for comparison endDate = new Date(currentDate.getTime()); endDate.setHours(endTime.split(":")[0]); endDate.setMinutes(endTime.split(":")[1]); endDate.setSeconds("00"); // Gets the difference between the start time and current time var difference = startDate.getTime() - currentDate.getTime(); // Converts the difference into minutes var minutes = Math.floor(difference / 1000 / 60); // Checks if current time is between the start time and end time of current tested lesson valid = startDate < currentDate && endDate > currentDate; id = lesson.code + num const date = new Date() var elementA = document.getElementById(id); if (!elementA) { clearInterval(LessonInterval); } else { if (currentSelectedDate.toLocaleDateString('en-au') == date.toLocaleDateString('en-au')) { if (valid) { // Apply the activelesson class to increase the box-shadow of current lesson elementA.classList.add("activelesson"); } else { // Removes the activelesson class to ensure only the active lesson have the class if (elementA != null) { elementA.classList.remove("activelesson"); } } } } // If 5 minutes before the start of another lesson: if (minutes == 5) { chrome.storage.local.get('lessonalert', function (result) { if (result.lessonalert) { // Checks if notifications are supported if (!window.Notification) { console.log("Browser does not support notifications."); } else { // check if permission is already granted if (Notification.permission === "granted") { // show notification here } else { // request permission from user Notification.requestPermission() .then(function (p) { if (p === "granted") { // show notification here var notify = new Notification("Next Lesson in 5 Minutes:", { body: "Subject: " + lesson.description + " \nRoom: " + lesson.room + " \nTeacher: " + lesson.staff, }); } else { console.log("User blocked notifications."); } }) .catch(function (err) { console.error(err); }); } } } }); } } function hexToRGB(hex) { try { var r = parseInt(hex.slice(1, 3), 16), g = parseInt(hex.slice(3, 5), 16), b = parseInt(hex.slice(5, 7), 16); return { 'r': r, 'g': g, 'b': b } } catch {} } function GetThresholdofHex(hex) { var rgb = hexToRGB(hex) return Math.sqrt(rgb.r ** 2 + rgb.g ** 2 + rgb.b ** 2) } function CheckCurrentLessonAll(lessons) { // Checks each lesson and sets an interval to run every 60 seconds to continue updating LessonInterval = setInterval( function () { for (i = 0; i < lessons.length; i++) { CheckCurrentLesson(lessons[i], i + 1); } }.bind(lessons), 60000 ); } function MakeLessonDiv(lesson, num) { assessmentstring = "" var lessonstring = `

    ${lesson?.description ?? "Unknown"}

    ${lesson?.staff ?? "Unknown"}

    ${lesson?.room ?? "Unknown"}

    ${lesson?.from ?? "Unknown"} - ${lesson?.until ?? "Unknown"}

    ${lesson?.attendanceTitle ?? "Unknown"}
    ` if (lesson.programmeID != 0) { lessonstring += `
    ${assessmentsicon}
    ${coursesicon}
    ` } if (lesson.assessments.length > 0) { for (let i = 0; i < lesson.assessments.length; i++) { const element = lesson.assessments[i] assessmentstring += `

    ${element.title}

    ` } lessonstring += `
    ${assessmentstring}
    ` } lessonstring += '
    '; var lessondiv = stringToHTML(lessonstring); return lessondiv; } function CheckUnmarkedAttendance(lessonattendance) { if (lessonattendance) { var lesson = lessonattendance.label; } else { var lesson = " "; } return lesson; } function callHomeTimetable(date, change) { // Creates a HTTP Post Request to the SEQTA page for the students timetable var xhr = new XMLHttpRequest(); xhr.open( "POST", `${location.origin}/seqta/student/load/timetable?`, true ); // Sets the response type to json xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); xhr.onreadystatechange = function () { // Once the response is ready if (xhr.readyState === 4) { var serverResponse = JSON.parse(xhr.response); lessonArray = []; var DayContainer = document.getElementById("day-container") // If items in response: if (serverResponse.payload.items.length > 0) { if (!DayContainer.innerText || change) { // console.log(serverResponse.payload.items.length); for (let i = 0; i < serverResponse.payload.items.length; i++) { lessonArray.push(serverResponse.payload.items[i]); } lessonArray.sort(function (a, b) { return a.from.localeCompare(b.from); }); // If items in the response, set each corresponding value into divs // lessonArray = lessonArray.splice(1) GetLessonColours().then((colours) => { subjects = colours; for (let i = 0; i < lessonArray.length; i++) { subjectname = `timetable.subject.colour.${lessonArray[i].code}` subject = subjects.find(element => element.name === subjectname) if (!subject) { lessonArray[i].colour = `--item-colour: #8e8e8e;` } else { lessonArray[i].colour = `--item-colour: ${subject.value};` result = GetThresholdofHex(subject.value); if (result > 300) { lessonArray[i].invert = true; } } // Removes seconds from the start and end times lessonArray[i].from = lessonArray[i].from.substring(0, 5); lessonArray[i].until = lessonArray[i].until.substring(0, 5); // Checks if attendance is unmarked, and sets the string to " ". lessonArray[i].attendanceTitle = CheckUnmarkedAttendance( lessonArray[i].attendance) } // If on home page, apply each lesson to HTML with information in each div DayContainer.innerText = ''; for (let i = 0; i < lessonArray.length; i++) { var div = MakeLessonDiv(lessonArray[i], i + 1); // Append each of the lessons into the day-container if (lessonArray[i].invert) { div.firstChild.classList.add('day-inverted'); } DayContainer.append(div.firstChild); } const today = new Date(); if (currentSelectedDate.getDate() == today.getDate()) { for (i = 0; i < lessonArray.length; i++) { CheckCurrentLesson(lessonArray[i], i + 1); } // For each lesson, check the start and end times CheckCurrentLessonAll(lessonArray); } }) } } else { if (!DayContainer.innerText || change) { DayContainer.innerText = ''; var dummyDay = document.createElement("div"); dummyDay.classList.add("day-empty"); img = document.createElement('img') img.src = chrome.runtime.getURL('icons/betterseqta-light-icon.png') text = document.createElement('p') text.innerText = "No lessons available." dummyDay.append(img); dummyDay.append(text); DayContainer.append(dummyDay); } } } }; xhr.send( JSON.stringify({ // Information sent to SEQTA page as a request with the dates and student number from: date, until: date, // Funny number student: 69, }) ); } function GetUpcomingAssessments() { func = fetch(`${location.origin}/seqta/student/assessment/list/upcoming?`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({ "student": 69 }) }) return func .then((result) => result.json()) .then(response => (response.payload)) } function GetActiveClasses() { func = fetch(`${location.origin}/seqta/student/load/subjects?`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({}) }) return func .then((result) => result.json()) .then(response => (response.payload)) } function comparedate(obj1, obj2) { if (obj1.date < obj2.date) { return -1; } if (obj1.date > obj2.date) { return 1; } return 0; } function CreateElement(type, class_, id, innerText, innerHTML, style) { element = document.createElement(type); if (class_ !== undefined) { element.classList.add(class_); } if (id !== undefined) { element.id = id; } if (innerText !== undefined) { element.innerText = innerText; } if (innerHTML !== undefined) { element.innerHTML = innerHTML; } if (style !== undefined) { element.style = style; } return element } function createAssessmentDateDiv(date, value, datecase = undefined) { var options = { weekday: 'long', month: 'long', day: 'numeric' }; const FormattedDate = new Date(date) const assessments = value.assessments; const container = value.div; DateTitleDiv = document.createElement('div'); DateTitleDiv.classList.add('upcoming-date-title'); if (datecase) { datetitle = document.createElement('h5'); datetitle.classList.add('upcoming-special-day') datetitle.innerText = datecase; DateTitleDiv.append(datetitle); container.setAttribute('data-day', datecase); } DateTitle = document.createElement('h5') DateTitle.innerText = FormattedDate.toLocaleDateString("en-AU", options); DateTitleDiv.append(DateTitle); container.append(DateTitleDiv); assessmentContainer = document.createElement('div') assessmentContainer.classList.add('upcoming-date-assessments'); for (let i = 0; i < assessments.length; i++) { const element = assessments[i]; item = document.createElement('div') item.classList.add('upcoming-assessment'); item.setAttribute('data-subject', element.code); item.id = `assessment${element.id}`; item.style = element.colour; titlediv = document.createElement('div'); titlediv.classList.add('upcoming-subject-title'); titlesvg = stringToHTML(` `).firstChild titlediv.append(titlesvg); detailsdiv = document.createElement('div'); detailsdiv.classList.add('upcoming-details'); detailstitle = document.createElement('h5'); detailstitle.innerText = `${element.subject} assessment`; subject = document.createElement('p'); subject.innerText = element.title; subject.classList.add('upcoming-assessment-title'); subject.onclick = function () { location.href = `../#?page=/assessments/${element.programmeID}:${element.metaclassID}&item=${element.id}` }; detailsdiv.append(detailstitle); detailsdiv.append(subject); item.append(titlediv); item.append(detailsdiv); assessmentContainer.append(item); fetch(`${location.origin}/seqta/student/assessment/submissions/get`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({ "assessment": element.id, "metaclass": element.metaclassID, "student": 69 }) }) .then((result) => result.json()) .then((response) => { if (response.payload.length > 0) { const assessment = document.querySelector(`#assessment${element.id}`); // ticksvg = stringToHTML(``).firstChild // ticksvg.classList.add('upcoming-tick'); // assessment.append(ticksvg); submittedtext = document.createElement('div') submittedtext.classList.add('upcoming-submittedtext'); submittedtext.innerText = "Submitted"; assessment.append(submittedtext); } }) } container.append(assessmentContainer); return container; } function CheckSpecialDay(date1, date2) { if ( date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && (date1.getDate() - 1) === date2.getDate() ) { return "Yesterday"; } if ( date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate() ) { TodayinUpcoming = true; return "Today"; } if ( date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && (date1.getDate() + 1) === date2.getDate() ) { TomorrowinUpcoming = true; return "Tomorrow"; } } function CreateDateCheckedDiv(text, date) { upcomingitemcontainer = document.querySelector('#upcoming-items') container = CreateElement(type = 'div', class_ = 'upcoming-date-container'); datecontainer = CreateElement(type = 'div', class_ = 'upcoming-date-title'); titletext = CreateElement(type = 'h5', class_ = 'upcoming-special-day', id = undefined, innerText = text); titledate = CreateElement(type = 'h5', class_ = undefined, id = undefined, innerText = date); textcontainer = CreateElement('div', 'upcoming-blank') textblank = CreateElement('p'); textblank.innerText = 'No assessments due'; textcontainer.append(textblank) datecontainer.append(titletext); datecontainer.append(titledate); container.append(datecontainer); container.append(textcontainer) upcomingitemcontainer.append(container); } function CreateSubjectFilter(subjectcode, itemcolour, checked) { label = CreateElement('label', "upcoming-checkbox-container") label.innerText = subjectcode; input = CreateElement('input'); input.type = "checkbox"; input.checked = checked; input.id = `filter-${subjectcode}`; label.style = itemcolour; span = CreateElement('span', 'upcoming-checkmark') label.append(input); label.append(span); input.addEventListener('change', function (change) { chrome.storage.local.get(null, function (storage) { filters = storage.subjectfilters; id = change.target.id.split('-')[1] filters[id] = change.target.checked chrome.storage.local.set({ subjectfilters: filters }) }) }) return label } function CreateFilters(subjects) { chrome.storage.local.get(null, function (result) { filteroptions = result.subjectfilters filterdiv = document.querySelector('#upcoming-filters') for (let i = 0; i < subjects.length; i++) { const element = subjects[i]; if (!filteroptions.hasOwnProperty(element.code)) { filteroptions[element.code] = true; chrome.storage.local.set({ subjectfilters: filteroptions }); } elementdiv = CreateSubjectFilter(element.code, element.colour, filteroptions[element.code]) filterdiv.append(elementdiv) } }) } function CreateUpcomingSection(assessments) { upcomingitemcontainer = document.querySelector('#upcoming-items') homecontainer = document.querySelector('#home-container') overdueDates = []; upcomingDates = {}; TodayinUpcoming = false; TomorrowinUpcoming = false; // date = '2022/3/20'; // var Today = new Date(date); var Today = new Date(); // Removes overdue assessments from the upcoming assessments array and pushes to overdue array for (let i = 0; i < assessments.length; i++) { const element = assessments[i]; assessmentdue = new Date(element.due); CheckSpecialDay(Today, assessmentdue) if (assessmentdue < Today) { if (!CheckSpecialDay(Today, assessmentdue)) { overdueDates.push(element); assessments.splice(i, 1); i--; } } } var options = { weekday: 'long', month: 'long', day: 'numeric' }; if (!TodayinUpcoming) { text = Today.toLocaleDateString("en-AU", options); CreateDateCheckedDiv("Today", text); } function addTomorrowinUpcoming() { // var TomorrowDate = new Date(date); var TomorrowDate = new Date(); TomorrowDate.setDate((TomorrowDate.getDate() + 1)) textDate = TomorrowDate.toLocaleDateString("en-AU", options); CreateDateCheckedDiv("Tomorrow", textDate); } if (!TomorrowinUpcoming && !TodayinUpcoming) { addTomorrowinUpcoming(); } GetLessonColours().then((colours) => { subjects = colours; for (let i = 0; i < assessments.length; i++) { subjectname = `timetable.subject.colour.${assessments[i].code}` subject = subjects.find(element => element.name === subjectname) if (!subject) { assessments[i].colour = `--item-colour: #8e8e8e;` } else { assessments[i].colour = `--item-colour: ${subject.value};` result = GetThresholdofHex(subject.value); } } for (let i = 0; i < activeSubjects.length; i++) { const element = activeSubjects[i]; subjectname = `timetable.subject.colour.${element.code}` colour = colours.find(element => element.name === subjectname); if (!colour) { element.colour = `--item-colour: #8e8e8e;` } else { element.colour = `--item-colour: ${colour.value};` result = GetThresholdofHex(colour.value); if (result > 300) { element.invert = true; } } } CreateFilters(activeSubjects); for (let i = 0; i < assessments.length; i++) { const element = assessments[i]; if (!upcomingDates[element.due]) { dateObj = new Object(); dateObj.div = CreateElement(type = 'div', class_ = 'upcoming-date-container') dateObj.assessments = []; upcomingDates[element.due] = dateObj; } assessmentDateDiv = upcomingDates[element.due]; assessmentDateDiv.assessments.push(element); } for (var date in upcomingDates) { assessmentdue = new Date(upcomingDates[date].assessments[0].due); specialcase = CheckSpecialDay(Today, assessmentdue); if (specialcase) { assessmentDate = createAssessmentDateDiv(date, upcomingDates[date], datecase = specialcase); } else { assessmentDate = createAssessmentDateDiv(date, upcomingDates[date]); } if (specialcase === 'Yesterday') { upcomingitemcontainer.insertBefore(assessmentDate, upcomingitemcontainer.firstChild); } else { upcomingitemcontainer.append(assessmentDate) } if (specialcase === 'Today' && !TomorrowinUpcoming) { addTomorrowinUpcoming(); } } chrome.storage.local.get(null, function (result) { FilterUpcomingAssessments(result.subjectfilters); }) }) } function AddPlaceHolderToParent(parent, numberofassessments) { textcontainer = CreateElement('div', 'upcoming-blank') textblank = CreateElement('p', 'upcoming-hiddenassessment'); s = ""; if (numberofassessments > 1) { s = "s"; } textblank.innerText = `${numberofassessments} hidden assessment${s} due`; textcontainer.append(textblank); textcontainer.setAttribute('data-hidden', true); parent.append(textcontainer); } function FilterUpcomingAssessments(subjectoptions) { for (var item in subjectoptions) { subjectdivs = document.querySelectorAll(`[data-subject="${item}"]`); for (let i = 0; i < subjectdivs.length; i++) { const element = subjectdivs[i]; if (!subjectoptions[item]) { element.classList.add('hidden'); } if (subjectoptions[item]) { element.classList.remove('hidden'); } element.parentNode.classList.remove('hidden'); children = element.parentNode.parentNode.children for (let i = 0; i < children.length; i++) { const element = children[i]; if (element.hasAttribute('data-hidden')) { element.remove(); } } if (element.parentNode.children.length == element.parentNode.querySelectorAll(".hidden").length) { if (element.parentNode.querySelectorAll(".hidden").length > 0) { if (!element.parentNode.parentNode.hasAttribute('data-day')) { element.parentNode.parentNode.classList.add('hidden'); } else { AddPlaceHolderToParent(element.parentNode.parentNode, element.parentNode.querySelectorAll(".hidden").length) } } } else { element.parentNode.parentNode.classList.remove('hidden'); } } } } chrome.storage.onChanged.addListener(function (changes) { if (changes.subjectfilters) { FilterUpcomingAssessments(changes.subjectfilters.newValue); } }) function GetLessonColours() { func = fetch(`${location.origin}/seqta/student/load/prefs?`, { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", }, body: JSON.stringify({ "request": "userPrefs", "asArray": true, "user": 69 }) }) return func .then((result) => result.json()) .then(response => (response.payload)) } function CreateCustomShortcutDiv(element) { // Creates the stucture and element information for each seperate shortcut var shortcut = document.createElement("a"); shortcut.setAttribute("href", element.url); shortcut.setAttribute("target", "_blank"); var shortcutdiv = document.createElement("div"); shortcutdiv.classList.add("shortcut"); shortcutdiv.classList.add("customshortcut"); image = stringToHTML(`${element.icon}`).firstChild image.classList.add("shortcuticondiv"); var text = document.createElement("p"); text.textContent = element.name; shortcutdiv.append(image); shortcutdiv.append(text); shortcut.append(shortcutdiv); document.getElementById("shortcuts").append(shortcut); } function AddCustomShortcutsToPage() { chrome.storage.local.get(["customshortcuts"], function (result) { var customshortcuts = Object.values(result)[0]; if (customshortcuts.length > 0) { document.getElementsByClassName("shortcut-container")[0].style.display = "block"; for (let i = 0; i < customshortcuts.length; i++) { const element = customshortcuts[i]; CreateCustomShortcutDiv(element); } } }); } function SendHomePage() { setTimeout(function () { // Sends the html data for the home page console.log("[BetterSEQTA] Started Loading Home Page"); document.title = "Home ― SEQTA Learn"; var element = document.querySelector("[data-key=home]"); // Apply the active class to indicate clicked on home button element.classList.add("active"); // Remove all current elements in the main div to add new elements var main = document.getElementById("main"); main.innerHTML = ""; const titlediv = document.getElementById('title').firstChild; titlediv.innerText = "Home"; document.querySelector('link[rel*="icon"]').href = chrome.runtime.getURL("icons/icon-48.png"); currentSelectedDate = new Date(); // Creates the root of the home page added to the main div var htmlStr = `
    `; var html = stringToHTML(htmlStr); // Appends the html file to main div // Note : firstChild of html is done due to needing to grab the body from the stringToHTML function main.append(html.firstChild); // Gets the current date const date = new Date(); // Formats the current date used send a request for timetable and notices later var TodayFormatted = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); // Replaces actual date with a selected date. Used for testing. // TodayFormatted = "2020-08-31"; // Creates the shortcut container into the home container var ShortcutStr = `
    `; var Shortcut = stringToHTML(ShortcutStr); // Appends the shortcut container into the home container document.getElementById("home-container").append(Shortcut.firstChild); // Creates the container div for the timetable portion of the home page var TimetableStr = `

    Today's Lessons

    `; var Timetable = stringToHTML(TimetableStr); // Appends the timetable container into the home container document.getElementById("home-container").append(Timetable.firstChild); var timetablearrowback = document.getElementById('home-timetable-back') var timetablearrowforward = document.getElementById('home-timetable-forward') function SetTimetableSubtitle() { var homelessonsubtitle = document.getElementById('home-lesson-subtitle'); const date = new Date(); if (date.getYear() == currentSelectedDate.getYear() && date.getMonth() == currentSelectedDate.getMonth()) { if (date.getDate() == currentSelectedDate.getDate()) { // Change text to Today's Lessons homelessonsubtitle.innerText = "Today's Lessons"; } else if ((date.getDate() - 1) == currentSelectedDate.getDate()) { // Change text to Yesterday's Lessons homelessonsubtitle.innerText = "Yesterday's Lessons"; } else if ((date.getDate() + 1) == currentSelectedDate.getDate()) { // Change text to Tomorrow's Lessons homelessonsubtitle.innerText = "Tomorrow's Lessons"; } else { // Change text to date of the day homelessonsubtitle.innerText = `${currentSelectedDate.toLocaleString('en-us', { weekday: 'short' })} ${currentSelectedDate.toLocaleDateString('en-au')}`; } } else { // Change text to date of the day homelessonsubtitle.innerText = `${currentSelectedDate.toLocaleString('en-us', { weekday: 'short' })} ${currentSelectedDate.toLocaleDateString('en-au')}`; } } function changeTimetable(value) { currentSelectedDate.setDate(currentSelectedDate.getDate() + value); FormattedDate = currentSelectedDate.getFullYear() + "-" + (currentSelectedDate.getMonth() + 1) + "-" + currentSelectedDate.getDate(); callHomeTimetable(FormattedDate, true); SetTimetableSubtitle(); } timetablearrowback.addEventListener('click', function () { changeTimetable(-1) }) timetablearrowforward.addEventListener('click', function () { changeTimetable(1) }) assessmentsicon = `` coursesicon = `` function createNewShortcut(link, icon, viewBox, title) { // Creates the stucture and element information for each seperate shortcut var shortcut = document.createElement("a"); shortcut.setAttribute("href", link); shortcut.setAttribute("target", "_blank"); var shortcutdiv = document.createElement("div"); shortcutdiv.classList.add("shortcut"); image = stringToHTML(``).firstChild image.classList.add("shortcuticondiv"); var text = document.createElement("p"); text.textContent = title; shortcutdiv.append(image); shortcutdiv.append(text); shortcut.append(shortcutdiv); document.getElementById("shortcuts").append(shortcut); } // Adds the shortcuts to the shortcut container chrome.storage.local.get(["shortcuts"], function (result) { var shortcuts = Object.values(result)[0]; for (let i = 0; i < shortcuts.length; i++) { if (shortcuts[i].enabled) { Itemname = (shortcuts[i].name).replace(/ /g, '') createNewShortcut( ShortcutLinks[Itemname].link, ShortcutLinks[Itemname].icon, ShortcutLinks[Itemname].viewBox, shortcuts[i].name ); } } AddCustomShortcutsToPage(); // Checks if shortcut container is empty if (document.getElementById("shortcuts").childElementCount == 0) { // If there are no shortcuts, hide the container document.getElementsByClassName("shortcut-container")[0].style.display = "none"; } }); // Creates the upcoming container and appends to the home container var upcomingcontainer = document.createElement('div'); upcomingcontainer.classList.add('upcoming-container'); upcomingcontainer.classList.add('border'); upcomingtitlediv = CreateElement('div', 'upcoming-title'); upcomingtitle = document.createElement('h2'); upcomingtitle.classList.add('home-subtitle'); upcomingtitle.innerText = 'Upcoming Assessments'; upcomingtitlediv.append(upcomingtitle); upcomingfilterdiv = CreateElement('div', 'upcoming-filters', 'upcoming-filters'); upcomingtitlediv.append(upcomingfilterdiv) upcomingcontainer.append(upcomingtitlediv); upcomingitems = document.createElement('div'); upcomingitems.id = 'upcoming-items'; upcomingitems.classList.add('upcoming-items'); upcomingcontainer.append(upcomingitems); document.getElementById("home-container").append(upcomingcontainer); // Creates the notices container into the home container var NoticesStr = `

    Notices

    `; var Notices = stringToHTML(NoticesStr); // Appends the shortcut container into the home container document.getElementById("home-container").append(Notices.firstChild); callHomeTimetable(TodayFormatted); // Sends similar HTTP Post Request for the notices var xhr2 = new XMLHttpRequest(); xhr2.open( "POST", `${location.origin}/seqta/student/load/notices?`, true ); xhr2.setRequestHeader("Content-Type", "application/json; charset=utf-8"); xhr2.onreadystatechange = function () { if (xhr2.readyState === 4) { var NoticesPayload = JSON.parse(xhr2.response); var NoticeContainer = document.getElementById("notice-container"); if (NoticesPayload.payload.length == 0) { if (!NoticeContainer.innerText) { // If no notices: display no notices var dummyNotice = document.createElement("div"); dummyNotice.textContent = "No notices for today."; dummyNotice.classList.add("dummynotice"); NoticeContainer.append(dummyNotice); } } else { if (!NoticeContainer.innerText) { // For each element in the response json: chrome.storage.local.get(["DarkMode"], function (result) { for (let i = 0; i < NoticesPayload.payload.length; i++) { // Create a div, and place information from json response var NewNotice = document.createElement("div"); NewNotice.classList.add("notice"); var title = stringToHTML( `

    ` + NoticesPayload.payload[i].title + `

    ` ); NewNotice.append(title.firstChild); if (NoticesPayload.payload[i].label_title != undefined) { var label = stringToHTML( `
    ` + NoticesPayload.payload[i].label_title + `
    ` ); NewNotice.append(label.firstChild); } var staff = stringToHTML( `
    ` + NoticesPayload.payload[i].staff + `
    ` ); NewNotice.append(staff.firstChild); // Converts the string into HTML var content = stringToHTML(NoticesPayload.payload[i].contents, styles=true); for (let i = 0; i < content.childNodes.length; i++) { NewNotice.append(content.childNodes[i]); } // Gets the colour for the top section of each notice var colour = NoticesPayload.payload[i].colour; if (typeof (colour) == "string") { rgb = GetThresholdofHex(colour); DarkModeResult = result.DarkMode if (rgb < 100 && DarkModeResult) { colour = undefined; } } var colourbar = document.createElement("div"); colourbar.classList.add("colourbar"); colourbar.style.background = "var(--colour)"; NewNotice.style = `--colour: ${colour}`; // Appends the colour bar to the new notice NewNotice.append(colourbar); // Appends the new notice into the notice container NoticeContainer.append(NewNotice); } }); } } } }; // Data sent as the POST request xhr2.send(JSON.stringify({ date: TodayFormatted })); // Sends similar HTTP Post Request for the notices chrome.storage.local.get(null, function (result) { if (result.notificationcollector) { var xhr3 = new XMLHttpRequest(); xhr3.open( "POST", `${location.origin}/seqta/student/heartbeat?`, true ); xhr3.setRequestHeader( "Content-Type", "application/json; charset=utf-8" ); xhr3.onreadystatechange = function () { if (xhr3.readyState === 4) { var Notifications = JSON.parse(xhr3.response); var alertdiv = document.getElementsByClassName( "notifications__bubble___1EkSQ" )[0]; if (typeof alertdiv == 'undefined') { console.log("[BetterSEQTA] No notifications currently") } else { alertdiv.textContent = Notifications.payload.notifications.length; } } }; xhr3.send( JSON.stringify({ timestamp: "1970-01-01 00:00:00.0", hash: "#?page=/home", }) ); } }); GetUpcomingAssessments() .then((assessments) => { GetActiveClasses().then((classes) => { // Gets all subjects for the student for (let i = 0; i < classes.length; i++) { const element = classes[i]; if (element.hasOwnProperty('active')) { // Finds the active class list with the current subjects activeClassList = classes[i] } } activeSubjects = activeClassList.subjects activeSubjectCodes = [] // Gets the code for each of the subjects and puts them in an array for (let i = 0; i < activeSubjects.length; i++) { const element = activeSubjects[i]; activeSubjectCodes.push(element.code) } CurrentAssessments = [] for (let i = 0; i < assessments.length; i++) { const element = assessments[i]; if (activeSubjectCodes.includes(element.code)) { CurrentAssessments.push(element) } } CurrentAssessments.sort(comparedate); CreateUpcomingSection(CurrentAssessments, activeSubjects); // Run function to check if gap between assessments > 7 days? }) }); }, 8); } function SendNewsPage() { setTimeout(function () { // Sends the html data for the home page console.log("[BetterSEQTA] Started Loading News Page"); document.title = "News ― SEQTA Learn"; var element = document.querySelector("[data-key=news]"); // Apply the active class to indicate clicked on home button element.classList.add("active"); // Remove all current elements in the main div to add new elements var main = document.getElementById("main"); main.innerHTML = ""; // Creates the root of the home page added to the main div var htmlStr = `

    Latest Headlines - ABC News

    `; var html = stringToHTML(htmlStr); // Appends the html file to main div // Note : firstChild of html is done due to needing to grab the body from the stringToHTML function main.append(html.firstChild); const titlediv = document.getElementById('title').firstChild; titlediv.innerText = "News"; AppendLoadingSymbol("newsloading", "#news-container"); chrome.runtime.sendMessage({ type: "sendNews" }, function (response) { newsarticles = response.news.articles; var newscontainer = document.querySelector('#news-container'); document.getElementById('newsloading').remove(); for (let i = 0; i < newsarticles.length; i++) { newsarticle = document.createElement('a'); newsarticle.classList.add('NewsArticle'); newsarticle.href = newsarticles[i].url; newsarticle.target = '_blank'; articleimage = document.createElement('div'); articleimage.classList.add('articleimage') if (newsarticles[i].urlToImage == 'null') { articleimage.style.backgroundImage = `url(${chrome.runtime.getURL("icons/betterseqta-light-outline.png")})`; articleimage.style.width = '20%' articleimage.style.margin = '0 7.5%'; } else { articleimage.style.backgroundImage = `url(${newsarticles[i].urlToImage})`; } articletext = document.createElement('div'); articletext.classList.add('ArticleText') title = document.createElement('a'); title.innerText = newsarticles[i].title; title.href = newsarticles[i].url; title.target = '_blank'; description = document.createElement('p'); description.innerHTML = newsarticles[i].description; articletext.append(title); articletext.append(description); newsarticle.append(articleimage); newsarticle.append(articletext); newscontainer.append(newsarticle); } }); }, 8); } function EnabledDisabledToBool(input) { if (input == "enabled") { return true; } if (input == "disabled") { return false; } } function LoadInit() { console.log("[BetterSEQTA] Started Init"); chrome.storage.local.get(null, function (result) { if (result.onoff) { SendHomePage(); } }); }