Add Keyboard Shortcut for Generic Next/Previous Page

Add CTRL+ArrowLeft and CTRL+ArrowRight for generic next/previous page. It will click the last found link/button whose text contain ">"/"»", "<"/"«", "Next", "Prev"/"Previous", or "Back".

  1. // ==UserScript==
  2. // @name Add Keyboard Shortcut for Generic Next/Previous Page
  3. // @namespace AddKeyboardShortcutForGenericNextPreviousPage
  4. // @version 1.0.22
  5. // @license GNU AGPLv3
  6. // @author jcunews
  7. // @description Add CTRL+ArrowLeft and CTRL+ArrowRight for generic next/previous page. It will click the last found link/button whose text contain ">"/"»", "<"/"«", "Next", "Prev"/"Previous", or "Back".
  8. // @website https://gf.qytechs.cn/en/users/85671-jcunews
  9. // @include *://*/*
  10. // @include *:*
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. /*
  15. The link/button text more specifically, are those which contain (non case sesitive) "Next", "Prev", "Previous";
  16. or has ">"/"<" (and similar meaning characters); or "«"/"»". The ID and class names are also checked. "«"/"»" have lower priority over the rest conditions.
  17.  
  18. This script doesn't take into account of links whose contents is an image rather than text, or whose text is a CSS text contents.
  19.  
  20. If next/previous navigation link is specified in the HTML metadata, it will be used as a priority.
  21. */
  22.  
  23. (function(rxPrev, rxPrev2, rxNext, rxNext2, ts) {
  24. rxPrev = /<|\u2039|(\b|_)(?:back|prev(ious)?)(\b|_)/i;
  25. rxPrev2 = /\u00ab/i;
  26. rxNext = />|\u203a|(\b|_)next(\b|_)/i;
  27. rxNext2 = /\u00bb/i;
  28. rxCarousel = /carousel/i;
  29.  
  30. addEventListener("keydown", function(ev, e, a) {
  31.  
  32. function clickLink(rx, e, i, l, r) {
  33. e = document.querySelectorAll('a,button,input[type="button"],input[type="submit"]');
  34. for (i = e.length - 1; i >= 0; i--) {
  35. if (
  36. (
  37. ((e[i].tagName === "A") && rx.test(e[i].rel)) ||
  38. ((e[i].tagName === "A") && Array.from(e[i].classList).some(cl => rx.test(cl))) ||
  39. ((e[i].tagName === "INPUT") && rx.test(e[i].value)) ||
  40. rx.test(e[i].textContent) ||
  41. (e[i].id && rx.test(e[i].id)) ||
  42. Array.from(e[i].classList).some(s => rx.test(s))
  43. ) && (!rxCarousel.test(e[i].className))
  44. ) {
  45. ev.stopImmediatePropagation();
  46. ev.stopPropagation();
  47. ev.preventDefault();
  48. e[i].click();
  49. return true
  50. }
  51. }
  52. return false
  53. }
  54.  
  55. if (ev.ctrlKey && !ev.altKey && !ev.shiftKey) {
  56. a = document.activeElement;
  57. while (a && a.shadowRoot?.activeElement) a = a.shadowRoot.activeElement;
  58. if (a && ((/^(INPUT|TEXTAREA)$/).test(a.tagName) || a.isContentEditable)) return;
  59. switch (ev.key) {
  60. case "ArrowLeft": //previous
  61. if (e = document.querySelector('link[rel="prev"][href]')) {
  62. ev.stopImmediatePropagation();
  63. ev.stopPropagation();
  64. ev.preventDefault();
  65. location.href = e.href;
  66. return
  67. }
  68. clickLink(rxPrev) || clickLink(rxPrev2);
  69. break;
  70. case "ArrowRight": //next
  71. if (e = document.querySelector('link[rel="next"][href]')) {
  72. ev.stopImmediatePropagation();
  73. ev.stopPropagation();
  74. ev.preventDefault();
  75. location.href = e.href;
  76. return
  77. }
  78. clickLink(rxNext) || clickLink(rxNext2);
  79. break
  80. }
  81. }
  82. }, true)
  83. })()

QingJ © 2025

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