您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Accurately sorts your anime list by progress, and displays correct progress percentages for each anime.
// ==UserScript== // @name MAL (MyAnimeList) - Accurate Progress & Sorting On Anime List // @version 3.4 // @author Ezektor // @description Accurately sorts your anime list by progress, and displays correct progress percentages for each anime. // @match http*://myanimelist.net/animelist/* // @grant none // @icon https://cdn.myanimelist.net/img/sp/icon/apple-touch-icon-256.png // @namespace https://gf.zukizuki.org/users/1414348 // ==/UserScript== (function() { 'use strict'; let isSortingEnabled = false; let originalRows = []; let sortDirection = 'desc'; const toggleButton = document.createElement('button'); toggleButton.innerHTML = '➖ Default'; toggleButton.style.position = 'fixed'; toggleButton.style.bottom = '20px'; toggleButton.style.right = '20px'; toggleButton.style.padding = '10px'; toggleButton.style.backgroundColor = '#9e9e9e'; toggleButton.style.color = 'white'; toggleButton.style.border = 'none'; toggleButton.style.borderRadius = '5px'; toggleButton.style.cursor = 'pointer'; toggleButton.style.zIndex = '9999'; document.body.appendChild(toggleButton); function isAllAnimePage() { return window.location.href.includes('/animelist/') && window.location.href.includes('?status=7'); } function calculateProgress(row) { const progressCell = row.querySelector('.data.progress'); if (!progressCell) return 0; const progressText = progressCell.innerText.trim(); const [watched, total] = progressText.replace(/\[[^\]]*\]/g, '').split('/').map(s => parseInt(s.trim(), 10) || 0); return total == null ? 100 : total === 0 ? 0 : Math.floor((watched / total) * 100); } function addProgressPercentage(row) { const progressCell = row.querySelector('.data.progress'); if (!progressCell) return; const progressText = progressCell.innerText.trim(); if (/^\d+$/.test(progressText)) return; const existingPercentage = progressCell.querySelector('.progress-percentage') if (existingPercentage) { existingPercentage.remove(); } const progressPercentage = calculateProgress(row); const progressPercentageElement = document.createElement('div'); progressPercentageElement.style.fontSize = '12px'; progressPercentageElement.style.marginTop = '5px'; progressPercentageElement.classList.add('progress-percentage'); progressPercentageElement.textContent = `${progressPercentage}% progress`; if (progressPercentage <= 33) { progressPercentageElement.style.color = '#f44336'; } else if (progressPercentage <= 66) { progressPercentageElement.style.color = '#ff9800'; } else { progressPercentageElement.style.color = '#4caf50'; } progressCell.appendChild(progressPercentageElement); } function sortRowsByProgress(rows, direction) { return [...rows].sort((a, b) => { const progressA = calculateProgress(a); const progressB = calculateProgress(b); const isCompletedA = a.querySelector('.data.status').classList.contains('completed'); const isCompletedB = b.querySelector('.data.status').classList.contains('completed'); const isDroppedA = a.querySelector('.data.status').classList.contains('dropped'); const isDroppedB = b.querySelector('.data.status').classList.contains('dropped'); if (isAllAnimePage()) { if (isDroppedA && !isDroppedB) return 1; if (!isDroppedA && isDroppedB) return -1; if (isCompletedA && !isCompletedB) return direction === 'desc' ? -1 : 1; if (!isCompletedA && isCompletedB) return direction === 'desc' ? 1 : -1; } return direction === 'asc' ? progressA - progressB : progressB - progressA; }); } function updateTable(sortedRows) { const table = document.querySelector('table'); const tbody = table.querySelector('tbody.list-item'); tbody.innerHTML = ''; sortedRows.forEach(row => tbody.appendChild(row)); } function restoreOriginalOrder() { const table = document.querySelector('table'); const tbody = table.querySelector('tbody.list-item'); tbody.innerHTML = ''; originalRows.forEach(row => tbody.appendChild(row)); } function storeOriginalRows() { const rows = document.querySelectorAll('tbody.list-item .list-table-data'); originalRows = [...rows]; } function main() { const rows = document.querySelectorAll('tbody.list-item .list-table-data'); rows.forEach(addProgressPercentage); if (isSortingEnabled) { const sortedRows = sortRowsByProgress(rows, sortDirection); updateTable(sortedRows); } } toggleButton.addEventListener('click', () => { if (!isSortingEnabled) { isSortingEnabled = true; sortDirection = 'desc'; toggleButton.style.backgroundColor = '#4CAF50'; toggleButton.innerHTML = 'Sorting In: 📉 Descending Order'; main(); } else if (sortDirection === 'desc') { sortDirection = 'asc'; toggleButton.innerHTML = 'Sorting In: 📈 Ascending Order'; main(); } else { isSortingEnabled = false; toggleButton.style.backgroundColor = '#9e9e9e'; toggleButton.innerHTML = '➖ Default'; restoreOriginalOrder(); } }); window.addEventListener('load', () => { storeOriginalRows(); main(); }); })();