☰

ImageFap Dark Mode

Dark theme for ImageFap with a toggle.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Вам потребуется установить расширение, например Tampermonkey или Violentmonkey, чтобы установить этот скрипт.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например 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();
    }
})();