Greasy Fork is available in English.

Save contents of unsubmitted Google Classroom question responses

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

  1. // ==UserScript==
  2. // @name Save contents of unsubmitted Google Classroom question responses
  3. // @namespace Violentmonkey Scripts
  4. // @match *://classroom.google.com/*
  5. // @grant GM_getValue
  6. // @grant GM_setValue
  7. // @version 1.0
  8. // @author CyrilSLi
  9. // @description Prevents unsubmitted work in question assignments from being lost after closing the tab or browser
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. const spanText = "Your answer";
  14. var textarea, span;
  15. const retries = 100;
  16. var retry = 0, retryTimeout = 0;
  17. function findEls() {
  18. textarea = [...document.getElementsByTagName("textarea")].filter(
  19. t => t.placeholder === "Type your answer" && window.getComputedStyle(t).visibility !== "hidden"
  20. )[0];
  21. span = [...document.getElementsByTagName("span")].filter(
  22. s => s.textContent.startsWith(spanText) && window.getComputedStyle(s).visibility !== "hidden"
  23. )[0];
  24.  
  25. if (textarea == null || span == null) {
  26. retryTimeout = setTimeout(findEls, 200);
  27. retry++;
  28. if (retry === retries) {
  29. alert("Question assignment not found on page.")
  30. clearTimeout(retryTimeout);
  31. throw new Error();
  32. }
  33. } else {
  34. console.log("Found question elements.")
  35. saveQuestion();
  36. clearTimeout(retryTimeout);
  37. }
  38. }
  39.  
  40. var pageURL = "", pageID = "";
  41. const pageRegEx = new RegExp("\/c\/[A-Z0-9a-z]+?\/sa\/[A-Z0-9a-z]+");
  42. const observer = new MutationObserver((muts) => {
  43. if (document.location.pathname !== pageURL) {
  44. pageURL = document.location.pathname;
  45. if (pageRegEx.test(document.location)) {
  46. removeEventListener("input", areaInput);
  47. clearTimeout(retryTimeout);
  48. console.log("Found question assignment.");
  49. retry = 0;
  50. pageID = document.location.pathname.match(pageRegEx)[0];
  51. setTimeout(findEls, 0);
  52. }
  53. }
  54. })
  55. observer.observe(document.body, {
  56. attributes: true
  57. })
  58.  
  59. function setSpanTime() {
  60. span.textContent = `${spanText} (last updated ${new Date().toLocaleTimeString("en-US", { hour12: false })})`;
  61. }
  62.  
  63. function areaInput(ev) {
  64. GM_setValue(pageID, textarea.value);
  65. setSpanTime();
  66. }
  67.  
  68. function saveQuestion(ev) {
  69. textarea.addEventListener("input", areaInput);
  70. textarea.value = GM_getValue(pageID, "");
  71. setSpanTime();
  72. }