Replace Dropdown Lists for Bangumi

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

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

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

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==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)
        );
    }
})();