K12 Dark Mode Remastered

THIS SCRIPT IS A WORK IN PROGRESS. Many features/looks are subject to change. Allows for full customization of the K12 Pages, including custom background images, fonts, styles, and more! Press TAB to open the customization menu.

  1. // ==UserScript==
  2. // @name K12 Dark Mode Remastered
  3. // @namespace https://greasyfork.org/en/scripts/438133-k12-dark-mode-remastered
  4. // @version 3.21
  5. // @description THIS SCRIPT IS A WORK IN PROGRESS. Many features/looks are subject to change. Allows for full customization of the K12 Pages, including custom background images, fonts, styles, and more! Press TAB to open the customization menu.
  6. // @author Chase Davis
  7. // @match *://*.k12.com/*
  8. // @match *://*.brightspace.com/*
  9. // @match *://*.api.brightspace.com/*
  10. // @icon https://www.google.com/s2/favicons?domain=k12.com
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @run-at document.start
  14. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19. jQuery(function($) {
  20. let first = GM_getValue('firsttime?');// Get the values from storage
  21. //let first = undefined;
  22. let pst = GM_getValue('preset');
  23. let bg = GM_getValue('background');
  24. let bg2 = GM_getValue('background2');
  25. let acc = GM_getValue('accent');
  26. let txt = GM_getValue('textcolor');
  27. let img = GM_getValue('image');
  28. let fnt = GM_getValue('font');
  29. let inv = GM_getValue('invertImages');
  30. //let customFont = GM_getValue('useCustomFont');
  31. let invCheck = ''
  32. //let customFontCheck = ''
  33.  
  34. var i; // Define some vars to be used later on
  35. var ch;
  36. var fon
  37. var invertAmt;
  38.  
  39. // Log values for debug purposes
  40. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nInvert Images: '+inv)
  41.  
  42.  
  43.  
  44. // Create menu HTML
  45. let preselect = ["","","","","",""]; // A very odd way to preselect the dropdown
  46. preselect[pst] = " selected "
  47. //let fontselect = ["","","","",""]
  48. //fontselect[fnt] = " selected "
  49. if (inv) { // Preselect the Invert Images checkbox
  50. let invCheck = ' checked ';
  51. }
  52.  
  53.  
  54. // Define the HTML to be injected into the site
  55. let menu = `
  56. <div class="menuItem" id="menuBlock" style="display: none; width: 100%; height: 100%; background-color: #00000090 !important; z-index: 9998;">
  57.  
  58.  
  59.  
  60. <div class="menuItem" id="menuMain" style="overflow: auto; text-align: center; padding: 16px; border-radius: 16px; left: 5%; top: 5%; display: none; width: 90%; height: 90%; z-index: 9999;">
  61. <h1 class="menuText" style="margin: auto; padding: 10px; width: fit-content; border-radius: 8px;">K12 Dark Mode Customization Menu</h1><hr><br>
  62.  
  63.  
  64.  
  65. <div id="mainWrapper" style="background-color: #00000000 !important; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; align-items: flex-start;">
  66.  
  67. <div class="menuItem" id="themeSelect" style="text-align: center; padding: 8px; border-radius: 8px; display: none; width: 20%; height: fit-content; position: relative;">
  68. <h2 class="menuText">Theme</h2><hr>
  69. Preset:
  70. <select id="themebox" class="menuDialog" style="width: 100%; height: 20%;">
  71. <option value="0"`+preselect[0]+`>Dark</option>
  72. <option value="1"`+preselect[1]+`>Extra Dark</option>
  73. <option value="2"`+preselect[2]+`>Light</option>
  74. <option value="3"`+preselect[3]+`>True Blue</option>
  75. <option value="4"`+preselect[4]+`>Contrast</option>
  76. <option value="5"`+preselect[5]+`>Custom</option>
  77. </select><hr>
  78. Background Image:
  79. <input id="img" class="menuDialog" style="width: 100%" value=`+img+`></input><br>
  80. Background:
  81. <input id="bg" class="menuDialog" style="width: 100%" value=`+bg+`></input><br>
  82. Secondary:
  83. <input id="bg2" class="menuDialog" style="width: 100%" value=`+bg2+`></input><br>
  84. Accent:
  85. <input id="acc" class="menuDialog" style="width: 100%" value=`+acc+`></input><br>
  86. Text Color:
  87. <input id="txt" class="menuDialog" style="width: 100%" value=`+txt+`></input><br>
  88. </div>
  89.  
  90.  
  91.  
  92. <div id="middleBox">
  93. </div>
  94.  
  95.  
  96.  
  97. <div class="menuItem" id="options" style="text-align: center; padding: 8px; border-radius: 8px; display: inline-block; width: 20%; height: fit-content; position: relative;">
  98. <h2 class="menuText">Options</h2><hr>
  99.  
  100. Invert Images
  101. <input checked=`+inv+` type="checkbox" id="invert" value=`+inv+`></input><br>
  102.  
  103.  
  104.  
  105. <hr><a href="https://discord.gg/xVsjWrK5cF" id="discord"
  106. <div class="menuItem" id="discordPromo" style="margin: auto; text-align: center; padding: 8px; border-radius: 8px; display: inline-block; max-width: 90%; width: 90%; height: fit-content; position: relative; background-position: center center; background-size: cover; background-image: url(https://i.ibb.co/cYzspHH/backdrop.png);">
  107. <div id="filter" style="padding: 3px; max-width: 95%; width: 95%; height: 100%; border-radius: 8px;">
  108. <b style="background-color: #00000000 !important;">Join our Discord & chat with other students from IDVA!</b>
  109. </div>
  110. </div></a>
  111.  
  112. </div>
  113.  
  114.  
  115.  
  116. </div>
  117. </div>
  118. `;
  119.  
  120.  
  121.  
  122. // Define Functions
  123. function setup() {// This will only be run once, it defines all the variables so the first time you load it the colors aren't 'undefined'
  124.  
  125. alert('Welcome to K12 Dark Mode! Press Tab to bring up the new menu! \n\nRefresh the page to activate the script.');
  126. GM_setValue('firsttime?',false);// Set the firsttime variable to false, so this doesnt execute again accidentally
  127.  
  128. let pst = 0 // Set all the values to default
  129. GM_setValue('preset',pst);
  130. let bg = '#202020';
  131. GM_setValue('background',bg);
  132. let bg2 = '#404040';
  133. GM_setValue('background2',bg2);
  134. let acc = '#004674';
  135. GM_setValue('accent',acc);
  136. let txt = '#b0b0b0';
  137. GM_setValue('textcolor',txt);
  138. let img = 'https://parade.com/wp-content/uploads/2021/11/new-year-wishes.jpg';
  139. GM_setValue('image',img);
  140. let fnt = 1;
  141. GM_setValue('font',fnt);
  142. let inv = 1
  143. GM_setValue('invertImages',inv);
  144. let customFont = 0
  145. GM_setValue('useCustomFont',customFont);
  146.  
  147. };
  148.  
  149. function makeCSS(background, background2, accent, textcolor, image, font, invert) {// Define the CSS for injection
  150. console.log('Updated CSS')
  151. let css = `
  152. <style id="K12DMR_CSS">
  153.  
  154. *:not(span) {
  155. background-color: `+background+` !important;
  156. `+/*fon+*/`
  157. color: `+textcolor+` !important;
  158. transition: background-color 1s ease;
  159. }
  160.  
  161. th {
  162. background-color: `+background+` !important;
  163. }
  164.  
  165. @keyframes fadeIn {
  166. 0% {opacity:0;}
  167. 100% {opacity:1;}
  168. }
  169.  
  170. .menuItem {
  171. animation: fadeIn 1s;
  172. font-family: `+font+` !important;
  173. color: `+textcolor+` !important;
  174. position: fixed;
  175. transition: background-color 1s ease;
  176. background-color: `+background2+` !important;
  177. box-shadow: 3px 3px 10px 1px #000000;
  178. }
  179.  
  180. .menuDialog {
  181. background-color: `+background+` !important;
  182. display: block
  183. }
  184.  
  185. .menuText {
  186. font-family: `+font+` !important;
  187. color: `+textcolor+` !important;
  188. background-color: `+background2+` !important;
  189. box-shadow: inset 2px 2px 5px 1px #000000;
  190. border-radius: 8px;
  191. padding: 3px;
  192. }
  193.  
  194. #menuMain {
  195. background: linear-gradient(180deg, `+background+`, `+accent+`)
  196. }
  197.  
  198. #filter {
  199. background-color: `+background+`b0 !important;
  200. }
  201.  
  202. #discordPromo {
  203. box-shadow: inset 0px 0px 8px 5px `+background2+`;
  204. }
  205.  
  206. .spacer {
  207. background-color: `+background+` !important;
  208. padding: 6px;
  209. border-radius: 8px;
  210. }
  211.  
  212. #side-nav {
  213. background: linear-gradient(180deg, `+background+` 10%, `+accent+`)
  214. }
  215.  
  216. #side-nav * {
  217. background-color: #00000000 !important;
  218. }
  219.  
  220. #content-area {
  221. background-color: #00000000 !important;
  222. }
  223.  
  224. #wallpaper {
  225. background: url(`+image+`) !important;
  226. background-size: cover !important;
  227. background-position: center center !important;
  228. z-index: 0 !important;
  229. }
  230.  
  231. .d2l-image-banner-overlay {
  232. background-image: url(`+image+`) !important;
  233. background-size: cover !important;
  234. background-position: center center !important;
  235. }
  236.  
  237. #background-chooser {
  238. display: none !important;
  239. }
  240.  
  241. .credit-photo {
  242. display: none !important;
  243. }
  244.  
  245. .cards-container {
  246. background-color: #00000000 !important;
  247. }
  248.  
  249. .grid-sizer {
  250. background-color: #00000000 !important;
  251. }
  252.  
  253. .item {
  254. background: linear-gradient(180deg, `+background+`, `+background2+`);
  255. border-radius: 12px;
  256. border: 4px solid `+accent+`;
  257. }
  258.  
  259. .item * {
  260. background-color: #00000000 !important;
  261. }
  262.  
  263. .card-info {
  264. background-color: `+background2+` !important;
  265. }
  266.  
  267.  
  268. .grade {
  269. background-color: `+background+` !important;
  270. }
  271.  
  272. .component-group {
  273. background-color: #00000000 !important;
  274. }
  275.  
  276. .widget-panel {
  277. border: 4px solid `+accent+` !important;
  278. }
  279.  
  280. #components {
  281. background-color: #00000000 !important;
  282. }
  283.  
  284. [id*="sidebar-nav-item"] {
  285. border-top: 1px solid `+accent+` !important;
  286. border-bottom: 1px solid `+accent+` !important;
  287. }
  288.  
  289. .goto {
  290. background-color: `+accent+` !important;
  291. }
  292.  
  293. .d2l-navigation-s-main-wrapper * {
  294. background-color: `+accent+` !important;
  295. }
  296.  
  297. .d2l-navigation-s-main-wrapper {
  298. background-color: `+accent+` !important;
  299. }
  300.  
  301. .d2l-branding-navigation-background-color {
  302. background-color: `+accent+` !important;
  303. }
  304.  
  305. .d2l-widget {
  306. background-color: `+background2+` !important;
  307. }
  308.  
  309. .d2l-widget * {
  310. background-color: `+background2+` !important;
  311. }
  312.  
  313. .d2l-collapsepane-header {
  314. background: none !important;
  315. }
  316.  
  317. .d2l-box {
  318. background: none !important;
  319. }
  320.  
  321. .d2l-twopanelselector-side {
  322. background: linear-gradient(315deg, `+background+`, `+accent+`) !important;
  323. }
  324.  
  325. .d2l-twopanelselector-side * {
  326. background: none !important;
  327. }
  328.  
  329. .d2l-input-focus {
  330. background: `+background2+` !important;
  331. }
  332.  
  333. .d2l-twopanelselector-main {
  334. background: `+background2+` !important;
  335. }
  336.  
  337. .d2l-twopanelselector-main * {
  338. background: none !important;
  339. }
  340.  
  341. img {
  342. filter: invert(`+invert+`) !important;
  343. }
  344.  
  345. .form-container {
  346. background: `+background2+` !important;
  347. }
  348.  
  349. .form-container * {
  350. background: none !important;
  351. }
  352.  
  353. .btn {
  354. background: linear-gradient(315deg, `+background+`, `+accent+`) !important;
  355. border: 4px solid `+accent+` !important;
  356. }
  357.  
  358. .form-control {
  359. background-color: `+background+` !important;
  360. border: 4px solid `+accent+` !important;
  361. }
  362.  
  363. #logo-container * {
  364. filter: invert(0) !important;
  365. }
  366.  
  367. .icon {
  368. background-color: #00000000 !important;
  369. color: `+textcolor+` !important;
  370. }
  371.  
  372. .link-text {
  373. background-color: #00000000 !important;
  374. color: `+textcolor+` !important;
  375. }
  376.  
  377. a:not(#discord) {
  378. background: linear-gradient(315deg, `+background+`, `+accent+`) !important;
  379. border: 2px solid `+accent+` !important;
  380. border-radius: 8px;
  381. padding: 2px;
  382. }
  383.  
  384. a * {
  385. background: none !important;
  386. }
  387.  
  388. td {
  389. background: url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)
  390. }
  391.  
  392. th {
  393. background: url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)
  394. }
  395.  
  396. </style>
  397. `;
  398.  
  399. if (document.getElementById('K12DMR_CSS') == undefined) {// If the css doesnt exist in the page yet
  400. $('head').append(css);// Inject css
  401. } else {
  402. $('#K12DMR_CSS').remove();// Otherwise remove it
  403. $('head').append(css);// And add it again, so the colors are up-to-date
  404. }
  405.  
  406. /*try {
  407. let divs = document.querySelectorAll('td');
  408.  
  409. for (i=0; i<divs.length; i++) {
  410. divs[i].style.background = "url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)";
  411. }
  412. } catch(err){console.log(err)}*/
  413.  
  414. };
  415.  
  416. function toggleMenu() {
  417. if (document.getElementById('menuBlock').style.display == 'none') {//If the menu is currently hidden
  418. console.log('toggle menu on');// Log the menu toggle, for debugging
  419. let divs = $('.menuItem')// Get all elements that belong to the menu
  420. for (i = 0; i<divs.length; i++) {// For each of those elements
  421. divs[i].style.display = 'block';// Turn its display on to make it visible
  422. }
  423. } else {// If the menu is currently on,
  424. console.log('toggle menu off');// Log the menu toggle, for debugging
  425. let divs = $('.menuItem');// Get all elements that belong to the menu
  426. for (i = 0; i<divs.length; i++) {// For each of those elements
  427. divs[i].style.display = 'none';// Turn its display off to make it invisible
  428. }
  429. }
  430. };
  431.  
  432. function onKeyDown(evt) { // When a key, any key is pressed
  433. if (evt.keyCode == 9) { // Every key has a key code, the code for Tab is 9
  434. toggleMenu(); // Toggle the menu
  435. }
  436. if (evt.keyCode == 81) { // This is the keycode for Q, dont press this, it triggers the setup. This will eventually be removed.
  437. setup();
  438. console.log('setup triggered')
  439. }
  440. }
  441. document.addEventListener('keydown', onKeyDown, true); // This adds the sensor for detecting key presses
  442.  
  443.  
  444.  
  445. // Now do the things
  446. $('body').append(menu); // Inject the menu HTML
  447. if (first == undefined) {setup()} else { // If this is the first time being used, trigger setup
  448. makeCSS(bg, bg2, acc, txt, img, fnt);// Otherwise inject CSS like usual
  449. };
  450.  
  451.  
  452.  
  453. // Menu sensory
  454.  
  455. // Theme selector
  456. document.querySelector('#themebox').addEventListener('change', (event) => {// When preset theme changes
  457. let ch = document.querySelector('#themebox').value // Get the value of selector
  458. ch = parseInt(ch) // Turn it into a number
  459.  
  460. let bgs = ["#202020", "#000000", "#fdfdfd", "#303940", "#000000", bg];// Colors for presets
  461. let bg2s = ["#404040", "#202020", "#d0d0d0", "#505960", "#404040", bg2];
  462. let accs = ["#004674", "#004674", "#83bade", "#004684", "#606060", acc];
  463. let txts = ["#b0b0b0", "#c0c0c0", "#404040", "#a0a0b0", "#cfcf2a", txt];
  464.  
  465. pst = ch // Set all the colors to their corresponding theme
  466. GM_setValue('preset',pst);
  467. bg = bgs[ch]
  468. GM_setValue('background',bg);
  469. bg2 = bg2s[ch]
  470. GM_setValue('background2',bg2);
  471. acc = accs[ch]
  472. GM_setValue('accent',acc);
  473. txt = txts[ch]
  474. GM_setValue('textcolor',txt);
  475. makeCSS(bg, bg2, acc, txt, img, fnt);
  476.  
  477. document.querySelector('#bg').value = bg;// Change all the input boxes to said color
  478. document.querySelector('#bg2').value = bg2;
  479. document.querySelector('#acc').value = acc;
  480. document.querySelector('#txt').value = txt;
  481.  
  482. console.log('Theme changed to '+['Dark','Extra Dark','Light','True Blue','Contrast','Custom'][ch])// Log the theme change
  483. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  484. // And log the rest of the values
  485.  
  486. });
  487.  
  488. // Font selector, removed for now.
  489. /*document.querySelector('#fnt').addEventListener('change', (event) => {
  490. let ch = document.querySelector('#fnt').value
  491. ch = parseInt(ch)
  492.  
  493. let fnts = ["arial","monospace","cursive","fantasy","'ng-icons'"];// Fonts
  494.  
  495. fnt = fnts[ch]
  496. GM_setValue('font',fnt);
  497. makeCSS(bg, bg2, acc, txt, img, fnt);
  498. console.log('Font changed to '+["arial","monospace","cursive","fantasy","'ng-icons'"][ch])
  499. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  500.  
  501. });*/
  502.  
  503. // Background Image input
  504. document.querySelector('#img').addEventListener('change', (event) => { // When the text changed
  505. let val = document.querySelector('#img').value // Get its value
  506.  
  507. img = val // Set the img variable to its value
  508. GM_setValue('image',img); // Store the value
  509. makeCSS(bg, bg2, acc, txt, img, fnt); // And update the CSS
  510. console.log('Background Image changed to '+val)
  511. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  512.  
  513. });
  514.  
  515. // Background input
  516. document.querySelector('#bg').addEventListener('change', (event) => {// Same story for the rest of these.
  517. let val = document.querySelector('#bg').value
  518.  
  519. bg = val
  520. GM_setValue('background',bg);
  521. makeCSS(bg, bg2, acc, txt, img, fnt);
  522. console.log('Background changed to '+val)
  523. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  524.  
  525. });
  526.  
  527. // Background2 input
  528. document.querySelector('#bg2').addEventListener('change', (event) => {
  529. let val = document.querySelector('#bg2').value
  530.  
  531. bg2 = val
  532. GM_setValue('background2',bg2);
  533. makeCSS(bg, bg2, acc, txt, img, fnt);
  534. console.log('Background 2 changed to '+val)
  535. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  536.  
  537. });
  538.  
  539. // Accent input
  540. document.querySelector('#acc').addEventListener('change', (event) => {
  541. let val = document.querySelector('#acc').value
  542.  
  543. acc = val
  544. GM_setValue('accent',acc);
  545. makeCSS(bg, bg2, acc, txt, img, fnt);
  546. console.log('Accent changed to '+val)
  547. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  548.  
  549. });
  550.  
  551. // Text Color input
  552. document.querySelector('#txt').addEventListener('change', (event) => {
  553. let val = document.querySelector('#txt').value
  554.  
  555. txt = val
  556. GM_setValue('textcolor',txt);
  557. makeCSS(bg, bg2, acc, txt, img, fnt);
  558. console.log('Text Color changed to '+val)
  559. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
  560.  
  561. });
  562.  
  563. // Invert Images checkbox
  564. document.querySelector('#invert').addEventListener('change', (event) => {
  565. let val = document.querySelector('#invert').checked
  566.  
  567. if (val) { inv = 1 } else { inv = 0};// With this one val is a boolean, so if val is true, set inv to 1, otherwise 0.
  568. GM_setValue('invertImages',inv);
  569. makeCSS(bg, bg2, acc, txt, img, fnt, inv);
  570. console.log('Invert Images changed to '+inv)
  571. console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nInvert: '+inv)
  572.  
  573. });
  574.  
  575.  
  576.  
  577. })})();