Replace Dropdown Lists for Bangumi

调整页面上的下拉列表选项顺序,保留原本的默认值,并按首字母排序,并且使用懒加载功能

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         Replace Dropdown Lists for Bangumi
// @name:zh-CN   bangumi下拉列表排序
// @namespace    https://github.com/Adachi-Git/ReplaceDropdownListsForBangumi
// @version      0.6
// @description  调整页面上的下拉列表选项顺序,保留原本的默认值,并按首字母排序,并且使用懒加载功能
// @author       Adachi
// @match        *://bangumi.tv/subject/*
// @match        *://bgm.tv/subject/*
// @match        *://chii.in/subject/*
// @grant        none
// @license MIT
// ==/UserScript==
(function() {
    'use strict';

    var delay = 2000; // 设置延迟执行时间,单位是毫秒

    // 汉字拼音首字母映射表
    var pinyinMap = {
        '原': 'Y',
        '总': 'Z',
        '导': 'D',
        '副': 'F',
        '脚': 'J',
        '分': 'F',
        '主': 'Z',
        '演': 'Y',
        '音': 'Y',
        '人': 'R',
        '构': 'G',
        '系': 'X',
        '美': 'M',
        '色': 'S',
        '机': 'J',
        '道': 'D',
        '作': 'Z',
        '动': 'D',
        '摄': 'S',
        'C': 'C',
        '3': '3',
        '监': 'J',
        '第': 'D',
        'O': 'O',
        '制': 'Z',
        '背': 'B',
        '数': 'S',
        '剪': 'J',
        '插': 'C',
        '企': 'Q',
        '宣': 'X',
        '录': 'L',
        '製': 'Z',
        '设': 'S',
        '特': 'T',
        '配': 'P',
        '联': 'L',
        '补': 'B',
        '执': 'Z',
        '助': 'Z',
        '台': 'T',
        '后': 'H',
        '协': 'X',
        '连': 'L',
        '译': 'Y',
        '客': 'K',
        '文': 'W',
        '出': 'C',
        '改': 'G',
        '前': 'Q',
        '续': 'X',
        '全': 'Q',
        '番': 'F',
        '相': 'X',
        '不': 'B',
        '衍': 'Y',
        '角': 'J',
        '其': 'Q',
        '开': 'K',
        '发': 'F',
        '游': 'Y',
        '剧': 'J',
        'S': 'S',
        '程': 'C',
        'Q': 'Q',
        '关': 'G',
        '创': 'C',
        '编': 'B',
        '共': 'G',
        '故': 'G',
        '艺': 'Y',
        '厂': 'C',
        '片': 'P',
        '印': 'Y',
        '广': 'G',
    };

    // 定义一个函数来处理下拉列表的逻辑
    function adjustSelectOptions(select) {
        // 保存原本的默认值
        var defaultValue = select.value;

        // 获取所有选项并转换为数组
        var optionsArray = Array.from(select.options);

        // 移除所有选项
        optionsArray.forEach(function(option) {
            select.remove(option.index);
        });

        // 按汉字的拼音首字母排序选项数组
        optionsArray.sort(function(a, b) {
            var pinyinA = pinyinMap[a.textContent[0]];
            var pinyinB = pinyinMap[b.textContent[0]];

            // 如果拼音首字母不存在,则将其视为 -Infinity,确保空值被放到列表的最上面
            pinyinA = pinyinA ? pinyinA : -Infinity;
            pinyinB = pinyinB ? pinyinB : -Infinity;

            // 排序时忽略空值
            if (pinyinA === -Infinity && pinyinB === -Infinity) {
                return 0;
            } else if (pinyinA === -Infinity) {
                return -1;
            } else if (pinyinB === -Infinity) {
                return 1;
            } else {
                return pinyinA.localeCompare(pinyinB);
            }
        });

        // 将重新排序后的选项重新添加到下拉列表中,并在选项文本前添加拼音首字母
        optionsArray.forEach(function(option) {
            var originalText = option.textContent;
            var pinyin = pinyinMap[originalText[0]];

            // 如果拼音首字母存在,则在文本前添加拼音首字母;否则只保留原始文本
            option.textContent = (pinyin ? pinyin + ' - ' : '') + originalText;
            select.add(option);
        });

        // 保留原本的默认值
        select.value = defaultValue;
    }

    // 延迟执行处理函数
    setTimeout(function() {
        // 查找可见的下拉列表并处理它们
        var selects = document.querySelectorAll('select[name^="infoArr"]:not([data-adjusted])');
        selects.forEach(function(select) {
            if (isElementInViewport(select)) {
                adjustSelectOptions(select);
                select.setAttribute('data-adjusted', 'true');
            }
        });
    }, delay);

    // 添加 DOM 变化的监听器
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            // 查找新增的下拉列表并处理
            var newSelects = mutation.target.querySelectorAll('select[name^="infoArr"]:not([data-adjusted])');
            newSelects.forEach(function(newSelect) {
                if (isElementInViewport(newSelect)) {
                    adjustSelectOptions(newSelect);
                    newSelect.setAttribute('data-adjusted', 'true');
                }
            });
        });
    });

    // 监听整个文档的变化
    observer.observe(document.documentElement, {
        childList: true,
        subtree: true
    });

    // 添加滚动事件监听器
    window.addEventListener('scroll', function() {
        // 查找尚未处理的下拉列表
        var selects = document.querySelectorAll('select[name^="infoArr"]:not([data-adjusted])');
        selects.forEach(function(select) {
            // 如果该下拉列表在视图内,进行处理并标记为已处理
            if (isElementInViewport(select)) {
                adjustSelectOptions(select);
                select.setAttribute('data-adjusted', 'true');
            }
        });
    });

    // 检查元素是否在视图内
    function isElementInViewport(element) {
        var rect = element.getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
    }
})();