Skip to content

Instantly share code, notes, and snippets.

@chapmanjacobd
Created September 4, 2025 14:19
Show Gist options
  • Select an option

  • Save chapmanjacobd/6c53e480eccf99188fde43301fb3b9f4 to your computer and use it in GitHub Desktop.

Select an option

Save chapmanjacobd/6c53e480eccf99188fde43301fb3b9f4 to your computer and use it in GitHub Desktop.
MangaPlus Spacebar Navigation
// ==UserScript==
// @name MangaPlus Spacebar Navigation
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Use space/shift+space to simulate clicks for MangaPlus navigation.
// @author You
// @match https://mangaplus.shueisha.co.jp/viewer/*
// @grant none
// ==/UserScript==
let lastMouseX = 0;
let lastMouseY = 0;
document.addEventListener('mousemove', (event) => {
lastMouseX = event.clientX;
lastMouseY = event.clientY;
});
document.addEventListener('keydown', (event) => {
if (event.key === ' ') {
event.preventDefault();
event.stopPropagation();
let x = lastMouseX;
let y = lastMouseY;
if (event.shiftKey) {
// Flip horizontally across the viewport → simulate clicking on the other side
x = window.innerWidth - lastMouseX;
}
const target = document.elementFromPoint(x, y);
if (target) {
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
clientX: x,
clientY: y
});
target.dispatchEvent(clickEvent);
}
}
}, true);
@chapmanjacobd
Copy link
Author

actually... this works better. the problem is that body is blocking the real scroll container

// ==UserScript==
// @name         Universal Scroll Blocker + Fallback Scroll
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Blocks hijacked scroll and restores PageUp/PageDown/Space on real scroll container.
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function getScrollTarget() {
        // try to find the actual scrollable element
        const candidates = document.querySelectorAll('*');
        for (const el of candidates) {
            const style = getComputedStyle(el);
            if (/(auto|scroll)/.test(style.overflowY) && el.scrollHeight > el.clientHeight) {
                return el;
            }
        }
        return document.scrollingElement || document.body;
    }

    window.addEventListener('keydown', (e) => {
        const target = e.target;
        if (['TEXTAREA', 'INPUT', 'SELECT'].includes(target.tagName) || target.isContentEditable) {
            return;
        }

        const scrollEl = getScrollTarget();
        const step = scrollEl.clientHeight * 0.9; // almost a page

        switch (e.code) {
            case 'Space':
            case 'PageDown':
                e.stopImmediatePropagation();
                e.preventDefault();
                scrollEl.scrollBy({ top: step, behavior: 'smooth' });
                break;
            case 'PageUp':
                e.stopImmediatePropagation();
                e.preventDefault();
                scrollEl.scrollBy({ top: -step, behavior: 'smooth' });
                break;
            case 'ArrowDown':
                e.stopImmediatePropagation();
                e.preventDefault();
                scrollEl.scrollBy({ top: 40, behavior: 'smooth' });
                break;
            case 'ArrowUp':
                e.stopImmediatePropagation();
                e.preventDefault();
                scrollEl.scrollBy({ top: -40, behavior: 'smooth' });
                break;
        }
    }, { capture: true });

    window.addEventListener('wheel', (e) => {
        e.stopImmediatePropagation();
    }, { capture: true, passive: false });

})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment