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)

  1. // ==UserScript==
  2. // @name Scroll to Nearest Paragraph (← → keys)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6
  5. // @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)
  6. // @author Işık Barış Fidaner
  7. // @match *://zizekanalysis.wordpress.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. let paragraphs = [];
  15. let current = 0;
  16. let initialized = false;
  17. const offset = 50; // pixels above paragraph
  18.  
  19. function init() {
  20. paragraphs = Array.from(document.querySelectorAll('p'))
  21. .filter(p => p.offsetHeight > 0 && p.offsetParent !== null);
  22. setInitialIndex();
  23. initialized = true;
  24. }
  25.  
  26. function setInitialIndex() {
  27. const viewportTop = window.scrollY;
  28. for (let i = 0; i < paragraphs.length; i++) {
  29. const rect = paragraphs[i].getBoundingClientRect();
  30. const paragraphTop = window.scrollY + rect.top;
  31. if (paragraphTop - offset >= viewportTop) {
  32. current = i;
  33. return;
  34. }
  35. }
  36. current = paragraphs.length; // in case scrolled past all
  37. }
  38.  
  39. function scrollToParagraph(index) {
  40. if (index >= 0 && index < paragraphs.length) {
  41. const rect = paragraphs[index].getBoundingClientRect();
  42. const scrollY = window.scrollY + rect.top - offset;
  43.  
  44. window.scrollTo({
  45. top: Math.max(scrollY, 0),
  46. behavior: 'smooth'
  47. });
  48.  
  49. current = index;
  50. }
  51. }
  52.  
  53. // SCROLL EVENT: Manuel scroll, Ctrl+F ile arama, vb. her türlü scroll'u algılar.
  54. let scrollTimeout;
  55. window.addEventListener('scroll', () => {
  56. if (!initialized) init();
  57. clearTimeout(scrollTimeout);
  58. scrollTimeout = setTimeout(setInitialIndex, 100); // 100ms sonra güncelle
  59. });
  60.  
  61. document.addEventListener('keydown', (e) => {
  62. // Ignore keypresses in input fields or editable areas
  63. const target = e.target;
  64. if (
  65. target.tagName === 'INPUT' ||
  66. target.tagName === 'TEXTAREA' ||
  67. target.isContentEditable
  68. ) {
  69. return;
  70. }
  71.  
  72. if (!initialized) init();
  73.  
  74. if (e.key === 'ArrowRight') {
  75. e.preventDefault();
  76. if (current < paragraphs.length) {
  77. scrollToParagraph(current);
  78. current++;
  79. }
  80. } else if (e.key === 'ArrowLeft') {
  81. e.preventDefault();
  82. current = Math.max(current - 2, 0); // adjust for previous move
  83. scrollToParagraph(current);
  84. current++;
  85. } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
  86. setTimeout(setInitialIndex, 0); // scroll sonrası current'ı güncelle
  87. }
  88. });
  89. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址