Scroll to Nearest Paragraph (← → keys)

Scroll to nearest paragraph using ← and → keys with 50px offset, starting from current scroll position if already scrolled down the page (no modifier keys required)

当前为 2025-08-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         Scroll to Nearest Paragraph (← → keys)
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  Scroll to nearest paragraph using ← and → keys with 50px offset, starting from current scroll position if already scrolled down the page (no modifier keys required)
// @author       Işık Barış Fidaner
// @match        *://zizekanalysis.wordpress.com/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let paragraphs = [];
    let current = 0;
    let initialized = false;
    const offset = 50; // pixels above paragraph

    function init() {
        paragraphs = Array.from(document.querySelectorAll('p'))
            .filter(p => p.offsetHeight > 0 && p.offsetParent !== null);
        setInitialIndex();
        initialized = true;
    }

    function setInitialIndex() {
        const viewportTop = window.scrollY;
        for (let i = 0; i < paragraphs.length; i++) {
            const rect = paragraphs[i].getBoundingClientRect();
            const paragraphTop = window.scrollY + rect.top;
            if (paragraphTop - offset >= viewportTop) {
                current = i;
                return;
            }
        }
        current = paragraphs.length; // in case scrolled past all
    }

	function scrollToParagraph(index) {
		if (index >= 0 && index < paragraphs.length) {
			const rect = paragraphs[index].getBoundingClientRect();
			const scrollY = window.scrollY + rect.top - offset;

			window.scrollTo({
				top: Math.max(scrollY, 0),
				behavior: 'smooth'
			});

			current = index;
		}
	}

    // SCROLL EVENT: Manuel scroll, Ctrl+F ile arama, vb. her türlü scroll'u algılar.
    let scrollTimeout;
    window.addEventListener('scroll', () => {
        if (!initialized) init();
        clearTimeout(scrollTimeout);
        scrollTimeout = setTimeout(setInitialIndex, 100); // 100ms sonra güncelle
    });

	document.addEventListener('keydown', (e) => {
		// Ignore keypresses in input fields or editable areas
		const target = e.target;
		if (
			target.tagName === 'INPUT' ||
			target.tagName === 'TEXTAREA' ||
			target.isContentEditable
		) {
			return;
		}

		if (!initialized) init();

		if (e.key === 'ArrowRight') {
			e.preventDefault();
			if (current < paragraphs.length - 1) {
				scrollToParagraph(current + 1);
			}
		} else if (e.key === 'ArrowLeft') {
			e.preventDefault();
			if (current > 0) {
				scrollToParagraph(current - 1);
			}
		} else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
			setTimeout(setInitialIndex, 0);
		}
	});
})();