Anime History

Highlights episodes that have been visited

  1. // ==UserScript==
  2. // @name Anime History
  3. // @namespace https://greasyfork.org/en/users/62848-klesus
  4. // @description Highlights episodes that have been visited
  5. // @include https://twist.moe/a/*
  6. // @version 2.0
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @license https://www.gnu.org/licenses/gpl-3.0-standalone.html
  10. // ==/UserScript==
  11. "use strict";
  12.  
  13. //wrap script in function scope
  14. (function(){
  15. //------------------------------Init------------------------------
  16. //inject our own styling we're gonna apply
  17. var node = document.createElement('style');
  18. node.innerHTML = '.visited {background-color: #e53232 !important}' +
  19. '.edit-Btn {display: inline-block; position: relative; margin-top: 16px; margin-right: 8px; transition: all .2s linear}' +
  20. '.edit-on {border-right: 8px solid #e53232; border-left: 0 solid #444}' +
  21. '.edit-off {border-left: 8px solid #444; border-right: 0 solid #e53232}' +
  22. '.edit-on:active, .edit-off:active {border-right: 8px solid #e53232; border-left: 8px solid #444; transition: all .2s linear}';
  23. document.body.appendChild(node);
  24.  
  25. //fetch which show we're watching and what episode
  26. var aniep = window.location.pathname.split('/').splice(2);
  27. var anime = aniep[0];
  28. var currentEpisode = parseInt(aniep[1], 10);
  29. var episodeElem = document.querySelector('.episode-list');
  30. var episodeList = episodeElem.children[0].children;
  31. var watchedEpisodes;
  32. var hasMoreButton = (function(){
  33. var more = document.querySelector(".more");
  34. return more === null ? 0 : 1;
  35. })();
  36.  
  37. //fetches watched episode-list
  38. function getEpisodes(show) {
  39. var episodes = GM_getValue(show, "[]");
  40. return JSON.parse(episodes);
  41. }
  42.  
  43. //populates list with watched episodes
  44. function setEpisodes(show, episodes) {
  45. GM_setValue(show, JSON.stringify(episodes));
  46. }
  47.  
  48. //check which episodes we've visited
  49. watchedEpisodes = getEpisodes(anime);
  50.  
  51. //add the current episode to the list, but only if we haven't watched it before
  52. if (!(watchedEpisodes.indexOf(currentEpisode) > -1)) {
  53. watchedEpisodes.push(currentEpisode);
  54. }
  55.  
  56. //add the visited class to watched episodes
  57. watchedEpisodes.forEach(function (episode) {
  58. episodeList[episode - 1 + hasMoreButton].children[0].classList.add('visited');
  59. });
  60.  
  61. //overwrite the new updated watchlist to localstorage
  62. setEpisodes(anime, watchedEpisodes);
  63. //open the full episode-list if any episode after the 8th has been watched
  64. for (var i = 0; i < watchedEpisodes.length; i++) {
  65. if (watchedEpisodes[i] > 8) {
  66. document.querySelectorAll(".episode-list")[0].classList.add("show-all");
  67. break;
  68. }
  69. }
  70.  
  71. //----------------------------End init----------------------------
  72. //------------------------Add Edit buttons------------------------
  73. function toggleItem(elem, i) {
  74. elem.classList.toggle('visited');
  75. var index = watchedEpisodes.indexOf(i);
  76. if (index > -1){
  77. watchedEpisodes.splice(index, 1);
  78. } else {
  79. watchedEpisodes.push(i);
  80. }
  81. }
  82.  
  83. var ln = episodeList.length;
  84. function toggleVisit(e) {
  85. //Don't toggle the more button
  86. if ((e.target === episodeList[0].children[0] || e.target === episodeList[0].children[0].children[0]) && hasMoreButton == 1) {
  87. return;
  88. }
  89. for (var i = 0; i < ln; i++){
  90. if (e.target === episodeList[i].children[0] || e.target === episodeList[i].children[0].children[0]){
  91. toggleItem(episodeList[i].children[0], i + 1 - hasMoreButton);
  92. setEpisodes(anime, watchedEpisodes);
  93. break;
  94. }
  95. }
  96. e.stopPropagation();
  97. e.preventDefault();
  98. }
  99.  
  100. function resetAll() {
  101. watchedEpisodes = [];
  102. for (var i = 0; i < ln; i++){
  103. episodeList[i].children[0].classList.remove('visited');
  104. }
  105. setEpisodes(anime, watchedEpisodes);
  106. }
  107.  
  108. function invertAll() {
  109. for (var i = 0; i < ln; i++){
  110. toggleItem(episodeList[i].children[0], i + 1 - hasMoreButton);
  111. }
  112. setEpisodes(anime, watchedEpisodes);
  113. }
  114.  
  115. var toggle = "off";
  116. function toggleEditMode() {
  117. if(toggle === "off") {
  118. toggle = "on";
  119. editButton.classList.remove('edit-off');
  120. editButton.classList.add('edit-on');
  121. episodeElem.children[0].addEventListener('click', toggleVisit, true);
  122. } else {
  123. toggle = "off";
  124. editButton.classList.remove('edit-on');
  125. editButton.classList.add('edit-off');
  126. episodeElem.children[0].removeEventListener('click', toggleVisit, true);
  127. }
  128. }
  129.  
  130. var editButton = document.createElement('button');
  131. editButton.classList.add("edit-Btn", "edit-off");
  132. editButton.innerHTML = "Edit";
  133. episodeElem.parentNode.insertBefore(editButton, episodeElem);
  134. editButton.addEventListener('click', toggleEditMode);
  135.  
  136. var resetButton = document.createElement('button');
  137. resetButton.classList.add("edit-Btn");
  138. resetButton.innerHTML = "Reset";
  139. episodeElem.parentNode.insertBefore(resetButton, episodeElem);
  140. resetButton.addEventListener('click', resetAll);
  141.  
  142. var invertButton = document.createElement('button');
  143. invertButton.classList.add("edit-Btn");
  144. invertButton.innerHTML = "Invert";
  145. episodeElem.parentNode.insertBefore(invertButton, episodeElem);
  146. invertButton.addEventListener('click', invertAll);
  147.  
  148. //for some reason I have to put this last
  149. //augment native ajax methods
  150. if(viSupported()){
  151. var tmp = player.queue.load;
  152. player.queue.load = function(){
  153. var i = parseInt(arguments[0]) + 1;
  154. if (!(watchedEpisodes.indexOf(i) > -1)) {
  155. toggleItem(document.querySelector('.episode-list').children[0].children[i - 1 + hasMoreButton].children[0], i);
  156. setEpisodes(anime, watchedEpisodes);
  157. }
  158. tmp.apply(window.vi, arguments);
  159. }
  160. }
  161. })();