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 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);
		}
	});
})();