NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name AniList - Show advanced scores in list // @namespace https://anilist.co/ // @downloadURL https://openuserjs.org/install/flxemt/AniList_-_Show_advanced_scores_in_list.user.js // @updateURL https://openuserjs.org/meta/flxemt/AniList_-_Show_advanced_scores_in_list.meta.js // @version 1.1 // @description Hover over a score in a user's list to view advanced scores // @author lumiuko // @match https://anilist.co/* // @grant none // @license MIT // ==/UserScript== (async function() { 'use strict'; let lastCheckedUrlPath = null; let additionalCSS = document.createElement('style'); document.head.appendChild(additionalCSS); additionalCSS.appendChild(document.createTextNode(`.list-entries > .entry.row .score::before { margin-left: 80px; }`)); const observer = new MutationObserver((mutations, observer) => { let pathname = window.location.pathname; if (lastCheckedUrlPath === pathname) return; lastCheckedUrlPath = pathname; if (lastCheckedUrlPath.includes('/animelist') || lastCheckedUrlPath.includes('/mangalist')) applyChanges(); }); const target = document.querySelector('head > title'); observer.observe(target, { childList: true, characterData: true }); })(); function applyChanges() { let waitForLoading = setInterval(() => { if (document.querySelectorAll('.list-entries > .entry.row').length) { clearInterval(waitForLoading); const query = ` query ($name: String) { User (name: $name) { mediaListOptions { animeList { advancedScoringEnabled } } } } `; const variables = { name: document.querySelector('.banner-content .name').innerText } const url = 'https://graphql.anilist.co'; const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: query, variables: variables }) }; fetch(url, options).then(res => { return res.json().then(json => { return res.ok ? json : Promise.reject(json); }); }).then(data => { if (data.data.User.mediaListOptions.animeList.advancedScoringEnabled) { document.querySelectorAll('.list-entries > .entry.row').forEach(entry => addNotes(entry)); const observer = new MutationObserver((mutations, observer) => { mutations.forEach(mutation => { if (mutation.addedNodes[0]) addNotes(mutation.addedNodes[0]); }); }); observer.observe(document.querySelector('.medialist'), { childList: true, characterData: true, subtree: true }); } }); } }, 500); } function addNotes(entry) { const scoreItem = entry.querySelector('.score'); if (scoreItem.getAttribute('score') != 0) { scoreItem.classList.add('notes'); scoreItem.style.marginLeft = 0; scoreItem.setAttribute('label', 'Loading...'); scoreItem.addEventListener('mouseover', () => { getData(scoreItem); }); } } function getData(item) { if (item.getAttribute('label') !== 'Loading...') return; const query = ` query ($name: String, $mediaId: Int, $type: MediaType) { MediaList (userName: $name, mediaId: $mediaId, type: $type) { userId, score, advancedScores } } `; const variables = { name: document.querySelector('.banner-content .name').innerText, mediaId: item.previousElementSibling.firstElementChild.href.match(/(anime|manga)\/(\d{1,})/)[2], type: item.previousElementSibling.firstElementChild.href.match(/(anime|manga)\/(\d{1,})/)[1].toUpperCase(), } const url = 'https://graphql.anilist.co'; const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: query, variables: variables }) }; fetch(url, options).then(res => { return res.json().then(json => { return res.ok ? json : Promise.reject(json); }); }).then(data => { let score = ''; if (!Object.values(data.data.MediaList.advancedScores).filter(item => item > 0).length) score = 'No Advanced Scores'; else { for (let [key, value] of Object.entries(data.data.MediaList.advancedScores)) { if (value !== 0) score += `${key}: ${value}\n`; } } item.setAttribute('label', score); }); }