cool thingy!

Per-page X-Mouse-like controls: custom actions for extra buttons, wheel, and hover focus (where possible) in Safari.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         cool thingy!
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Per-page X-Mouse-like controls: custom actions for extra buttons, wheel, and hover focus (where possible) in Safari.
// @author       You
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // =========================
    // CONFIG: TWEAK THIS PART
    // =========================

    // Example actions:
    //  - "back": window.history.back()
    //  - "forward": window.history.forward()
    //  - "scrollUp"/"scrollDown": window.scrollBy(...)
    //  - "top": scroll to top
    //  - "bottom": scroll to bottom
    //  - "none": do nothing / let default happen

    const CONFIG = {
        // Map mouse buttons to actions
        // 0 = left, 1 = middle, 2 = right, 3+ = extra (if browser exposes them)
        buttonMap: {
            1: 'autoScrollToggle', // middle click toggles auto-scroll
            3: 'back',             // XButton1 (if exposed) -> back
            4: 'forward'           // XButton2 (if exposed) -> forward
        },

        // Auto-scroll speed (pixels per frame)
        autoScrollSpeed: 8,

        // Enable "focus window on hover" style behavior (limited in browser)
        focusOnHover: true
    };

    // =========================
    // INTERNAL STATE
    // =========================

    let autoScrollActive = false;
    let autoScrollDirection = 1; // 1 = down, -1 = up
    let autoScrollRAF = null;

    // =========================
    // ACTION HANDLERS
    // =========================

    function doAction(action, event) {
        switch (action) {
            case 'back':
                event.preventDefault();
                window.history.back();
                break;
            case 'forward':
                event.preventDefault();
                window.history.forward();
                break;
            case 'scrollUp':
                event.preventDefault();
                window.scrollBy({ top: -200, left: 0, behavior: 'smooth' });
                break;
            case 'scrollDown':
                event.preventDefault();
                window.scrollBy({ top: 200, left: 0, behavior: 'smooth' });
                break;
            case 'top':
                event.preventDefault();
                window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
                break;
            case 'bottom':
                event.preventDefault();
                window.scrollTo({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' });
                break;
            case 'autoScrollToggle':
                event.preventDefault();
                toggleAutoScroll(event);
                break;
            case 'none':
            default:
                // Let default behavior happen
                break;
        }
    }

    // =========================
    // AUTO-SCROLL
    // =========================

    function autoScrollLoop() {
        if (!autoScrollActive) return;
        window.scrollBy(0, CONFIG.autoScrollSpeed * autoScrollDirection);
        autoScrollRAF = window.requestAnimationFrame(autoScrollLoop);
    }

    function toggleAutoScroll(event) {
        // Direction based on where you clicked relative to center
        const centerY = window.innerHeight / 2;
        autoScrollDirection = (event.clientY < centerY) ? -1 : 1;

        if (autoScrollActive) {
            autoScrollActive = false;
            if (autoScrollRAF) {
                window.cancelAnimationFrame(autoScrollRAF);
                autoScrollRAF = null;
            }
        } else {
            autoScrollActive = true;
            autoScrollLoop();
        }
    }

    // =========================
    // EVENT LISTENERS
    // =========================

    // Mouse button remapping
    window.addEventListener('mousedown', function (e) {
        // e.button: 0=left,1=middle,2=right, 3+=extra (if supported)
        const action = CONFIG.buttonMap[e.button];
        if (!action) return;
        doAction(action, e);
    }, true);

    // Optional: focus-on-hover style (limited)
    if (CONFIG.focusOnHover) {
        window.addEventListener('mouseover', function (e) {
            // We can't change OS-level focus, but we can visually "focus" elements.
            const el = e.target;
            if (el && el.focus && typeof el.focus === 'function') {
                // Only auto-focus inputs, textareas, and contenteditable
                const tag = el.tagName.toLowerCase();
                const isEditable =
                    tag === 'input' ||
                    tag === 'textarea' ||
                    el.isContentEditable;

                if (isEditable) {
                    el.focus({ preventScroll: true });
                }
            }
        }, true);
    }

    // Safety: stop auto-scroll on user input
    ['wheel', 'keydown', 'mousedown'].forEach(type => {
        window.addEventListener(type, () => {
            if (!autoScrollActive) return;
            autoScrollActive = false;
            if (autoScrollRAF) {
                window.cancelAnimationFrame(autoScrollRAF);
                autoScrollRAF = null;
            }
        }, { passive: true });
    });

})();