Customize Zeit Online

Entferne unerwünschte Artikel/Abschnitte aus Zeit Online

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Customize Zeit Online
// @namespace    https://greasyfork.org/en/users/689160-georg-vogt
// @version      4.13
// @description  Entferne unerwünschte Artikel/Abschnitte aus Zeit Online
// @author       Georg Vogt
// @match        https://www.zeit.de/*
// @icon         https://icons.duckduckgo.com/ip2/zeit.de.ico
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-body
// @license      MIT
// ==/UserScript==

"use strict";

function hideNode(node) {
    if (node) {
        node.style.display = "none";
        //  node.style.background = "red"; //  debug
    }
}

function clearMainPage() {
    // bad single nodes
    const queries = new Map([
        ["div.cp-region.cp-region--kpi-table", "div"], // Beliebte Artikel
        ["div.cp-region.cp-region--kpi-accordion", "div"], // Beliebte Artikel mobile
        ["section[data-ct-context='shop']", "div.cp-region"], // Shop
        ["section[data-ct-context='headed-spiele']", "div.cp-region"], // Spiele
        ["section[data-ct-context='newsticker']", "div.cp-region"], // Newsticker
        ["section>div.zg-wiegehtesihnen", "div"], // Stimmungsumfrage
        ["a[href*='die-49']", "div"], // Die 49
    ]);
    const main = document.querySelector("main");
    queries.forEach((node, query) => hideNode(main.querySelector(query)?.closest(node)));

    // remove zeit+
    if (GM_getValue("tm_czo_zeitplus", true)) {
        const zplusArticles = main.querySelectorAll("article svg.svg-symbol.zplus-logo:not(.invisible)");
        zplusArticles.forEach(node => hideNode(node.closest("article")));
    }

    // remove wochenmarkt
    if (GM_getValue("tm_czo_wochenmarkt", true)) {
        const wochenmarkt = main.querySelectorAll(
            "article[data-unique-id^='http://xml.zeit.de/zeit-magazin/wochenmarkt'], article.zon-teaser-wochenmarkt"
        );
        wochenmarkt.forEach(node => hideNode(node));
    }

    // remove zett
    if (GM_getValue("tm_czo_zett", true)) {
        const zettArticles = main.querySelectorAll("article>[href^='https://www.zeit.de/zett']");
        zettArticles.forEach(node => hideNode(node.closest("article")));
    }

    // remove Verlagsangebot
    if (GM_getValue("tm_czo_verlag", true)) {
        const verlagsangebotArticles = main.querySelectorAll(":scope>div>*>article.zon-teaser-standard.zon-teaser-standard--ad");
        verlagsangebotArticles.forEach(node => hideNode(node));
        const veranstaltungen = main.querySelectorAll(":scope>div>*>article>a[href^='https://z2x.zeit.de']");
        veranstaltungen.forEach(node => hideNode(node.parentElement));
    }

    // remove podcasts
    if (GM_getValue("tm_czo_podcast", true)) {
        const podcasts = main.querySelectorAll([
            "article.zon-teaser-standard.zon-teaser-standard--podcast",
            "article.teaser-podcast-lead",
            "article.zon-teaser-wide.zon-teaser-wide--podcast"
        ]);
        podcasts.forEach(node => hideNode(node));
    }

    // remove videos
    if (GM_getValue("tm_czo_video", true)) {
        const videos = main.querySelectorAll(":scope>div>*>article[data-video-id]");
        videos.forEach(node => hideNode(node));
    }

    // remove newsletter
    if (GM_getValue("tm_czo_newsletter", true)) {
        const newsletters = main.querySelectorAll(":scope>div>*>article>a[href^='https://www.zeit.de/newsletter']");
        newsletters.forEach(node => hideNode(node.parentElement));
        main.querySelectorAll(":scope>div>div>aside.newsletter-signup").forEach(node => hideNode(node));
    }

    // remove Känguru Comic
    if (GM_getValue("tm_czo_comic", true)) {
        const comic = main.querySelector("figure [href^='https://www.zeit.de/serie/die-kaenguru-comics'], figure [src^='https://img.zeit.de/administratives/kaenguru-comics']");
        hideNode(comic?.closest("div.scrollable-wrapper, div.collapsible-wrapper"));
    }

    // remove Quiz region
    if (GM_getValue("tm_czo_quiz", true)) {
        const quiz = main.querySelector(":scope>div>div>section.frame.frame--quiz");
        hideNode(quiz?.closest("div.cp-region"));
    }

    // remove Spiele
    if (GM_getValue("tm_czo_spiele", true)) {
        const quiz = main.querySelector("article a[href*='spiele.zeit.de'], article a[href*='soduko.zeit.de']");
        hideNode(quiz?.closest("div.cp-region"));
    }

    // remove offline angebote
    if (GM_getValue("tm_czo_offline", true)) {
        hideNode(main.querySelector(":scope>div>section[data-ct-context='printkiosk']")?.closest("div.cp-region")); // Jetzt für sie am Kiosk
        hideNode(main.querySelector(":scope>div>div>section.zon-teaser-printbox")?.closest("div.cp-region")); // Diese Woche in der ZEIT
    }

    // remove regions without articles
    const wantedContent = [
        "article:not([style*='display: none'])",
        ":scope>div>aside>div.zg-corona-dashboard",
        ":scope>div>section>iframe", // Quiz
        ":scope>div[class='czo-settings']",
    ]
    main.querySelectorAll(":scope>div").forEach(node => node.querySelector(wantedContent)? "": hideNode(node));
}

function clearArticle() {
    // bad single nodes
    const queries = new Map([
        ["aside.jobbox-ticker", "aside"], // Jobbörse
    ]);
    queries.forEach((node, query) => hideNode(document.querySelector(query)?.closest(node)));

    // remove sidebar Zeit+
    if (GM_getValue("tm_czo_zeitplus", true)) {
        const possibleHeadings = ["DAS BESTE AUS Z+", "Z+"];
        const sideBoxes = document.querySelectorAll("article aside.topicbox");
        for (const sideBox of sideBoxes) {
            if (possibleHeadings.includes(sideBox.firstElementChild?.firstElementChild?.innerText)) {
                hideNode(sideBox);
            }
        }
    }

    // remove videos
    if (GM_getValue("tm_czo_video", true)) {
        const videos = document.querySelectorAll("figure>div.js-videoplayer");
        videos.forEach(node => hideNode(node.parentElement));
    }

    // remove newsletter
    if (GM_getValue("tm_czo_newsletter", true)) {
        hideNode(document.querySelector("aside.newsletter-signup"));
        hideNode(document.querySelector("[action*='community.zeit.de/newsletter']")?.closest("form")); // Newsletter inline
    }

    // offline angebote
    if (GM_getValue("tm_czo_offline", true)) {
        hideNode(document.querySelectorAll("aside.volume-teaser"));
    }

    // Anzeige
    const nextRead = document.querySelector("span.nextread-note__label")
    if (nextRead?.innerText == "ANZEIGE") {
        hideNode(nextRead?.closest("article"));
    }
}

document.addEventListener("DOMContentLoaded", () => {
    if (document.querySelector("div.cp-region")) {
        clearMainPage();
        setTimeout(clearMainPage, 2000);
    } else {
        clearArticle();
    };

    // Create Settings on bottom
    function createCheckbox(text, id, defaultValue=true) {
        const div = document.createElement("div");
        div.innerHTML = `
            <input type="checkbox" id="${id}+" name="${id}+" ${GM_getValue(id, defaultValue)? "checked": ""}>
            <label for="${id}+">${text}</label>
        `;
        div.onclick = function () {
            GM_setValue(id, div.firstElementChild.checked);
        };
        return div;
    }
    const main = document.querySelector("main");
    const settings = document.createElement("div");
    settings.innerHTML = "<h3>Customize Zeit Online Einstellungen: Blocke</h3>";
    const boxes = document.createElement("div");
    boxes.className = "czo-settings";
    boxes.style = "display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 175px));";
    boxes.appendChild(createCheckbox("Zeit+", "tm_czo_zeitplus"));
    boxes.appendChild(createCheckbox("Zett", "tm_czo_zett"));
    boxes.appendChild(createCheckbox("Verlagsangebote", "tm_czo_verlag"));
    boxes.appendChild(createCheckbox("Podcasts", "tm_czo_podcast"));
    boxes.appendChild(createCheckbox("Videos", "tm_czo_video"));
    boxes.appendChild(createCheckbox("Newsletter", "tm_czo_newsletter"));
    boxes.appendChild(createCheckbox("Känguru Comic", "tm_czo_comic"));
    boxes.appendChild(createCheckbox("Offline Angebot", "tm_czo_offline"));
    boxes.appendChild(createCheckbox("Wochenmarkt", "tm_czo_wochenmarkt"));
    boxes.appendChild(createCheckbox("Quiz + Nachbarartikel", "tm_czo_quiz"));
    boxes.appendChild(createCheckbox("Spiele", "tm_czo_spiele"));
    settings.appendChild(boxes);
    main.appendChild(settings);
});

// remove paywall footer
const callback = function(mutationsList, observer) {
    for(const mutation of mutationsList) {
        for (const node of mutation.addedNodes) {
            if (node.className?.startsWith("paywall-footer")) {
                hideNode(node);
                observer.disconnect();
            }
        }
    }
};

const observerFooter = new MutationObserver(callback);
observerFooter.observe(document.body, {childList: true});