8muses Improved

Improvements to 8muses: Mark-as-read, move image page breadcrumb to sidebar, hide image page header etc.

  1. // ==UserScript==
  2. // @name 8muses Improved
  3. // @namespace Hentiedup
  4. // @version 0.2.4
  5. // @description Improvements to 8muses: Mark-as-read, move image page breadcrumb to sidebar, hide image page header etc.
  6. // @author Hentiedup
  7. // @license MIT
  8. // @include https://comics.8muses.com/*
  9. // @include https://8muses.io/*
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @noframes
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. //================================================================= OPTIONS =================================================================//
  19. var moveBreadcrumbsAndHideHeaderOnImages = true; //Hides the header on image pages and moves the page path thing to the sidepanel
  20. var hideTitleAttributeFromImages = true; //that little text popup that appears when hovering over images on image pages
  21. var hideEmptyOrAdSectionsFromSidebar = true; //Hides empty/ad sections from the sidebar
  22. var fixSomeObviousProblems = true; //Fixes some obvious problems with the site
  23. var markAsReadSystemEnabled = true; //Mark pages with collections of images as read (appears as read on parent page)
  24. var expandImagesToScreenHeight = true; //doesn't shrink bigger images, only expands smaller
  25. //===========================================================================================================================================//
  26.  
  27.  
  28. var MarkedAsSeenString = GM_getValue("MarkedAsSeenString", "[]");
  29. var MarkedAsSeen = JSON.parse(MarkedAsSeenString);
  30.  
  31. //Mark as read system
  32. if(markAsReadSystemEnabled && window.location.href.includes("/album/")) {
  33. //Add MAR links
  34. if(true) {
  35. let MAREl = document.createElement("a");
  36. MAREl.innerHTML = "Mark this page as " + (MarkedAsSeen.includes(window.location.pathname) ? "unseen" : "seen");
  37. MAREl.setAttribute("id", "MARElem");
  38. MAREl.setAttribute("href", "#");
  39. MAREl.style.position = "absolute";
  40. MAREl.style.top = "-15px";
  41. MAREl.style.left = "0px";
  42. MAREl.style.fontSize = "1.5em";
  43. let galleryDiv = document.getElementById("content").getElementsByClassName("gallery")[0];
  44. galleryDiv.style.position = "relative";
  45. galleryDiv.style.paddingTop = "15px";
  46. galleryDiv.appendChild(MAREl);
  47.  
  48. MAREl.onclick = function(e) {
  49. e.preventDefault();
  50. AddRemoveFromMAR(window.location.pathname);
  51. };
  52. }
  53.  
  54. //Fade out and mark read comics
  55. if(true) {
  56. let comicElems = document.getElementById("content").getElementsByClassName("gallery")[0].getElementsByClassName("c-tile");
  57. for(let i = 0, count = comicElems.length; i < count; i++)
  58. {
  59. if(MarkedAsSeen.includes(comicElems[i].getAttribute("href")))
  60. {
  61. let readTagElem = document.createElement("span");
  62. readTagElem.style.position = "absolute";
  63. readTagElem.style.right = "20px";
  64. readTagElem.style.bottom = "20px";
  65. readTagElem.style.color = "white";
  66. readTagElem.style.fontSize = "20px";
  67. readTagElem.style.fontWeight = "bold";
  68. readTagElem.innerHTML = "READ";
  69.  
  70. comicElems[i].appendChild(readTagElem);
  71. comicElems[i].getElementsByClassName("image")[0].style.opacity = "0.2";
  72. comicElems[i].getElementsByClassName("image-title")[0].style.opacity = "0.2";
  73. }
  74. }
  75. }
  76. }
  77.  
  78. if(hideEmptyOrAdSectionsFromSidebar) {
  79. let targets = document.querySelectorAll(".menu-items > .ui-menu-item > a[rel=noopener]");
  80. for(let i = 0; i < targets.length; i++)
  81. {
  82. targets[i].parentNode.remove();
  83. }
  84. let adTiles = document.querySelectorAll("#content .gallery .c-tile[title='']");
  85. for(let i = 0, count = adTiles.length; i < count; i++)
  86. {
  87. adTiles[i].remove();
  88. }
  89. }
  90.  
  91. if(fixSomeObviousProblems) {
  92. addGlobalStyle(`
  93. html, body, #ractive-body, #b-wrapper { min-height: 100vh !important; }
  94. `);
  95. }
  96.  
  97. //Comic viewer page
  98. if(window.location.href.includes("/comics/picture/")) {
  99. if(expandImagesToScreenHeight) {
  100. addGlobalStyle(".show-tablet.block { display: none !important; }");
  101. var img = document.getElementsByClassName("photo")[0].getElementsByTagName("img")[0];
  102. var nativeImgHeight = img.clientHeight;
  103.  
  104. SetImageSizing();
  105. setInterval(SetImageSizing, 200);
  106. }
  107.  
  108. if(hideTitleAttributeFromImages) {
  109. document.querySelector(".photo > a").setAttribute("title", "");
  110. let target = document.querySelector(".photo > meta");
  111. let observer = new MutationObserver(() => {
  112. document.querySelector(".photo > a").setAttribute("title", "");
  113. });
  114. observer.observe(target, {attributes: true});
  115. }
  116.  
  117. if(moveBreadcrumbsAndHideHeaderOnImages) {
  118. addGlobalStyle(`
  119. #top-menu, #left-menu-close { display: none; }
  120. #left-menu, #left-menu.force-open, #b-wrapper { padding-top: 0; }
  121. #newBreadcrumb li { line-height: 1.2em; padding: 0 10px; }
  122. #newBreadcrumb ol { list-style: none; padding: 10px 0; }
  123. #content[style*="display: inline-block;"] .photo img { max-height: calc(100vh) !important; }
  124. `);
  125.  
  126. var breadcrumb = document.querySelector(".top-menu-breadcrumb").cloneNode(true);
  127. breadcrumb.setAttribute("id", "newBreadcrumb");
  128. document.querySelector(".menu-items > .menu-logo").className = "";
  129.  
  130. let beforeTarget = document.querySelector(".page-select");
  131. beforeTarget.parentNode.insertBefore(breadcrumb, beforeTarget);
  132.  
  133. var lis = document.getElementById("newBreadcrumb").getElementsByTagName("li");
  134. for(let i = 0; i < lis.length; i++)
  135. {
  136. if(i != 0)
  137. lis[i].insertBefore(document.createTextNode("⤷ "), lis[i].firstChild);
  138. }
  139. }
  140. }
  141.  
  142. function SetImageSizing()
  143. {
  144. img.style.objectFit = "contain";
  145. img.style.objectPosition = "top";
  146. img.style.width = "100%";
  147. //alert("nativeImgHeight: " + nativeImgHeight + ", window.innerHeight: " + window.innerHeight);
  148. img.style.height = ((nativeImgHeight > (window.innerHeight - (moveBreadcrumbsAndHideHeaderOnImages ? 0 : 50))) ? nativeImgHeight : (window.innerHeight - (moveBreadcrumbsAndHideHeaderOnImages ? 0 : 50))) + "px";
  149. }
  150.  
  151. function AddRemoveFromMAR(url) {
  152. //refresh current state of MAR
  153. MarkedAsSeenString = GM_getValue("MarkedAsSeenString", "[]");
  154. MarkedAsSeen = JSON.parse(MarkedAsSeenString);
  155.  
  156. //remove or add item
  157. if(MarkedAsSeen.includes(url)) {
  158. //remove
  159. MarkedAsSeen.splice(MarkedAsSeen.indexOf(url), 1);
  160. document.getElementById("MARElem").innerHTML = "Mark this page as seen";
  161. }
  162. else {
  163. //add
  164. MarkedAsSeen.push(url);
  165. document.getElementById("MARElem").innerHTML = "Mark this page as unseen";
  166. }
  167.  
  168. //update MAR
  169. MarkedAsSeenString = JSON.stringify(MarkedAsSeen);
  170. GM_setValue("MarkedAsSeenString", MarkedAsSeenString);
  171. }
  172.  
  173. function addGlobalStyle(css) {
  174. var head, style;
  175. head = document.getElementsByTagName('head')[0];
  176. if (!head) { return; }
  177. style = document.createElement('style');
  178. style.type = 'text/css';
  179. style.innerHTML = css;
  180. head.appendChild(style);
  181. }
  182. })();