Proxer Statistics

Zählt die bereits geschauten/gelesenen Animes/Mangas und erlaubt es die Tabellen per Klick zusammenzuklappen bzw. sich mehr Details anzeigen zu lassen.

  1. // ==UserScript==
  2. // @name Proxer Statistics
  3. // @namespace https://greasyfork.org/de/users/83349-deimos
  4. // @version 1.31
  5. // @description Zählt die bereits geschauten/gelesenen Animes/Mangas und erlaubt es die Tabellen per Klick zusammenzuklappen bzw. sich mehr Details anzeigen zu lassen.
  6. // @author Deimos
  7. // @run-at document-start
  8. // @include http://proxer.me/*
  9. // @include https://proxer.me/*
  10. // @include http://www.proxer.me/*
  11. // @include https://www.proxer.me/*
  12. // @grant unsafeWindow
  13. // @history 1.31 Beheben von Cookie Problem, Beheben von nicht erkannten URLs
  14. // @history 1.30 Entferne Userscript Anker, Ergänze Novel, Zähle Medienkategorien dynamisch
  15. // @history 1.2 Script funktioniert auch im User-Control-Panel
  16. // @history 1.1 Einbinden des Userscript Anker von Blue.Reaper
  17. // @history 1.0 Zählen von Anime/Manga, anzeigen von Details, minimieren von Tabellen
  18. // ==/UserScript==
  19.  
  20. //############## Initialisierung ####################
  21.  
  22. var page = 0;
  23. var n_values = 12
  24.  
  25. //guckt ob Cookie vorhanden ist und korrekted Format hat, ansonsten wird neuer erstellt
  26. var hv_values = checkCookie("hv_values", "v".repeat(n_values)); //v:= visible h:= hidden
  27. var dn_values = checkCookie("dn_values", "n".repeat(n_values)); //d:= details n:= no details
  28.  
  29. //############################# Einbinden des Scripts #############################
  30.  
  31. //startet das Script beim Laden der Seite und
  32. document.addEventListener('DOMContentLoaded', function(event) {
  33. waitForKeyElements ("#pageMetaAjax", applyChange, false);
  34. });
  35.  
  36. function applyChange(){
  37. var path1 = window.location.pathname.split('/')[3]
  38. var path2 = window.location.search
  39.  
  40. if(path1 == "anime" || path2.substring(0,8) === "?s=anime") ///User befindet sich auf Anime Verzeichnis
  41. {
  42. page = 0;
  43. tableListener();
  44. }
  45. else if(path1 == "manga" || path2.substring(0,8) === "?s=manga") ///User befindet sich auf Manga Verzeichnis
  46. {
  47. page = 1;
  48. tableListener();
  49. }
  50. else if(path1 == "novel" || path2.substring(0,8) === "?s=novel") ///User befindet sich auf Novel Verzeichnis
  51. {
  52. page = 2;
  53. tableListener();
  54. }
  55. }
  56.  
  57. //############################# Hauptteil #############################
  58.  
  59. //Ermitteln der Tabellenlänge und setzen der EventListener
  60. function tableListener()
  61. {
  62. var tables = document.getElementsByTagName("table");
  63.  
  64. for(var i = 0; i<tables.length;i++){
  65.  
  66. var tr = tables[i].rows;
  67. var l = 0;
  68.  
  69. if(tr[2].getElementsByTagName("td")[0].innerHTML !== "Keine Einträge.")
  70. l = tr.length - 2;
  71. var message= ": " + l;
  72.  
  73. //Anzahl anzeigen
  74. tr[0].getElementsByTagName("th")[0].innerHTML+= message;
  75. tr[0].addEventListener("click",action);
  76. tr[0].id ="tr"+(i+page*4);
  77.  
  78. //Tabellen einklappen
  79. if(hv_values[i+page*4]=="h")
  80. hide(tr);
  81.  
  82. //Details anzeigen
  83. if(dn_values[i+page*4]=="d")
  84. details(tr);
  85. }
  86. }
  87.  
  88. //Auswahl ob "hide" oder "details", setzen des neuen Cookies
  89. function action(e)
  90. {
  91. var tr = this.parentElement.parentElement.rows;
  92. var xPosition = e.clientX;
  93. var rect = tr[0].getBoundingClientRect();
  94. var width = tr[0].offsetWidth;
  95.  
  96. if(xPosition<width/2){
  97. details(tr);
  98. setCookie("dn_values",dn_values);
  99. }
  100. else{
  101. hide(tr);
  102. setCookie("hv_values",hv_values);
  103. }
  104. }
  105.  
  106. //Anzeigen der genaueren Details der ausgewählten Tabelle
  107. function details(tr)
  108. {
  109. //Checke ob Einträge vorhanden sind
  110. if(!tr[2].getElementsByTagName("td")[2]){
  111. return false
  112. }
  113.  
  114. var id = parseInt(tr[0].id.substring(2));
  115. var text = tr[0].getElementsByTagName("th")[0].innerHTML;
  116.  
  117. //Details werden minimiert
  118. if(text.includes("<br>")){
  119. text = text.slice(0,text.indexOf("<br>"));
  120. tr[0].getElementsByTagName("th")[0].innerHTML = text;
  121.  
  122. //Update des Status
  123. dn_values = dn_values.substring(0,id) + "n" + dn_values.substring(id+1, dn_values.length); //erstellen eines neuen Cookies
  124. return true;
  125. }
  126.  
  127. var l = tr.length;
  128. var content = {}
  129.  
  130. //Zähle verschieden Medientypen
  131. for(var e = 2; e<l; e++){
  132. var type = tr[e].getElementsByTagName("td")[2].innerHTML;
  133. if(type in content)
  134. content[type] +=1
  135. else
  136. content[type] =1
  137. }
  138.  
  139. //Anzeigen
  140. var message= "";
  141. for(type in content){
  142. message += "<br> "+type.replace("<br>"," ")+": "+content[type]
  143. }
  144. tr[0].getElementsByTagName("th")[0].innerHTML+= message;
  145.  
  146. //Update des Status
  147. dn_values = dn_values.substring(0,id) + "d" + dn_values.substring(id+1, dn_values.length);
  148. }
  149.  
  150. //Einklappen der ausgewählten Tabelle
  151. function hide(tr)
  152. {
  153. var id = parseInt(tr[0].id.substring(2));
  154. var visibility;
  155. var char;
  156.  
  157. if(tr[1].style.display == "none") {
  158. visibility = "table-row";
  159. char = "v";
  160. }
  161. else{
  162. visibility = "none";
  163. char = "h";
  164. }
  165.  
  166. //Update des Status
  167. hv_values = hv_values.substring(0,id) + char + hv_values.substring(id+1, hv_values.length);
  168.  
  169. for(var e = 1; e < tr.length; e++){
  170. tr[e].style.display = visibility;
  171. }
  172. }
  173.  
  174. //############################# Cookies #############################
  175. function checkCookie(cname,ctext)
  176. {
  177. var cookie = getCookie(cname);
  178. if (cookie === "" || cookie.length != n_values)
  179. {
  180. cookie = ctext;
  181. setCookie(cname, cookie);
  182. }
  183. return cookie;
  184. }
  185. function getCookie(cname)
  186. {
  187. var name = cname + "=";
  188. var ca = document.cookie.split(";");
  189. for(var i = 0; i < ca.length; i++) {
  190. var c = ca[i];
  191. while (c.charAt(0) == ' ') {
  192. c = c.substring(1);
  193. }
  194. if (c.indexOf(name) === 0) {
  195. return c.substring(name.length, c.length);
  196. }
  197. }
  198. return "";
  199. }
  200. function setCookie(cname, cvalue)
  201. {
  202. var d = new Date();
  203. d.setTime(d.getTime() + (365*24*60*60*1000));
  204. var expires = "expires="+d.toUTCString();
  205. document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/" + ";SameSite=Strict;"
  206. }
  207.  
  208. //############################### Hintergrund Thread #######################################
  209. //Code from: https://github.com/CoeJoder/waitForKeyElements.js
  210. //(Greasy Fork doesn't allow to include this project by "require")
  211.  
  212. function waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals) {
  213. if (typeof waitOnce === "undefined") {
  214. waitOnce = true;
  215. }
  216. if (typeof interval === "undefined") {
  217. interval = 300;
  218. }
  219. if (typeof maxIntervals === "undefined") {
  220. maxIntervals = -1;
  221. }
  222. var targetNodes = (typeof selectorOrFunction === "function")
  223. ? selectorOrFunction()
  224. : document.querySelectorAll(selectorOrFunction);
  225.  
  226. var targetsFound = targetNodes && targetNodes.length > 0;
  227. if (targetsFound) {
  228. targetNodes.forEach(function(targetNode) {
  229. var attrAlreadyFound = "data-userscript-alreadyFound";
  230. var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false;
  231. if (!alreadyFound) {
  232. var cancelFound = callback(targetNode);
  233. if (cancelFound) {
  234. targetsFound = false;
  235. }
  236. else {
  237. targetNode.setAttribute(attrAlreadyFound, true);
  238. }
  239. }
  240. });
  241. }
  242.  
  243. if (maxIntervals !== 0 && !(targetsFound && waitOnce)) {
  244. maxIntervals -= 1;
  245. setTimeout(function() {
  246. waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals);
  247. }, interval);
  248. }
  249. }