Save contents of unsubmitted Google Classroom question responses

Prevents unsubmitted work in question assignments from being lost after closing the tab or browser

// ==UserScript==
// @name        Save contents of unsubmitted Google Classroom question responses
// @namespace   Violentmonkey Scripts
// @match       *://classroom.google.com/*
// @grant GM_getValue
// @grant GM_setValue
// @version     1.0
// @author      CyrilSLi
// @description Prevents unsubmitted work in question assignments from being lost after closing the tab or browser
// @license     MIT
// ==/UserScript==

const spanText = "Your answer";
var textarea, span;
const retries = 100;
var retry = 0, retryTimeout = 0;
function findEls() {
    textarea = [...document.getElementsByTagName("textarea")].filter(
        t => t.placeholder === "Type your answer" && window.getComputedStyle(t).visibility !== "hidden"
    )[0];
    span = [...document.getElementsByTagName("span")].filter(
        s => s.textContent.startsWith(spanText) && window.getComputedStyle(s).visibility !== "hidden"
    )[0];

    if (textarea == null || span == null) {
        retryTimeout = setTimeout(findEls, 200);
        retry++;
        if (retry === retries) {
            alert("Question assignment not found on page.")
            clearTimeout(retryTimeout);
            throw new Error();
        }
    } else {
        console.log("Found question elements.")
        saveQuestion();
        clearTimeout(retryTimeout);
    }
}

var pageURL = "", pageID = "";
const pageRegEx = new RegExp("\/c\/[A-Z0-9a-z]+?\/sa\/[A-Z0-9a-z]+");
const observer = new MutationObserver((muts) => {
    if (document.location.pathname !== pageURL) {
        pageURL = document.location.pathname;
        if (pageRegEx.test(document.location)) {
            removeEventListener("input", areaInput);
            clearTimeout(retryTimeout);
            console.log("Found question assignment.");
            retry = 0;
            pageID = document.location.pathname.match(pageRegEx)[0];
            setTimeout(findEls, 0);
        }
    }
})
observer.observe(document.body, {
    attributes: true
})

function setSpanTime() {
    span.textContent = `${spanText} (last updated ${new Date().toLocaleTimeString("en-US", { hour12: false })})`;
}

function areaInput(ev) {
    GM_setValue(pageID, textarea.value);
    setSpanTime();
}

function saveQuestion(ev) {
    textarea.addEventListener("input", areaInput);
    textarea.value = GM_getValue(pageID, "");
    setSpanTime();
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址