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.

目前為 2022-01-11 提交的版本,檢視 最新版本

// ==UserScript==
// @name         K12 Dark Mode Remastered
// @namespace    https://greasyfork.org/en/scripts/438133-k12-dark-mode-remastered
// @version      3.2
// @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.
// @author       Chase Davis
// @match        *://*.k12.com/*
// @match        *://*.brightspace.com/*
// @match        *://*.api.brightspace.com/*
// @icon         https://www.google.com/s2/favicons?domain=k12.com
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document.start
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js
// ==/UserScript==

(function() {
    'use strict';
jQuery(function($) {
let first = GM_getValue('firsttime?');// Get the values from storage
//let first = undefined;
let pst = GM_getValue('preset');
let bg = GM_getValue('background');
let bg2 = GM_getValue('background2');
let acc = GM_getValue('accent');
let txt = GM_getValue('textcolor');
let img = GM_getValue('image');
let fnt = GM_getValue('font');
let inv = GM_getValue('invertImages');
//let customFont = GM_getValue('useCustomFont');
let invCheck = ''
//let customFontCheck = ''

var i; // Define some vars to be used later on
var ch;
var fon
var invertAmt;

// Log values for debug purposes
console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nInvert Images: '+inv)



// Create menu HTML
let preselect = ["","","","","",""]; // A very odd way to preselect the dropdown
preselect[pst] = " selected "
//let fontselect = ["","","","",""]
//fontselect[fnt] = " selected "
if (inv) { // Preselect the Invert Images checkbox
    let invCheck = ' checked ';
}


// Define the HTML to be injected into the site
let menu = `
<div class="menuItem" id="menuBlock" style="display: none; width: 100%; height: 100%; background-color: #00000090 !important; z-index: 9998;">



    <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;">
        <h1 class="menuText" style="margin: auto; padding: 10px; width: fit-content; border-radius: 8px;">K12 Dark Mode Customization Menu</h1><hr><br>



    <div id="mainWrapper" style="background-color: #00000000 !important; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; align-items: flex-start;">

        <div class="menuItem" id="themeSelect" style="text-align: center; padding: 8px; border-radius: 8px; display: none; width: 20%; height: fit-content; position: relative;">
            <h2 class="menuText">Theme</h2><hr>
                Preset:
                <select id="themebox" class="menuDialog" style="width: 100%; height: 20%;">
                    <option value="0"`+preselect[0]+`>Dark</option>
                    <option value="1"`+preselect[1]+`>Extra Dark</option>
                    <option value="2"`+preselect[2]+`>Light</option>
                    <option value="3"`+preselect[3]+`>True Blue</option>
                    <option value="4"`+preselect[4]+`>Contrast</option>
                    <option value="5"`+preselect[5]+`>Custom</option>
                </select><hr>
                Background Image:
                <input id="img" class="menuDialog" style="width: 100%" value=`+img+`></input><br>
                Background:
                <input id="bg" class="menuDialog" style="width: 100%" value=`+bg+`></input><br>
                Secondary:
                <input id="bg2" class="menuDialog" style="width: 100%" value=`+bg2+`></input><br>
                Accent:
                <input id="acc" class="menuDialog" style="width: 100%" value=`+acc+`></input><br>
                Text Color:
                <input id="txt" class="menuDialog" style="width: 100%" value=`+txt+`></input><br>
            </div>



        <div id="middleBox">
        </div>



        <div class="menuItem" id="options" style="text-align: center; padding: 8px; border-radius: 8px; display: inline-block; width: 20%; height: fit-content; position: relative;">
            <h2 class="menuText">Options</h2><hr>

                Invert Images
                <input checked=`+inv+` type="checkbox" id="invert" value=`+inv+`></input><br>



            <hr><a href="https://discord.gg/xVsjWrK5cF" id="discord"
                <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);">
                <div id="filter" style="padding: 3px; max-width: 95%; width: 95%; height: 100%; border-radius: 8px;">
                    <b style="background-color: #00000000 !important;">Join our Discord & chat with other students from IDVA!</b>
                </div>
            </div></a>

        </div>



    </div>
</div>
`;



// Define Functions
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'

        alert('Welcome to K12 Dark Mode! Press Tab to bring up the new menu! \n\nRefresh the page to activate the script.');
        GM_setValue('firsttime?',false);// Set the firsttime variable to false, so this doesnt execute again accidentally

        let pst = 0 // Set all the values to default
        GM_setValue('preset',pst);
        let bg = '#202020';
        GM_setValue('background',bg);
        let bg2 = '#404040';
        GM_setValue('background2',bg2);
        let acc = '#004674';
        GM_setValue('accent',acc);
        let txt = '#b0b0b0';
        GM_setValue('textcolor',txt);
        let img = 'https://parade.com/wp-content/uploads/2021/11/new-year-wishes.jpg';
        GM_setValue('image',img);
        let fnt = 1;
        GM_setValue('font',fnt);
        let inv = 1
        GM_setValue('invertImages',inv);
        let customFont = 0
        GM_setValue('useCustomFont',customFont);

};

function makeCSS(background, background2, accent, textcolor, image, font, invert) {// Define the CSS for injection
    console.log('Updated CSS')
    let css = `
    <style id="K12DMR_CSS">

        *:not(span) {
            background-color: `+background+` !important;
            `+/*fon+*/`
            color: `+textcolor+` !important;
            transition: background-color 1s ease;
        }

        th {
            background-color: `+background+` !important;
        }

        @keyframes fadeIn {
            0% {opacity:0;}
            100% {opacity:1;}
        }

        .menuItem {
            animation: fadeIn 1s;
            font-family: `+font+` !important;
            color: `+textcolor+` !important;
            position: fixed;
            transition: background-color 1s ease;
            background-color: `+background2+` !important;
            box-shadow: 3px 3px 10px 1px #000000;
        }

        .menuDialog {
            background-color: `+background+` !important;
            display: block
        }

        .menuText {
            font-family: `+font+` !important;
            color: `+textcolor+` !important;
            background-color: `+background2+` !important;
            box-shadow: inset 2px 2px 5px 1px #000000;
            border-radius: 8px;
            padding: 3px;
        }

        #menuMain {
            background: linear-gradient(180deg, `+background+`, `+accent+`)
        }

        #filter {
            background-color: `+background+`b0 !important;
        }

        #discordPromo {
            box-shadow: inset 0px 0px 8px 5px `+background2+`;
        }

        .spacer {
            background-color: `+background+` !important;
            padding: 6px;
            border-radius: 8px;
        }

        #side-nav {
            background: linear-gradient(180deg, `+background+` 10%, `+accent+`)
        }

        #side-nav * {
            background-color: #00000000 !important;
        }

        #content-area {
            background-color: #00000000 !important;
        }

        #wallpaper {
            background: url(`+image+`) !important;
            background-size: cover !important;
            background-position: center center !important;
            z-index: 0 !important;
        }

        .d2l-image-banner-overlay {
            background-image: url(`+image+`) !important;
            background-size: cover !important;
            background-position: center center !important;
        }

        #background-chooser {
            display: none !important;
        }

        .credit-photo {
            display: none !important;
        }

        .cards-container {
            background-color: #00000000 !important;
        }

        .grid-sizer {
            background-color: #00000000 !important;
        }

        .item {
            background: linear-gradient(180deg, `+background+`, `+background2+`);
            border-radius: 12px;
            border: 4px solid `+accent+`;
        }

        .item * {
            background-color: #00000000 !important;
        }

        .card-info {
            background-color: `+background2+` !important;
        }


        .grade {
            background-color: `+background+` !important;
        }

        .component-group {
            background-color: #00000000 !important;
        }

        .widget-panel {
            border: 4px solid `+accent+` !important;
        }

        #components {
            background-color: #00000000 !important;
        }

        [id*="sidebar-nav-item"] {
            border-top: 1px solid `+accent+` !important;
            border-bottom: 1px solid `+accent+` !important;
        }

        .goto {
            background-color: `+accent+` !important;
        }

        .d2l-navigation-s-main-wrapper * {
            background-color: `+accent+` !important;
        }

        .d2l-navigation-s-main-wrapper {
            background-color: `+accent+` !important;
        }

        .d2l-branding-navigation-background-color {
            background-color: `+accent+` !important;
        }

        .d2l-widget {
            background-color: `+background2+` !important;
        }

        .d2l-widget * {
            background-color: `+background2+` !important;
        }

        .d2l-collapsepane-header {
            background: none !important;
        }

        .d2l-box {
            background: none !important;
        }

        .d2l-twopanelselector-side {
            background: linear-gradient(315deg, `+background+`, `+accent+`) !important;
        }

        .d2l-twopanelselector-side * {
            background: none !important;
        }

        .d2l-input-focus {
            background: `+background2+` !important;
        }

        .d2l-twopanelselector-main {
            background: `+background2+` !important;
        }

        .d2l-twopanelselector-main * {
            background: none !important;
        }

        img {
            filter: invert(`+invert+`) !important;
        }

        .form-container {
            background: `+background2+` !important;
        }

        .form-container * {
            background: none !important;
        }

        .btn {
            background: linear-gradient(315deg, `+background+`, `+accent+`) !important;
            border: 4px solid `+accent+` !important;
        }

        .form-control {
            background-color: `+background+` !important;
            border: 4px solid `+accent+` !important;
        }

        #logo-container * {
            filter: invert(0) !important;
        }

        .icon {
            background-color: #00000000 !important;
            color: `+textcolor+` !important;
        }

        .link-text {
            background-color: #00000000 !important;
            color: `+textcolor+` !important;
        }

        a:not(#discord) {
            background: linear-gradient(315deg, `+background+`, `+background2+`) !important;
            border: 2px solid `+accent+` !important;
            border-radius: 8px;
            padding: 2px;
        }

        a * {
            background: none !important;
        }

        td {
            background: url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)
        }

        th {
            background: url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)
        }

    </style>
    `;

    if (document.getElementById('K12DMR_CSS') == undefined) {// If the css doesnt exist in the page yet
        $('head').append(css);// Inject css
    } else {
        $('#K12DMR_CSS').remove();// Otherwise remove it
        $('head').append(css);// And add it again, so the colors are up-to-date
    }

    /*try {
        let divs = document.querySelectorAll('td');

        for (i=0; i<divs.length; i++) {
            divs[i].style.background = "url(http://justfunfacts.com/wp-content/uploads/2021/03/black.jpg)";
        }
    } catch(err){console.log(err)}*/

};

function toggleMenu() {
    if (document.getElementById('menuBlock').style.display == 'none') {//If the menu is currently hidden
        console.log('toggle menu on');// Log the menu toggle, for debugging
        let divs = $('.menuItem')// Get all elements that belong to the menu
        for (i = 0; i<divs.length; i++) {// For each of those elements
             divs[i].style.display = 'block';// Turn its display on to make it visible
        }
    } else {// If the menu is currently on,
        console.log('toggle menu off');// Log the menu toggle, for debugging
        let divs = $('.menuItem');// Get all elements that belong to the menu
        for (i = 0; i<divs.length; i++) {// For each of those elements
             divs[i].style.display = 'none';// Turn its display off to make it invisible
        }
    }
};

function onKeyDown(evt) { // When a key, any key is pressed
    if (evt.keyCode == 9) { // Every key has a key code, the code for Tab is 9
        toggleMenu(); // Toggle the menu
    }
    if (evt.keyCode == 81) { // This is the keycode for Q, dont press this, it triggers the setup. This will eventually be removed.
        setup();
        console.log('setup triggered')
    }
}
document.addEventListener('keydown', onKeyDown, true); // This adds the sensor for detecting key presses



// Now do the things
$('body').append(menu); // Inject the menu HTML
if (first == undefined) {setup()} else { // If this is the first time being used, trigger setup
makeCSS(bg, bg2, acc, txt, img, fnt);// Otherwise inject CSS like usual
};



// Menu sensory

// Theme selector
document.querySelector('#themebox').addEventListener('change', (event) => {// When preset theme changes
    let ch = document.querySelector('#themebox').value // Get the value of selector
    ch = parseInt(ch) // Turn it into a number

    let bgs = ["#202020", "#000000", "#fdfdfd", "#303940", "#000000", bg];// Colors for presets
    let bg2s = ["#404040", "#202020", "#d0d0d0", "#505960", "#404040", bg2];
    let accs = ["#004674", "#004674", "#83bade", "#004684", "#606060", acc];
    let txts = ["#b0b0b0", "#c0c0c0", "#404040", "#a0a0b0", "#cfcf2a", txt];

    pst = ch // Set all the colors to their corresponding theme
    GM_setValue('preset',pst);
    bg = bgs[ch]
    GM_setValue('background',bg);
    bg2 = bg2s[ch]
    GM_setValue('background2',bg2);
    acc = accs[ch]
    GM_setValue('accent',acc);
    txt = txts[ch]
    GM_setValue('textcolor',txt);
    makeCSS(bg, bg2, acc, txt, img, fnt);

    document.querySelector('#bg').value = bg;// Change all the input boxes to said color
    document.querySelector('#bg2').value = bg2;
    document.querySelector('#acc').value = acc;
    document.querySelector('#txt').value = txt;

    console.log('Theme changed to '+['Dark','Extra Dark','Light','True Blue','Contrast','Custom'][ch])// Log the theme change
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)
    // And log the rest of the values

});

// Font selector, removed for now.
/*document.querySelector('#fnt').addEventListener('change', (event) => {
    let ch = document.querySelector('#fnt').value
    ch = parseInt(ch)

    let fnts = ["arial","monospace","cursive","fantasy","'ng-icons'"];// Fonts

    fnt = fnts[ch]
    GM_setValue('font',fnt);
    makeCSS(bg, bg2, acc, txt, img, fnt);
    console.log('Font changed to '+["arial","monospace","cursive","fantasy","'ng-icons'"][ch])
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});*/

// Background Image input
document.querySelector('#img').addEventListener('change', (event) => { // When the text changed
    let val = document.querySelector('#img').value // Get its value

    img = val // Set the img variable to its value
    GM_setValue('image',img); // Store the value
    makeCSS(bg, bg2, acc, txt, img, fnt); // And update the CSS
    console.log('Background Image changed to '+val)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});

// Background input
document.querySelector('#bg').addEventListener('change', (event) => {// Same story for the rest of these.
    let val = document.querySelector('#bg').value

    bg = val
    GM_setValue('background',bg);
    makeCSS(bg, bg2, acc, txt, img, fnt);
    console.log('Background changed to '+val)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});

// Background2 input
document.querySelector('#bg2').addEventListener('change', (event) => {
    let val = document.querySelector('#bg2').value

    bg2 = val
    GM_setValue('background2',bg2);
    makeCSS(bg, bg2, acc, txt, img, fnt);
    console.log('Background 2 changed to '+val)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});

// Accent input
document.querySelector('#acc').addEventListener('change', (event) => {
    let val = document.querySelector('#acc').value

    acc = val
    GM_setValue('accent',acc);
    makeCSS(bg, bg2, acc, txt, img, fnt);
    console.log('Accent changed to '+val)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});

// Text Color input
document.querySelector('#txt').addEventListener('change', (event) => {
    let val = document.querySelector('#txt').value

    txt = val
    GM_setValue('textcolor',txt);
    makeCSS(bg, bg2, acc, txt, img, fnt);
    console.log('Text Color changed to '+val)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nFont: '+fnt)

});

// Invert Images checkbox
document.querySelector('#invert').addEventListener('change', (event) => {
    let val = document.querySelector('#invert').checked

    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.
    GM_setValue('invertImages',inv);
    makeCSS(bg, bg2, acc, txt, img, fnt, inv);
    console.log('Invert Images changed to '+inv)
    console.log('Display Vars\n\nPreset: '+pst+'\nBackground: '+bg+'\nBackground 2: '+bg2+'\nAccent: '+acc+'\nText Color: '+txt+'\nBackground Image: '+img+'\nInvert: '+inv)

});



})})();