AniDB.net status icons next to titles

Adds icons next to anime titles corresponding to its filestate, liststate, wishlist & notification status. Also adds red "(18+)" if anime is "18 Restricted". On Anime page it also adds Mylist & Seen count.

  1. // ==UserScript==
  2. // @name AniDB.net status icons next to titles
  3. // @namespace dexter86
  4. // @description Adds icons next to anime titles corresponding to its filestate, liststate, wishlist & notification status. Also adds red "(18+)" if anime is "18 Restricted". On Anime page it also adds Mylist & Seen count.
  5. // @include http://anidb.net/*
  6. // @include https://anidb.net/*
  7. // @grant none
  8. // @version 6.4.8
  9. // @supportURL https://anidb.net/forum/thread/50589
  10. // ==/UserScript==
  11. "use strict";
  12. /*
  13. TO DO
  14. detecting dynamic changes with wishlist/notify (animepage, seasons chart, etc)
  15. title wrap in related/similar on animepage
  16. customization per pagetype
  17. check with https://www.microsoft.com/en-us/store/p/tampermonkey/9nblggh5162s
  18. */
  19. var classes = [
  20. "restricted",
  21. "state_deleted",
  22. "state_mixed",
  23. "state_oncd",
  24. "state_onhdd",
  25. "state_onserver",
  26. "state_unknown",
  27. "liststate_collecting",
  28. "liststate_completed",
  29. "liststate_dropped",
  30. "liststate_stalled",
  31. "liststate_unknown",
  32. "liststate_watching",
  33. "blacklist",
  34. "wishlist_type_buddy",
  35. "wishlist_type_toget",
  36. "wishlist_type_towatch",
  37. "wishlist_type_undefined",
  38. "wishlist_priority_low",
  39. "wishlist_priority_med",
  40. "wishlist_priority_high",
  41. "notification",
  42. "notification_type_all",
  43. "notification_type_new",
  44. "notification_type_group",
  45. "notification_type_complete",
  46. "notification_priority_low",
  47. "notification_priority_med",
  48. "notification_priority_high"
  49. ];
  50.  
  51. var img = [
  52. "<span style='color: #BC1818'> (18+)</span>", //&#10084;
  53. "<span style='margin-left:0.5em;' class='i_icon i_state_deleted' title='File with status: deleted'></span>",
  54. "<span style='margin-left:0.5em;' class='i_icon i_state_mixed' title='File with status: mixed state'></span>",
  55. "<span style='margin-left:0.5em;' class='i_icon i_state_oncd' title='File with status: external storage (cd/dvd/...)'></span>",
  56. "<span style='margin-left:0.5em;' class='i_icon i_state_onhdd' title='File with status: internal storage (hdd)'></span>",
  57. "<span style='margin-left:0.5em;' class='i_icon i_state_onserver' title='File with status: remote storage (NAS/cloud/...)'></span>",
  58. "<span style='margin-left:0.5em;' class='i_icon i_state_unknown' title='File with status: unknown'></span>",
  59. "<span style='margin-left:0.5em;' class='i_icon i_liststate_collecting' title='State: collecting'></span>",
  60. "<span style='margin-left:0.5em;' class='i_icon i_liststate_completed' title='State: completed'></span>",
  61. "<span style='margin-left:0.5em;' class='i_icon i_liststate_dropped' title='State: dropped'></span>",
  62. "<span style='margin-left:0.5em;' class='i_icon i_liststate_stalled' title='State: stalled'></span>",
  63. "<span style='margin-left:0.5em;' class='i_icon i_liststate_unknown' title='State: unknown'></span>",
  64. "<span style='margin-left:0.5em;' class='i_icon i_liststate_watching' title='State: watching'></span>",
  65. "<span style='margin-left:0.5em;' class='i_icon i_wishlist_blacklist' title='Wishlist Type: blacklist'></span>",
  66. "<span style='margin-left:0.5em;' class='i_icon i_wishlist_buddy' title='Wishlist Type: buddy recommendations'></span>",
  67. "<span style='margin-left:0.5em;' class='i_icon i_wishlist_toget' title='Wishlist Type: to get'></span>",
  68. "<span style='margin-left:0.5em;' class='i_icon i_wishlist_towatch' title='Wishlist Type: to watch'></span>",
  69. "<span style='margin-left:0.5em;' class='i_icon i_wishlist_undefined' title='Wishlist Type: undefined'></span>",
  70. "<span style='margin-left:0.2em;' class='i_icon i_pri_low' title='Wishlist priority: low'></span>",
  71. "<span style='margin-left:0.2em;' class='i_icon i_pri_med' title='Wishlist priority: medium'></span>",
  72. "<span style='margin-left:0.2em;' class='i_icon i_pri_high' title='Wishlist priority: high'></span>",
  73. "<span style='margin-left:0.5em;' class='i_icon i_notify' title='Notification'></span>",
  74. " all",
  75. " new",
  76. " group",
  77. " complete",
  78. "<span style='margin-left:0.2em;' class='i_icon i_pri_low' title='Notification priority: low'></span>",
  79. "<span style='margin-left:0.2em;' class='i_icon i_pri_med' title='Notification priority: medium'></span>",
  80. "<span style='margin-left:0.2em;' class='i_icon i_pri_high' title='Notification priority: high'></span>"
  81. ];
  82.  
  83. function ExtractValue(a) {
  84. var i,
  85. querystring = document.head.querySelector("meta[data-anidb-url]").getAttribute("data-anidb-url").substring(document.head.querySelector("meta[data-anidb-url]").getAttribute("data-anidb-url").indexOf("?")+1).split("&");
  86. //console.log("querystring: ", querystring);
  87. for (i = 0; i < querystring.length; i++) {
  88. if (querystring[i].split("=")[0] === a) {
  89. return querystring[i].split("=")[1];
  90. }
  91. }
  92. }
  93.  
  94. function AniDB(page) {
  95. if (page === "anime") {
  96. var aftertitle = "",
  97. i,
  98. j,
  99. mylisteps = document.querySelector("tr.inmylist>td.value"),
  100. mylistseen = document.querySelector("tr.mylistseen>td.value"),
  101. myliststats = "";
  102. var mydata_filestate = [
  103. "i_state_deleted",
  104. "i_state_mixed",
  105. "i_state_oncd",
  106. "i_state_onhdd",
  107. "i_state_onserver",
  108. "i_state_unknown"
  109. ];
  110. var mydata_liststate = [
  111. "i_liststate_collecting",
  112. "i_liststate_completed",
  113. "i_liststate_dropped",
  114. "i_liststate_stalled",
  115. "i_liststate_unknown",
  116. "i_liststate_watching"
  117. ];
  118. var mydata_priorities = [
  119. "i_pri_low",
  120. "i_pri_med",
  121. "i_pri_high"
  122. ];
  123. var mydata_wishlist = [
  124. "i_wishlist_blacklist",
  125. "i_wishlist_buddy",
  126. "i_wishlist_toget",
  127. "i_wishlist_towatch",
  128. "i_wishlist_undefined"
  129. ];
  130. //18 restricted
  131. if (document.querySelector("a[href='/tag/2615/animetb']") !== null) {
  132. aftertitle += img[0];
  133. }
  134. //filestate
  135. for (i = 0; i < mydata_filestate.length; i++) {
  136. if (document.querySelector("tr.status a." + mydata_filestate[i]) !== null) {
  137. aftertitle += img[1+i];
  138. break;
  139. }
  140. }
  141. //liststate
  142. for (i = 0; i < mydata_liststate.length; i++) {
  143. if (document.querySelector("tr.status a." + mydata_liststate[i]) !== null) {
  144. aftertitle += img[7+i];
  145. break;
  146. }
  147. }
  148. //wishlist
  149. for (i = 0; i < mydata_wishlist.length; i++) {
  150. if (document.querySelector("tr.wishlist div.state>." + mydata_wishlist[i]) !== null) {
  151. aftertitle += img[13+i];
  152. for (j = 0; j < mydata_priorities.length; j++) {
  153. if (document.querySelector("tr.wishlist div.state>." + mydata_priorities[j]) !== null) {
  154. aftertitle += img[18+j];
  155. break;
  156. }
  157. }
  158. break;
  159. }
  160. }
  161. //notification
  162. if (document.querySelector("tr.notification div.state") !== null) {
  163. var notifytype = document.querySelector("tr.notification div.state>span[title='Notification Type']").textContent;
  164. aftertitle += img[21] + notifytype;
  165. for (i = 0; i < mydata_priorities.length; i++) {
  166. if (document.querySelector("tr.notification div.state>." + mydata_priorities[i]) !== null) {
  167. aftertitle += img[26+i];
  168. break;
  169. }
  170. }
  171. }
  172. //mylist stats
  173. if (mylisteps === null || mylistseen === null) {
  174. mylisteps = document.querySelector("div.g_section.mylist td.state:nth-child(2)");
  175. mylistseen = document.querySelector("div.g_section.mylist td.state:nth-child(3)");
  176. }
  177. if (mylisteps !== null && mylistseen !== null) {
  178. myliststats = "Mylist state: " + mylisteps.innerHTML + ", Seen: " + mylistseen.innerHTML;
  179. //myliststats = "";
  180. }
  181. //finishing touch :)
  182. var title = document.querySelector("h1.anime");
  183. if (title !== null) {
  184. title.innerHTML = "<div style='display: flex; white-space: nowrap;'><div>" + title.innerHTML + aftertitle + "</div><div style='width: 100%;'></div><div>" + myliststats + "</div></div>";
  185. }
  186. }
  187. AddStatusIcons(page);
  188. }
  189.  
  190. function AddStatusIcons(page) {
  191. //console.log("page: ", page);
  192. var ElementsWithClassInfo,
  193. i,
  194. j,
  195. k,
  196. LinksToProcess,
  197. LinksToProcessAdditional;
  198. for (i = 0; i < classes.length; i++) {
  199. if ((page === "mywishlist" && ((i >= 1 && i <=6) || (i>= 13 && i <= 28))) || (page === "mylist" && i >= 1 && i <= 12) || (page === "mynotifies" && ((i >= 1 && i <=6) || (i>= 21 && i <= 28)))) {
  200. continue;
  201. }
  202. ElementsWithClassInfo = document.querySelectorAll("." + classes[i]);
  203. //console.log(classes[i] + ": ", ElementsWithClassInfo);
  204. for (j = 0; j < ElementsWithClassInfo.length; j++) {
  205. //console.log("zmienna j: " + j);
  206. if ((ElementsWithClassInfo[j].nodeName === "TABLE") || (ElementsWithClassInfo[j].nodeName === "IMG")) {
  207. continue;
  208. }
  209. LinksToProcess = ElementsWithClassInfo[j].querySelectorAll("a[href^='/anime/']");
  210. //console.log("LinksToProcess ID " + j + ": ", LinksToProcess);
  211. if ((page === "userpage") || (page === "myfavourites") || (page === "addfavourite")) {
  212. //https://anidb.net/perl-bin/animedb.pl?show=userpage
  213. //https://anidb.net/perl-bin/animedb.pl?show=myfavourites
  214. //https://anidb.net/perl-bin/animedb.pl?show=addfavourite
  215. LinksToProcessAdditional = ElementsWithClassInfo[j].querySelectorAll("a[href^='/character/']");
  216. }
  217. if ((LinksToProcess === null) || (LinksToProcess === undefined)) {
  218. } else {
  219. for (k = 0; k < LinksToProcess.length; k++) {
  220. if (page === "anime" && LinksToProcess[k].getAttribute("title") === "Expand this release") {
  221. continue;
  222. //without it, script would add status icons on Anime page > Groups > Plus button on the left
  223. }
  224. if (LinksToProcess[k].querySelector(".g_image") !== null) {
  225. continue;
  226. //without it, script would add status icons under thumbnails
  227. }
  228. LinksToProcess[k].innerHTML += img[i];
  229. break;
  230. }
  231. }
  232. if ((LinksToProcessAdditional === null) || (LinksToProcessAdditional === undefined)) {
  233. } else {
  234. for (k = 0; k < LinksToProcessAdditional.length; k++) {
  235. if (LinksToProcessAdditional[k].querySelector(".g_image") !== null) {
  236. continue;
  237. //without it, script would add status icons under thumbnails
  238. }
  239. LinksToProcessAdditional[k].innerHTML += img[i];
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. }
  246.  
  247. AniDB(ExtractValue("show"));