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