// ==UserScript== // @name Chapter Changer + Smooth Scrolling // @description For Mangakakalot & Manganelo & ReaperScans // @version 0.81 // @namespace https://greasyfork.org/en/users/55535-sllypper // @author sllypper // @match https://mangakakalot.com/chapter/* // @match https://manganelo.com/chapter/* // @match https://reaperscans.com/comics/* // @grant none // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Smooth Scrolling Settings // how much it scrolls every tick (in pixels) let scrollAmount = 64; // how long between ticks (in ms) // 16.666667 = 60 frames per second let scrollPeriod = 33.33; // how much holding Shift will multiply the scrollAmount let shiftSpeedMod = 2.0; // let implementations = [ { name: 'mangakakalot', match: '^https?://mangakakalot.com/chapter/*', nextchap: function(prev) { let nextButtonSel = '.btn-navigation-chap > .back'; let prevButtonSel = '.btn-navigation-chap > .next'; if (!prev) return document.querySelector(nextButtonSel); return document.querySelector(prevButtonSel); }, prevchap: function() { return this.nextchap(true); } }, { name: 'manganelo', match: '^https?://manganelo.com/chapter/*', nextchap: function(prev) { let nextButtonSel = '.navi-change-chapter-btn-next'; let prevButtonSel = '.navi-change-chapter-btn-prev'; if (!prev) return document.querySelector(nextButtonSel); return document.querySelector(prevButtonSel); }, prevchap: function() { return this.nextchap(true); } }, { name: 'reaperscans', match: '^https?://reaperscans.com/comics/*', nextchap: function(prev) { let buttons = document.querySelector('div.d-flex:nth-child(4)'); if (!prev) return buttons.querySelector('div:nth-child(3) > a'); return buttons.querySelector('div:nth-child(1) > a'); }, prevchap: function() { return this.nextchap(true); } } ]; let clickEl = el => { if (!el) return; el.click(); } let loadHotkeys = imp => { window.addEventListener('keydown', event => { switch(event.code) { case 'KeyC': clickEl(imp.nextchap()); break; case 'KeyZ': clickEl(imp.prevchap()); break; } }); } let pageUrl = window.location.href; implementations.some(function(imp) { if (imp.match && (new RegExp(imp.match, 'i')).test(pageUrl)) { loadHotkeys(imp); return true; } }); // Scroller const states = { NONE: 0, UP: 1, SHIFTUP: 2, DOWN: 3, SHIFTDOWN: 4 } let scrollState = states.NONE; let currScrollAction = null; /* let buttonsContainer = document.getElementsByClassName('navi-change-chapter-btn'); if (buttonsContainer.length === 0) { buttonsContainer = document.getElementsByClassName('btn-navigation-chap'); if (buttonsContainer.length === 0) { console.log('Chapter Changer + Smooth Scrolling ERROR: No Navigation Buttons found'); return; } } let buttons = buttonsContainer[0].childNodes; let prevButton = buttons[0]; let nextButton = buttons[buttons.length-1]; // if there's only one button if (buttons.length != 2) { // check if it's the next button // mangakakalot has "back" and "next" button classes are switched around if (buttons[0].classList.contains("back") || buttons[0].classList.contains("navi-change-chapter-btn-next")) { // then we're in chapter 1 and there's no prev button prevButton = null; } else { // else we're in the last chapter and there's no next button nextButton = null; } } */ document.addEventListener("keydown", event => { if (event.code === "KeyW" || event.code === "KeyK") { if (scrollState !== states.UP && !event.shiftKey) { clearScrollAction(); scrollState = states.UP; scrollAction(-scrollAmount); } else if (scrollState !== states.SHIFTUP && event.shiftKey) { clearScrollAction(); scrollState = states.SHIFTUP; scrollAction(-scrollAmount*shiftSpeedMod); } } else if (event.code === "KeyS" || event.code === "KeyJ") { if (scrollState !== states.DOWN && !event.shiftKey) { clearScrollAction(); scrollState = states.DOWN; scrollAction(scrollAmount); } else if (scrollState !== states.SHIFTDOWN && event.shiftKey) { clearScrollAction(); scrollState = states.SHIFTDOWN; scrollAction(scrollAmount*shiftSpeedMod); } /* } else if (event.code === "KeyC" && nextButton != null) { nextButton.click(); } else if (event.code === "KeyZ" && prevButton != null) { prevButton.click(); */ } }); document.addEventListener("keyup", event => { if (event.code === "KeyW" || event.code === "KeyK") { clearScrollAction(); } else if (event.code === "KeyS" || event.code === "KeyJ") { clearScrollAction(); } else if (event.key === "Shift") { clearScrollAction(); } }); function scrollAction(amount) { currScrollAction = setInterval(() => { window.scrollBy(0, amount); }, scrollPeriod) } function clearScrollAction() { clearInterval(currScrollAction); currScrollAction = null; scrollState = states.NONE; } })();