// ==UserScript==
// @name Aniscripts
// @namespace http://tampermonkey.net/
// @version 4.64
// @description Change stuff on Anilist.co
// @author hoh
// @match https://anilist.co/*
// @grant GM_xmlhttpRequest
// @license GPLv3
// @downloadURL none
// ==/UserScript==
(function(){
"use strict";
const scriptInfo = {
"version" : "4.64",
"link" : "https://greasyfork.org/en/scripts/370473-aniscripts",
"author" : "hoh",
"authorLink" : "https://anilist.co/user/hoh/",
"license" : "GPLv3"
};
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
*/
/*
"useScripts" contains the defauls for the various modules. This is stored in the user's localStorage.
*/
//a shared style node for all the modules. All classes are prefixed by "hoh" to avoid collisions with native Anilist classes
var style = document.createElement("style");
style.type = "text/css";
//The default colour is rgb(var(--color-blue)) provided by Anilist, but rgb(var(--color-green)) is preferred for things related to manga
style.textContent = `
.hohTime{
position: absolute;
right: 12px;
top: 6px;
font-size: 1.1rem;
}
.hohUnread{
border-right: 8px;
border-color: rgba(var(--color-blue));
border-right-style: solid;
}
.hohNotification{
margin-bottom: 10px;
background: rgb(var(--color-foreground));
border-radius: 4px;
justify-content: space-between;
line-height: 0;
min-height: 72px;
position: relative;
}
.hohNotification *{
line-height: 1.15;
}
.hohUserImageSmall{
display: inline-block;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
position: absolute;
}
.hohUserImage{
height: 72px;
width: 72px;
display: inline-block;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
position: absolute;
}
.hohMediaImage{
height: 70px;
margin-right: 5px;
}
.hohMessageText{
position: absolute;
margin-top: 30px;
margin-left: 80px;
max-width: 330px;
}
.hohMediaImageContainer{
vertical-align: bottom;
margin-left: 400px;
display: inline;
position: relative;
display: inline-block;
min-height: 70px;
}
.hohMediaImageContainer > a{
height: 70px;
line-height: 0!important;
}
span.hohMediaImageContainer{
line-height: 0!important;
}
.hohCommentsContainer{
margin-top: 5px;
}
.hohCommentsArea{
margin: 10px;
display: none;
padding-bottom: 2px;
margin-top: 5px;
width: 95%;
}
.hohComments{
float: right;
display: none;
margin-top: -30px;
margin-right: 15px;
cursor: pointer;
margin-left: 600px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.hohCombined .hohComments{
display: none!important;
}
.hohQuickCom{
padding: 5px;
background-color: rgb(var(--color-background));
margin-bottom: 5px;
position: relative;
}
.hohQuickComName{
margin-right: 15px;
color: rgb(var(--color-blue));
}
.hohThisIsMe{
color: rgb(var(--color-green));
}
.hohILikeThis{
color: rgb(var(--color-red));
}
.hohQuickComName::after{
content: ":";
}
.hohQuickComContent{
margin-right: 40px;
display: block;
}
.hohQuickComContent > p{
margin: 1px;
}
.hohQuickComLikes{
position: absolute;
right: 5px;
bottom: 5px;
display: inline-block;
}
.hohQuickComContent img {
max-width: 100%;
}
.hohSpoiler::before{
color: rgb(var(--color-blue));
cursor: pointer;
background: rgb(var(--color-background));
border-radius: 3px;
content: "Spoiler, click to view";
font-size: 1.3rem;
padding: 0 5px;
}
.hohSpoiler.hohClicked::before{
display: none;
}
.hohSpoiler > span{
display: none;
}
.hohMessageText > span > div.time{
display: none;
}
.hohUnhandledSpecial > div{
margin-top: -15px;
}
.hohMonospace{
font-family: monospace;
}
.hohSocialTabActivityCompressedContainer{
min-width: 480px;
}
.hohSocialTabActivityCompressedStatus{
vertical-align: middle;
padding-bottom: 7px;
}
.hohSocialTabActivityCompressedName{
vertical-align: middle;
margin-left: 3px;
}
.hohForumHider{
margin-right: 3px;
cursor: pointer;
font-family: monospace;
}
.hohForumHider:hover{
color: rgb(var(--color-blue));
}
.hohBackgroundCover{
height: 70px;
width: 50px;
display: inline-block;
background-repeat: no-repeat;
background-size: cover;
margin-top: 1px;
line-height: 0;
margin-bottom: 1px;
}
#hohDescription{
width: 280px;
height: 150px;
float: left;
color: rgb(var(--color-blue));
}
.hohStatsTrigger{
cursor: pointer;
border-radius: 3px;
color: rgb(var(--color-text-lighter));
display: block;
font-size: 1.4rem;
margin-bottom: 8px;
padding: 5px 10px;
}
.hohActive{
background: rgba(var(--color-foreground),.8);
color: rgb(var(--color-text));
font-weight: 500;
}
#hohFavCount{
position: absolute;
right: 30px;
color: rgba(var(--color-red));
top: 10px;
font-weight: 400;
}
.hohShamelessLink{
display: block;
margin-bottom: 5px;
}
.hohSlidePlayer{
display: block;
position: relative;
width: 500px;
}
.hohSlide{
position: absolute;
top: 0px;
font-size: 500%;
height: 100%;
display: flex;
align-items: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity:0.5;
}
.hohSlide:hover{
background-color: rgb(0,0,0,0.4);
cursor: pointer;
opacity:1;
}
.hohRightSlide{
right: 0px;
padding-left: 10px;
padding-right: 20px;
}
.hohLeftSlide{
left: 0px;
padding-left: 20px;
padding-right: 10px;
}
.hohShare{
position: absolute;
right: 12px;
top: 30px;
cursor: pointer;
color: rgb(var(--color-blue-dim));
}
.activity-entry{
position: relative;
}
.hohEmbed{
border-style: solid;
border-color: rgb(var(--color-text));
border-width: 1px;
padding: 15px;
position: relative;
}
.hohEmbed .avatar{
border-radius: 3px;
height: 40px;
width: 40px;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
display: inline-block;
}
.hohEmbed .name{
display: inline-block;
height: 40px;
line-height: 40px;
vertical-align: top;
color: rgb(var(--color-blue));
font-size: 1.4rem;
margin-left: 12px !important;
}
.hohEmbed .time{
color: rgb(var(--color-text-lighter));
font-size: 1.1rem;
position: absolute;
right: 12px;
top: 12px;
}
.hohRecsLabel{
color: rgb(var(--color-blue)) !important;
}
.hohRecsItem{
margin-top: 5px;
margin-bottom: 10px;
}
.hohTaglessLinkException{
display: block;
}
.hohTaglessLinkException::after{
content: ""!important;
}
.hohStatValue{
color: rgb(var(--color-blue));
}
.markdown-editor > [title="Image"],
.markdown-editor > [title="Youtube Video"],
.markdown-editor > [title="WebM Video"]{
color: rgba(var(--color-red));
}
.hohBackgroundUserCover{
height: 70px;
width: 70px;
display: inline-block;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
margin-top: 1px;
margin-bottom: 1px;
}
.history-day.lv-9{
z-index:1!important
}
.hohRegularTag{
border-style: solid;
border-width: 1px;
border-radius: 3px;
padding: 2px;
margin-right: 3px;
}
.hohTableHider{
cursor: pointer;
margin: 4px;
color: rgb(var(--color-blue));
}
.hohCross{
cursor: pointer;
margin-left: 2px;
color: red;
}
.hohFavCountBrowse{
color: white;
position: absolute;
right: 2px;
font-size: 60%;
opacity: 0.7;
}
.hohColourPicker{
position: absolute;
right: 60px;
margin-top: -110px;
}
.hohColourPicker h2{
color: #3db4f2;
font-size: 1.6rem;
font-weight: 400;
padding-bottom: 12px;
}
.hohSecondaryRow{
background-color: rgb(var(--color-background));
}
.hohSecondaryRow:hover{
background-color: rgb(var(--color-foreground));
}
.media-preview-card meter{
width: 150px;
margin-bottom: 5px;
}
.sidebar .tags .tag{
min-height: 35px;
margin-bottom: 5px !important;
}
.custom-lists .el-checkbox__label{
display: inline !important;
white-space: pre-wrap;
white-space: -webkit-pre-wrap;
white-space: normal;
word-wrap: anywhere;
word-break: break-all;
}
.hohStatusDot{
position: absolute;
width: 10px;
height: 10px;
border-radius: 50px;
}
.hohStatusDotRight{
top: 2px;
right: 2px;
}
.studio .container.header{
position: relative;
}
.studio .favourite{
position: absolute;
top: 10px;
right: 30px;
}
.filter .view-all{
background-color: rgb(var(--color-foreground));
height: 32px;
border-radius: 3px;
text-align: center;
padding-top: 8px;
}
.title > a{
line-height: 1.15!important;
}
.embed .title{
line-height: 18px!important;
}
#dubNotice{
font-size: 12px;
font-weight: 500;
text-align: center;
text-transform: capitalize;
background: rgb(var(--color-foreground));
margin-top: 0em;
margin-bottom: 16px;
border-radius: 3px;
padding: 8px 12px;
}
#hohDraw3x3{
margin-top: 5px;
cursor: pointer;
}
.hohDisplayBox{
position: fixed;
top: 80px;
left: 200px;
z-index: 999;
padding: 20px;
background-color: rgb(var(--color-foreground));
}
.hohDisplayBoxClose{
position: absolute;
right: 20px;
top: 20px;
cursor: pointer;
background-color: red;
}
.hohFeedFilter{
position: absolute;
top: 2px;
font-size: 1.4rem;
font-weight: 500;
}
.hohFeedFilter input{
width: 55px;
}
div.page-content > div > div.header-wrap > div.nav-wrap > div > a:nth-child(5):after{
content: "/Script";
}
.actions .list .add{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.list-wrap .section-name,
.quick-search input[placeholder="Search AniList"]{
text-transform: none;
}
.list-wrap{
counter-reset: animeCounter;
}
.medialist.table.compact .entry .title::before{
counter-increment: animeCounter;
content: counter(animeCounter);
display: inline-block;
margin-right: 4px;
margin-left: -17px;
opacity: 0.2;
text-align: right;
width: 25px;
min-width: 25px;
font-size: 70%;
}
.hohEnumerateStaff{
position: absolute;
margin-left: -12px;
margin-top: 10px;
}
#hohMALscore{
padding-bottom: 14px;
}
#hohMALscore .type{
font-size: 1.3rem;
font-weight: 500;
padding-bottom: 5px;
}
#hohMALscore .value{
color: rgb(var(--color-text-lighter));
font-size: 1.2rem;
line-height: 1.3;
}
.hohMediaScore{
color: rgb(var(--color-text-lighter));
font-size: 1.2rem;
position: absolute;
top: -10px;
}
.forum-thread .like .button{
margin-right: 0px!important;
}
#hohFilters{
margin-top: 5px;
margin-bottom: 5px;
}
#hohFilters input{
width: 55px;
margin: 5px;
}
.hohCompare{
margin-top: 10px;
counter-reset: animeCounterComp;
position: relative;
}
.hohCompare .hohUserRow,
.hohCompare .hohHeaderRow{
background: rgb(var(--color-foreground));
}
.hohCompare table,
.hohCompare th,
.hohCompare td{
border-top-width: 0px;
border-bottom-width: 1px;
border-right-width: 1px;
border-left-width: 0px;
border-style: solid;
border-color: black;
padding: 5px;
}
.hohCompare table{
background: rgb(var(--color-foreground-grey));
border-spacing: 0px;
margin-top: 10px;
border-right: none;
border-bottom: none;
}
.hohUserRow td,
.hohUserRow th{
min-width: 120px;
border-top-width: 1px;
}
.hohHeaderRow td,
.hohHeaderRow th{
border-top: none;
}
.hohUserRow input{
width: 100px;
}
.hohUserRow img{
width: 30px;
height: 30px;
border-radius: 2px;
}
tr.hohAnimeTable:nth-child(2n+1) td{
background-color: rgb(var(--color-foreground));
}
.hohAnimeTable,
.hohAnimeTable td{
position: relative;
}
.hohAnimeTable .hohStatusDot{
top: calc(50% - 5px);
right: 5px;
}
.hohHeaderRow .hohStatusDot{
background: rgb(var(--color-background));
top: calc(50% - 5px);
right: 5px;
cursor: pointer;
}
.hohStatusProgress{
position: absolute;
left: 60px;
top: calc(50% - 5px);
font-size: 60%;
}
.hohAnimeTable > td:nth-child(1)::before{
counter-increment: animeCounterComp;
content: counter(animeCounterComp) ". ";
position: absolute;
left: 1px;
text-align: right;
width: 40px;
color: rgb(var(--color-blue));
}
.hohAnimeTable > td:nth-child(1){
padding-left: 43px;
border-left-width: 1px;
}
.hohUserRow > td:nth-child(1),
.hohHeaderRow > th:nth-child(1){
border-left: solid;
border-left-width: 1px;
border-color: black;
}
.hohArrowSort{
font-size: 3rem;
cursor: pointer;
margin-left: 4px;
margin-right: 4px;
}
.hohFilterSort{
cursor: pointer;
border-width: 1px;
border-style: solid;
padding: 2px;
borderRadius: 4px;
}
.hohArrowSort:hover,
.hohFilterSort:hover{
color: rgb(var(--color-blue));
}
.hohAnimeTableRemove{
cursor: pointer;
position: absolute;
top: 0px;
right: 0px;
}
.hohCheckbox.el-checkbox__input > span.el-checkbox__inner{
background-color: rgb(var(--color-foreground));
margin-right:10px;
border-color: rgba(var(--color-text),.2);
}
.hohCheckbox input:checked + .el-checkbox__inner{
background-color: #409eff;
border-color: #409eff;
}
.hohCheckbox input:checked + .el-checkbox__inner::after{
transform: rotate(45deg) scaleY(1);
}
.hohCheckbox input{
display: none;
}
.media-card .list-status[status="Repeating"]{
background: violet;
}
.sense-wrap{
display: none;
}
.hohDismiss{
cursor: pointer;
transform: translate(20px,-5px);
width: 10px;
height: 5px;
}
@media(max-width: 760px){
#hohMALscore{
padding-right: 25px;
}
#hohMALscore .type{
font-weight: 400;
}
#hohMALscore .value{
color: rgb(var(--color-text));
font-size: 1.4rem;
}
.hohMediaImageContainer{
position: absolute;
right: -22px;
max-height: 30px;
overflow: scroll;
}
.hohMediaImage{
height: 20px;
width: 20px;
margin-right: 0px
}
.hohNotification{
margin-right: 18px;
font-size: 1.5rem;
}
.hohCommentsContainer{
position: relative;
top: 70px;
}
.hohComments{
position: absolute;
right: -5px;
top: 10px;
}
.notifications-feed .filters p{
display: inline;
margin-left: 10px;
}
.activity-feed .actions{
font-size: 1.6rem;
}
}
`;
let documentHead = document.querySelector("head");
if(documentHead){
documentHead.appendChild(style);
}
else{
return;//xml documents or something. At least it's not a place where the script can run
}
var localStorageAvailable;//localStorage is great for not having to fetch the api data every time
var test = "test";
try{
localStorage.setItem(test,test);
localStorage.removeItem(test);
localStorageAvailable = true;
}
catch(e){
localStorageAvailable = false;
}
if(localStorageAvailable){
var aniscriptsUsed = localStorage.getItem("aniscriptsUsed");
if(aniscriptsUsed === null){
aniscriptsUsed = {
keys : []
};
}
else{
aniscriptsUsed = JSON.parse(aniscriptsUsed);
}
localStorage.setItem("aniscriptsUsed",JSON.stringify(aniscriptsUsed));
}
const notificationColourDefaults = {
"ACTIVITY_LIKE":{"colour":"rgb(250,122,122)","supress":false},
"ACTIVITY_REPLY_LIKE":{"colour":"rgb(250,122,122)","supress":false},
"THREAD_COMMENT_LIKE":{"colour":"rgb(250,122,122)","supress":false},
"THREAD_LIKE":{"colour":"rgb(250,122,122)","supress":false},
"THREAD_COMMENT_REPLY":{"colour":"rgb(61,180,242)","supress":false},
"ACTIVITY_REPLY":{"colour":"rgb(61,180,242)","supress":false},
"ACTIVITY_MESSAGE":{"colour":"rgb(123,213,85)","supress":false},
"FOLLOWING":{"colour":"rgb(123,213,85)","supress":false},
"ACTIVITY_MENTION":{"colour":"rgb(123,213,85)","supress":false},
"THREAD_COMMENT_MENTION":{"colour":"rgb(123,213,85)","supress":false},
"THREAD_SUBSCRIBED":{"colour":"rgb(247,191,99)","supress":false},
"AIRING":{"colour":"rgb(247,191,99)","supress":false}
};
var useScripts = {//most modules are turned on by default
notifications: true,
socialTab: true,
forumComments: true,
staffPages: true,
tagDescriptions: true,
completedScore: true,
droppedScore: false,
moreStats: true,
characterFavouriteCount: true,
studioFavouriteCount: true,
CSSfavs: true,
CSScompactBrowse: true,
CSSmangaGreen: false,
CSSfollowCounter: true,
CSSsubmissionCounter: false,
CSSprofileClutter: false,
CSSdecimalPoint: false,
CSSverticalNav: false,
hideLikes: false,
dubMarker: false,
CSSstudioStats: true,
CSSsmileyScore: true,
CSSexpandFeedFilters: false,
feedCommentFilter: false,
feedCommentComments: 0,
feedCommentLikes: 0,
colourPicker: true,
colourSettings: [],
mangaBrowse: false,
progressBar: false,
noRewatches: false,
hideCustomTags: false,
shortRomaji: false,
replaceNativeTags: true,
draw3x3: true,
limitProgress8: false,
limitProgress10: false,
tagIndex: true,
ALbuttonReload: true,
expandRight: false,
timeToCompleteColumn: false,
mangaGuess: true,
replaceStaffRoles: true,
settingsTip: true,
enumerateSubmissionStaff: true,
MALscore: false,
mobileFriendly: false,
entryScore: true,
activityTimeline: true,
browseFilters: true,
comparissionPage: true,
databaseStats: {//default numbers
"anime": 12881,
"manga": 44908,
"users": 267747,
"staff": 28160,
"characters": 70654,
"reviews": 2178,
"updated": 0
},
notificationColours: notificationColourDefaults,
staffRoleOrder: "alphabetical",
titleLanguage: "Romaji",
dubMarkerLanguage: "English",
accessToken: "",
};
var forceRebuildFlag = false;
useScripts.save = function(){
localStorage.setItem("hohSettings",JSON.stringify(useScripts));
};
if(localStorageAvailable){
const useScriptsSettings = JSON.parse(localStorage.getItem("hohSettings"));
if(useScriptsSettings){
var keys = Object.keys(useScriptsSettings);
keys.forEach(function(key){//this is to keep the default settings if the version in local storage is outdated
useScripts[key] = useScriptsSettings[key];
});
}
useScripts.save();
}
let whoAmI = "";
let whoAmIid = 0;
//replace with query selector?
try{//use later for some scripts
whoAmI = document.getElementById("nav").children[1].children[1].children[1].href.match(/[\w\-]*\/$/)[0].slice(0,-1);//looks at the nav
}
catch(err){
try{
whoAmI = document.querySelector(".menu [href^='/user/']").href.match(/\/user\/(.*)\//)[1];
}
catch(err2){
console.log("could not get username");
}
}
function safeURL(URL){
return encodeURIComponent(URL.replace(/\s|\//g,"-").replace(/(\.|\)|\\|#)/g,""));
}
Number.prototype.roundPlaces = function(places){
return +(
Math.round(
this * Math.pow(10,places)
) / Math.pow(10,places)
);
}
function create(type,classes,text,appendLocation,cssText){
let element = document.createElement(type);
if(Array.isArray(classes)){
element.classList.add(...classes);
}
else if(classes){
if(classes[0] === "#"){
element.id = classes.substring(1);
}
else{
element.classList.add(classes);
}
};
if(text){
element.innerText = text;
};
if(appendLocation){
appendLocation.appendChild(element);
};
if(cssText){
element.style.cssText = cssText;
};
return element;
};
function createCheckbox(target){
let hohCheckbox = create("label",["hohCheckbox","el-checkbox__input"],false,target);
let checkbox = create("input",false,false,hohCheckbox);
checkbox.type = "checkbox";
create("span","el-checkbox__inner",false,hohCheckbox);
return checkbox;
}
const svgAssets = {
envelope : "✉",
cross : "✕",
frown : `
`,
meh : `
`,
smile : `
`,
star : `
`,
//the column sorting arrow
angleDown : `
`,
view : `
`,
reply : `
`,
repeat : `
`,
external : `
`
};
const distributionColours = {
"COMPLETED" : "rgb(104, 214, 57)",
"CURRENT" : "rgb( 2, 169, 255)",
"PAUSED" : "rgb(247, 121, 164)",
"DROPPED" : "rgb(232, 93, 117)",
"PLANNING" : "rgb(247, 154, 99)",
"REPEATING" : "violet"
};
if(useScripts.mangaBrowse){
const navLinks = document.querySelector(".links");
for(var i=0;i .wrap > .footer > .container");
if(colourPickerLocation){
const supportedColours = [
"--color-background",
"--color-foreground",
"--color-foreground-grey",
"--color-foreground-grey-dark",
"--color-foreground-blue",
"--color-foreground-blue-dark",
"--color-background-blue-dark",
"--color-overlay",
"--color-shadow",
"--color-shadow-dark",
"--color-text",
"--color-text-light",
"--color-text-lighter",
"--color-text-bright",
"--color-blue",
"--color-blue-dim",
"--color-white",
"--color-black",
"--color-red",
"--color-peach",
"--color-orange",
"--color-yellow",
"--color-green"
];
let colourChanger = function(){
for(var i=0;i a${dataSelect}
,a.title${dataSelect}
,.overlay > a.title${dataSelect}
,.media-preview-card a.title${dataSelect}
,.quick-search-results .el-select-dropdown__item a${dataSelect}> span
,.media-embed${dataSelect} .title
,.status > a.title${dataSelect}
,.role-card a.content${dataSelect} > .name{
visibility: hidden;
font-size: 2%;
line-height: 0px;
}
a.title${dataSelect}::before
,.quick-search-results .el-select-dropdown__item a${dataSelect} > span::before
,.role-card a.content${dataSelect} > .name::before
,.title > a${dataSelect}::before
,.home .status > a.title${dataSelect}::before
,.media-embed${dataSelect} .title::before
,.overlay > a.title${dataSelect}::before
,.media-preview-card a.title${dataSelect}::before{
content:"${targetName}"
}`;
}
}
const shortRomaji = [
["/anime/30/","Evangelion"],
["/anime/32/","End of Evangelion"],
["/anime/5114/","FMA:B"],
["/anime/10620/","Mirai Nikki"],
["/anime/1575/","Code Geass"],
["/anime/2904/","Code Geass R2"],
["/anime/21355/","Re:Zero"],
["/anime/2001/","Gurren Lagann"],
["/anime/21202/","Konosuba!"],
["/anime/21699/","Konosuba! 2"],
["/anime/21574/","Konosuba!: Kono Subarashii Choker ni Shufuku wo!"],
["/anime/9756/","Madoka★Magica"],
["/anime/9989/","AnoHana"],
["/anime/20623/","Kiseijuu"],
["/anime/14741/","Chuunibyou!"],
["/anime/18671/","Chuunibyou! 2"],
["/anime/14813/","OreGairu"],
["/anime/20920/","Danmachi"],
["/anime/8074/","HIGHSCHOOL OF THE DEAD"],
["/anime/849/","Haruhi"],
["/anime/4382/","Haruhi (2009)"],
["/anime/19603/","Unlimited Blade Works"],
["/anime/20792/","Unlimited Blade Works 2"],
["/anime/8769/","OreImo"],
["/anime/10020/","OreImo Specials"],
["/anime/13659/","OreImo 2"],
["/anime/18857/","OreImo 2 Specials"],
["/anime/2025/","Darker than BLACK"],
["/anime/20698/","OreGairu 2"],
["/anime/16592/","Danganronpa"],
["/anime/16742/","WataMote"],
["/anime/101291/","Bunny Girl-senpai"],
["/anime/104157/","Bunny Girl-senpai Movie"],
["/anime/19221/","NouKome"],
["/anime/45/","Rurouni Kenshin"],
["/anime/8795/","Panty & Stocking"],
["/anime/21860/","Sukasuka"],
["/anime/33/","Berserk"],
["/anime/97938/","Boruto"],
["/anime/97907/","Death March"],
["/anime/100183/","Gun Gale Online"],
["/anime/20474/","JoJo: Stardust Crusaders"],
["/anime/20799/","JoJo: Stardust Crusaders - Egypt-hen"],
["/anime/21450/","JoJo: Diamond wa Kudakenai"],
["/anime/102883/","JoJo: Ougon no Kaze"],
["/anime/101921/","Kaguya-sama wa Kokuraseta"],
["/anime/101166/","Danmachi: Orion no Ya"],
["/anime/20791/","Heaven’s Feel I. presage flower"],
["/anime/21718/","Heaven’s Feel II. lost butterfly"],
["/anime/21719/","Heaven’s Feel III. spring song"],
["/anime/1089/","Macross: Ai Oboete Imasu ka"],
["/anime/572/","Nausicaa"],
["/anime/513/","Laputa"],
["/anime/44/","Rurouni Kenshin: Tsuioku-hen"],
["/anime/528/","Mewtwo no Gyakushuu"],
["/anime/530/","Sailor Moon"],
["/anime/740/","Sailor Moon R"],
["/anime/532/","Sailor Moon S"],
["/anime/1239/","Sailor Moon SuperS"],
["/anime/996/","Sailor Moon Sailor Stars"],
["/anime/949/","Gunbuster!"],
["/anime/18677/","Yuushibu"],
["/manga/86635/","Kaguya-sama wa Kokurasetai"],
["/anime/17074/","Monogatari Second Season"],
["/anime/20910/","Shimoseka"]
];
let aliasFlag = false;
if(useScripts.shortRomaji){
shortRomaji.forEach(createAlias);
aliasFlag = true;
}
if(localStorageAvailable){
const titleAliases = JSON.parse(localStorage.getItem("titleAliases"));
if(titleAliases){
aliasFlag = true;
titleAliases.forEach(createAlias);
}
}
if(aliasFlag){
moreStyle.textContent += `
a.title::before
,.quick-search-results .el-select-dropdown__item a > span::before{
visibility: visible;
font-size: 5000%;
line-height: 1.15;
margin-right: 2px;
}
.medialist.table .title > a::before{
visibility: visible;
font-size: 1.5rem;
margin-right: 2px;
}
.medialist.compact .title > a::before
,.medialist.cards .title > a::before
,.home .status > a.title::before
,.media-embed .title::before{
visibility: visible;
font-size: 1.3rem;
margin-right: 2px;
}
.role-card a.content > .name::before{
visibility: visible;
font-size: 1.2rem;
}
.overlay > a.title::before
,.media-preview-card a.title::before{
visibility: visible;
font-size: 1.4rem;
line-height: 1.15;
}
.role-card a.content > .name{
line-height: 1.3!important;
}`;
}
if(useScripts.CSSfavs || useScripts.CSSstudioStats){
/*adds a logo to most favourite studio entries. Add more if needed */
const favStudios = [
[1, "Studio-Pierrot", "https://upload.wikimedia.org/wikipedia/en/thumb/1/10/Studio_Pierrot.jpg/220px-Studio_Pierrot.jpg","studio"],
[2, "Kyoto-Animation", "https://upload.wikimedia.org/wikipedia/en/thumb/b/bf/Kyoto_Animation_logo.svg/250px-Kyoto_Animation_logo.svg.png","studio"],
[3, "GONZO", "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Gonzo_company.png/220px-Gonzo_company.png","studio"],
[4, "BONES", "https://i.stack.imgur.com/7pRQn.png","studio"],
[5, "Bee-Train", "https://upload.wikimedia.org/wikipedia/commons/4/45/Bee_Train.svg","studio"],
[6, "Gainax", "https://upload.wikimedia.org/wikipedia/en/thumb/a/a8/Gainax_logo.svg/220px-Gainax_logo.svg.png","studio"],
[7, "JC-Staff", "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/J.C.Staff_Logo.svg/220px-J.C.Staff_Logo.svg.png","studio"],
[8, "Artland", "https://upload.wikimedia.org/wikipedia/en/thumb/a/ae/Artland_logo.gif/200px-Artland_logo.gif","studio"],
[10, "Production-IG", "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Production_I.G_Logo.svg/250px-Production_I.G_Logo.svg.png","studio"],
[11, "MADHOUSE", "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Madhouse_studio_logo.svg/300px-Madhouse_studio_logo.svg.png","studio"],
[13, "Studio-4C", "https://upload.wikimedia.org/wikipedia/en/e/ec/Studio_4C_logo.png","studio"],
[14, "Sunrise", "https://upload.wikimedia.org/wikipedia/en/thumb/8/8c/Sunrise_company_logo.svg/220px-Sunrise_company_logo.svg.png","studio"],
[17, "Aniplex", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Aniplex_logo.svg/220px-Aniplex_logo.svg.png",""],
[18, "Toei-Animation", "https://i.stack.imgur.com/AjzVI.png","studio",76,30],
[21, "Studio-Ghibli", "https://upload.wikimedia.org/wikipedia/en/thumb/c/ca/Studio_Ghibli_logo.svg/220px-Studio_Ghibli_logo.svg.png","studio",76,30],
[22, "Nippon-Animation", "https://upload.wikimedia.org/wikipedia/en/thumb/b/b4/Nippon.png/200px-Nippon.png","studio"],
[25, "Milky-Animation-Label", "https://img.fireden.net/a/image/1467/16/1467164781976.png","studio"],
[27, "Xebec", "https://upload.wikimedia.org/wikipedia/fr/b/bd/Logo_Xebec.svg","studio"],
[28, "Oriental-Light-and-Magic","https://i.stack.imgur.com/Sbllv.png","studio"],
[32, "Manglobe", "https://i.imgur.com/W8U74wO.png","studio"],
[34, "Hal-Film-Maker", "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Hal_film_maker_logo.gif/220px-Hal_film_maker_logo.gif","studio"],
[35, "Seven-Arcs", "https://upload.wikimedia.org/wikipedia/en/a/ac/Seven_Arcs_logo.png","studio",76,25],
[36, "Studio-Gallop", "https://upload.wikimedia.org/wikipedia/commons/3/37/Studio_Gallop.png","studio"],
[37, "Studio-DEEN", "https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Studio_Deen_logo.svg/220px-Studio_Deen_logo.svg.png","studio"],
[38, "Arms", "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Arms_Corporation.png/200px-Arms_Corporation.png","studio"],
[41, "Satelight", "https://i.stack.imgur.com/qZVQg.png","studio",76,30],
[43, "ufotable", "https://upload.wikimedia.org/wikipedia/en/5/56/Ufotable-Logo.png","studio",76,30],
[44, "Shaft", "https://i.stack.imgur.com/tuqhK.png","studio"],
[45, "Pink-Pineapple", "https://i.stack.imgur.com/2NMQ0.png","studio"],
[47, "Studio-Khara", "https://i.stack.imgur.com/2d1TT.png","studio",76,30],
[48, "AIC", "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/AIC_logo.png/220px-AIC_logo.png","studio"],
[51, "diomeda", "https://i.stack.imgur.com/ZHt3T.jpg","studio"],
[53, "Dentsu", "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Dentsu_logo.svg/200px-Dentsu_logo.svg.png",""],
[58, "Square-Enix", "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Square_Enix_logo.svg/230px-Square_Enix_logo.svg.png",""],
[65, "Tokyo-Movie-Shinsha", "https://upload.wikimedia.org/wikipedia/en/2/22/Tokyo_Movie_Shinsha.png","studio"],
[66, "Key", "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Key_Visual_Arts_Logo.svg/167px-Key_Visual_Arts_Logo.svg.png","",76,25],
[68, "Mushi-Productions", "https://i.stack.imgur.com/HmYdT.jpg","studio"],
[73, "TMS-Entertainment", "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/TMS_Entertainment_logo.svg/220px-TMS_Entertainment_logo.svg.png","studio"],
[79, "Genco", "https://www.thefilmcatalogue.com/assets/company-logos/5644/logo_en.png",""],
[86, "Group-TAC", "https://upload.wikimedia.org/wikipedia/commons/b/b7/Group_TAC.png","studio"],
[91, "feel", "https://upload.wikimedia.org/wikipedia/en/thumb/0/07/Feel_%28company%29_logo.png/220px-Feel_%28company%29_logo.png","studio",76,25],
[95, "Doga-Kobo", "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Doga_Kobo_Logo.svg/220px-Doga_Kobo_Logo.svg.png","studio"],
[97, "ADV-Films", "https://upload.wikimedia.org/wikipedia/en/4/45/A.D._Vision_%28logo%29.png","licensor"],
[102, "FUNimation-Entertainment","https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Funimation_2016.svg/320px-Funimation_2016.svg.png","licensor"],
[103, "Tatsunoko-Production", "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Tatsunoko_2016_logo.png/300px-Tatsunoko_2016_logo.png","studio"],
[104, "Lantis", "https://upload.wikimedia.org/wikipedia/commons/3/39/Lantis_logo.png",""],
[108, "Media-Factory", "https://i.stack.imgur.com/rR7yU.png","",76,25],
[112, "Brains-Base", "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Brain%27s_Base_logo.png/200px-Brain%27s_Base_logo.png","studio"],
[113, "Kadokawa-Shoten", "https://i.stack.imgur.com/ZsUDR.gif",""],
[119, "Viz-Media", "https://upload.wikimedia.org/wikipedia/en/thumb/e/e9/Viz_Media_logo.png/220px-Viz_Media_logo.png","licensor"],
[132, "PA-Works", "https://i.stack.imgur.com/7kjSn.png","studio"],
[143, "Mainichi-Broadcasting", "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Mainichi_Broadcasting_System_logo.svg/200px-Mainichi_Broadcasting_System_logo.svg.png",""],
[144, "Pony-Canyon", "https://i.stack.imgur.com/9kkew.png",""],
[145, "TBS", "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/TBS_logo.svg/200px-TBS_logo.svg.png",""],
[150, "Sanrio", "https://upload.wikimedia.org/wikipedia/en/thumb/4/41/Sanrio_logo.svg/220px-Sanrio_logo.svg.png",""],
[159, "Kodansha", "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Kodansha.png/200px-Kodansha.png",""],
[166, "Movic", "https://upload.wikimedia.org/wikipedia/commons/f/f3/Movic_logo.png",""],
[167, "Sega", "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Sega_logo.svg/200px-Sega_logo.svg.png",""],
[169, "Fuji-TV", "https://upload.wikimedia.org/wikipedia/en/thumb/e/e9/Fuji_TV_logo.svg/225px-Fuji_TV_logo.svg.png","",76,30],
[193, "Idea-Factory", "https://upload.wikimedia.org/wikipedia/en/e/eb/Idea_factory.gif",""],
[196, "Production-Reed", "https://upload.wikimedia.org/wikipedia/fr/7/7d/Production_Reed_Logo.png","studio"],
[199, "Studio-Nue", "https://i.stack.imgur.com/azzKH.png","studio"],
[200, "Tezuka-Productions", "https://upload.wikimedia.org/wikipedia/fr/f/fe/Tezuka_Productions_Logo.png","studio"],
[217, "The-Right-Stuf-International","","licensor"],
[238, "ATX", "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/AT-X_logo.svg/150px-AT-X_logo.svg.png","",76,30],
[247, "ShinEi-Animation", "https://i.stack.imgur.com/b2lcL.png","studio"],
[250, "Media-Blasters", "","licensor"],
[262, "Kadokawa-Pictures-USA", "https://i.stack.imgur.com/ZsUDR.gif",""],
[284, "Central-Park-Media", "","licensor"],
[287, "David-Production", "https://upload.wikimedia.org/wikipedia/en/thumb/7/75/David_production.jpg/220px-David_production.jpg","studio",76,30],
[290, "Kinema-Citrus", "https://upload.wikimedia.org/wikipedia/commons/c/c0/Kinema_Citrus_logo.png","studio",76,25],
[291, "CoMix-Wave", "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Cwflogo.png/150px-Cwflogo.png","studio"],
[292, "AIC-Plus", "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/AIC_logo.png/220px-AIC_logo.png","studio"],
[300, "SILVER-LINK", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Silver_Link_Logo.svg/220px-Silver_Link_Logo.svg.png","studio"],
[309, "GoHands", "https://i.stack.imgur.com/pScIZ.jpg","studio"],
[314, "White-Fox", "https://i.stack.imgur.com/lwG1T.png","studio",76,30],
[333, "TYO-Animations", "https://i.stack.imgur.com/KRqAp.jpg","studio",76,25],
[334, "Ordet", "https://i.stack.imgur.com/evr12.png","studio",76,30],
[346, "Hoods-Entertainment", "https://i.stack.imgur.com/p7S0I.png","studio"],
[352, "Kadokawa-Pictures-Japan","https://i.stack.imgur.com/ZsUDR.gif",""],
[365, "PoRO", "https://i.stack.imgur.com/3rlAh.png","studio"],
[372, "NIS-America-Inc", "https://upload.wikimedia.org/wikipedia/en/e/e7/Nis.png","licensor"],
[376, "Sentai-Filmworks", "https://i.stack.imgur.com/JV8R6.png","licensor",74,30],
[397, "Bridge", "https://i.imgur.com/4Qn4EmK.png","studio"],
[415, "Warner-Bros", "","licensor"],
[417, "Walt-Disney-Studios", "","licensor"],
[418, "Studio-Gokumi", "https://i.stack.imgur.com/w1y22.png","studio"],
[436, "AIC-Build", "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/AIC_logo.png/220px-AIC_logo.png","studio"],
[437, "Kamikaze-Douga", "https://img7.anidb.net/pics/anime/178777.jpg",""],
[456, "Lerche", "https://i.stack.imgur.com/gRQPc.png","studio"],
[459, "Nitroplus", "https://upload.wikimedia.org/wikipedia/en/thumb/0/09/Nitroplus_logo.png/220px-Nitroplus_logo.png",""],
[467, "Discotek", "","licensor"],
[493, "Aniplex-of-America", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Aniplex_logo.svg/220px-Aniplex_logo.svg.png","licensor"],
[499, "The-Pokemon-Company-International","","licensor"],
[503, "Nintendo-Co-Ltd", "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Nintendo.svg/220px-Nintendo.svg.png",""],
[537, "SANZIGEN", "https://i.stack.imgur.com/CkuqH.png","",76,30],
[541, "Seven", "","studio"],
[555, "Studio-Chizu", "https://i.stack.imgur.com/h2RuH.gif","studio"],
[561, "A1-Pictures", "https://i.stack.imgur.com/nBUYo.png","studio",76,30],
[569, "MAPPA", "https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/MAPPA_Logo.svg/220px-MAPPA_Logo.svg.png","studio"],
[681, "ASCII-Media-Works", "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/ASCII_Media_Works_logo.svg/220px-ASCII_Media_Works_logo.svg.png",""],
[803, "Trigger", "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Trigger_Logo.svg/220px-Trigger_Logo.svg.png","studio"],
[783, "GKids", "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/GKIDS_logo.svg/150px-GKIDS_logo.svg.png","licensor"],
[829, "Studio-Jack", "","studio"],
[839, "LIDENFILMS", "https://upload.wikimedia.org/wikipedia/en/6/6e/LidenFilms.png","studio",76,30],
[858, "Wit-Studio", "https://i.stack.imgur.com/o3Rro.png","studio",76,30],
[911, "Passione", "https://i.stack.imgur.com/YyEGg.jpg","studio"],
[2524,"4Kids-Entertainment", "","licensor"],
[4418,"8bit", "https://upload.wikimedia.org/wikipedia/en/e/ea/8-Bit_Animation_Studio.png","studio"],
[6069,"Studio-3Hz", "https://i.stack.imgur.com/eD0oe.jpg","studio"],
[6071,"Studio-Shuka", "https://upload.wikimedia.org/wikipedia/commons/f/fa/Shuka_studio.jpg","studio"],
[6077,"Orange", "https://i.stack.imgur.com/ve9mm.gif","studio"],
[6142,"Geno-Studio", "https://upload.wikimedia.org/wikipedia/en/thumb/f/f4/Genostudio.jpg/220px-Genostudio.jpg","",76,25],
[6145,"Science-SARU", "https://i.stack.imgur.com/zo9Fx.png","studio"],
[6222,"CloverWorks", "https://i.stack.imgur.com/9Fvr7.jpg","studio"],
[6225,"TriF-studio", "https://i.stack.imgur.com/lL85s.png","studio",60,50],
[6235,"SEK-Studio", "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Flag_of_North_Korea.svg/125px-Flag_of_North_Korea.svg.png","studio",74,25]
];
let favStudioString = "";
if(useScripts.CSSfavs){
favStudioString += `
.favourites > div > .wrap > div,
.favourites > div > .wrap > a{
/*make the spaces in the grid even*/
margin-bottom: 0px!important;
margin-right: 0px!important;
column-gap: 10px!important;
}
.user .overview{
grid-template-columns: 460px auto!important;
}
.favourites > div > .wrap{
padding: 0px!important;
display: grid;
grid-gap: 10px;
column-gap: 10px!important;
grid-template-columns: repeat(auto-fill,85px);
grid-template-rows: repeat(auto-fill,115px);
background: rgb(0,0,0,0) !important;
width: 470px;
}
.favourite.studio{
cursor: pointer;
min-height: 115px;
font-size: 15px;
display: grid;
grid-gap: 10px;
padding: 2px!important;
padding-top: 8px!important;
background-color: rgba(var(--color-foreground))!important;
text-align: center;
align-content: center;
}
.site-theme-dark .favourite.studio{
background-color: rgb(49,56,68)!important;
}
.favourite.studio::after{
display: inline-block;
background-repeat: no-repeat;
content:"";
margin-left:5px;
background-size: 76px 19px;
width: 76px;
height: 19px;
}`;
favStudios.forEach(function(studio){
if(studio[2] !== ""){
favStudioString += `.favourite.studio[href="/studio/${studio[0]}/${studio[1]}"]::after{background-image: url("${studio[2]}");`;
if(studio.length === 6){
favStudioString += `background-size: ${studio[4]}px ${studio[5]}px;width: ${studio[4]}px;height: ${studio[5]}px;`;
}
favStudioString += "}";
}
});
}
if(useScripts.CSSstudioStats){
favStudios.forEach(function(studio){
if(studio[3] === "studio"){
favStudioString += `.stats-wrap .row a[href="/studio/${studio[0]}/${studio[1]}"],`;
}
});
favStudioString = favStudioString.replace(/,$/,"");
favStudioString += "{color:rgb(var(--color-blue))}";
favStudios.forEach(function(studio){
if(studio[3] === "licensor"){
favStudioString += `.stats-wrap .row a[href="/studio/${studio[0]}/${studio[1]}"],`;
}
});
favStudioString = favStudioString.replace(/,$/,"");
favStudioString += "{color:rgb(var(--color-green))}";
}
moreStyle.textContent += favStudioString;
}
if(useScripts.CSScompactBrowse){
moreStyle.textContent += `
.search-page-unscoped.container{
padding-left: 10px;
padding-right: 0px;
}
.search-page-unscoped .description{
display: none;
}
.search-page-unscoped .preview-section,
.search-page-unscoped,
.results > .studio{
counter-reset: ranking;
}
.search-page-unscoped .character,
.search-page-unscoped .staff{
position: relative;
}
.search-page-unscoped .data::before,
.search-page-unscoped .results > .character .cover::before,
.search-page-unscoped .results > .staff .cover::before{
left: 2px;
opacity: 0.4;
font-size: 70%;
position: absolute;
counter-increment: ranking;
content: counter(ranking);
}
.search-page-unscoped .media-card{
min-width: 150px!important;
grid-template-columns: 150px auto!important;
height: 297px!important;
width: 150px !important;
}
.search-page-unscoped .cover .overlay{
padding-left: 8px!important;
padding-right: 8px!important;
padding-top: 4px!important;
padding-bottom: 14px!important;
}
.search-page-unscoped .grid-wrap > .media-card{
margin-left: 30px;
}
.search-page-unscoped .media-card .cover{
width: 150px;
height: 215px;
margin-top: 53px;
z-index: 100;
}
.search-page-unscoped .data{
margin-left: -150px;
}
.search-page-unscoped .genres{
min-height:29px;
z-index: 101;
padding: 8px 5px!important;
padding-bottom: 2px !important;
font-size: 1rem!important;
line-height: 1.15;
}
.search-page-unscoped .list-edit{
z-index: 101;
}
.search-page-unscoped .airing-countdown{
padding: 5px!important;
}
.search-page-unscoped .grid-wrap{
grid-template-columns: repeat(auto-fill, 150px) !important;
}
.search-page-unscoped .media{
grid-template-columns: repeat(auto-fill, 150px) !important;
width:100%;
}
.search-page-unscoped .overlay .studio{
margin-top: 2px!important;
margin-bottom: -8px!important;
}
.search-page-unscoped .list-status{
width: 20px!important;
height: 20px!important;
}
.search-page-unscoped .media-card:nth-child(5){
display: inline-grid!important;
}
`;
}
if(useScripts.CSSsubmissionCounter){
moreStyle.textContent += `
.submissions-wrap{
counter-reset: acceptedCount partialCount pendingCount rejectedCount;
}
.submissions-wrap .submission .status.accepted{
counter-increment: acceptedCount;
}
.submissions-wrap .submission .status.accepted::after{
content: counter(acceptedCount);
}
.submissions-wrap .submission .status.pending{
counter-increment: pendingCount;
}
.submissions-wrap .submission .status.pending::after{
content: counter(pendingCount);
}
.submissions-wrap .submission .status.partially_accepted{
counter-increment: partialCount;
}
.submissions-wrap .submission .status.partially_accepted::after{
content: counter(partialCount);
}
.submissions-wrap .submission .status.rejected{
counter-increment: rejectedCount;
}
.submissions-wrap .submission .status.rejected::after{
content: counter(rejectedCount);
}
.submissions-wrap::after{
content: "pending: " counter(pendingCount) ", accepted: " counter(acceptedCount) ", partially accepted: " counter(partialCount) ", rejected: " counter(rejectedCount);
}
`;
}
if(useScripts.CSSprofileClutter){
moreStyle.textContent += `
.overview .list-stats > .footer{
display: none;
}
.overview > .section > .desktop:nth-child(2){
display: none;
}
.overview > .section > .desktop:nth-child(3){
display: none;
}
.overview > .section > .desktop.favourites{
display: inherit;
}
`;
}
if(useScripts.CSSgreenManga){
moreStyle.textContent += `
.activity-manga_list > div > div > div > div > .title{
color: rgba(var(--color-green))!important;
}
.media .relations .cover[href^="/manga/"] + div div{
color: rgba(var(--color-green));
}
.media .relations .cover[href^="/anime/"] + div div{
color: rgba(var(--color-blue));
}
.media .relations .cover[href^="/manga/"]{
border-bottom-style: solid;
border-bottom-color: rgba(var(--color-green));
border-bottom-width: 2px;
}
.media .relations.small .cover[href^="/manga/"]::after{
position:absolute;
left:1px;
bottom:3px;
content:"";
border-style: solid;
border-color: rgba(var(--color-green));
border-width: 2px;
}
.media .relations .cover[href^="/anime/"]{
border-bottom-style: solid;
border-bottom-color: rgba(var(--color-blue));
border-bottom-width: 2px;
}
.media .relations .cover div.image-text{
margin-bottom: 2px!important;
border-radius: 0px!important;
padding-bottom: 8px!important;
padding-top: 8px!important;
font-weight: 500!important;
}
.media-embed[data-media-type="manga"] .title{
color: rgba(var(--color-green));
}
`;
}
if(useScripts.CSSexpandFeedFilters && (!useScripts.mobileFriendly)){
moreStyle.textContent += `
.home .activity-feed-wrap .section-header .el-dropdown-menu {
background: none;
position: static;
display: inline !important;
margin-right: 15px;
box-shadow: none !important;
}
.home .activity-feed-wrap .section-header .el-dropdown-menu__item {
font-weight: normal;
color: rgb(var(--color-text-lighter));
margin-left: -2px !important;
display: inline;
font-size: 1.2rem;
padding: 4px 15px 5px 15px;
border-radius: 3px;
transition: .2s;
}
.home .activity-feed-wrap .section-header .el-dropdown-menu__item.active{
background: none!important;
color: rgb(var(--color-blue));
}
.home .activity-feed-wrap .section-header .el-dropdown-menu__item:hover{
background: none!important;
color: rgb(var(--color-blue));
}
.home .feed-select .feed-filter{
display: none;
}
`;
}
if(useScripts.CSSverticalNav && (!useScripts.mobileFriendly)){
moreStyle.textContent += `
.logo{
margin-left: -60px!important;
/*the compact layout uses more of the space to the side, so we line up the logo to the left*/
}
.footer{
margin-top: 0px !important;
/*less space wasted over the footer*/
}
.container{
padding-left: 10px;
padding-right: 0px;
}
.hide{
top: 0px!important;
/*stop that top bar from jumping all over the place*/
}
.notification{
margin-bottom: 10px!important;
}
/*Dropdown menus are site theme based*/
.quick-search .el-select .el-input .el-input__inner,
.quick-search .el-select .el-input.is-focus .el-input__inner,
.el-select-dropdown,
.el-dropdown-menu,
.el-dropdown-menu__item--divided::before{
background: rgba(var(--color-foreground));
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover{
background: rgba(159, 173, 189, .2);
}
.el-dropdown-menu__item--divided{
border-color: rgba(var(--color-background));
}
.el-select-group__wrap:not(:last-of-type)::after{
background: rgba(var(--color-foreground));
}
.el-popper[x-placement^="bottom"] .popper__arrow,
.el-popper[x-placement^="bottom"] .popper__arrow::after{
border-bottom-color: rgba(var(--color-foreground));
}
.el-popper[x-placement^="top"] .popper__arrow,
.el-popper[x-placement^="top"] .popper__arrow::after{
border-top-color: rgba(var(--color-foreground));
}
/*Additions to dark theme dropdown*/
.site-theme-dark .quick-search.el-select .el-input.el-input__inner,
.site-theme-dark .quick-search .el-select .el-input.is-focus .el-input__inner,
.site-theme-dark .el-select-dropdown,
.site-theme-dark .el-dropdown-menu,
.site-theme-dark .el-dropdown-menu__item--divided::before{
background: rgba(17, 22, 29);
}
.site-theme-dark .el-select-group__wrap:not(:last-of-type)::after{
background: rgba(17, 22, 29);
}
.site-theme-dark .el-popper[x-placement^="bottom"] .popper__arrow,
.site-theme-dark .el-popper[x-placement^="bottom"] .popper__arrow::after{
border-bottom-color: rgba(17, 22, 29);
opacity: 1;
}
.site-theme-dark .el-popper[x-placement^="top"] .popper__arrow,
.site-theme-dark .el-popper[x-placement^="top"] .popper__arrow::after{
border-top-color: rgba(17, 22, 29);
opacity: 1;
}
/*--------------VERTICAL-NAV----------------*/
/*modified code from Kuwabara: https://userstyles.org/styles/161017/my-little-anilist-theme-can-not-be-this-cute*/
.hohDismiss{
transform: translate(17.5px,-40px);
}
div#nav{
width: 65px;
height: 100%;
position: fixed!important;
top: 0!important;
left: 0!important;
transition: none!important;
}
div#nav.transparent{
background: rgba(var(--color-nav))!important;
}
.nav .wrap .links{
font-size: 1rem;
height: 355px;
margin-left: 0px;
padding-left: 0px;
width: 65px;
flex-direction: column;
}
.nav .wrap .links .link{
width: 65px;
padding: 5px 0px;
margin-bottom: 10px;
text-align: center;
/*color: rgba(var(--color-blue),0.6);*/
transition: 0.3s;
}
.nav .wrap .links .link:hover{
background: rgba(var(--color-blue),0.1);
}
.nav .wrap .links .link::before{
display: block;
content: "";
height: 24px;
width: 65px;
background-size: 24px;
margin-left: 0;
margin-bottom: 3px;
background-repeat: no-repeat;
background-position: center;
filter: grayscale(100%) brightness(1.4);
}
.nav .link[href*="/user/"]:hover::before,
.nav .link[href^="/forum/"]:hover::before,
.nav .link[href^="/search/"]:hover::before,
.nav .link[href^="/home"]:hover::before{
filter: grayscale(0%);
}
.nav .link[href="/home"]::before{
background: url('data:image/svg+xml;utf8,');
}
.nav .link[href^="/user/"]::before{
background: url('data:image/svg+xml;utf8,');
}
.nav .link[href*="/animelist"]::before,
.nav .link[href*="/mangalist"]::before{
background: url('data:image/svg+xml;utf8,');
}
.nav .link[href^="/search/"]::before{
background: url('data:image/svg+xml;utf8,');
}
.nav .link[href*="/forum"]::before{
background: url('data:image/svg+xml;utf8,');
}
div#nav.transparent{
background: #1f2631!important;
}
#app{
margin-top: 0;
padding-left: 65px;
}
.nav .user{
position: fixed;
top: 0;
display: grid;
grid-gap: 40px;
width: 65px;
grid-template-rows: 50px 20px;
}
.search .dropdown.el-dropdown{
font-size: 10px;
}
.search .el-dropdown-link svg{
width: 65px;
height: 23px;
padding: 5px 0;
background: rgba(0, 0, 0, 0.2);
}
.nav .search{
width: 65px;
margin: 0;
text-align: center;
position: fixed;
top: 56px;
}
.quick-search-results{
z-index: 999!important;
top: 136px!important;
}
.user .avatar:hover+.chevron{
opacity: 0!important;
}
.hide{
top:0px!important;
}
/*-------------------*/
::selection{
background: rgba(var(--color-blue),0.4);
}
::-webkit-selection{
background: rgba(var(--color-blue),0.4);
}
::-moz-selection{
background: rgba(var(--color-blue),0.4);
}
::-webkit-scrollbar{
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb{
background: #4e4e4e!important;
}
#app{
overflow:unset;
}
.user .header-wrap{
position: sticky;
top: -332px;
z-index: 100;
}
.list-stats{
margin-bottom:0px!important;
}
.activity-feed-wrap{
margin-top:25px;
}
.logo{
position: absolute;
margin-bottom: -500px;
display:none!important;
margin-left: 0px !important;
}
/*home stuff*/
.reply .header a.name[href="/user/Abyss/"]::after{
content: "Prima Undine";
margin-left:10px;
padding:3px;
border-radius:2px;
animation-duration: 20s;
animation-iteration-count: infinite;
animation-name: rainbow;
animation-timing-function: ease-in-out;
color: rgba(var(--color-white));
}
.reply .header a.name[href="/user/Taluun/"]::after{
content: "Best Friend";
margin-left:10px;
padding:3px;
border-radius:2px;
animation-duration: 20s;
animation-iteration-count: infinite;
animation-name: rainbow;
animation-timing-function: ease-in-out;
color: rgba(var(--color-white));
}
.details > .donator-badge{
left:105px!important;
padding:2px!important;
top: 100%!important;
-ms-transform: translate(0px, -34px);
-webkit-transform: translate(0px, -34px);
transform: translate(0px, -34px);
}
.activity-text > div > div > div > .donator-badge{
position:relative!important;
display:inline-block!important;
left:0px!important;
top:-10px!important;
-ms-transform: translate(0px, 0px);
-webkit-transform: translate(0px, 0px);
transform: translate(0px, 0px);
}
.activity-replies{
margin-top:5px!important;
margin-left:30px!important;
margin-right:0px!important;
}
.activity-entry{
margin-bottom: 10px!important;
}
.list-preview{
grid-gap: 10px!important;
padding:0px!important;
background: rgb(0,0,0,0)!important;
}
.home{
grid-column-gap: 30px!important;
margin-top: 20px!important;
grid-template-columns: auto 470px!important;
}
.activity-feed .reply{
padding:8px!important;
margin-bottom: 5px!important;
}
.list .details{
padding-left:10px!important;
padding-top:5px!important;
padding: 10px 16px!important;
padding-bottom: 7px !important;
}
.search{
margin-top:0px!important;
}
.emoji-spinner{
display:none!important;
}
.wrap{
border-radius: 2px!important;
}
.name{
margin-left: 0px!important;
}
.activity-text > div > div > div > .name{
margin-left: 12px!important;
}
.button{
margin-right: 5px!important;
}
.actions{
margin-bottom: 5px!important;
bottom: 0px!important;
}
.status{
display: inline-block!important;
}
.avatar{
display: block!important;
}
/*https://anilist.co/activity/29333544*/
.activity-entry .header a:nth-child(1){
display: inline-block!important;
}
.wrap > .list{
min-height: 80px!important;
grid-template-columns: 60px auto!important;
}
.popper__arrow{
display: none!important;
}
.media-preview{
grid-gap: 10px!important;
padding: 0px!important;
background: rgb(0,0,0,0)!important;
}
.media-preview-card{
display: inline-grid!important;
}
.replies > .count{
color: rgba(var(--color-blue));
}
.action.likes{
color: unset;
}
.like-wrap > .button:hover{
color: rgba(var(--color-red));
}
.replies > *:nth-child(2){
color: rgba(var(--color-blue));
}
.actions{
cursor: default;
}
.activity-manga_list > div > div > div > div > .title{
color: rgba(var(--color-green))!important;
}
.markdown-editor > [title="Image"],
.markdown-editor > [title="Youtube Video"],
.markdown-editor > [title="WebM Video"]{
color: rgba(var(--color-red));
}
.markdown-editor > div > svg{
min-width: 1em!important;
}
.feed-select .toggle > div.active[data-v-f37b0a84]{
color: rgba(var(--color-blue))!important;
}
.home .details .status:first-letter,
.social .details .status:first-letter,
.activity-entry .details .status:first-letter{
text-transform: lowercase;
}
.activity-edit .markdown-editor,
.activity-edit .input{
margin-bottom: 10px!important;
}
.activity-edit .actions{
margin-bottom: 25px!important;
}
.like-wrap .users{
overflow-y: scroll!important;
}
.page-content .container .home.full-width{
grid-template-columns: unset !important;
}
.activity-text .text {
border-left: solid 5px rgba(var(--color-blue));
}
.section-header{
padding-left:0px!important;
}
.cover[href="/anime/440/Shoujo-Kakumei-Utena/"] + .details{
border-color: #eb609e;
border-width: 4px;
border-style: solid;
border-left-width: 0px;
}
.sticky .avatar, .sticky .body-preview,
.sticky .categories, .sticky .name{
display: none!important;
}
.search > .filter,
.search > .preview{
margin-top: 20px;
}
`;
}
if(useScripts.CSSdecimalPoint){
moreStyle.textContent += `
.medialist.POINT_10_DECIMAL .score[score="10"]::after,
.medialist.POINT_10_DECIMAL .score[score="9"]::after,
.medialist.POINT_10_DECIMAL .score[score="8"]::after,
.medialist.POINT_10_DECIMAL .score[score="7"]::after,
.medialist.POINT_10_DECIMAL .score[score="6"]::after,
.medialist.POINT_10_DECIMAL .score[score="5"]::after,
.medialist.POINT_10_DECIMAL .score[score="4"]::after,
.medialist.POINT_10_DECIMAL .score[score="3"]::after,
.medialist.POINT_10_DECIMAL .score[score="2"]::after,
.medialist.POINT_10_DECIMAL .score[score="1"]::after{
margin-left:-4px;
content: ".0";
}
`;
}
if(useScripts.CSSsmileyScore){
moreStyle.textContent += `
.fa-frown{
color: red;
}
.fa-smile{
color: green;
}
`;
}
if(useScripts.limitProgress8){
moreStyle.textContent += `
.home:not(.full-width) .media-preview-card:nth-child(n+9){
display:none!important;
}
`;
}
else if(useScripts.limitProgress10){
moreStyle.textContent += `
.home:not(.full-width) .media-preview-card:nth-child(n+11){
display:none!important;
}
`;
}
documentHead.appendChild(moreStyle);
const queryMediaList = `
query ($name: String!, $listType: MediaType) {
MediaListCollection (userName: $name, type: $listType) {
lists {
name
isCustomList
entries {
... mediaListEntry
}
}
}
}
fragment mediaListEntry on MediaList {
mediaId
status
progress
progressVolumes
repeat
notes
startedAt {
year
month
day
}
media {
episodes
chapters
volumes
duration
nextAiringEpisode {
episode
}
format
title {
romaji
}
tags {
name
}
genres
}
scoreRaw: score (format: POINT_100)
}
`;
const queryMediaListNotes = `
query ($name: String!, $listType: MediaType) {
MediaListCollection (userName: $name, type: $listType) {
lists {
entries {
... mediaListEntry
}
}
}
}
fragment mediaListEntry on MediaList {
mediaId
notes
}
`;
const queryActivity = `
query ($id: Int!) {
Activity(id: $id) {
... on TextActivity {
id
userId
type
text
user {
id
name
avatar {
large
}
}
likes {
id
}
replies {
text(asHtml: true)
user {
name
}
likes {
name
}
}
}
... on ListActivity {
id
userId
type
status
progress
user {
id
name
avatar {
large
}
}
media {
coverImage {
large
}
}
likes {
id
}
replies {
text(asHtml: true)
user {
name
}
likes {
name
}
}
}
... on MessageActivity {
id
type
likes {
id
}
replies {
text(asHtml: true)
user {
name
}
likes {
name
}
}
}
}
}
`;
const queryAuthNotifications = `
query ($page: Int,$name: String) {
User (name: $name){
unreadNotificationCount
}
Page (page: $page){
notifications {
... on AiringNotification {
type
}
... on FollowingNotification {
type
}
... on ActivityMessageNotification {
type
}
... on ActivityMentionNotification {
type
}
... on ActivityReplyNotification {
type
}
... on ActivityLikeNotification {
type
}
... on ActivityReplyLikeNotification {
type
}
... on ThreadCommentMentionNotification {
type
}
... on ThreadCommentReplyNotification {
type
}
... on ThreadCommentSubscribedNotification {
type
}
... on ThreadCommentLikeNotification {
type
}
... on ThreadLikeNotification {
type
}
}
}
}
`;
let APIlimit = 90;
let APIcallsUsed = 0;//this is NOT a reliable way to figure out how many more calls we can use, just a way to set some limit
let pending = {};
let APIcounter = setTimeout(function(){
APIcallsUsed = 0;
},60*1000);//reset counter every minute
let activityCache = {};//reduce API calls even if localStorage is not available.
let handleResponse = function(response){
APIlimit = response.headers.get("x-ratelimit-limit");
APIcallsUsed = APIlimit - response.headers.get("x-ratelimit-remaining");
return response.json().then(function(json){
return (response.ok ? json : Promise.reject(json));
});
};
const url = "https://graphql.anilist.co";//Current Anilist API location
const authUrl = "https://anilist.co/api/v2/oauth/authorize?client_id=1933&response_type=token";
function listActivityCall(query,variables,callback,vars,cache){
/*
query, graphql request
vars, just, values to pass on to the callback function
cache::true, use cached data if available
cache::false, allways fetch new data
*/
let handleData = function(data){
pending[variables.id] = false;
if(localStorageAvailable){
localStorage.setItem(variables.id + "",JSON.stringify(data));
aniscriptsUsed.keys.push(variables.id);
if(aniscriptsUsed.keys.length > 1000){//don't hog too much of localStorage
localStorage.removeItem(aniscriptsUsed.keys[0]);
aniscriptsUsed.keys.shift();
}
localStorage.setItem("aniscriptsUsed",JSON.stringify(aniscriptsUsed));
}
else{
activityCache[variables.id] = data;//still useful even if we don't have localstorage
}
callback(data,vars);
};
let options = {//generic headers provided by API examples
"method" : "POST",
"headers" : {
"Content-Type": "application/json",
"Accept": "application/json"
},
"body" : JSON.stringify({
"query": query,
"variables": variables
})
};
if(localStorageAvailable && cache){
let localStorageItem = localStorage.getItem(variables.id + "");
if(!(localStorageItem === null)){
callback(JSON.parse(localStorageItem),vars);
return;
}
}
else if(activityCache.hasOwnProperty(variables.id) && cache){
callback(activityCache[variables.id],vars);
return;
}
let handleError = function(error){
console.error(error,query,variables);
};
fetch(url,options).then(handleResponse).then(handleData).catch(handleError);
APIcallsUsed++;
};
function generalAPIcall(query,variables,callback){//has no cache stuff to worry about, use this for all other calls to the API
let handleData = function(data){
callback(data,variables);
};
let options = {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
"query": query,
"variables": variables
})
};
let handleError = function(error){
if(error.errors && error.errors[0].status === 404){//not really an error
return;
};
console.error(error,query,variables);
};
fetch(url,options).then(handleResponse).then(handleData).catch(handleError);
APIcallsUsed++;
}
function authAPIcall(query,variables,callback){//only use for auth
let handleData = function(data){
callback(data,variables);
};
let options = {
method: "POST",
headers: {
"Authorization": "Bearer " + useScripts.accessToken,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
"query": query,
"variables": variables
})
};
let handleError = function(error){
console.error(error);
error.errors.forEach(function(thing){
if(thing.message === "Invalid token"){
useScripts.accessToken = "";
useScripts.save();
console.log("access token retracted");
};
});
};
fetch(url,options).then(handleResponse).then(handleData).catch(handleError);
APIcallsUsed++;
}
function scoreFormatter(score,format,name){
if(name === "shuurei"){
const shuureiSystem = ["",">:(","Ew","Ugh","Hm","Ok","Nice","Ooh","Wow","Fave",":D"];
return shuureiSystem[score];
}
else if(format === "POINT_100"){
return score + "/100";
}
else if(
format === "POINT_10_DECIMAL" ||
format === "POINT_10"
){
return score + "/10";
}
else if(format === "POINT_3"){
if(score === 3){
return svgAssets.smile;
}
else if(score === 2){
return svgAssets.meh;
}
else if(score === 1){
return svgAssets.frown;
};
}
else if(format === "POINT_5"){
return score + svgAssets.star;
}
}
function convertScore(score,format){
if(format === "POINT_100"){
return score;
}
else if(
format === "POINT_10_DECIMAL" ||
format === "POINT_10"
){
return score*10;
}
else if(format === "POINT_3"){
if(score === 3){
return 85;
}
else if(score === 2){
return 60;
}
else if(score === 1){
return 45;
}
return 0;
}
else if(format === "POINT_5"){
if(score === 0){
return 0;
};
return score*20 - 10;
}
}
function enhanceSocialTab(){
if(!location.pathname.match(/^\/(anime|manga)\/\d*\/[\w\-]*\/social/)){
return;
}
let listOfActs = Array.from(document.getElementsByClassName("activity-entry"));
listOfActs.forEach(function(act){//compress activities without comments, they are all the same media entry anyway
if(
!act.hasOwnProperty("marked") &&
!(act.children[0].children[2].children[0].children.length > 1)
){
act.marked = true;
act.children[0].children[0].removeChild(act.children[0].children[0].children[0]);//remove cover image
let elements = act.children[0].children[0].children[0].children;
elements[2].parentNode.insertBefore(elements[2],elements[0]);//move profile picture to the beginning of the line
elements[0].parentNode.parentNode.style.minHeight = "70px";
elements[0].parentNode.classList.add("hohSocialTabActivityCompressedContainer");
elements[0].style.verticalAlign = "bottom";
elements[0].style.marginTop = "0px";
elements[1].classList.add("hohSocialTabActivityCompressedName");
elements[2].classList.add("hohSocialTabActivityCompressedStatus");
act.style.marginBottom = "10px";
}
});
/*add average score to social tab*/
let listOfFollowers = Array.from(document.getElementsByClassName("follow"));
let averageScore = 0;
let averageCount = 0;
listOfFollowers.forEach(function(follower){
if(
follower.children.length === 4
){
if(follower.children[3].nodeName != "svg"){
const followScore = follower.children[3].innerText.match(/\d+\.?\d*/g);
if(followScore && followScore.length === 2){
averageScore += 100*followScore[0]/followScore[1];
averageCount++;
}
else if(followScore && followScore.length === 1){//star rating
averageScore += (followScore[0]*20 - 10);
averageCount++;
}
}
else{//do count smiley scores, but with lower confidence
const smileyScore = follower.children[3].dataset.icon;
if(smileyScore === "frown"){
averageScore += (45)*0.5;
averageCount += 0.5;
}
else if(smileyScore === "meh"){
averageScore += (60)*0.5;
averageCount += 0.5;
}
else if(smileyScore === "smile"){
averageScore += (85)*0.5;
averageCount += 0.5;
}
}
}
});
if(averageCount){
averageScore = averageScore/averageCount;
let locationForIt = document.getElementById("averageScore");
if(!locationForIt){
locationForIt = create("span","#averageScore",false,);
document.getElementsByClassName("following")[0].insertBefore(
locationForIt,
document.getElementsByClassName("following")[0].children[0]
);
}
locationForIt.innerText = "Average: " + averageScore.roundPlaces(1) + "/100";
locationForIt.nextSibling.style.marginTop = "5px";
}
setTimeout(enhanceSocialTab,100);
}
function enhanceForum(){//purpose: reddit-style comment three collapse button
if(!document.URL.match(/^https:\/\/anilist\.co\/forum\/thread\/.*/)){
return;
}
let comments = Array.from(document.getElementsByClassName("comment-wrap"));
comments.forEach(function(comment){
if(!comment.hasOwnProperty("hohVisited")){
comment.hohVisited = true;
let hider = create("span","hohForumHider","[-]");
hider.onclick = function(){
let parentComment = this.parentNode.parentNode;
if(this.innerHTML === "[-]"){
this.innerText = "[+]";
parentComment.children[1].style.display = "none";
if(parentComment.parentNode.children.length > 1){
parentComment.parentNode.children[1].style.display = "none";
}
}
else{
this.innerText = "[-]";
parentComment.children[1].style.display = "block";
if(parentComment.parentNode.children.length > 1){
parentComment.parentNode.children[1].style.display = "block";
}
}
};
comment.children[0].children[0].insertBefore(
hider,
comment.children[0].children[0].children[0]
);
}
});
setTimeout(enhanceForum,100);
}
function dubMarker(){
if(!document.URL.match(/^https:\/\/anilist\.co\/anime\/.*/)){
return;
}
if(document.getElementById("dubNotice")){
return;
}
const variables = {
id: document.URL.match(/\/anime\/(\d+)\//)[1],
page: 1,
language: useScripts.dubMarkerLanguage.toUpperCase()
};
const query = `
query ($id: Int!, $type: MediaType, $page: Int = 1, $language: StaffLanguage) {
Media(id: $id, type: $type) {
characters(page: $page, sort: [ROLE], role: MAIN) {
edges {
node {
id
}
voiceActors (language: $language) {
language
}
}
}
}
}
`;
let dubCallback = function(data){
if(!document.URL.match(/^https:\/\/anilist\.co\/anime\/.*/)){
return;
};
let dubNoticeLocation = document.getElementsByClassName("sidebar");
if(!dubNoticeLocation.length){
setTimeout(function(){
dubCallback(data);
},200);
return;
}
if(data.data.Media.characters.edges.reduce(
(actors,a) => actors + a.voiceActors.length,0
)){//any voice actors for this language?
if(document.getElementById("dubNotice")){
return;
}
let dubNotice = create("p","#dubNotice",useScripts.dubMarkerLanguage + " dub available");
dubNoticeLocation[0].insertBefore(dubNotice,dubNoticeLocation[0].firstChild);
}
};
generalAPIcall(query,variables,dubCallback);
}
function enhanceStaff(){//currently only adds a favourite count
if(!document.URL.match(/^https:\/\/anilist\.co\/staff\/.*/)){
return;
}
if(document.getElementById("hohFavCount")){
return;
};
let filterGroup = document.getElementsByClassName("content");
if(!filterGroup.length){
setTimeout(function(){
enhanceStaff();
},200);//may take some time to load
return;
}
filterGroup = filterGroup[0];
let favCount = create("span","#hohFavCount",false,filterGroup);
const variables = {id: document.URL.match(/\/staff\/(\d+)\//)[1]};
const query = "query($id: Int!){Staff(id: $id){favourites}}";
let favCallback = function(data){
let favButton = document.getElementsByClassName("favourite");
if(data.data.Staff.favourites === 0 && favButton[0].classList.contains("isFavourite")){//safe to assume
favCount.innerText = data.data.Staff.favourites + 1;
}
else{
favCount.innerText = data.data.Staff.favourites;
}
if(favButton.length){
favButton[0].onclick = function(){
if(this.classList.contains("isFavourite")){
favCount.innerText = Math.max(parseInt(favCount.innerText)-1,0);//0 or above, just to avoid looking silly
}
else{
favCount.innerText = parseInt(favCount.innerText)+1;
}
};
}
};
generalAPIcall(query,variables,favCallback);
}
function replaceStaffRoles(){
let URLstuff = location.pathname.match(/^\/staff\/(\d+)\/.*/);
if(!URLstuff){
return;
};
if(document.getElementById("hoh-media-roles")){
return;
};
let insertParent = document.querySelector(".media-roles");
if(!insertParent){
setTimeout(replaceStaffRoles,200);
return;
};
let hohMediaRoles = create("div","#hoh-media-roles");
let hohMediaRolesAnimeHeader = create("h4",false,"Anime",hohMediaRoles);
hohMediaRolesAnimeHeader.style.display = "none";
let hohMediaRolesAnime = create("div","grid-wrap",false,hohMediaRoles);
hohMediaRolesAnime.setAttribute("data-v-09607311","");
hohMediaRolesAnime.style.margin = "10px";
let hohMediaRolesMangaHeader = create("h4",false,"Manga",hohMediaRoles);
hohMediaRolesMangaHeader.style.display = "none";
let hohMediaRolesManga = create("div","grid-wrap",false,hohMediaRoles);
hohMediaRolesManga.setAttribute("data-v-09607311","");
hohMediaRolesManga.style.margin = "10px";
let hohMediaSort = create("div");
let sortText = create("span",false,"Sort",hohMediaSort);
let sortSelect = create("select",false,false,hohMediaSort);
sortSelect.style.marginLeft = "5px";
let filterText = create("span",false," Filter ",hohMediaSort);
let filterSelect = create("input",false,false,hohMediaSort);
filterSelect.setAttribute("list","staffRoles");
let dataList = create("datalist",false,false,hohMediaSort);
dataList.id = "staffRoles";
let digestStats = create("span",false,false,hohMediaSort,"margin-left:100px;");
let sortOptionAlpha = create("option",false,"Alphabetical",sortSelect);
sortOptionAlpha.value = "alphabetical";
let sortOptionChrono = create("option",false,"Chronological",sortSelect);
sortOptionChrono.value = "chronological";
let sortOptionPopularity = create("option",false,"Popularity",sortSelect);
sortOptionPopularity.value = "popularity";
let sortOptionLength = create("option",false,"Length",sortSelect);
sortOptionLength.value = "length";
let sortOptionScore = create("option",false,"Score",sortSelect);
sortOptionScore.value = "score";
let autocomplete = [];
sortSelect.value = useScripts.staffRoleOrder;
hohMediaSort.style.marginBottom = "10px";
hohMediaSort.style.marginTop = "3px";
let initPerformed = false;
let UIinit = function(){
initPerformed = true;
insertParent.insertBefore(hohMediaRoles,insertParent.children[1]);
insertParent.insertBefore(hohMediaSort,insertParent.children[1]);
for(var i=3;i Chapters Read: " + sumChapters + "";
};
};
sortSelect.oninput = listRenderer;
filterSelect.oninput = listRenderer;
let animeHandler = function(data){
if(data.data.Staff.staffMedia.pageInfo.currentPage === 1){
for(var i=2;i<=data.data.Staff.staffMedia.pageInfo.lastPage;i++){
let variables = {
page: i+0,
type: "ANIME",
id: URLstuff[1]
};
if(useScripts.accessToken){
authAPIcall(staffQuery,variables,animeHandler);
}
else{
generalAPIcall(staffQuery,variables,animeHandler);
}
};
};
data.data.Staff.staffMedia.edges.forEach(function(edge){
let anime = {
role: [edge.staffRole],
title: edge.node.title.romaji,
image: edge.node.coverImage.large,
startDate: edge.node.startDate,
id: edge.node.id,
episodes: edge.node.episodes,
popularity: edge.node.popularity,
duration: edge.node.duration,
score: edge.node.averageScore,
myStatus: edge.node.mediaListEntry
};
if(useScripts.titleLanguage === "Native" && edge.node.title.native){
anime.title = edge.node.title.native;
}
else if(useScripts.titleLanguage === "English" && edge.node.title.english){
anime.title = edge.node.title.english;
};
animeAliasesToLookFor.forEach(function(alias){
if(alias[0] === anime.id){
anime.title = alias[1];
};
});
if(autocomplete.indexOf(anime.title) === -1){
autocomplete.push(anime.title);
let filterOption = create("option",false,false,dataList);
filterOption.value = anime.title;
};
if(autocomplete.indexOf(edge.staffRole) === -1){
autocomplete.push(edge.staffRole);
let filterOption = create("option",false,false,dataList);
filterOption.value = edge.staffRole;
};
animeRolesList.push(anime);
});
animeRolesList.sort(function(a,b){return a.id - b.id});
for(var i=1;i 0){
if(data.media.type === "ANIME"){
rewatchSuffix = " [rewatch";
}
else{
rewatchSuffix = " [reread";
}
if(data.repeat === 1){
rewatchSuffix += "]";
}
else{
rewatchSuffix += " " + data.repeat + "]";
}
};
if(data.score){
if(status.innerText.match(/^completed/i)){
scoreInfo.innerHTML = suffix + rewatchSuffix;
}
else{
scoreInfo.innerHTML = suffix;
};
scoreInfo.style.display = "inline";
};
};
const variables = {
userName: status.parentNode.children[0].innerText,
mediaId: mediaId[1]
};
const query = `
query (
$userName: String,
$mediaId: Int
) {
MediaList (
userName: $userName,
mediaId: $mediaId
) {
score
mediaId
notes
repeat
media {
type
}
user {
name
mediaListOptions {
scoreFormat
}
}
}
}
`;
generalAPIcall(query,variables,callback)
};
}
else if(status.children.length === 2 && !status.classList.contains("form")){
status.removeChild(status.children[1]);
};
});
};
function enhanceTags(){//show tag definition in drop down menu when adding tags
if(!location.pathname.match(/^\/(anime|manga)\/.*/)){
return;
};
setTimeout(enhanceTags,400);
let possibleTagContainers = document.getElementsByClassName("el-select-dropdown__list");
let bestGuess = false;
for(var i=0;i 205){//horrible test, but we have not markup to go from. Assumes the tag dropdown is the only one with more than that number of children
bestGuess = i;
};
};
if(bestGuess === false){
return;
};
if(possibleTagContainers[bestGuess].hasOwnProperty("hohMarked")){
return;
}
else{
possibleTagContainers[bestGuess].hohMarked = true;
};
let superBody = document.getElementsByClassName("el-dialog__body")[0];
let descriptionTarget = create("span","#hohDescription");
superBody.insertBefore(descriptionTarget,superBody.children[2]);
for(var i=0;i the tab "Stats/Script" > "Script & More stats".
You can also turn off this notice there.`,setting);
};
let regularNotifications = create("span",false,svgAssets.envelope + " Show default notifications");
regularNotifications.style.cursor = "pointer";
regularNotifications.style.fontSize = "small";
regularNotifications.onclick = function(){
if(displayMode === "hoh"){
displayMode = "native";
hohNotsToToggle = document.getElementById("hohNotifications");
if(hohNotsToToggle){
hohNotsToToggle.style.display = "none";
};
var regNotsToToggle = document.getElementsByClassName("notification");
for(var i=0;i 1){
quickComLikes.innerText = reply.likes.length + "♥";
}
else if(reply.likes.length === 1){
quickComLikes.innerText = "♥";
};
reply.likes.forEach(function(like){
if(like.name === whoAmI){
quickComLikes.classList.add("hohILikeThis");
};
});
quickCom.appendChild(quickComName);
quickCom.appendChild(quickComContent);
quickCom.appendChild(quickComLikes);
comment.children[1].appendChild(quickCom);
});
});
};
let notificationDrawer = function(activities){
let newContainer = document.getElementById("hohNotifications")
if(newContainer){
newContainer.parentNode.removeChild(newContainer);
};
newContainer = create("div","#hohNotifications");
let notificationsContainer = document.querySelector(".notifications");
if(!notificationsContainer){
return;
}
notificationsContainer.insertBefore(newContainer,notificationsContainer.firstChild);
for(var i=0;i 5){
timeHideFlag = true;
}
else if(document.getElementById("hohNotifications").offsetWidth < 800 && counter > 2){
timeHideFlag = true;
};
text.href = activities[i].directLink;
textSpan.innerText = activities[i].textSpan;
if(counter > 1){
textSpan.innerText = " liked your activities.";
};
if(counter === 1){
while(
i + counter < activities.length
&& activities[i + counter].type === "like"
&& activities[i + counter].link === activities[i].link
){//several people likes one of your activities
let miniImageWidth = 40;
let miniImage = create("a","hohUserImageSmall",false,newNotification);
miniImage.href = activities[i + counter].href;
miniImage.title = activities[i + counter].textName;
miniImage.style.backgroundImage = activities[i + counter].image;
miniImage.style.height = miniImageWidth + "px";
miniImage.style.width = miniImageWidth + "px";
miniImage.style.marginLeft = (72 + (counter-1)*miniImageWidth) + "px";
counter++;
};
if(counter > 1){
text.style.marginTop = "45px";
activities[i].textName += " +";
};
}
else{
newNotification.classList.add("hohCombined");
};
textName.innerText = activities[i].textName;
text.appendChild(textName);
text.appendChild(textSpan);
i += counter -1;
}
else if(activities[i].type === "reply" ){
let notNotImage = create("a",false,false,notNotImageContainer);
create("img",["hohMediaImage",activities[i].link],false,notNotImage);
notNotImage.href = activities[i].directLink;
while(
i + counter < activities.length
&& activities[i + counter].type === "reply"
&& activities[i + counter].link === activities[i].link
){
let miniImageWidth = 40;
let miniImage = create("a","hohUserImageSmall",false,newNotification);
miniImage.href = activities[i + counter].href;
miniImage.style.backgroundImage = activities[i + counter].image;
miniImage.style.height = miniImageWidth + "px";
miniImage.style.width = miniImageWidth + "px";
miniImage.style.marginLeft = (72 + (counter-1)*miniImageWidth) + "px";
counter++;
};
if(counter > 1){
text.style.marginTop = "45px";
activities[i].textName += " +";
};
text.href = activities[i].directLink;
textName.innerText = activities[i].textName;
textSpan.innerText = activities[i].textSpan;
text.appendChild(textName);
text.appendChild(textSpan);
i += counter -1;
}
else if(activities[i].type === "replyReply" ){
let notNotImage = create("a",false,false,notNotImageContainer);
create("img",["hohMediaImage",activities[i].link],false,notNotImage);
notNotImage.href = activities[i].directLink;
while(
i + counter < activities.length
&& activities[i + counter].type === "replyReply"
&& activities[i + counter].link === activities[i].link
){
let miniImageWidth = 40;
let miniImage = create("a","hohUserImageSmall",false,newNotification);
miniImage.href = activities[i + counter].href;
miniImage.style.backgroundImage = activities[i + counter].image;
miniImage.style.height = miniImageWidth + "px";
miniImage.style.width = miniImageWidth + "px";
miniImage.style.marginLeft = (72 + (counter-1)*miniImageWidth) + "px";
counter++;
};
if(counter > 1){
text.style.marginTop = "45px";
activities[i].textName += " +";
};
text.href = activities[i].directLink;
textName.innerText = activities[i].textName;
textSpan.innerText = " replied to the same activity as you.";
text.appendChild(textName);
text.appendChild(textSpan);
i += counter -1;
}
else if(
activities[i].type === "message"
|| activities[i].type === "likeReply"
|| activities[i].type === "mention"
){
let notNotImage = create("a",false,false,notNotImageContainer);
create("img",["hohMediaImage",activities[i].link],false,notNotImage);
notNotImage.href = activities[i].directLink;
text.href = activities[i].directLink;
textName.innerText = activities[i].textName;
textSpan.innerText = activities[i].textSpan;
text.appendChild(textName);
text.appendChild(textSpan);
}
else if(activities[i].type === "airing"){
textSpan.innerHTML = activities[i].text;
text.appendChild(textSpan);
}
else if(activities[i].type === "follow"){
text.href = activities[i].directLink;
textName.innerText = activities[i].textName;
textSpan.innerText = activities[i].textSpan;
text.appendChild(textName);
text.appendChild(textSpan);
}
else if(
activities[i].type === "forumCommentLike"
|| activities[i].type === "forumSubscribedComment"
|| activities[i].type === "forumCommentReply"
|| activities[i].type === "forumLike"
|| activities[i].type === "forumMention"
){
text.href = activities[i].directLink;
textName.innerText = activities[i].textName;
textSpan.innerText = activities[i].textSpan;
text.appendChild(textName);
text.appendChild(textSpan);
let textSpan2 = create("span",false,activities[i].text,text,"color:rgb(var(--color-blue));");
text.style.maxWidth = "none";
text.style.marginTop = "17px";
}
else{//display as-is
textSpan.classList.add("hohUnhandledSpecial");
textSpan.innerHTML = activities[i].text;
text.appendChild(textSpan);
};
let time = create("div","hohTime");
time.innerHTML = activities[i - counter + 1].time;
let commentsContainer = create("div",["hohCommentsContainer","b" + activities[i].link]);
let comments = create("a",["hohComments","link"],"comments",commentsContainer);
create("span","hohMonospace","+",comments);
comments.onclick = function(){
if(this.children[0].innerText === "+"){
this.children[0].innerText = "-";
this.parentNode.children[1].style.display = "inline-block";
let variables = {
id: +this.parentNode.classList[1].substring(1)
};
listActivityCall(queryActivity,variables,commentCallback,{},false);
}
else{
this.children[0].innerText = "+";
this.parentNode.children[1].style.display = "none";
};
};
let commentsArea = create("div","hohCommentsArea",false,commentsContainer);
newNotification.appendChild(notImage);
newNotification.appendChild(text);
newNotification.appendChild(notNotImageContainer);
if(!timeHideFlag){
newNotification.appendChild(time);
};
newNotification.appendChild(commentsContainer);
newContainer.appendChild(newNotification);
};
};
if(useScripts.accessToken && false){
let callback = function(data){
let activities = [];
data.data.Page.notifications.forEach(function(notification){
});
notificationDrawer(activities);
};
}
else{
let activities = [];
let notifications = document.getElementsByClassName("notification");//collect the "real" notifications
if(notifications.length === prevLength && forceRebuildFlag === false){
return;
}
else{
prevLength = notifications.length;
forceRebuildFlag = false;
};
const activityTypes = {
" liked your activity." : "like",
" replied to your activity." : "reply",
" sent you a message." : "message",
" liked your activity reply." : "likeReply",
" mentioned you in their activity." : "mention",
" replied to activity you previously replied to." : "replyReply",
" liked your comment, in the forum thread " : "forumCommentLike",
" commented in your subscribed forum thread " : "forumSubscribedComment",
" replied to your comment, in the forum thread " : "forumCommentReply",
" liked your forum thread, " : "forumLike",
" mentioned you, in the forum thread " : "forumMention"
};
Array.from(notifications).forEach(function(notification){//parse real notifications
notification.already = true;
notification.style.display = "none";
var active = {};
if(
notification.classList.length > 1
&& notification.classList[1] != "hasMedia"
){//"notification unread" classlist
active.unread = true;
}
else{
active.unread = false;
};
active.type = "special";
active.link = "aaa";//fixme. Edit 2019: I have no idea
if(//check if we can query that
notification.children.length >= 2
&& notification.children[1].children.length
&& notification.children[1].children[0].children.length
&& notification.children[1].children[0].children[0].children.length
){
const info = notification.children[1].children[0].children[0];
active.directLink = info.href
active.text = info.innerHTML;
active.textName = info.childNodes[0].textContent.trim();
active.textSpan = info.childNodes[1].textContent;
let linkMatch = info.href.match(/activity\/(\d+)/);
if(linkMatch){
active.link = linkMatch[1];
};
var testType = info.children[0].textContent;
active.type = activityTypes[testType];
if(!active.type){
active.type = "special"; //by default every activity is some weird thing we are displaying as-is
}
else if(
active.type === "forumCommentLike"
|| active.type === "forumSubscribedComment"
|| active.type === "forumCommentReply"
|| active.type === "forumLike"
|| active.type === "forumMention"
){
active.text = info.children[1].textContent;
}
};
if(active.type === "special"){
active.text = notification.children[1].innerHTML;//default
if(notification.children[1].children.length){
const info = notification.children[1].children[0];
if(
info.children.length >= 2
&& info.children[1].textContent === " started following you."
){
active.type = "follow";
active.directLink = info.children[0].href;
active.text = info.children[0].innerHTML;
active.textName = info.children[0].textContent.trim();
active.textSpan = info.children[1].textContent;
}
else if(
info.children.length >= 4
&& info.children[3].textContent === " aired."
){
active.type = "airing";
active.directLink = info.children[0].href;
active.text = info.innerHTML;
};
};
};
if(
notification.children.length > 1
&& notification.children[1].children.length > 1
){
active.time = notification.children[1].children[1].innerHTML;
}
else{
active.time = create("span");
};
active.image = notification.children[0].style.backgroundImage;
active.href = notification.children[0].href;
activities.push(active);
});
notificationDrawer(activities);
for(var i=0;APIcallsUsed < (APIlimit - 5);i++){//heavy
if(!activities.length || i >= activities.length){//loading is difficult to predict. There may be nothing there when this runs
break;
};
var imageCallBack = function(data){
var type = data.data.Activity.type;
for(var j=0;j div");
if(!mediaCards.length){
setTimeout(function(){
addProgressBar();
},200);//may take some time to load
return;
};
mediaCards.forEach(function(card){
const progressInformation = card.innerText.match(/Progress:\ (\d+)\/(\d+)/);
if(progressInformation){
let pBar = create("meter");
pBar.value = progressInformation[1];
pBar.min = 0;
pBar.max = progressInformation[2];
card.parentNode.insertBefore(pBar,card);
card.parentNode.parentNode.parentNode.querySelector(".plus-progress").onclick = function(){
pBar.value++;
setTimeout(function(){
pBar.value = card.innerText.match(/Progress:\ (\d+)\/(\d+)/)[1];
},1000);
}
};
});
document.querySelector(".size-toggle").onclick = function(){
setTimeout(function(){
addProgressBar();
},200);
};
}
function enhanceCharacter(){//adds a favourite count on every character page
if(!location.pathname.match(/^\/character(\/.*)?/)){
return;
};
if(document.getElementById("hohFavCount")){
return;
};
var filterGroup = document.getElementsByClassName("content");
if(!filterGroup.length){
setTimeout(function(){
enhanceCharacter();
},200);//may take some time to load
return;
};
const variables = {id: document.URL.match(/\/character\/(\d+)\/?/)[1]};
const query = `
query($id: Int!){
Character(id: $id){
favourites
}
}
`;
let favCallback = function(data){
let favButton = document.getElementsByClassName("favourite");
if(!favButton){
setTimeout(function(){
if(location.pathname.match(/^\/character(\/.*)?/)){
favCallback(data);
};
},100);
return;
};
filterGroup = filterGroup[0];
let favCount = create("span","#hohFavCount",false,filterGroup);
if(data.data.Character.favourites === 0 && favButton[0].classList.contains("isFavourite")){//safe to assume
favCount.innerText = data.data.Character.favourites + 1;
}
else{
favCount.innerText = data.data.Character.favourites;
};
if(favButton.length){
favButton[0].onclick = function(){
if(this.classList.contains("isFavourite")){
favCount.innerText = Math.max(parseInt(favCount.innerText)-1,0);//0 or above, just to avoid looking silly
}
else{
favCount.innerText = parseInt(favCount.innerText)+1;
};
};
};
let names = document.querySelector(".content .names");
if(names){
names.innerText = names.innerText.replace(/,$/,"");
};
};
generalAPIcall(query,variables,favCallback);
let names = document.querySelector(".content .names");
if(names){
names.innerText = names.innerText.replace(/,$/,"");
};
};
function enhanceStudio(){//adds a favourite count to every studio page
if(!location.pathname.match(/^\/studio(\/.*)?/)){
return;
};
var filterGroup = document.querySelector(".container.header");
if(!filterGroup){
setTimeout(function(){
enhanceStudio();
},200);//may take some time to load
return;
};
const variables = {id: location.pathname.match(/\/studio\/(\d+)\/?/)[1]};
const query = `
query($id: Int!){
Studio(id: $id){
favourites
}
}
`;
let favCallback = function(data){
let favButton = document.getElementsByClassName("favourite");
if(!favButton){
setTimeout(function(){
if(location.pathname.match(/^\/studio(\/.*)?/)){
favCallback(data);
};
},100);
return;
};
let favCount = create("span","#hohFavCount",false,filterGroup,"top:-10px;");
if(data.data.Studio.favourites === 0 && favButton[0].classList.contains("isFavourite")){//safe to assume
favCount.innerText = data.data.Studio.favourites + 1;
}
else{
favCount.innerText = data.data.Studio.favourites;
};
if(favButton.length){
favButton[0].onclick = function(){
if(this.classList.contains("isFavourite")){
favCount.innerText = Math.max(parseInt(favCount.innerText)-1,0);//0 or above, just to avoid looking silly
}
else{
favCount.innerText = parseInt(favCount.innerText)+1;
};
};
};
};
generalAPIcall(query,variables,favCallback);
};
function returnList(list,skipProcessing){
let retl = [];
for(var i=0;i 100){
retlObj.scoreRaw = 100;
}
if(!retlObj.media.episodes && retlObj.media.nextAiringEpisode){
retlObj.media.episodes = retlObj.media.nextAiringEpisode.episode - 1;
}
};
retl.push(retlObj);
};
};
retl.sort((a,b) => a.mediaId - b.mediaId);
for(var i=1;i element.scoreRaw);
let list3 = [];
let indeks1 = 0;
let indeks2 = 0;
while(indeks1 < list.length && indeks2 < list2.length){
if(list2[indeks2].mediaId > list[indeks1].mediaId){
indeks1++;
continue;
};
if(list2[indeks2].mediaId < list[indeks1].mediaId){
indeks2++;
continue;
};
if(list2[indeks2].mediaId === list[indeks1].mediaId){
list3.push({
mediaId: list[indeks1].mediaId,
score1: list[indeks1].scoreRaw,
score2: list2[indeks2].scoreRaw
});
indeks1++;
indeks2++;
};
};
let average1 = 0;
let average2 = 0;
list3.forEach(function(item){
average1 += item.score1;
average2 += item.score2;
item.sdiff = item.score1 - item.score2;
});
average1 = average1/list3.length;
average2 = average2/list3.length;
let standev1 = 0;
let standev2 = 0;
list3.forEach(function(item){
standev1 += Math.pow(item.score1 - average1,2);
standev2 += Math.pow(item.score2 - average2,2);
});
standev1 = Math.sqrt(standev1/(list3.length - 1));
standev2 = Math.sqrt(standev2/(list3.length - 1));
let difference = 0;
list3.forEach(function(item){
difference += Math.abs(
(item.score1 - average1)/standev1
- (item.score2 - average2)/standev2
);
});
difference = difference/list3.length;
let differenceSpan = create("span",false,difference.roundPlaces(3));
if(difference < 0.9){
differenceSpan.style.color = "green";
}
else if(difference > 1.1){
differenceSpan.style.color = "red";
};
targetLocation.innerText = "";
targetLocation.appendChild(differenceSpan);
let countSpan = create("span",false," based on " + list3.length + " shared entries. Lower is better. 0.8 - 1.1 is common",targetLocation);
});
}
//used by the stats module, and to safeguard the manga chapter guesses
const commonUnfinishedManga = {
"53390":{//aot
chapters:116,
volumes:26
},
"30002":{//berserk
chapters:358,
volumes:40
},
"30013":{//one piece
chapters:942,
volumes:92
},
"85486":{//mha
chapters:202,
volumes:20
},
"74347":{//opm
chapters:154,
volumes:17
},
"30026":{//HxH
chapters:390,
volumes:36
},
"30656":{//vagabond
chapters:327,
volumes:37
},
"30105":{//yotsuba&
chapters:103,
volumes:14
}
};
const listCreatedTime = new Date(2019,4,26);
const currentTime = new Date();
if(currentTime - listCreatedTime > 365*24*60*60*1000){
console.log("remind hoh to update the commonUnfinishedManga list");
};
function addMoreStats(){
if(!document.URL.match(/\/stats\/?$/)){
return;
};
let filterGroup = document.querySelector(".filter-group");
if(!filterGroup){
setTimeout(function(){
addMoreStats();
},200);//takes some time to load
return;
};
let hohStatsTrigger = create("span","hohStatsTrigger","Script & More stats");
hohStatsTrigger.onclick = function(){
hohStatsTrigger.classList.add("hohActive");
let otherActive = document.getElementsByClassName("active");
for(var j=0;j" + scriptInfo.version + "";
let sHome = create("p",false,"Homepage: ",scriptStats);
let sHomeLink = create("a",false,scriptInfo.link,sHome);
sHomeLink.href = scriptInfo.link;
create("p",false,"Some changes requires reloading the page.",scriptStats);
let scriptSettings = create("div");
if(localStorageAvailable){
for(var j=0;j 10*60*1000;//ten min
let query = "query($page:Int,$type:MediaType){Page(page:$page){pageInfo{total}media(type:$type){id}}}";
let generalStatCall = function(type,path,isMedia){
let updater = function(data){
let target = document.getElementById("hohTotal" + type + "Target");
target.innerText = data.data.Page.pageInfo.total;
target.style.cursor = "pointer";
target.title = "go to a random " + path;
target.onclick = function(){
const selected = Math.floor(Math.random()*data.data.Page.pageInfo.total);
generalAPIcall(
isMedia ? query : "query($page:Int){Page(page:$page){pageInfo{total}" + type + "{id}}}",
{page:Math.ceil(selected/50),type:type.toUpperCase()},
function(data){
window.location.href = "https://anilist.co/" + path + "/" + data.data.Page[isMedia ? "media" : type][selected % 50].id + "/";
}
)
};
}
if(expired){
generalAPIcall(
isMedia ? query : "query($page:Int){Page(page:$page){pageInfo{total}" + type + "{id}}}",
{page:0,type:type.toUpperCase()},
function(data){
useScripts.databaseStats[type] = data.data.Page.pageInfo.total;
useScripts.save();
updater(data);
}
);
}
else{
updater({data:{Page:{pageInfo:{total:useScripts.databaseStats[type]}}}});//cache
}
};
generalStatCall("anime","anime",true);
generalStatCall("manga","manga",true);
generalStatCall("users","user");
generalStatCall("staff","staff");//nasty plurals in the API
generalStatCall("characters","character");
generalStatCall("reviews","review");
if(expired){
useScripts.databaseStats.updated = currentTime.valueOf();
useScripts.save();
};
var customTagsCollection = function(list,title,fields){
let customTags = [];
let regularTags = [];
let customLists = [];
if(localStorageAvailable){
const localStorageItem = JSON.parse(localStorage.getItem("regularTags" + title));
if(localStorageItem){
localStorageItem.forEach(function(tag){
regularTags.push({
name : tag,
list : []
});
});
};
};
list.forEach(function(media){
let item = {};
fields.forEach(function(field){
item[field.key] = field.method(media);
});
if(media.notes){
var tagMatches = media.notes.match(/(#\S+)/g);
if(tagMatches){
for(var j=0;j a.list.length - b.list.length);
};
var regularTagsCollection = function(list,fields){
let tags = [];
list.forEach(function(media){
let item = {};
fields.forEach(function(field){
item[field.key] = field.method(media);
});
media.media.tags.forEach(function(tag){
var foundFlag = false;
for(var i=0;i a.average - b.average);
};
let drawTable = function(data,formatter,tableLocation){
while(tableLocation.childElementCount){
tableLocation.removeChild(tableLocation.lastChild);
};
const randomData = "data-v-e2beaf26";//some native css selectors want this
let header = create("p",false,formatter.title);
let tableContent = create("div","table");
tableContent.setAttribute(randomData,"");
let headerRow = create("div",["header","row"],false,tableContent);
headerRow.setAttribute(randomData,"");
let indexAccumulator = 0;
formatter.headings.forEach(function(heading){
let columnTitle = create("div",false,heading,headerRow);
if(formatter.focus === indexAccumulator){
columnTitle.innerHTML += " " + svgAssets.angleDown;
};
columnTitle.setAttribute(randomData,"");
columnTitle.index = +indexAccumulator;
columnTitle.addEventListener("click",function(){
formatter.focus = this.index;
data.sort(formatter.sorting[this.index]);
drawTable(data,formatter,tableLocation);
});
indexAccumulator++;
});
for(var i=0;i a.score - b.score);
}
else{
data[i].list.sort(formatter.sorting[formatter.focus]);
}
for(var j=0;j 1){
cel.innerHTML = svgAssets.repeat + data[index].repeat;
}
}
},
function(cel,data,index,isPrimary){
if(isPrimary){
if(data[index].average === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].average);
}
}
else{
if(data[index].score === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].score);
}
}
},
function(cel,data,index,isPrimary){
if(!isPrimary && data[index].type === "MANGA"){
cel.innerText = "-";
}
else if(data[index].duration === 0){
cel.innerText = "-";
}
else if(data[index].duration < 60){
cel.innerText = Math.round(data[index].duration) + "min";
}
else{
cel.innerText = Math.round(data[index].duration/60) + "h";
};
},
function(cel,data,index,isPrimary){
if(isPrimary || data[index].type === "MANGA"){
cel.innerText = data[index].chaptersRead;
}
else{
cel.innerText = "-";
}
}
],
sorting : [
(a,b) => ("" + a.name).localeCompare(b.name),
(b,a) => a.list.length - b.list.length,
(b,a) => a.average - b.average,
(b,a) => a.duration - b.duration,
(b,a) => a.chaptersRead - b.chaptersRead
]
};
let collectedMedia = semaPhoreAnime.concat(semaPhoreManga);
let listOfTags = regularTagsCollection(collectedMedia,mixedFields);
for(var i=0;i div > h2");
if(possibleNativeLocation && possibleNativeLocation.length > 1 && possibleNativeLocation[1].innerText === "Tags"){
if(possibleNativeLocation[1].nextSibling.id != "regularTagsTable"){
let regularTagsTable = create("div","#regularTagsTable");
possibleNativeLocation[1].parentNode.insertBefore(regularTagsTable,possibleNativeLocation[1].nextSibling);
drawTable(listOfTags,mixedFormatter,regularTagsTable);
possibleNativeLocation[1].parentNode.lastChild.style.display = "none";
};
}
setTimeout(checkNativeTable,200);
};
checkNativeTable();
//recycle most of the formatter for genres
mixedFormatter.headings[0] = "Genre";
mixedFormatter.celData[0] = function(cel,data,index,isPrimary){
if(isPrimary){
let nameCellCount = create("div","count",(index+1),cel);
nameCellCount.setAttribute("data-v-e2beaf26","");
let nameCellTag = create("a",false,data[index].name,cel,"cursor:pointer;");
nameCellTag.setAttribute("data-v-2f71893a","");
nameCellTag.href = "https://anilist.co/search/anime?includedGenres=" + data[index].name + "&onList=true";
}
else{
let nameCellTag = create("a","title",data[index].name,cel,"margin-left:50px;display:block;");
nameCellTag.setAttribute("data-v-2f71893a","");
if(data[index].type === "ANIME"){
nameCellTag.href = "/anime/" + data[index].mediaId + "/";
nameCellTag.style.color = "rgb(var(--color-blue))";
}
else{
nameCellTag.href = "/manga/" + data[index].mediaId + "/";
nameCellTag.style.color = "rgb(var(--color-green))";
};
}
};
collectedMedia.forEach(function(entry){//swap out the tags for genres so we can reuse the code
entry.media.tags = [];
entry.media.genres.forEach(function(genre){
entry.media.tags.push({name:genre});
});
});
let listOfGenres = regularTagsCollection(collectedMedia,mixedFields);
let checkNativeTable2 = function(){
if(!document.URL.match(/\/stats$/)){
return;
};
let possibleNativeLocation = document.querySelectorAll(".stats-wrap > div > h2");
if(possibleNativeLocation && possibleNativeLocation.length && possibleNativeLocation[0].innerText === "Genres"){
if(possibleNativeLocation[0].nextSibling.id != "regularGenresTable"){
let regularGenresTable = create("div","#regularGenresTable");
possibleNativeLocation[0].parentNode.insertBefore(regularGenresTable,possibleNativeLocation[0].nextSibling);
drawTable(listOfGenres,mixedFormatter,regularGenresTable);
possibleNativeLocation[0].parentNode.lastChild.style.display = "none";
};
}
setTimeout(checkNativeTable2,200);
};
checkNativeTable2();
};
//get anime list
let personalStatsCallback = function(data){
personalStats.innerText = "";
const thisName = document.URL.match(/\/([\w\-]+)\/stats/)[1];
create("hr",false,false,personalStats)
create("h1",false,"Anime stats for " + thisName,personalStats);
let list = returnList(data);
let scoreList = list.filter(element => element.scoreRaw);
if(whoAmI != thisName){
let compatabilityButton = create("button",false,"Compatibility",personalStats);
compatabilityButton.onclick = function(){
compatCheck(
scoreList,
whoAmI,"hohCheckCompat")
};
create("div","#hohCheckCompat",false,personalStats);
};
let addStat = function(text,value,comment){//value,value,html
let newStat = create("p","hohStat",false,personalStats);
create("span",false,text,newStat);
create("span","hohStatValue",value,newStat);
if(comment){
let newStatComment = create("span",false,false,newStat);
newStatComment.innerHTML = comment;
};
};
//first activity
let oldest = list.filter(
item => item.startedAt.year
).map(
item => item.startedAt
).sort((b,a) =>
(a.year < b.year)
|| (a.year === b.year && a.month < b.month)
|| (a.year === b.year && a.month === b.month && a.day < b.day)
)[0];
//scoring stats
let previouScore = 0;
let maxRunLength = 0;
let maxRunLengthScore = 0;
let runLength = 0;
let sumEntries = 0;
let amount = scoreList.length;
let sumWeight = 0;
let sumEntriesWeight = 0;
let average = 0;
let median = 0;
let sumDuration = 0;
let standardDeviation;
let longestDuration = {
time: 0,
name: "",
status: "",
rewatch: 0,
id: 0
};
scoreList.sort((a,b) => a.scoreRaw - b.scoreRaw);
list.forEach(function(item){
let entryDuration = (item.media.duration|0)*(item.progress|0);//curent round
item.episodes = (item.progress|0);
if(useScripts.noRewatches && (item.repeat|0)){
entryDuration = Math.max(1,(item.media.episodes|0),(item.progress|0))*(item.media.duration|0);//first round
item.episodes = Math.max(1,(item.media.episodes|0),(item.progress|0));
}
else{
entryDuration += (item.repeat|0)*Math.max(1,(item.media.episodes|0),(item.progress|0))*(item.media.duration|0);//repeats
item.episodes += (item.repeat|0)*Math.max(1,(item.media.episodes|0),(item.progress|0));
}
item.watchedDuration = entryDuration;
sumDuration += entryDuration;
if(entryDuration > longestDuration.time){
longestDuration.time = entryDuration;
longestDuration.name = item.media.title.romaji;
longestDuration.status = item.status;
longestDuration.rewatch = item.repeat;
longestDuration.id = item.mediaId;
};
});
if(scoreList.length % 2){
median = scoreList[(scoreList.length-1)/2].scoreRaw;
}
else if(scoreList.length){
median = scoreList[(scoreList.length)/2].scoreRaw/2 + scoreList[(scoreList.length)/2-1].scoreRaw/2;
};
scoreList.forEach(function(item){
sumEntries += item.scoreRaw;
if(item.scoreRaw === previouScore){
runLength++;
if(runLength > maxRunLength){
maxRunLength = runLength;
maxRunLengthScore = item.scoreRaw;
};
}
else{
runLength = 1;
previouScore = item.scoreRaw;
};
sumWeight += (item.media.duration|0)*(item.media.episodes|0);
sumEntriesWeight += item.scoreRaw*(item.media.duration|0)*(item.media.episodes|0);
});
if(amount){
average = sumEntries/amount;
}
standardDeviation = Math.sqrt(
scoreList.map(a => a.scoreRaw).reduce(
(accum,element) => accum + Math.pow(average - element,2)
)/amount
);
list.sort((a,b) => a.mediaId - b.mediaId);
//display scoring stats
addStat("Anime on list: ",list.length);
addStat("Anime rated: ",amount);
if(amount != 0){//no scores
if(amount === 1){
addStat("Only one score given: ",maxRunLengthScore);
}
else{
addStat(
"Average score: ",
average.roundPlaces(2)
);
addStat(
"Average score: ",
(sumEntriesWeight/sumWeight).roundPlaces(2),
" (weighted by duration)"
);
addStat("Median score: ",median);
addStat(
"Standard deviation: ",
standardDeviation.roundPlaces(2)
);
if(maxRunLength > 1){
addStat("Most common score: ",maxRunLengthScore, " (" + maxRunLength + " instances)");
}
else{
addStat("Most common score: ","","no two scores alike");
};
};
//longest activity
let singleText = (100*longestDuration.time/sumDuration).roundPlaces(2) + "% is ";
singleText += "" + longestDuration.name + "";
if(longestDuration.rewatch === 0){
if(longestDuration.status === "CURRENT"){
singleText += ". Currently watching."
}
else if(longestDuration.status === "PAUSED"){
singleText += ". On hold."
}
else if(longestDuration.status === "DROPPED"){
singleText += ". Dropped."
};
}
else{
if(longestDuration.status === "COMPLETED"){
if(longestDuration.rewatch === 1){
singleText += ". Rewatched once.";
}
else if(longestDuration.rewatch === 2){
singleText += ". Rewatched twice.";
}
else{
singleText += ". Rewatched " + longestDuration.rewatch + " times.";
};
}
else if(longestDuration.status === "CURRENT" || status === "REPEATING"){
if(longestDuration.rewatch === 1){
singleText += ". First rewatch in progress.";
}
else if(longestDuration.rewatch === 2){
singleText += ". Second rewatch in progress.";
}
else{
singleText += ". Rewatch number " + longestDuration.rewatch + " in progress.";
};
}
else if(longestDuration.status === "PAUSED"){
if(longestDuration.rewatch === 1){
singleText += ". First rewatch on hold.";
}
else if(longestDuration.rewatch === 2){
singleText += ". Second rewatch on hold.";
}
else{
singleText += ". Rewatch number " + longestDuration.rewatch + " on hold.";
};
}
else if(longestDuration.status === "DROPPED"){
if(longestDuration.rewatch === 1){
singleText += ". Dropped on first rewatch.";
}
else if(longestDuration.rewatch === 2){
singleText += ". Dropped on second rewatch.";
}
else{
singleText += ". Dropped on rewatch number " + longestDuration.rewatch + ".";
};
};
};
addStat(
"Time watched: ",
(sumDuration/(60*24)).roundPlaces(2),
" days (" + singleText + ")"
);
};
let TVepisodes = 0;
let TVepisodesLeft = 0;
list.filter(show => show.media.format === "TV").forEach(function(show){
TVepisodes += show.progress;
TVepisodes += show.repeat * Math.max(1,(show.media.episodes|0),show.progress);
if(show.status === "CURRENT"){
TVepisodesLeft += Math.max((show.media.episodes|0) - show.progress,0);
};
});
addStat("TV episodes watched: ",TVepisodes);
addStat("TV episodes remaining for current shows: ",TVepisodesLeft);
let tagless = list.filter(
show => show.media.tags.length === 0 && show.status != "PLANNING"
).map(
show => ({
id: show.mediaId,
name: show.media.title.romaji
})
);
if(tagless.length){
create("p",false,"Some shows on your list have no tags. Would you like to help with that?",personalStats);
for(var i=0;i largestValue){
largestValue = distribution[format][statusi];
};
};
};
};
};
let yAxisLimit = Math.ceil(
largestValue/Math.pow(10,(largestValue+"").length-1)
)*Math.pow(10,(largestValue+"").length-1);//cast to string and check the length is floor(log10(x))
let diagramFill = function(statusHeaders,formatHeaders,statusArray,formatArray){
const chartHeight = margins.height - margins.chartTextBottom - margins.bottom - margins.top;
ctx.fillStyle = "rgb(133,150,165)";
ctx.strokeStyle = "rgb(133,150,165)";
ctx.textAlign = "end";
ctx.fillText(yAxisLimit,margins.left + 20,margins.top);
ctx.fillText(0,margins.left + 20,margins.top + chartHeight);
ctx.fillText(yAxisLimit/2,margins.left + 20,margins.top + chartHeight/2);
const chartCellWidth = 100;
ctx.textAlign = "center";
for(var i=0;i 1){
cel.innerHTML += svgAssets.repeat + data[index].repeat;
}
}
},
function(cel,data,index,isPrimary){
if(isPrimary){
if(data[index].average === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].average);
}
}
else{
if(data[index].score === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].score);
}
}
},
function(cel,data,index){
if(data[index].duration === 0){
cel.innerText = "-";
}
else if(data[index].duration < 60){
cel.innerText = Math.round(data[index].duration) + "min";
}
else{
cel.innerText = Math.round(data[index].duration/60) + "h";
};
},
function(cel,data,index){
cel.innerText = data[index].episodes;
},
function(cel,data,index){
if(data[index].episodes === 0 && data[index].remaining === 0){
cel.innerText = "-";
}
else if(data[index].remaining === 0){
cel.innerText = "completed";
}
else{
if(useScripts.timeToCompleteColumn){
if(data[index].remainingTime < 60){
cel.innerText = data[index].remaining + " (" + data[index].remainingTime + "min)";
}
else{
cel.innerText = data[index].remaining + " (" + Math.round(data[index].remainingTime/60) + "h)";
};
}
else{
cel.innerText = data[index].remaining;
}
}
}
],
sorting: [
(a,b) => ("" + a.name).localeCompare(b.name),
(b,a) => a.list.length - b.list.length,
(b,a) => a.average - b.average,
(b,a) => a.duration - b.duration,
(b,a) => a.episodes - b.episodes,
(b,a) => a.remaining - b.remaining
]
};
const animeFields = [
{
key : "name",
sumable : false,
method : function(media){
return media.media.title.romaji;
}
},{
key : "mediaId",
sumable : false,
method : function(media){
return media.mediaId;
}
},{
key : "score",
sumable : false,
method : function(media){
return media.scoreRaw;
}
},{
key : "repeat",
sumable : false,
method : function(media){
return media.repeat;
}
},{
key : "status",
sumable : false,
method : function(media){
return media.status;
}
},{
key : "duration",
sumable : true,
method : function(media){
return media.watchedDuration;
}
},{
key : "episodes",
sumable : true,
method : function(media){
return media.episodes;
}
},{
key : "remaining",
sumable : true,
method : function(media){
return Math.max((media.media.episodes|0) - media.progress,0);
}
},{
key : "remainingTime",
sumable : true,
method : function(media){
return Math.max(((media.media.episodes|0) - media.progress) * (media.media.duration|0),0);
}
}
];
let customTags = customTagsCollection(list,animeFormatter.title,animeFields);
if(customTags.length){
let customTagsAnimeTable = create("div","#customTagsAnimeTable",false,personalStats);
drawTable(customTags,animeFormatter,customTagsAnimeTable);
};
semaPhoreAnime = list;
nativeTagsReplacer();
};
generalAPIcall(
queryMediaList,
{
name: document.URL.match(/\/([\w\-]+)\/stats\/?$/)[1],
listType: "ANIME"
},
personalStatsCallback
);
//manga stats
let personalStatsMangaCallback = function(data){
let thisName = document.URL.match(/\/([\w\-]+)\/stats/)[1];
personalStatsManga.innerText = "";
create("hr",false,false,personalStatsManga);
create("h1",false,"Manga stats for " + thisName,personalStatsManga);
let list = returnList(data);
let scoreList = list.filter(element => element.scoreRaw);
let personalStatsMangaContainer = create("div",false,false,personalStatsManga);
let addStat = function(text,value,comment){//value,value,html
let newStat = create("p","hohStat",false,personalStatsManga);
create("span",false,text,newStat);
create("span","hohStatValue",value,newStat);
if(comment){
let newStatComment = create("span",false,false,newStat);
newStatComment.innerHTML = comment;
};
};
let chapters = 0;
let volumes = 0;
/*
For most airing anime, Anilist provides "media.nextAiringEpisode.episode"
Unfortunately, the same is not the case for releasing manga.
THIS DOESN'T MATTER the first time a user is reading something, as we are then just using the current progress.
But on a re-read, we need the total length to count all the chapters read.
I can (and do) get a lower bound for this by using the current progress (this is what Anilist does),
but this is not quite accurate, especially early in a re-read.
The list below is to catch some of those exceptions
*/
let unfinishedLookup = function(mediaId,mode,mediaStatus,mediaProgress){
if(mediaStatus === "FINISHED"){
return 0;//it may have finished since the list was updated
};
if(commonUnfinishedManga.hasOwnProperty(mediaId)){
if(mode === "chapters"){
return commonUnfinishedManga[mediaId].chapters;
}
else if(mode === "volumes"){
return commonUnfinishedManga[mediaId].volumes;
}
else if(mode === "volumesNow"){
if(commonUnfinishedManga[mediaId].chapters <= mediaProgress){
return commonUnfinishedManga[mediaId].volumes;
}
else{
return 0;//conservative
};
};
return 0;//fallback
}
else{
return 0;//not in our list
};
};
list.forEach(function(item){
let chaptersRead = 0;
let volumesRead = 0;
if(item.status === "COMPLETED"){//if it's completed, we can make some safe assumptions
chaptersRead += Math.max(//chapter progress on the current read
item.media.chapters,//in most cases, it has a chapter count
item.media.volumes,//if not, there's at least 1 chapter per volume
item.progress,//if it doesn't have a volume count either, the current progress is probably not out of date
item.progressVolumes,//if it doesn't have a chapter progress, count at least 1 chapter per volume
1//finally, an entry has at least 1 chapter
);
volumesRead += Math.max(
item.progressVolumes,
item.media.volumes,
unfinishedLookup(item.mediaId+"","volumesNow",item.media.status,item.progress)//if people have forgotten to update their volume count and have caught up.
);
}
else{//we may only assume what's on the user's list.
chaptersRead += Math.max(
item.progress,
item.progressVolumes
);
volumesRead += Math.max(
item.progressVolumes,
unfinishedLookup(item.mediaId+"","volumesNow",item.media.status,item.progress)
);
};
if(useScripts.noRewatches && (item.repeat|0)){//if they have a reread, they have at least completed it
chaptersRead = Math.max(//first round
item.media.chapters,
item.media.volumes,
item.progress,
item.progressVolumes,
unfinishedLookup(item.mediaId+"","chapters",item.media.status),//use our lookup table
1
);
volumesRead = Math.max(
item.media.volumes,
item.progressVolumes,
unfinishedLookup(item.mediaId+"","volumes",item.media.status)
);
}
else{
chaptersRead += item.repeat * Math.max(//chapters from rereads
item.media.chapters,
item.media.volumes,
item.progress,
item.progressVolumes,
unfinishedLookup(item.mediaId+"","chapters",item.media.status),//use our lookup table
1
);
volumesRead += item.repeat * Math.max(//many manga have no volumes, so we can't make all of the same assumptions
item.media.volumes,
item.progressVolumes,//better than nothing if a volume count is missing
unfinishedLookup(item.mediaId+"","volumes",item.media.status)
);
};
chapters += chaptersRead;
volumes += volumesRead;
item.volumesRead = volumesRead;
item.chaptersRead = chaptersRead;
});
//
let previouScore = 0;
let maxRunLength = 0;
let maxRunLengthScore = 0;
let runLength = 0;
let sumEntries = 0;
let average = 0;
let standardDeviation;
let amount = scoreList.length;
let median = 0
scoreList.sort((a,b) => a.scoreRaw - b.scoreRaw);
if(scoreList.length % 2){
median = scoreList[(scoreList.length-1)/2].scoreRaw;
}
else if(scoreList.length){
median = scoreList[(scoreList.length)/2].scoreRaw/2 + scoreList[(scoreList.length)/2-1].scoreRaw/2;
};
scoreList.forEach(function(item){
sumEntries += item.scoreRaw;
if(item.scoreRaw === previouScore){
runLength++;
if(runLength > maxRunLength){
maxRunLength = runLength;
maxRunLengthScore = item.scoreRaw;
};
}
else{
runLength = 1;
previouScore = item.scoreRaw;
};
});
addStat("Manga on list: ",list.length);
addStat("Manga rated: ",amount);
addStat("Total chapters: ",chapters);
addStat("Total volumes: ",volumes);
if(amount){
average = sumEntries/amount;
};
standardDeviation = Math.sqrt(
scoreList.map(a => a.scoreRaw).reduce(
(accum,element) => accum + Math.pow(average - element,2)
)/amount
);
list.sort((a,b) => a.mediaId - b.mediaId);
if(amount){//no scores
if(amount === 1){
addStat(
"Only one score given: ",
maxRunLengthScore
);
}
else{
addStat(
"Average score: ",
average.roundPlaces(2)
);
addStat("Median score: ",median);
addStat(
"Standard deviation: ",
standardDeviation.roundPlaces(2)
);
if(maxRunLength > 1){
addStat("Most common score: ",maxRunLengthScore, " (" + maxRunLength + " instances)");
}
else{
addStat("Most common score: ","","no two scores alike");
};
};
};
//
let mangaFormatter = {
title: "Custom Manga Tags",
display: !useScripts.hideCustomTags,
headings: ["Tag","Count","Mean Score","Chapters","Volumes"],
focus: 1,
celData: [
function(cel,data,index,isPrimary){
if(isPrimary){
let nameCellCount = ("div","count",(index+1),cel);
nameCellCount.setAttribute("data-v-e2beaf26","");
let nameCellTag = create("a",false,data[index].name,cel);
nameCellTag.setAttribute("data-v-2f71893a","");
nameCellTag.style.cursor = "pointer";
}
else{
let nameCellTag = create("a","title",data[index].name,cel);
nameCellTag.setAttribute("data-v-2f71893a","");
nameCellTag.href = "/manga/" + data[index].mediaId + "/";
nameCellTag.style.marginLeft = "50px";
nameCellTag.style.display = "block";
}
},
function(cel,data,index,isPrimary){
if(isPrimary){
cel.innerText = data[index].list.length;
}
else{
let statusDot = create("div","hohStatusDot",false,cel);
statusDot.style.backgroundColor = distributionColours[data[index].status];
statusDot.title = data[index].status.toLowerCase();
if(data[index].status === "COMPLETED"){
statusDot.style.backgroundColor = "transparent";//default case
}
if(data[index].repeat === 1){
cel.innerHTML = svgAssets.repeat;
}
else if(data[index].repeat > 1){
cel.innerHTML = svgAssets.repeat + data[index].repeat;
}
}
},
function(cel,data,index,isPrimary){
if(isPrimary){
if(data[index].average === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].average);
}
}
else{
if(data[index].score === 0){
cel.innerText = "-";
}
else{
cel.innerText = Math.round(data[index].score);
}
}
},
function(cel,data,index){
cel.innerText = data[index].chaptersRead;
},
function(cel,data,index){
cel.innerText = data[index].volumesRead;
}
],
sorting: [
(a,b) => ("" + a.name).localeCompare(b.name),
(b,a) => a.list.length - b.list.length,
(b,a) => a.average - b.average,
(b,a) => a.chaptersRead - b.chaptersRead,
(b,a) => a.volumesRead - b.volumesRead
]
};
const mangaFields = [
{
key : "name",
sumable : false,
method : function(media){
return media.media.title.romaji;
}
},{
key : "repeat",
sumable : false,
method : function(media){
return media.repeat;
}
},{
key : "status",
sumable : false,
method : function(media){
return media.status;
}
},{
key : "mediaId",
sumable : false,
method : function(media){
return media.mediaId;
}
},{
key : "score",
sumable : false,
method : function(media){
return media.scoreRaw;
}
},{
key : "chaptersRead",
sumable : true,
method : function(media){
return media.chaptersRead;
}
},{
key : "volumesRead",
sumable : true,
method : function(media){
return media.volumesRead;
}
}
];
let customTags = customTagsCollection(list,mangaFormatter.title,mangaFields);
if(customTags.length){
let customTagsMangaTable = create("div","#customTagsMangaTable",false,personalStatsManga);
drawTable(customTags,mangaFormatter,customTagsMangaTable);
};
semaPhoreManga = list;
nativeTagsReplacer();
};
generalAPIcall(
queryMediaList,
{
name: document.URL.match(/\/([\w\-]+)\/stats/)[1],
listType: "MANGA"
},
personalStatsMangaCallback
);
};
for(var i=1;ia.count - b.count);
while(tagIndex.childElementCount){
tagIndex.removeChild(tagIndex.lastChild);
};
customTags.forEach(function(tag){
let tagElement = create("p",false,tag.name,tagIndex,"cursor:pointer;");
tagElement.onclick = function(){
let filterBox = document.querySelector(".entry-filter input");
filterBox.value = tag.name;
let event = new Event("input");
filterBox.dispatchEvent(event);
};
});
};
let variables = {
name: URLstuff[1],
listType: "ANIME"
};
if(URLstuff[2] === "mangalist"){
variables.listType = "MANGA";
};
generalAPIcall(queryMediaListNotes,variables,collectNotes);
}
filters.appendChild(extraFilters);
};
function addFeedFilters(){
if(!location.pathname.match(/^\/home\/?$/)){
return;
};
let filterBox = document.querySelector(".hohFeedFilter");
if(filterBox){
return;
};
let activityFeedWrap = document.querySelector(".activity-feed-wrap");
if(!activityFeedWrap){
setTimeout(addFeedFilters,100);
return;
};
filterBox = create("div","hohFeedFilter","At least ",activityFeedWrap);
activityFeedWrap.style.position = "relative";
activityFeedWrap.children[0].childNodes[0].nodeValue = "";
let commentFilterBoxInput = create("input");
let likeFilterBoxInput = create("input");
commentFilterBoxInput.type = "number";
likeFilterBoxInput.type = "number";
if(localStorageAvailable){
commentFilterBoxInput.value = useScripts.feedCommentComments;
likeFilterBoxInput.value = useScripts.feedCommentLikes;
commentFilterBoxInput.onchange = function(){
useScripts.feedCommentComments = commentFilterBoxInput.value;
useScripts.save();
};
likeFilterBoxInput.onchange = function(){
useScripts.feedCommentLikes = likeFilterBoxInput.value;
useScripts.save();
};
}
else{
commentFilterBoxInput.value = 0;
likeFilterBoxInput.value = 0;
};
let commentFilterBoxLabel = create("span",false," comments ");
let likeFilterBoxLabel = create("span",false," likes. ");
let allFilterBox = create("button",false,"⟳");
allFilterBox.style.padding = "0px";
allFilterBox.onclick = function(){
commentFilterBoxInput.value = 0;
likeFilterBoxInput.value = 0;
if(localStorageAvailable){
useScripts.feedCommentComments = 0;
useScripts.feedCommentLikes = 0;
useScripts.save();
}
};
filterBox.appendChild(commentFilterBoxInput);
filterBox.appendChild(commentFilterBoxLabel);
filterBox.appendChild(likeFilterBoxInput);
filterBox.appendChild(likeFilterBoxLabel);
filterBox.appendChild(allFilterBox);
let postRemover = function(){
if(!location.pathname.match(/^\/home\/?$/)){
return;
};
let activityFeed = activityFeedWrap.querySelector(".activity-feed");
if(activityFeed){
let duplicates = [];
for(var i=0;i a.action").href;
if(
actionLikes >= likeFilterBoxInput.value
&& (likeFilterBoxInput.value >= 0 || actionLikes < -likeFilterBoxInput.value)
&& actionReplies >= commentFilterBoxInput.value
&& (commentFilterBoxInput.value >= 0 || actionReplies < -commentFilterBoxInput.value)
&& (duplicates.indexOf(actionHref) === -1)
){
activityFeed.children[i].style.display = "";
}
else{
activityFeed.children[i].style.display = "none";
};
duplicates.push(actionHref);
};
};
setTimeout(function(){
postRemover();
},200);
};
postRemover();
};
function expandRight(){
if(!location.pathname.match(/^\/home\/?$/)){
return;
};
let possibleFullWidth = document.querySelector(".home.full-width");
if(possibleFullWidth){
let homeContainer = possibleFullWidth.parentNode;
let sideBar = document.querySelector(".activity-feed-wrap")
if(!sideBar){
setTimeout(expandRight,100);
return;
};
sideBar = sideBar.nextElementSibling;
sideBar.insertBefore(possibleFullWidth,sideBar.firstChild);
let setSemantics = function(){
let toggle = document.querySelector(".size-toggle.fa-compress");
if(toggle){
toggle.onclick = function(){
homeContainer.insertBefore(possibleFullWidth,homeContainer.firstChild);
};
}
else{
setTimeout(setSemantics,200);
};
};setSemantics();
}
}
let globalMatchingID = 0;
function mangaGuess(){
let URLstuff = location.pathname.match(/^\/manga\/(\d+)\/?(.*)?/);
if(!URLstuff){
return;
};
let possibleReleaseStatus = Array.from(
document.querySelectorAll(".data-set .value")
).find(
element => element.innerText.match(/^Releasing/)
);
if(possibleReleaseStatus){
if(globalMatchingID !== URLstuff[1]){
possibleReleaseStatus.innerText = "Releasing";
}
else{
if(possibleReleaseStatus.innerText !== "Releasing"){
return;
}
};
globalMatchingID = URLstuff[1];
const variables = {id: URLstuff[1],userName: whoAmI};
let query = `
query (
$id: Int,
$userName: String
) {
Page (page: 1) {
activities(
mediaId: $id,
sort: ID_DESC
) {
... on ListActivity {
progress
userId
}
}
}
MediaList (
userName: $userName,
mediaId: $id
) {
progress
}
}`;
let possibleMyStatus = document.querySelector(".actions .list .add");
const simpleQuery = !possibleMyStatus || possibleMyStatus.innerText === "Add To List" || possibleMyStatus.innerText === "Planning";
if(simpleQuery){
query = `
query (
$id: Int
) {
Page (page: 1) {
activities(
mediaId: $id,
sort: ID_DESC
) {
... on ListActivity {
progress
userId
}
}
}
}`;
};
let highestChapterFinder = function(data){
if(possibleReleaseStatus.innerText !== "Releasing"){
return;
}
let guesses = [];
let userIdCache = [];
data.data.Page.activities.forEach(function(activity){
if(activity.progress){
let chapterMatch = parseInt(activity.progress.match(/\d+$/)[0]);
if(userIdCache.indexOf(activity.userId) === -1){
guesses.push(chapterMatch);
userIdCache.push(activity.userId);
};
};
});
guesses.sort((b,a)=>a-b);
if(guesses.length){
let bestGuess = guesses[0];
if(guesses.length > 2){
let diff = guesses[0] - guesses[1];
let inverseDiff = 1 + Math.ceil(50/diff);
if(guesses.length >= inverseDiff){
if(guesses[1] === guesses[inverseDiff]){
bestGuess = guesses[1];
};
};
};
if(commonUnfinishedManga.hasOwnProperty(variables.id)){
if(bestGuess < commonUnfinishedManga[variables.id].chapters){
bestGuess = commonUnfinishedManga[variables.id].chapters;
};
};
if(simpleQuery){
if(bestGuess > 0){
possibleReleaseStatus.innerText += " (" + bestGuess + "?)";
}
}
else{
if(bestGuess < data.data.MediaList.progress){
bestGuess = data.data.MediaList.progress;
};
if(bestGuess > 0){
if(bestGuess === data.data.MediaList.progress){
possibleReleaseStatus.innerHTML += " (" + bestGuess + "?)";
}
else{
possibleReleaseStatus.innerHTML += " (" + bestGuess + "?) [+" + (bestGuess - data.data.MediaList.progress) + "]";
};
}
};
};
};
generalAPIcall(query,variables,highestChapterFinder);
}
else{
setTimeout(mangaGuess,200);
};
}
if(useScripts.ALbuttonReload){
let logo = document.querySelector(".logo");
if(logo){
logo.onclick = function(){
if(location.pathname.match(/^home\/?$/)){//we only want this behaviour here
window.location.reload(false);//reload page, but use cache if possible
}
}
}
}
function enumerateSubmissionStaff(){
if(!location.pathname.match(/^\/edit/)){
return;
};
setTimeout(function(){
enumerateSubmissionStaff();
},500);
let staffFound = [];
let staffEntries = document.querySelectorAll(".staff-row .col > .image");
Array.from(staffEntries).forEach(function(staff){
let enumerate = staffFound.filter(a => a===staff.href).length;
if(enumerate === 1){
let firstStaff = document.querySelector(".staff-row .col > .image[href=\"" + staff.href.replace("https://anilist.co","") + "\"]");
if(!firstStaff.previousSibling){
let enumerateSpan = create("span","hohEnumerateStaff",1);
firstStaff.parentNode.insertBefore(enumerateSpan,firstStaff);
};
}
if(enumerate > 0){
if(staff.previousSibling){
staff.previousSibling.innerText = enumerate + 1;
}
else{
let enumerateSpan = create("span","hohEnumerateStaff",(enumerate + 1));
staff.parentNode.insertBefore(enumerateSpan,staff);
}
};
staffFound.push(staff.href);
});
}
function addMALscore(type,id){
if(!location.pathname.match(/^\/(anime|manga)/)){
return;
};
if(document.getElementById("hohMALscore")){
return;
};
let possibleReleaseStatus = Array.from(document.querySelectorAll(".data-set .type"));
const MALlocation = possibleReleaseStatus.find(element => element.innerText === "Mean Score");
if(MALlocation){
let MALscore = create("div","data-set");
MALscore.id = "hohMALscore";
MALlocation.parentNode.parentNode.insertBefore(MALscore,MALlocation.parentNode.nextSibling);
generalAPIcall("query($id:Int){Media(id:$id){idMal}}",{id:id},
function(data){
if(data.data.Media.idMal){
GM_xmlhttpRequest({
method: "GET",
url: "https://myanimelist.net/" + type + "/" + data.data.Media.idMal,
onload: function(response){
let score = response.responseText.match(/ratingValue.+?(\d+\.\d+)/);
if(score){
create("div","type","MAL Score",MALscore);
create("div","value",score[1],MALscore);
}
}
});
}
}
);
}
else{
setTimeout(function(){addMALscore(type,id)},200);
};
}
function addEntryScore(id){
if(!location.pathname.match(/^\/(anime|manga)/)){
return;
};
if(document.getElementById("hohEntryScore")){
return;
};
let possibleLocation = document.querySelector(".actions .list .add");
if(possibleLocation){
let miniHolder = create("div","#hohEntryScore",false,possibleLocation.parentNode.parentNode,"position:relative;");
let type = possibleLocation.innerText;
if(type === "Reading" || type === "Completed" || type === "Watching" || type === "Paused" || type === "Repeating" || type === "Dropped"){
generalAPIcall(
"query($id:Int,$name:String){MediaList(mediaId:$id,userName:$name){score progress user{mediaListOptions{scoreFormat}}}}",
{id:id,name:whoAmI},
function(data){
let MediaList = data.data.MediaList;
let scoreSpan = create("span","hohMediaScore",false,miniHolder);
if(MediaList.score){
scoreSpan.innerHTML = scoreFormatter(MediaList.score,MediaList.user.mediaListOptions.scoreFormat,whoAmI);
};
if(type != "Completed"){
create("span","hohMediaScore",MediaList.progress,miniHolder,"right:0px;");
};
}
);
}
}
else{
setTimeout(function(){addEntryScore(id)},200);
};
}
function notificationCake(){
let notificationDot = document.querySelector(".notification-dot");
if(notificationDot && (!notificationDot.childElementCount)){
authAPIcall(
queryAuthNotifications,
{page:1,name:whoAmI},
function(data){
let Page = data.data.Page;
let User = data.data.User;
let types = [];
for(var i=0;i value))|0;
});
}
else if(ratingMode === "difference"){
shows.forEach(function(show){
let mini = Math.min(...show.score.filter(value => value))|0;
let maks = Math.max(...show.score);
show.average = maks - mini;
});
}
else if(ratingMode === "ratings"){
shows.forEach(function(show){
show.average = show.score.filter(value => value).length;
});
}
else if(ratingMode === "planned"){
shows.forEach(function(show){
show.average = show.status.filter(value => value === "PLANNING").length;
});
}
else if(ratingMode === "median"){
shows.forEach(function(show){
let newScores = show.score.filter(value => value).sort((a,b) => a - b);
if(newScores.length === 0){
show.average = 0;
}
else if(newScores.length % 2){
show.average = newScores[(newScores.length-1)/2];
}
else{
show.average = (newScores[newScores.length/2] + newScores[newScores.length/2 - 1])/2;
};
});
};
if(ratingMode === "user"){
shows.sort(function(a,b){
return b.score[guser] - a.score[guser];
});
}
else if(ratingMode === "userInverse"){
shows.sort(function(b,a){
return b.score[guser] - a.score[guser];
});
}
else if(ratingMode === "title"){
shows.sort(function(a,b){
return a.title.localeCompare(b.title)
});
}
else if(ratingMode === "titleInverse"){
shows.sort(function(b,a){
return a.title.localeCompare(b.title)
});
}
else if(inverse){
shows.sort((b,a) => b.average - a.average);
}
else{
shows.sort((a,b) => b.average - a.average);
};
};
let drawTable = function(){
while(table.childElementCount > 2){
table.removeChild(table.lastChild);
};
shows.forEach(function(show){
let display = users.every(function(user,index){
if(user.demand === 1 && show.score[index] === 0){
return false;
}
else if(user.demand === -1 && show.score[index] != 0){
return false;
};
return (!user.status || show.status[index] === user.status);
});
if(formatFilter.value != "all"){
if(formatFilter.value != show.format){
display = false;
};
};
if(show.numberWatched < ratingFilter.value){
display = false;
};
if(!display){
return;
};
let row = create("tr","hohAnimeTable");
let showID = create("td");
let showIDlink = create("a",false,show.title,showID);
showIDlink.href = "https://anilist.co/" + type + "/" + show.id + "/" + safeURL(show.title);
showID.style.maxWidth = "250px";
showIDlink.setAttribute("target","_blank");
let showAverage = create("td");
if(show.average){
showAverage.innerText = show.average.roundPlaces(2);
};
row.appendChild(showID);
row.appendChild(showAverage);
for(var i=0;i user.name).join(",");
}
if(formatFilter.value != "all"){
params += "&filter=" + encodeURIComponent(formatFilter.value);
};
if(params.length){
params = "?" + params.substring(1);
}
current = baseState + params;
history.replaceState({},"",baseState + params);
};
let drawUsers = function(){
while(table.childElementCount){
table.removeChild(table.lastChild);
};
let userRow = create("tr");
let resetCel = create("td",false,false,userRow);
let resetButton = create("button",false,"Reset",resetCel);
resetButton.onclick = function(){
users = [];
shows = [];
drawUsers();
changeUserURL();
};
let digestCel = create("td");
digestSelect = create("select");
let addOption = function(value,text){
let newOption = create("option",false,text,digestSelect);
newOption.value = value;
};
addOption("average","Average");
addOption("median","Median");
addOption("average0","Average~0");
addOption("min","Minimum");
addOption("max","Maximum");
addOption("ratings","#Ratings");
addOption("difference","Difference");
addOption("standardDeviation","Std. Deviation");
addOption("absoluteDeviation","Abs. Deviation");
addOption("planned","#Planning");
if(ratingMode != "title" && ratingMode != "titleInverse" && ratingMode != "user" && ratingMode != "userInverse"){
digestSelect.value = ratingMode;
};
digestSelect.oninput = function(){
ratingMode = digestSelect.value;
sortShows();
drawTable();
};
digestCel.appendChild(digestSelect);
userRow.appendChild(digestCel);
users.forEach(function(user,index){
let userCel = create("td",false,false,userRow);
userCel.style.position = "relative";
let avatar = create("img",false,false,userCel);
avatar.src = listCache[user.name].data.MediaListCollection.user.avatar.medium;
let name = create("span",false,user.name,userCel);
name.style.padding = "8px";
let remove = create("span","hohAnimeTableRemove","✕",userCel);
remove.onclick = function(){
deleteUser(index);
};
});
let addCel = create("td");
let addInput = create("input");
let addButton = create("button",false,"Add");
addButton.style.cursor = "pointer";
addButton.onclick = function(){
if(addInput.value != ""){
addUser(addInput.value);
addButton.innerText = "...";
addButton.disabled = true;
addInput.readOnly = true;
};
};
addCel.appendChild(addInput);
addCel.appendChild(addButton);
userRow.appendChild(addCel);
let headerRow = create("tr");
let typeCel = create("th");
let downArrowa = create("span","hohArrowSort","▼",typeCel);
downArrowa.onclick = function(){
ratingMode = "title";
sortShows();
drawTable();
};
let typeCelLabel = create("span",false,type[0].toUpperCase() + type.substring(1),typeCel);
let upArrowa = create("span","hohArrowSort","▲",typeCel);
upArrowa.onclick = function(){
ratingMode = "titleInverse";
sortShows();
drawTable();
};
headerRow.appendChild(typeCel);
let digestSortCel = create("td");
digestSortCel.style.textAlign = "center";
let downArrow = create("span","hohArrowSort","▼",digestSortCel);
downArrow.onclick = function(){
ratingMode = digestSelect.value;
inverse = false;
sortShows(digestSelect.value);
drawTable();
};
let upArrow = create("span","hohArrowSort","▲",digestSortCel);
upArrow.onclick = function(){
ratingMode = digestSelect.value;
inverse = true;
sortShows();
drawTable();
};
headerRow.appendChild(digestSortCel);
users.forEach(function(user,index){
let userCel = create("td");
userCel.style.textAlign = "center";
userCel.style.position = "relative";
let filter = create("span");
if(user.demand === 0){
filter.innerText = "☵";
}
else if(user.demand === 1){
filter.innerText = "✓";
filter.style.color = "green";
}
else{
filter.innerText = "✕";
filter.style.color = "red";
};
filter.classList.add("hohFilterSort");
filter.onclick = function(){
if(filter.innerText === "☵"){
filter.innerText = "✓";
filter.style.color = "green";
user.demand = 1;
}
else if(filter.innerText === "✓"){
filter.innerText = "✕";
filter.style.color = "red";
user.demand = -1;
}
else{
filter.innerText = "☵";
filter.style.color = "";
user.demand = 0;
};
drawTable();
};
let downArrow = create("span","hohArrowSort","▼");
downArrow.onclick = function(){
ratingMode = "user";
guser = index;
sortShows();
drawTable();
};
let upArrow = create("span","hohArrowSort","▲");
upArrow.onclick = function(){
ratingMode = "userInverse";
guser = index;
sortShows();
drawTable();
};
let statusFilterDot = create("div","hohStatusDot");
const stati = ["COMPLETED","CURRENT","PLANNING","PAUSED","DROPPED","REPEATING"];
statusFilterDot.onclick = function(){
if(user.status === "REPEATING"){
user.status = false;
statusFilterDot.style.background = "rgb(var(--color-background))";
statusFilterDot.title = "all";
}
else if(user.status === false){
user.status = "COMPLETED";
statusFilterDot.style.background = distributionColours["COMPLETED"];
statusFilterDot.title = "completed";
}
else{
user.status = stati[stati.indexOf(user.status) + 1];
statusFilterDot.style.background = distributionColours[user.status];
statusFilterDot.title = user.status.toLowerCase();
};
drawTable();
};
userCel.appendChild(downArrow);
userCel.appendChild(filter);
userCel.appendChild(upArrow);
userCel.appendChild(statusFilterDot);
headerRow.appendChild(userCel);
});
userRow.classList.add("hohUserRow");
headerRow.classList.add("hohHeaderRow");
table.appendChild(userRow);
table.appendChild(headerRow);
};
let addUser = function(userName){
let handleData = function(data,cached){
users.push({
name: userName,
demand: 0,
system: data.data.MediaListCollection.user.mediaListOptions.scoreFormat,
status: false
});
let list = returnList(data,true);
if(!cached){
let aliasesToLookFor = [];
if(useScripts.shortRomaji){
shortRomaji.forEach(function(alias){
let matches = alias[0].match(/\/(anime|manga)\/(\d+)\//);
aliasesToLookFor[matches[2]] = alias[1];
});
};
if(localStorageAvailable){
const titleAliases = JSON.parse(localStorage.getItem("titleAliases"));
if(titleAliases){
titleAliases.forEach(function(alias){
let matches = alias[0].match(/\/(anime|manga)\/(\d+)\//);
if(matches){
aliasesToLookFor[matches[2]] = alias[1];
};
});
}
};
let language = useScripts.titleLanguage.toLowerCase();
list.forEach(function(alia){
if(aliasesToLookFor[alia.mediaId]){
alia.media.title = aliasesToLookFor[alia.mediaId];
}
else{
alia.media.title = alia.media.title[language] ? alia.media.title[language] : alia.media.title.romaji;
};
alia.scoreRaw = convertScore(alia.score,data.data.MediaListCollection.user.mediaListOptions.scoreFormat);
});
};
shows.sort(function(a,b){return a.id - b.id;});
let listPointer = 0;
let userIndeks = 0;
if(shows.length){
userIndeks = shows[0].score.length;
};
let createEntry = function(mediaEntry){
let entry = {
id: mediaEntry.mediaId,
average: mediaEntry.scoreRaw,
title: mediaEntry.media.title,
format: mediaEntry.media.format,
score: Array(userIndeks).fill(0),
scorePersonal: Array(userIndeks).fill(0),
status: Array(userIndeks).fill("NOT"),
progress: Array(userIndeks).fill(false),
numberWatched: mediaEntry.scoreRaw ? 1 : 0
};
entry.score.push(mediaEntry.scoreRaw);
entry.scorePersonal.push(mediaEntry.score);
entry.status.push(mediaEntry.status);
if(mediaEntry.status != "PLANNING" && mediaEntry.status != "COMPLETED"){
entry.progress.push(mediaEntry.progress + "/" + (mediaEntry.media.chapters|mediaEntry.media.episodes));
}
else{
entry.progress.push(false);
};
return entry;
};
shows.forEach(function(show){
show.score.push(0);
show.scorePersonal.push(0);
show.status.push("NOT");
show.progress.push(false);
});
for(var i=0;i status === "NOT")
});
if(guser === index){
guser = false;
}
else if(user > index){
guser--;
};
sortShows();
drawUsers();
drawTable();
changeUserURL();
};
formatFilter.oninput = function(){drawTable();changeUserURL()};
ratingFilter.oninput = drawTable;
systemFilter.oninput = drawTable;
colourFilter.oninput = drawTable;
let searchParams = new URLSearchParams(location.search);
let paramFilter = searchParams.get("filter");
if(paramFilter){
formatFilter.value = paramFilter;
};
let paramUsers = searchParams.get("users");
if(paramUsers){
paramUsers.split(",").forEach(function(user){
addUser(user);
});
}
else{
addUser(whoAmI);
addUser(userA);
}
}
function addFollowCount(){
let URLstuff = location.pathname.match(/^\/user\/(.*)\/social/)
if(!URLstuff){
return;
};
generalAPIcall("query($name:String){User(name:$name){id}}",{name:URLstuff[1]},function(data){
generalAPIcall("query($id:Int!){Page(perPage:1){pageInfo{total} followers(userId:$id){id}}}",{id:data.data.User.id},function(data){
let target = document.querySelector(".filter-group");
if(target){
target.style.position = "relative";
create("span",false,data.data.Page.pageInfo.total,target.children[2],"position:absolute;right:3px;");
};
});
generalAPIcall("query($id:Int!){Page(perPage:1){pageInfo{total} following(userId:$id){id}}}",{id:data.data.User.id},function(data){
let target = document.querySelector(".filter-group");
if(target){
target.style.position = "relative";
create("span",false,data.data.Page.pageInfo.total,target.children[1],"position:absolute;right:3px;");
};
});
});
}
var urlChangedDependence = false;
function handleScripts(url){
if(url === "https://anilist.co/notifications" && useScripts.notifications){
enhanceNotifications();
return;
};
if(url.match(/^https:\/\/anilist\.co\/(anime|manga)\/\d*\/[\w\-]*\/social/)){
if(useScripts.socialTab){
enhanceSocialTab();
};
if(useScripts.activityTimeline){
addActivityTimeline();
};
};
if(
url.match(/\/stats\/?$/)
&& useScripts.moreStats
){
addMoreStats();
};
if(
url.match(/^https:\/\/anilist\.co\/home#access_token/)
){
let tokenList = location.hash.split("&").map(a=>a.split("="));
useScripts.accessToken = tokenList[0][1];
useScripts.save();
location.replace(location.protocol + "//" + location.hostname + location.pathname);
};
if(
url.match(/^https:\/\/anilist\.co\/home#aniscripts-login/)
){
if(useScripts.accessToken){
alert("Already authorized. You can rewoke this under 'apps' in your Anilist settings");
}
else{
location.href = authUrl;
};
};
if(url.match(/^https:\/\/anilist\.co\/user/)){
if(useScripts.completedScore || useScripts.droppedScore){//we also want this script to run on user pages
addCompletedScores();
};
setTimeout(function(){
let banner = document.querySelector(".banner");
if(banner){
let bannerLink = create("a",false,"⭳",banner,"position:absolute;right:10px;top:305px;font-weight:bolder;font-size:120%;");
bannerLink.href = banner.style.backgroundImage.replace("url(","").replace(")","").replace('"',"").replace('"',"");
};
},500);
}
else if(
url.match(/^https:\/\/anilist\.co\/forum\/thread\/.*/)
&& useScripts.forumComments
){
enhanceForum();
}
else if(url.match(/^https:\/\/anilist\.co\/staff\/.*/)){
if(useScripts.staffPages){
enhanceStaff();
}
if(useScripts.replaceStaffRoles){
replaceStaffRoles();
};
}
else if(
url.match(/^https:\/\/anilist\.co\/character\/.*/)
&& useScripts.characterFavouriteCount
){
enhanceCharacter();
}
else if(
url.match(/^https:\/\/anilist\.co\/studio\/.*/)
&& useScripts.studioFavouriteCount
){
enhanceStudio();
}
else if(
url.match(/^https:\/\/anilist\.co\/edit/)
&& useScripts.enumerateSubmissionStaff
){
enumerateSubmissionStaff();
}
if(
url.match(/^https:\/\/anilist\.co\/user\/.*\/social/)
&& useScripts.CSSfollowCounter
){
addFollowCount();
};
if(
url.match(/^https:\/\/anilist\.co\/.+\/(anime|manga)list\/?$/)
&& useScripts.draw3x3
&& (!useScripts.mobileFriendly)
){
draw3x3();
}
else if(
url.match(/^https:\/\/anilist\.co\/user\/(.*)\/(anime|manga)list\/compare/)
&& useScripts.comparissionPage
){
addComparissionPage();
}
if(url.match(/^https:\/\/anilist\.co\/search\/characters/)){
if(useScripts.characterFavouriteCount){
enhanceCharacterBrowse();
};
document.title = "Find Characters · AniList";
}
else if(url.match(/^https:\/\/anilist\.co\/search\/staff/)){
if(useScripts.staffPages){
enhanceStaffBrowse();
};
document.title = "Find Staff · AniList";
}
else if(url.match(/^https:\/\/anilist\.co\/search\/studios/)){
document.title = "Find Studios · AniList";
}
else if(url.match(/^https:\/\/anilist\.co\/search\/anime/)){
document.title = "Find Anime · AniList";
setTimeout(function(){
if(document.URL.match(/^https:\/\/anilist\.co\/search\/anime/)){
document.title = "Find Anime · AniList";
};
},100);
if(useScripts.browseFilters){
addBrowseFilters("anime");
};
}
else if(url.match(/^https:\/\/anilist\.co\/search\/manga/)){
document.title = "Find Manga · AniList";
if(useScripts.browseFilters){
addBrowseFilters("manga");
};
};
let mangaAnimeMatch = url.match(/^https:\/\/anilist\.co\/(anime|manga)\/(\d+)\/?([^/]*)?\/?(.*)?/);
if(mangaAnimeMatch){
setTimeout(function(){
let banner = document.querySelector(".banner");
if(banner){
let bannerLink = create("a",false,"⭳",banner,"position:absolute;right:10px;top:375px;font-weight:bolder;font-size:120%;");
bannerLink.href = banner.style.backgroundImage.replace("url(","").replace(")","").replace('"',"").replace('"',"");
};
},500);
if(useScripts.tagDescriptions){
enhanceTags();
};
if(useScripts.dubMarker && mangaAnimeMatch[1] === "anime"){
dubMarker();
}
else if(useScripts.mangaGuess && mangaAnimeMatch[1] === "manga"){
mangaGuess();
};
if(useScripts.MALscore){
addMALscore(mangaAnimeMatch[1],mangaAnimeMatch[2]);
};
if(useScripts.entryScore){
addEntryScore(mangaAnimeMatch[2]);
};
if(localStorageAvailable){
let titleAliases = JSON.parse(localStorage.getItem("titleAliases"));
if(useScripts.shortRomaji){
titleAliases = shortRomaji.concat(titleAliases);
};
if(titleAliases){
const urlID = mangaAnimeMatch[2];
for(var i=0;i 60*60*1000;//one hour
};
if(expired){
generalAPIcall("query{MediaTagCollection{name description}}",{},function(data){
data.data.MediaTagCollection.forEach(function(tag){
tagDescriptions[tag.name] = tag.description;
});
localStorage.setItem("hohTagCache",JSON.stringify({tags:tagDescriptions,updated:currentTime.valueOf()}));
});
}
else{
tagDescriptions = tagCache.tags;
};
};
console.log("Aniscripts " + scriptInfo.version);
})();