☰

ImageFap Dark Mode

Dark theme for ImageFap with a toggle.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴、Greasemonkey 油猴子 或 Violentmonkey 暴力猴,才能安装此脚本。

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴 或 Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴 或 Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         ImageFap Dark Mode
// @namespace    imagefap@nereids
// @version      1.0.0
// @description  Dark theme for ImageFap with a toggle.
// @author       nereids
// @license      MIT
// @match        *://imagefap.com/*
// @match        *://*.imagefap.com/*
// @icon         https://icons.duckduckgo.com/ip3/imagefap.com.ico
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Set to true to desaturate photos and video as well. The chrome is always grayscale.
    var GRAYSCALE_MEDIA = false;

    var STORAGE_KEY = 'if-dark-mode';

    function isOn() {
        try {
            var v = localStorage.getItem(STORAGE_KEY);
            return v === null || v === '1';
        } catch (e) {
            return true;
        }
    }

    function setOn(on) {
        try {
            localStorage.setItem(STORAGE_KEY, on ? '1' : '0');
        } catch (e) {}
    }

    var CSS = [
        'html.if-dark {',
        '  color-scheme: dark !important;',
        '  background: #141414 !important;',
        '  scrollbar-color: #4a4a4a #141414;',
        '}',
        'html.if-dark body {',
        '  background: #141414 !important;',
        '  color: #cfcfcf !important;',
        '}',
        'html.if-dark body,',
        'html.if-dark table,',
        'html.if-dark tbody,',
        'html.if-dark thead,',
        'html.if-dark tfoot,',
        'html.if-dark tr,',
        'html.if-dark td,',
        'html.if-dark th,',
        'html.if-dark div,',
        'html.if-dark span,',
        'html.if-dark p,',
        'html.if-dark font,',
        'html.if-dark center,',
        'html.if-dark li,',
        'html.if-dark ul,',
        'html.if-dark ol,',
        'html.if-dark dl,',
        'html.if-dark dt,',
        'html.if-dark dd,',
        'html.if-dark h1,',
        'html.if-dark h2,',
        'html.if-dark h3,',
        'html.if-dark h4,',
        'html.if-dark label,',
        'html.if-dark small,',
        'html.if-dark big,',
        'html.if-dark blockquote,',
        'html.if-dark pre,',
        'html.if-dark i,',
        'html.if-dark em,',
        'html.if-dark u,',
        'html.if-dark s {',
        '  background-color: transparent !important;',
        '  color: #cfcfcf !important;',
        '  border-color: #3a3a3a !important;',
        '  outline-color: #5a5a5a !important;',
        '}',
        'html.if-dark b,',
        'html.if-dark strong {',
        '  background-color: transparent !important;',
        '  color: #f2f2f2 !important;',
        '}',
        'html.if-dark hr,',
        'html.if-dark .hr {',
        '  background-color: #3a3a3a !important;',
        '  border-color: #3a3a3a !important;',
        '  color: #3a3a3a !important;',
        '}',
        'html.if-dark [class$="_hdr"],',
        'html.if-dark h1#title,',
        'html.if-dark td.colhead,',
        'html.if-dark .right_side_top,',
        'html.if-dark .our_niches,',
        'html.if-dark .announceBox .close,',
        'html.if-dark #playlist .head,',
        'html.if-dark #flag .head,',
        'html.if-dark #share .head,',
        'html.if-dark .gallerylist table tr.head,',
        'html.if-dark .gallerylist table tr.head td {',
        '  background-color: #343434 !important;',
        '  color: #f3f3f3 !important;',
        '  border-color: #4a4a4a !important;',
        '}',
        'html.if-dark [class^="blk_"]:not(a):not([class$="_hdr"]),',
        'html.if-dark #controlpanel,',
        'html.if-dark div#controlpanel div.content,',
        'html.if-dark .left_side,',
        'html.if-dark .right_side {',
        '  background-color: #1b1b1b !important;',
        '  color: #cfcfcf !important;',
        '  border-color: #3a3a3a !important;',
        '}',
        'html.if-dark .avatar {',
        '  border: none !important;',
        '  background-color: #242424 !important;',
        '  border-color: #555 !important;',
        '  color: #ddd !important;',
        '}',
        'html.if-dark .avatar .subscribers,',
        'html.if-dark .avatar .comments {',
        '  color: #cfcfcf !important;',
        '}',
        'html.if-dark img.gal_thumb,',
        'html.if-dark .gal_thumb {',
        '  border-color: #6a6a6a !important;',
        '  background-color: #111 !important;',
        '}',
        'html.if-dark #cat {',
        '  background-color: #1c1c1c !important;',
        '  border-color: #4a4a4a !important;',
        '}',
        'html.if-dark .msgCont,',
        'html.if-dark .relCont,',
        'html.if-dark .relatedgalleriescontainer,',
        'html.if-dark .relatedgalleriescontainer .relateditem,',
        'html.if-dark #flag,',
        'html.if-dark #share,',
        'html.if-dark #playlist,',
        'html.if-dark .blockwidgetpopup,',
        'html.if-dark #cat_tooltip,',
        'html.if-dark .tooltip,',
        'html.if-dark .sample_popup,',
        'html.if-dark .sample_popup div,',
        'html.if-dark .announceBox,',
        'html.if-dark div#controlpanel div.messages ul,',
        'html.if-dark div#controlpanel div.content ul.tabs,',
        'html.if-dark div#controlpanel div.content ul.tabs li a,',
        'html.if-dark div#controlpanel div.content div.tabs-content,',
        'html.if-dark div#controlpanel div.content table.list thead tr th,',
        'html.if-dark div#controlpanel div.content table.list tbody tr td,',
        'html.if-dark table.request tr td {',
        '  background-color: #262626 !important;',
        '  color: #e0e0e0 !important;',
        '  border-color: #555 !important;',
        '  box-shadow: none !important;',
        '}',
        'html.if-dark .itemCounter,',
        'html.if-dark .isblocked,',
        'html.if-dark .notblocked {',
        '  background-color: #3f3f3f !important;',
        '  color: #f5f5f5 !important;',
        '  border-color: #6a6a6a !important;',
        '}',
        'html.if-dark div#controlpanel div.content p.pagination strong {',
        '  background-color: #4a4a4a !important;',
        '  color: #ffffff !important;',
        '  border-color: #4a4a4a !important;',
        '}',
        'html.if-dark .tnaBarBlueWrap {',
        '  filter: grayscale(1) brightness(0.55) contrast(1.05);',
        '}',
        'html.if-dark a[title="ImageFap.com"] img,',
        'html.if-dark img[alt="ImageFap.com"] {',
        '  filter: invert(1) grayscale(1) contrast(1.15) !important;',
        '  background: transparent !important;',
        '}',
        'html.if-dark.if-gray-media img,',
        'html.if-dark.if-gray-media video {',
        '  filter: grayscale(1) !important;',
        '}',
        'html.if-dark.if-gray-media a[title="ImageFap.com"] img,',
        'html.if-dark.if-gray-media img[alt="ImageFap.com"] {',
        '  filter: invert(1) grayscale(1) contrast(1.15) !important;',
        '}',
        'html.if-dark input:not([type="checkbox"]):not([type="radio"]):not([type="image"]):not([type="hidden"]),',
        'html.if-dark textarea,',
        'html.if-dark select,',
        'html.if-dark button {',
        '  background-color: #1c1c1c !important;',
        '  color: #e8e8e8 !important;',
        '  border: 1px solid #5c5c5c !important;',
        '  box-shadow: none !important;',
        '}',
        'html.if-dark input::placeholder,',
        'html.if-dark textarea::placeholder {',
        '  color: #8a8a8a !important;',
        '}',
        'html.if-dark ::selection {',
        '  background: #3a3a3a !important;',
        '  color: #ffffff !important;',
        '}',
        'html.if-dark a,',
        'html.if-dark a:link,',
        'html.if-dark a:visited,',
        'html.if-dark a *,',
        'html.if-dark a font,',
        'html.if-dark a span,',
        'html.if-dark a b,',
        'html.if-dark a i,',
        'html.if-dark a u {',
        '  color: #3f75aa !important;',
        '  background-color: transparent !important;',
        '}',
        'html.if-dark a:visited,',
        'html.if-dark a:visited *,',
        'html.if-dark a:visited font,',
        'html.if-dark a:visited b {',
        '  color: #6573b1 !important;',
        '}',
        'html.if-dark a:hover,',
        'html.if-dark a:hover *,',
        'html.if-dark a:hover font,',
        'html.if-dark a:hover b {',
        '  color: #4d87c2 !important;',
        '}',
        'html.if-dark .blockwidget a,',
        'html.if-dark .blockwidget a:hover,',
        'html.if-dark .isblocked a,',
        'html.if-dark .notblocked a,',
        'html.if-dark .itemCounter a {',
        '  color: #f5f5f5 !important;',
        '}',
        'html.if-dark a[class$="_hdr"],',
        'html.if-dark a[class$="_hdr"] *,',
        'html.if-dark .gallerylist table tr.head a,',
        'html.if-dark .gallerylist table tr.head a * {',
        '  color: #6cb6ff !important;',
        '}',
        'html.if-dark .gallerylist table tbody tr * {',
        '  background-color: #141414 !important;',
        '}',
        'html.if-dark .gallerylist table tbody tr td center img {',
        '  filter: invert(1) contrast(1.05) hue-rotate(170deg) opacity(50%) !important;',
        '  background: transparent !important;',
        '}',
        'html.if-dark a[class$="_hdr"]:visited,',
        'html.if-dark a[class$="_hdr"]:visited * {',
        '  color: #9aa8e8 !important;',
        '}',
        'html.if-dark a[class$="_hdr"]:hover,',
        'html.if-dark a[class$="_hdr"]:hover *,',
        'html.if-dark .gallerylist table tr.head a:hover,',
        'html.if-dark .gallerylist table tr.head a:hover * {',
        '  color: #b9dcff !important;',
        '}',
        'html.if-dark img._lazy {',
        ' border: none !important;',
        '}',
        'html.if-dark img.gal_thumb',
        'html.if-dark img.lazy',
        'html.if-dark #mainPhoto',
        'html.if-dark #slideshow img',
        'html.if-dark #gallery img',
        'html.if-dark #_navi_cavi img',
        'html.if-dark #playlist li.thumb img {',
        '  border: 0 !important;',
        '  padding: 0 !important;',
        '  background: transparent !important;',
        '  background-color: transparent !important;',
        '  box-shadow: none !important;',
        '}',
        '#if-dark-toggle {',
        '  position: fixed !important;',
        '  right: 12px !important;',
        '  bottom: 12px !important;',
        '  z-index: 2147483647 !important;',
        '  margin: 0 !important;',
        '  padding: 6px 6px !important;',
        '  background: #2a2a2a !important;',
        '  color: #e8e8e8 !important;',
        '  border: none !important;',
        '  border-radius: 50px !important;',
        '  font: 22px/1.2 Verdana, Tahoma, sans-serif !important;',
        '  cursor: pointer !important;',
        '}',
    ].join('\n');

    function applyRoot(on) {
        var root = document.documentElement;
        if (!root) return;
        root.classList.toggle('if-dark', !!on);
        root.classList.toggle('if-gray-media', !!on && GRAYSCALE_MEDIA);
        if (!on) unpaint();
    }

    function parseColor(c) {
        if (!c) return null;
        c = String(c).trim().toLowerCase();
        var m;
        if ((m = /^#([0-9a-f]{3})$/.exec(c))) {
            return [
                parseInt(m[1].charAt(0) + m[1].charAt(0), 16),
                parseInt(m[1].charAt(1) + m[1].charAt(1), 16),
                parseInt(m[1].charAt(2) + m[1].charAt(2), 16)
            ];
        }
        if ((m = /^#([0-9a-f]{6})$/.exec(c))) {
            return [
                parseInt(m[1].slice(0, 2), 16),
                parseInt(m[1].slice(2, 4), 16),
                parseInt(m[1].slice(4, 6), 16)
            ];
        }
        if ((m = /^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(c))) {
            return [+m[1], +m[2], +m[3]];
        }
        var named = {
            white: [255, 255, 255],
            black: [0, 0, 0],
            red: [255, 0, 0],
            blue: [0, 0, 255],
            green: [0, 128, 0],
            yellow: [255, 255, 0],
            gray: [128, 128, 128],
            grey: [128, 128, 128],
            silver: [192, 192, 192]
        };
        return named[c] || null;
    }

    // Light page colors fold into a short dark-gray ramp. Saturated blues become mid gray bars.
    function grayFor(rgb) {
        var y = (0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]) / 255;
        var sat = (Math.max(rgb[0], rgb[1], rgb[2]) - Math.min(rgb[0], rgb[1], rgb[2])) / 255;
        if (y < 0.16 && sat < 0.25) return null;
        var out;
        if (y >= 0.94) out = 20;
        else if (y >= 0.82) out = 34;
        else if (y >= 0.62) out = 42;
        else out = 56;
        var h = out.toString(16);
        if (h.length < 2) h = '0' + h;
        return '#' + h + h + h;
    }

    function declaredBackground(el) {
        var attr = el.getAttribute && el.getAttribute('bgcolor');
        if (attr) return attr;
        var style = el.getAttribute && el.getAttribute('style');
        if (!style || style.indexOf('background') === -1) return null;
        var m = /background(?:-color)?\s*:\s*([^;]+)/i.exec(style);
        if (!m) return null;
        var v = m[1];
        var hex = /#(?:[0-9a-f]{3}|[0-9a-f]{6})\b/i.exec(v);
        if (hex) return hex[0];
        var named = /\b(white|black|red|blue|green|yellow|gray|grey|silver)\b/i.exec(v);
        return named ? named[1] : null;
    }

    function paint(el) {
        if (!el || el.nodeType !== 1 || el.id === 'if-dark-toggle') return;
        if (el.hasAttribute('data-if-painted')) return;
        var raw = declaredBackground(el);
        if (!raw) return;
        var rgb = parseColor(raw);
        if (!rgb) return;
        var gray = grayFor(rgb);
        if (!gray) return;
        el.setAttribute('data-if-prev-bg', el.style.getPropertyValue('background-color') || '');
        el.setAttribute('data-if-prev-pri', el.style.getPropertyPriority('background-color') || '');
        el.setAttribute('data-if-painted', '1');
        el.style.setProperty('background-color', gray, 'important');
    }

    function scan(root) {
        if (!root || !document.documentElement.classList.contains('if-dark')) return;
        if (root.nodeType === 1) paint(root);
        if (!root.querySelectorAll) return;
        var nodes = root.querySelectorAll('[bgcolor], [style*="background"]');
        for (var i = 0; i < nodes.length; i++) paint(nodes[i]);
    }

    function unpaint() {
        var nodes = document.querySelectorAll('[data-if-painted]');
        for (var i = 0; i < nodes.length; i++) {
            var el = nodes[i];
            var prev = el.getAttribute('data-if-prev-bg');
            var pri = el.getAttribute('data-if-prev-pri');
            if (prev) el.style.setProperty('background-color', prev, pri || '');
            else el.style.removeProperty('background-color');
            el.removeAttribute('data-if-prev-bg');
            el.removeAttribute('data-if-prev-pri');
            el.removeAttribute('data-if-painted');
        }
    }

    function updateButton() {
        var b = document.getElementById('if-dark-toggle');
        if (!b) return;
        var on = document.documentElement.classList.contains('if-dark');
        b.textContent = on ? '🌞' : '🌙';
        b.setAttribute('aria-pressed', on ? 'true' : 'false');
    }

    function mountToggle() {
        if (document.getElementById('if-dark-toggle') || !document.body) return;
        var b = document.createElement('button');
        b.id = 'if-dark-toggle';
        b.type = 'button';
        b.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var on = !document.documentElement.classList.contains('if-dark');
            setOn(on);
            applyRoot(on);
            if (on) scan(document);
            updateButton();
        }, true);
        document.body.appendChild(b);
        updateButton();
    }

    applyRoot(isOn());

    var style = document.createElement('style');
    style.id = 'if-dark-style';
    style.textContent = CSS;
    document.documentElement.appendChild(style);

    function boot() {
        mountToggle();
        if (document.documentElement.classList.contains('if-dark')) scan(document);
        if (window.MutationObserver && document.body) {
            var obs = new MutationObserver(function (muts) {
                if (!document.documentElement.classList.contains('if-dark')) return;
                for (var i = 0; i < muts.length; i++) {
                    var added = muts[i].addedNodes;
                    for (var j = 0; j < added.length; j++) {
                        var n = added[j];
                        if (n.nodeType === 1 && n.id !== 'if-dark-toggle') scan(n);
                    }
                }
            });
            obs.observe(document.body, { childList: true, subtree: true });
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', boot);
    } else {
        boot();
    }
})();