SmoothScroll & Navigation Enhancer

You can quickly access the previous and next episodes, perform smooth scrolling up or down, and even enable or disable full-screen mode. This script is designed to enhance the reading experience of web content such as manga and comics in a more convenient and efficient way.

当前为 2024-08-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name SmoothScroll & Navigation Enhancer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description You can quickly access the previous and next episodes, perform smooth scrolling up or down, and even enable or disable full-screen mode. This script is designed to enhance the reading experience of web content such as manga and comics in a more convenient and efficient way.
  6. // @match https://westmanga.fun/*
  7. // @match https://komikcast.cz/*
  8. // @match https://aquamanga.org/read/*
  9. // @match https://www.webtoons.com/*
  10. // @match https://kiryuu.org/*
  11. // @match https://kiryuu.co/*
  12. // @match https://mangatale.co/*
  13. // @match https://mangaku.mom/*
  14. // @match https://manhwatop.com/*
  15. // @match https://komiku.id/*
  16. // @match https://komiknesia.xyz/*
  17. // @grant none
  18. // @license MIT
  19. // ==/UserScript==
  20.  
  21. // @match https://mangadex.org/chapter/*
  22.  
  23. (function() {
  24. 'use strict';
  25.  
  26. var scrollInterval = null;
  27. var isScrolling = false
  28. var isFullscreen = false;
  29. var activeElement;
  30.  
  31. var smoothScrollSpeed = 10.5; // Kecepatan pengguliran yang mulus
  32. var smoothScrollDelay = 10; // Penundaan di antara setiap langkah pengguliran yang mulus
  33.  
  34. const HOSTS = {
  35. 'westmanga.fun': {
  36. next: '.ch-next-btn',
  37. prev: '.ch-prev-btn'
  38. },
  39. 'komikcast.cz': {
  40. next: '.nextprev a[rel="next"]',
  41. prev: '.nextprev a[rel="prev"]'
  42. },
  43. 'www.webtoons.com': {
  44. next: 'a[title="Episode selanjutnya"]',
  45. prev: 'a[title="Episode sebelumnya"]'
  46. },
  47. 'aquamanga.org': {
  48. next: 'a.btn.next_page',
  49. prev: 'a.btn.prev_page'
  50. },
  51. 'kiryuu.org': {
  52. next: 'a.ch-next-btn',
  53. prev: 'a.ch-prev-btn'
  54. },
  55. 'mangatale.co': {
  56. next: 'a.ch-next-btn',
  57. prev: 'a.ch-prev-btn'
  58. },
  59. 'mangaku.mom': {
  60. prev: 'button.glho.glkp_1:-soup-contains("PREV")',
  61. next: 'button.glho.glkn_1:-soup-contains("NEXT")'
  62. },
  63. 'manhwatop.com': {
  64. prev: '.prev_page',
  65. next: '.next_page'
  66. },
  67. 'komiku.id': {
  68. prev: 'div.nxpr > a.rl:first-of-type',
  69. next: 'div.nxpr > a.rl:last-of-type'
  70. },
  71. 'komiknesia.xyz': {
  72. prev: 'a.ch-prev-btn',
  73. next: 'a.ch-next-btn'
  74. },
  75. 'mangadex.org': {
  76. prev: '',
  77. next: ''
  78. }
  79. };
  80.  
  81. let btnNext, btnPrev;
  82. let host = window.location.host;
  83. if (HOSTS[host]) {
  84. btnNext = HOSTS[host].next;
  85. btnPrev = HOSTS[host].prev;
  86. }
  87.  
  88. const zoomLevel = () => {
  89. return document.body.style.zoom || 1;
  90. }
  91.  
  92. function adjustSmoothScroll() {
  93.  
  94. let zLevel = zoomLevel();
  95.  
  96. smoothScrollSpeed = smoothScrollSpeed * zLevel;
  97. smoothScrollDelay = smoothScrollDelay / zLevel;
  98. }
  99.  
  100. function smoothScrollStep(direction) {
  101. var scrollDistance = direction === 'up' ? -smoothScrollSpeed : smoothScrollSpeed;
  102. window.scrollBy(0, scrollDistance);
  103. }
  104.  
  105. function startSmoothScrolling(direction) {
  106. if (!isScrolling) {
  107. isScrolling = true;
  108. smoothScrollStep(direction);
  109. scrollInterval = setInterval(function() {
  110. smoothScrollStep(direction);
  111. }, smoothScrollDelay);
  112. }
  113. }
  114.  
  115. function stopSmoothScrolling() {
  116. if (isScrolling) {
  117. isScrolling = false;
  118. clearInterval(scrollInterval);
  119. }
  120. }
  121.  
  122. // Deteksi saat zoom berubah
  123. document.addEventListener('zoomchange', adjustSmoothScroll);
  124.  
  125. // Sesuaikan juga saat scroll dihentikan
  126. document.addEventListener('keyup', event => {
  127.  
  128. if (isScrolling) {
  129. stopSmoothScrolling();
  130. adjustSmoothScroll();
  131. }
  132. });
  133.  
  134. adjustSmoothScroll();
  135.  
  136. document.addEventListener('keydown', function(event) {
  137. if ((event.key === 'a' || event.key === 'A' || event.key === 'ArrowLeft') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  138. let prevButton = document.querySelector(btnPrev);
  139. if (prevButton) {
  140. // Periksa elemen yang sedang dalam fokus
  141. activeElement = document.activeElement;
  142. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  143. // Pengguna tidak sedang mengetik
  144. prevButton.click();
  145. }
  146. }
  147. } else if ((event.key === 'd' || event.key === 'D' || event.key === 'ArrowRight') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  148. let nextButton = document.querySelector(btnNext);
  149. if (nextButton) {
  150. // Periksa elemen yang sedang dalam fokus
  151. activeElement = document.activeElement;
  152. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  153. // Pengguna tidak sedang mengetik
  154. nextButton.click();
  155. }
  156. }
  157. } else if ((event.key === 's' || event.key === 'S') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  158. // Periksa elemen yang sedang dalam fokus
  159. activeElement = document.activeElement;
  160. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  161. // Pengguna tidak sedang mengetik
  162. startSmoothScrolling('down');
  163. }
  164. } else if ((event.key === 'w' || event.key === 'W') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  165. // Periksa elemen yang sedang dalam fokus
  166. activeElement = document.activeElement;
  167. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  168. // Pengguna tidak sedang mengetik
  169. startSmoothScrolling('up');
  170. }
  171. } else if ((event.key === 'f' || event.key === 'F') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  172. // Periksa elemen yang sedang dalam fokus
  173. activeElement = document.activeElement;
  174. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  175. // Pengguna tidak sedang mengetik, masuk ke mode fullscreen
  176. event.preventDefault();
  177. toggleFullscreen(); // Fungsi Anda untuk masuk/keluar dari mode fullscreen
  178. }
  179. } else if ((event.key === 'q' || event.key === 'Q') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  180. var allChapterButton;
  181. if (window.location.host === 'westmanga.fun') {
  182. allChapterButton = document.querySelector('.allc a');
  183. } else if (window.location.host === 'www.webtoons.com') {
  184. allChapterButton = document.querySelector('a[class="subj NPI=a:end,g:in_id"]');
  185. } else if (window.location.host === 'komiknesia.xyz') {
  186. allChapterButton = document.querySelector('.allc a');
  187. } else if (window.location.host === 'kiryuu.org') {
  188. allChapterButton = document.evaluate("//div[contains(text(), 'Semua chapter ada di')]/a", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  189. } else if (window.location.host === 'komikcast.cz') {
  190. allChapterButton = document.querySelector('div.allc a');
  191. } else if (window.location.host === 'mangatale.co') {
  192. allChapterButton = document.evaluate("//div[contains(text(), 'All chapters are in ')]/a", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  193. } else if (window.location.host === 'aquamanga.org') {
  194. // Ambil URL saat ini
  195. var currentUrl = window.location.href;
  196. // Gunakan ekspresi reguler untuk menghapus segmen URL setelah judul komik
  197. var newUrl = currentUrl.replace(/\/read\/([^/]+)\/.*/, '/read/$1/');
  198. // Periksa elemen yang sedang dalam fokus
  199. activeElement = document.activeElement;
  200. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  201. // Pengguna tidak sedang mengetik memindahkan pengguna ke URL yang telah diubah
  202. window.location.href = newUrl;
  203. }
  204. }
  205. if (allChapterButton) {
  206. // Periksa elemen yang sedang dalam fokus
  207. activeElement = document.activeElement;
  208. if (!(activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'))) {
  209. // Pengguna tidak sedang mengetik
  210. allChapterButton.click();
  211. }
  212. }
  213. }
  214. });
  215.  
  216. function toggleFullscreen() {
  217. if (!isFullscreen) {
  218. enterFullscreen();
  219. } else {
  220. exitFullscreen();
  221. }
  222. isFullscreen = !isFullscreen;
  223. }
  224.  
  225. function enterFullscreen() {
  226. const elem = document.documentElement;
  227. if (elem.requestFullscreen) {
  228. elem.requestFullscreen();
  229. } else if (elem.mozRequestFullScreen) {
  230. elem.mozRequestFullScreen();
  231. } else if (elem.webkitRequestFullscreen) {
  232. elem.webkitRequestFullscreen();
  233. } else if (elem.msRequestFullscreen) {
  234. elem.msRequestFullscreen();
  235. }
  236. }
  237.  
  238. function exitFullscreen() {
  239. if (document.exitFullscreen) {
  240. document.exitFullscreen();
  241. } else if (document.mozCancelFullScreen) {
  242. document.mozCancelFullScreen();
  243. } else if (document.webkitExitFullscreen) {
  244. document.webkitExitFullscreen();
  245. } else if (document.msExitFullscreen) {
  246. document.msExitFullscreen();
  247. }
  248. }
  249.  
  250. document.addEventListener('keyup', function(event) {
  251. if ((event.key === 's' || event.key === 'S' || event.key === 'w' || event.key === 'W') && !event.ctrlKey && !event.altKey && event.key !== 'Tab') {
  252. stopSmoothScrolling();
  253. window.scrollTo(window.pageXOffset, window.pageYOffset); // Menghentikan scroll secara instan
  254. }
  255. });
  256. })();