DeepL UI Cleaner

Streamlines DeepL's interface for translation-focused use by removing footers, cookie banners, and adding toggle buttons for sidebar and header

// ==UserScript==
// @name         DeepL UI Cleaner
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  Streamlines DeepL's interface for translation-focused use by removing footers, cookie banners, and adding toggle buttons for sidebar and header
// @match        https://www.deepl.com/*
// @include      https://www.deepl.com/*
// @license      Unlicense
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function () {
    "use strict";

    // Define selectors for target elements
    const TARGETS = {
        remove: {
            footer: [
                "footer",
                ".relative.bg-neutral-next-50 > .mobile\\:hidden",
                '.bg-white[class*="px-0"][class*="xl:px-"][class*="md:px-"][class*="min-"][class*="px"]',
            ],
            cookieBanner: ['[id*="cookieBanner"]', '[class*="cookieBanner"]'],
            writePageElements: [
                '.bg-white.px-0[class*="xl:px-"][class*="px"][class*="md:px-"][class*="px"][class*="min-"][class*="px"][class*="px"]',
                '.mobile\\:hidden.p-8.px-0[class*="xl:px-"][class*="px"][class*="md:px-"][class*="px"][class*="min-"][class*="px"][class*="px"]',
                '.bg-white.min-\\[1280px\\]\\:px-\\[70px\\]'
            ],
        },
        toggle: {
            topHeader: 'header'
        },
    };

    // CSS styles for toggle buttons and initial header state
    const BUTTON_STYLES = `
        .toggle-button {
            position: fixed;
            z-index: 10000;
            width: 2em;
            height: 2em;
            background-color: rgba(240, 240, 240, 0.7);
            border: 1px solid #ccc;
            border-radius: 50%;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
            transition: all 0.3s;
        }
        .toggle-button:hover {
            background-color: rgba(220, 220, 220, 0.9);
        }
        ${TARGETS.toggle.topHeader} {
            display: none !important;
        }
    `;

    // Function to inject CSS styles into the page
    function injectStyles() {
        const style = document.createElement("style");
        const hideSelectors = [
            ...Object.values(TARGETS.remove).flat(),
        ].join(", ");
        style.textContent = `
            ${hideSelectors} { display: none !important; }
            ${BUTTON_STYLES}
        `;
        (document.head || document.documentElement).appendChild(style);
    }

    // Function to remove unwanted elements from the page
    function removeElements() {
        Object.values(TARGETS.remove)
            .flat()
            .forEach((selector) => {
                document
                    .querySelectorAll(selector)
                    .forEach((element) => element.remove());
            });
    }

    // Function to create a toggle button
    function createToggleButton(
        showIcon,
        hideIcon,
        onClick,
        position,
        ariaLabel
    ) {
        const button = document.createElement("button");
        button.className = "toggle-button";
        button.textContent = showIcon;  // Starting with show icon since header is hidden
        button.setAttribute("aria-label", ariaLabel);
        button.addEventListener("click", onClick);
        Object.assign(button.style, position);
        return button;
    }

    // Function to adjust button positions based on header visibility
    function adjustButtonPositions() {
        const header = document.querySelector(TARGETS.toggle.topHeader);
        const topPosition =
            header && getComputedStyle(header).display !== "none"
                ? `${header.offsetHeight}px`
                : "0.5em";
        document.querySelectorAll(".toggle-button").forEach((button) => {
            button.style.top = topPosition;
        });
    }

    // Function to toggle visibility of elements
    function toggleElementVisibility(selector, button, showIcon, hideIcon) {
        const elements = document.querySelectorAll(selector);
        const isVisible = [...elements].some(
            (el) => getComputedStyle(el).display !== "none"
        );
        elements.forEach((el) =>
            el.style.setProperty("display", isVisible ? "none" : "block", "important")
        );
        button.textContent = isVisible ? showIcon : hideIcon;
        adjustButtonPositions();
    }

    // Function to initialize the script
    function init() {
        try {
            removeElements();

            const buttons = [
                {
                    selector: TARGETS.toggle.topHeader,
                    icons: ["▼", "▲"],
                    position: { left: "0.5em" },
                    ariaLabel: "Toggle header visibility",
                },
            ];

            buttons.forEach(
                ({ selector, icons: [showIcon, hideIcon], position, ariaLabel }) => {
                    const button = createToggleButton(
                        showIcon,
                        hideIcon,
                        () => toggleElementVisibility(selector, button, showIcon, hideIcon),
                        position,
                        ariaLabel
                    );
                    document.body.appendChild(button);
                }
            );

            adjustButtonPositions();

            // Set up MutationObserver to handle dynamically added elements
            const observer = new MutationObserver(() => {
                removeElements();
                adjustButtonPositions();
            });
            observer.observe(document.body, { childList: true, subtree: true, attributes: true });
        } catch (error) {
            console.error("DeepL UI Cleaner encountered an error:", error);
        }
    }

    // Inject styles immediately
    injectStyles();

    // Run initialization when DOM is ready
    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", init);
    } else {
        init();
    }
})();

QingJ © 2025

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