Customize Zeit Online

Entferne unerwünschte Artikel/Abschnitte aus Zeit Online

当前为 2021-09-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Customize Zeit Online
  3. // @namespace https://greasyfork.org/en/users/689160-georg-vogt
  4. // @version 4.12
  5. // @description Entferne unerwünschte Artikel/Abschnitte aus Zeit Online
  6. // @author Georg Vogt
  7. // @match https://www.zeit.de/*
  8. // @icon https://icons.duckduckgo.com/ip2/zeit.de.ico
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @run-at document-body
  12. // ==/UserScript==
  13.  
  14. "use strict";
  15.  
  16. function hideNode(node) {
  17. if (node) {
  18. node.style.display = "none";
  19. // node.style.background = "red"; // debug
  20. }
  21. }
  22.  
  23. function clearMainPage() {
  24. // bad single nodes
  25. const queries = new Map([
  26. ["div.cp-region.cp-region--kpi-table", "div"], // Beliebte Artikel
  27. ["div.cp-region.cp-region--kpi-accordion", "div"], // Beliebte Artikel mobile
  28. ["section[data-ct-context='shop']", "div.cp-region"], // Shop
  29. ["section[data-ct-context='headed-spiele']", "div.cp-region"], // Spiele
  30. ["section[data-ct-context='newsticker']", "div.cp-region"], // Newsticker
  31. ["section>div.zg-wiegehtesihnen", "div"], // Stimmungsumfrage
  32. ["a[href*='die-49']", "div"], // Die 49
  33. ]);
  34. const main = document.querySelector("main");
  35. queries.forEach((node, query) => hideNode(main.querySelector(query)?.closest(node)));
  36.  
  37. // remove zeit+
  38. if (GM_getValue("tm_czo_zeitplus", true)) {
  39. const zplusArticles = main.querySelectorAll("article svg.svg-symbol.zplus-logo:not(.invisible)");
  40. zplusArticles.forEach(node => hideNode(node.closest("article")));
  41. }
  42.  
  43. // remove wochenmarkt
  44. if (GM_getValue("tm_czo_wochenmarkt", true)) {
  45. const wochenmarkt = main.querySelectorAll(
  46. "article[data-unique-id^='http://xml.zeit.de/zeit-magazin/wochenmarkt'], article.zon-teaser-wochenmarkt"
  47. );
  48. wochenmarkt.forEach(node => hideNode(node));
  49. }
  50.  
  51. // remove zett
  52. if (GM_getValue("tm_czo_zett", true)) {
  53. const zettArticles = main.querySelectorAll("article>[href^='https://www.zeit.de/zett']");
  54. zettArticles.forEach(node => hideNode(node.closest("article")));
  55. }
  56.  
  57. // remove Verlagsangebot
  58. if (GM_getValue("tm_czo_verlag", true)) {
  59. const verlagsangebotArticles = main.querySelectorAll(":scope>div>*>article.zon-teaser-standard.zon-teaser-standard--ad");
  60. verlagsangebotArticles.forEach(node => hideNode(node));
  61. const veranstaltungen = main.querySelectorAll(":scope>div>*>article>a[href^='https://z2x.zeit.de']");
  62. veranstaltungen.forEach(node => hideNode(node.parentElement));
  63. }
  64.  
  65. // remove podcasts
  66. if (GM_getValue("tm_czo_podcast", true)) {
  67. const podcasts = main.querySelectorAll([
  68. ":scope>div>*>article.zon-teaser-standard.zon-teaser-standard--podcast",
  69. ":scope>div>*>article.teaser-podcast-lead",
  70. ":scope>div>*>article.zon-teaser-wide.zon-teaser-wide--podcast"
  71. ]);
  72. podcasts.forEach(node => hideNode(node));
  73. }
  74.  
  75. // remove videos
  76. if (GM_getValue("tm_czo_video", true)) {
  77. const videos = main.querySelectorAll(":scope>div>*>article[data-video-id]");
  78. videos.forEach(node => hideNode(node));
  79. }
  80.  
  81. // remove newsletter
  82. if (GM_getValue("tm_czo_newsletter", true)) {
  83. const newsletters = main.querySelectorAll(":scope>div>*>article>a[href^='https://www.zeit.de/newsletter']");
  84. newsletters.forEach(node => hideNode(node.parentElement));
  85. main.querySelectorAll(":scope>div>div>aside.newsletter-signup").forEach(node => hideNode(node));
  86. }
  87.  
  88. // remove Känguru Comic
  89. if (GM_getValue("tm_czo_comic", true)) {
  90. const comic = main.querySelector("figure [href^='https://www.zeit.de/serie/die-kaenguru-comics'], figure [src^='https://img.zeit.de/administratives/kaenguru-comics']");
  91. hideNode(comic?.closest("div.scrollable-wrapper, div.collapsible-wrapper"));
  92. }
  93.  
  94. // remove Quiz region
  95. if (GM_getValue("tm_czo_quiz", true)) {
  96. const quiz = main.querySelector(":scope>div>div>section.frame.frame--quiz");
  97. hideNode(quiz?.closest("div.cp-region"));
  98. }
  99.  
  100. // remove offline angebote
  101. if (GM_getValue("tm_czo_offline", true)) {
  102. hideNode(main.querySelector(":scope>div>section[data-ct-context='printkiosk']")?.closest("div.cp-region")); // Jetzt für sie am Kiosk
  103. hideNode(main.querySelector(":scope>div>div>section.zon-teaser-printbox")?.closest("div.cp-region")); // Diese Woche in der ZEIT
  104. }
  105.  
  106. // remove regions without articles
  107. main.querySelectorAll(":scope>div").forEach(
  108. node => node.querySelector("article:not([style*='display: none']), :scope>div>aside>div.zg-corona-dashboard, :scope>div>section>iframe, :scope>div[class='czo-settings']")? "": hideNode(node)
  109. );
  110. }
  111.  
  112. function clearArticle() {
  113. // bad single nodes
  114. const queries = new Map([
  115. ["aside.jobbox-ticker", "aside"], // Jobbörse
  116. ]);
  117. queries.forEach((node, query) => hideNode(document.querySelector(query)?.closest(node)));
  118.  
  119. // remove sidebar Zeit+
  120. if (GM_getValue("tm_czo_zeitplus", true)) {
  121. const possibleHeadings = ["DAS BESTE AUS Z+", "Z+"];
  122. const sideBoxes = document.querySelectorAll("article aside.topicbox");
  123. for (const sideBox of sideBoxes) {
  124. if (possibleHeadings.includes(sideBox.firstElementChild?.firstElementChild?.innerText)) {
  125. hideNode(sideBox);
  126. }
  127. }
  128. }
  129.  
  130. // remove videos
  131. if (GM_getValue("tm_czo_video", true)) {
  132. const videos = document.querySelectorAll("figure>div.js-videoplayer");
  133. videos.forEach(node => hideNode(node.parentElement));
  134. }
  135.  
  136. // remove newsletter
  137. if (GM_getValue("tm_czo_newsletter", true)) {
  138. hideNode(document.querySelector("aside.newsletter-signup"));
  139. hideNode(document.querySelector("[action*='community.zeit.de/newsletter']")?.closest("form")); // Newsletter inline
  140. }
  141.  
  142. // offline angebote
  143. if (GM_getValue("tm_czo_offline", true)) {
  144. hideNode(document.querySelectorAll("aside.volume-teaser"));
  145. }
  146.  
  147. // Anzeige
  148. const nextRead = document.querySelector("span.nextread-note__label")
  149. if (nextRead?.innerText == "ANZEIGE") {
  150. hideNode(nextRead?.closest("article"));
  151. }
  152. }
  153.  
  154. document.addEventListener("DOMContentLoaded", () => {
  155. if (document.querySelector("div.cp-region")) {
  156. clearMainPage();
  157. setTimeout(clearMainPage, 2000);
  158. } else {
  159. clearArticle();
  160. };
  161.  
  162. // Create Settings on bottom
  163. function createCheckbox(text, id, defaultValue=true) {
  164. const div = document.createElement("div");
  165. div.innerHTML = `
  166. <input type="checkbox" id="${id}+" name="${id}+" ${GM_getValue(id, defaultValue)? "checked": ""}>
  167. <label for="${id}+">${text}</label>
  168. `;
  169. div.onclick = function () {
  170. GM_setValue(id, div.firstElementChild.checked);
  171. };
  172. return div;
  173. }
  174. const main = document.querySelector("main");
  175. const settings = document.createElement("div");
  176. settings.innerHTML = "<h3>Customize Zeit Online Einstellungen: Blocke</h3>";
  177. const boxes = document.createElement("div");
  178. boxes.className = "czo-settings";
  179. boxes.style = "display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 175px));";
  180. boxes.appendChild(createCheckbox("Zeit+", "tm_czo_zeitplus"));
  181. boxes.appendChild(createCheckbox("Zett", "tm_czo_zett"));
  182. boxes.appendChild(createCheckbox("Verlagsangebote", "tm_czo_verlag"));
  183. boxes.appendChild(createCheckbox("Podcasts", "tm_czo_podcast"));
  184. boxes.appendChild(createCheckbox("Videos", "tm_czo_video"));
  185. boxes.appendChild(createCheckbox("Newsletter", "tm_czo_newsletter"));
  186. boxes.appendChild(createCheckbox("Känguru Comic", "tm_czo_comic"));
  187. boxes.appendChild(createCheckbox("Offline Angebot", "tm_czo_offline"));
  188. boxes.appendChild(createCheckbox("Wochenmarkt", "tm_czo_wochenmarkt"));
  189. boxes.appendChild(createCheckbox("Quiz + Nachbarartikel", "tm_czo_quiz"));
  190. settings.appendChild(boxes);
  191. main.appendChild(settings);
  192. });
  193.  
  194. // remove paywall footer
  195. const callback = function(mutationsList, observer) {
  196. for(const mutation of mutationsList) {
  197. for (const node of mutation.addedNodes) {
  198. if (node.className?.startsWith("paywall-footer")) {
  199. hideNode(node);
  200. observer.disconnect();
  201. }
  202. }
  203. }
  204. };
  205.  
  206. const observerFooter = new MutationObserver(callback);
  207. observerFooter.observe(document.body, {childList: true});