Mensaar Show Next Day

A userscript that switches to the meal plans for the next day when the canteen has already closed for today

  1. // ==UserScript==
  2. // @name Mensaar Show Next Day
  3. // @namespace https://github.com/ikelax/userscripts
  4. // @match https://mensaar.de/
  5. // @grant none
  6. // @version 0.2.3
  7. // @author Alexander Ikonomou
  8. // @description A userscript that switches to the meal plans for the next day when the canteen has already closed for today
  9. // @license MIT
  10. // @supportURL https://github.com/ikelax/userscripts/issues
  11. // @copyright 2025, Alexander Ikonomou (https://github.com/ikelax)
  12. // @homepageURL https://github.com/ikelax/userscripts
  13. // @homepage https://github.com/ikelax/userscripts
  14. // @contributionURL https://github.com/ikelax/userscripts
  15. // @collaborator ikelax
  16. // @icon https://mensaar.de/img/icon.png
  17. // ==/UserScript==
  18.  
  19. waitForKeyElements("div.active", switchToNextDay);
  20.  
  21. function switchToNextDay(activeTab) {
  22. let activeTabDate = new Date(activeTab.innerText);
  23. let closeDate = new Date(
  24. activeTabDate.getFullYear(),
  25. activeTabDate.getMonth(),
  26. activeTabDate.getDay(),
  27. 14,
  28. 30,
  29. );
  30.  
  31. let now = new Date();
  32.  
  33. if (now - closeDate >= 0) {
  34. activeTab.nextSibling?.click();
  35. }
  36. }
  37.  
  38. // The code was copied from https://github.com/CoeJoder/waitForKeyElements.js.
  39. /**
  40. * A utility function for userscripts that detects and handles AJAXed content.
  41. *
  42. * @example
  43. * waitForKeyElements("div.comments", (element) => {
  44. * element.innerHTML = "This text inserted by waitForKeyElements().";
  45. * });
  46. *
  47. * waitForKeyElements(() => {
  48. * const iframe = document.querySelector('iframe');
  49. * if (iframe) {
  50. * const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
  51. * return iframeDoc.querySelectorAll("div.comments");
  52. * }
  53. * return null;
  54. * }, callbackFunc);
  55. *
  56. * @param {(string|function)} selectorOrFunction - The selector string or function.
  57. * @param {function} callback - The callback function; takes a single DOM element as parameter.
  58. * If returns true, element will be processed again on subsequent iterations.
  59. * @param {boolean} [waitOnce=true] - Whether to stop after the first elements are found.
  60. * @param {number} [interval=300] - The time (ms) to wait between iterations.
  61. * @param {number} [maxIntervals=-1] - The max number of intervals to run (negative number for unlimited).
  62. */
  63. function waitForKeyElements(
  64. selectorOrFunction,
  65. callback,
  66. waitOnce,
  67. interval,
  68. maxIntervals,
  69. ) {
  70. if (typeof waitOnce === "undefined") {
  71. waitOnce = true;
  72. }
  73. if (typeof interval === "undefined") {
  74. interval = 300;
  75. }
  76. if (typeof maxIntervals === "undefined") {
  77. maxIntervals = -1;
  78. }
  79. if (typeof waitForKeyElements.namespace === "undefined") {
  80. waitForKeyElements.namespace = Date.now().toString();
  81. }
  82. var targetNodes =
  83. typeof selectorOrFunction === "function"
  84. ? selectorOrFunction()
  85. : document.querySelectorAll(selectorOrFunction);
  86.  
  87. var targetsFound = targetNodes && targetNodes.length > 0;
  88. if (targetsFound) {
  89. targetNodes.forEach(function (targetNode) {
  90. var attrAlreadyFound = `data-userscript-${waitForKeyElements.namespace}-alreadyFound`;
  91. var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false;
  92. if (!alreadyFound) {
  93. var cancelFound = callback(targetNode);
  94. if (cancelFound) {
  95. targetsFound = false;
  96. } else {
  97. targetNode.setAttribute(attrAlreadyFound, true);
  98. }
  99. }
  100. });
  101. }
  102.  
  103. if (maxIntervals !== 0 && !(targetsFound && waitOnce)) {
  104. maxIntervals -= 1;
  105. setTimeout(function () {
  106. waitForKeyElements(
  107. selectorOrFunction,
  108. callback,
  109. waitOnce,
  110. interval,
  111. maxIntervals,
  112. );
  113. }, interval);
  114. }
  115. }