Shikimori Filter Reset Button

Добавляет кнопку сброса всех выбранных фильтров на все страницы с фильтрацией

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name Shikimori Filter Reset Button
// @namespace http://tampermonkey.net/
// @version 5.3
// @description Добавляет кнопку сброса всех выбранных фильтров на все страницы с фильтрацией
// @author You
// @match https://shikimori.one/*
// @match https://shikimori.org/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
    'use strict';
    function rgbToArray(color) {
        return color.match(/\d+/g).map(Number);
    }
    function arrayToRgb(arr) {
        return `rgb(${arr[0]}, ${arr[1]}, ${arr[2]})`;
    }
    function darken(color, percent) {
        const rgb = rgbToArray(color);
        return arrayToRgb(rgb.map(v => Math.max(0, Math.floor(v * (1 - percent / 100)))));
    }
    function lighten(color, percent) {
        const rgb = rgbToArray(color);
        return arrayToRgb(rgb.map(v => Math.min(255, Math.floor(v + (255 - v) * (percent / 100)))));
    }
    function getBrightness(color) {
        const [r, g, b] = rgbToArray(color);
        return (r * 0.299 + g * 0.587 + b * 0.114);
    }
    function getActualBackgroundColor(el) {
        let cur = el;
        while (cur) {
            const bg = getComputedStyle(cur).backgroundColor;
            if (bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') {
                return bg;
            }
            cur = cur.parentElement;
        }
        return 'rgb(255,255,255)';
    }
    function getThemeColors(container) {
        const bgRaw = getActualBackgroundColor(container);
        const isLight = getBrightness(bgRaw) > 128;
        const text = isLight ? '#000000' : '#ffffff';
        const border = isLight ? '#000000' : '#ffffff';
        const borderHover = border;
        const baseAdjust = 5;
        const hoverAdjust = 10;
        const bg = isLight ? darken(bgRaw, baseAdjust) : lighten(bgRaw, baseAdjust);
        const bgHover = isLight ? darken(bgRaw, hoverAdjust) : lighten(bgRaw, hoverAdjust);
        return { bg, bgHover, border, borderHover, text };
    }
    const SELECTORS_FOR_BUTTON = [
        '#user_rates_index > section > div > div > div.menu-slide-outer.x199 > div > aside > div:nth-child(3) > div.subheadline',
        '.b-collection-filters > aside > div:nth-child(3) > div.subheadline',
        '.b-collection-filters aside .subheadline'
    ];
    const INSERT_BEFORE = true;
    function createResetButton(targetElement) {
        const container = targetElement.closest('aside') || document.body;
        const theme = getThemeColors(container);
        const btn = document.createElement('div');
        btn.id = 'custom-reset-filters-btn';
        btn.className = 'block';
        btn.style.cssText = `
            padding: 12px 15px !important;
            margin: 15px 0 !important;
            background: ${theme.bg} !important;
            border: 1px solid ${theme.border} !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            text-align: center !important;
            transition: all 0.2s !important;
            user-select: none !important;
            z-index: 1000 !important;
        `;
        btn.innerHTML = `<div style="color:${theme.text};font-size:13px;font-weight:600;">Сбросить все фильтры</div>`;
        const textEl = btn.firstChild;
        btn.addEventListener('mouseenter', () => {
            const th = getThemeColors(container);
            btn.style.background = th.bgHover;
            btn.style.borderColor = th.borderHover;
        });
        btn.addEventListener('mouseleave', () => {
            const th = getThemeColors(container);
            btn.style.background = th.bg;
            btn.style.borderColor = th.border;
        });
        btn.addEventListener('click', () => {
            const th = getThemeColors(container);
            textEl.textContent = 'Сброс...';
            btn.style.background = th.bgHover;
            const url = new URL(location.href);
            url.searchParams.forEach((_, k) => {
                if (!['order', 'page'].includes(k)) url.searchParams.delete(k);
            });
            const path = url.pathname.replace(/\/(status|genre|kind|season|rating|mylist|studio|publisher|duration|airdate|block|search)\/[^/]+/g, '');
            location.href = path + url.search + url.hash;
        });
        return btn;
    }
    function findTargetElement() {
        for (let sel of SELECTORS_FOR_BUTTON) {
            const el = document.querySelector(sel);
            if (el) return el;
        }
        const fc = document.querySelector('.b-collection-filters');
        return fc ? fc.querySelector('.subheadline') : null;
    }
    function addResetButton() {
        if (document.getElementById('custom-reset-filters-btn')) return false;
        const target = findTargetElement();
        if (!target) return false;
        const btn = createResetButton(target);
        target.parentNode.insertBefore(btn, INSERT_BEFORE ? target : target.nextSibling);
        return true;
    }
    function isFilterPage() {
        return location.pathname.includes('/list/') || !!document.querySelector('.b-collection-filters');
    }
    function init() {
        if (!isFilterPage()) return;
        if (addResetButton()) return;
        let tries = 0;
        const iv = setInterval(() => {
            if (addResetButton() || tries++ > 50) clearInterval(iv);
        }, 100);
    }
    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
    else init();
    const obs = new MutationObserver(() => { if (isFilterPage() && !document.getElementById('custom-reset-filters-btn')) init(); });
    obs.observe(document.body, { childList: true, subtree: true });
    setInterval(() => { if (isFilterPage() && !document.getElementById('custom-reset-filters-btn')) init(); }, 500);
})();