NovelHelper

Add navigation features to some web novels.

  1. // ==UserScript==
  2. // @name NovelHelper
  3. // @name:vi NovelHelper
  4. // @namespace https://lelinhtinh.github.io
  5. // @description Add navigation features to some web novels.
  6. // @description:vi Bổ sung tính năng điều hướng cho một vài trang web truyện.
  7. // @version 1.3.2
  8. // @icon https://i.imgur.com/FHgT0E4.png
  9. // @author Zzbaivong
  10. // @oujs:author baivong
  11. // @license MIT; https://baivong.mit-license.org/license.txt
  12. // @match https://tienhieptruyen.net/*
  13. // @match https://truyendich.com/*
  14. // @match https://bachngocsach.com/reader/*
  15. // @match https://truyenbns.com/reader/*
  16. // @match https://bachngocsach.com.vn/reader/*
  17. // @match https://vlognovel.com/*
  18. // @require https://unpkg.com/hotkeys-js/dist/hotkeys.min.js
  19. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
  20. // @noframes
  21. // @supportURL https://github.com/lelinhtinh/Userscript/issues
  22. // @run-at document-idle
  23. // @grant GM_addStyle
  24. // @inject-into content
  25. // ==/UserScript==
  26.  
  27. /* global hotkeys */
  28. const k = hotkeys.noConflict();
  29.  
  30. let chapSelector, preSelector, nextSelector;
  31. switch (location.host) {
  32. case 'tienhieptruyen.net':
  33. chapSelector = '.chapter-c';
  34. preSelector = () => {
  35. const preBtn = document.querySelector('.chap-header .btn-next:not([disabled]) .fa-angle-double-left');
  36. if (preBtn === null) return;
  37. preBtn.parentNode.click();
  38. };
  39. nextSelector = () => {
  40. const nextBtn = document.querySelector('.chap-header .btn-next:not([disabled]) .fa-angle-double-right');
  41. if (nextBtn === null) return;
  42. nextBtn.parentNode.click();
  43. };
  44. break;
  45. case 'truyendich.com':
  46. chapSelector = '#read-content';
  47. preSelector = '.btn-chapter-pre:not(.disable)';
  48. nextSelector = '.btn-chapter-next:not(.disable)';
  49. break;
  50. case 'bachngocsach.com':
  51. case 'truyenbns.com':
  52. case 'bachngocsach.com.vn':
  53. chapSelector = '#noi-dung';
  54. preSelector = '.page-prev:not(.invisible)';
  55. nextSelector = '.page-next:not(.invisible)';
  56. GM.addStyle(`
  57. .page-menu{position:relative!important}
  58. #backtotop,.qc-chuong-top,#thongbao,#chuong-footer,#liked-list,#like-note,.qc-chuong,#thaoluan,#noi-dung~.chuong-nav{display:none!important}
  59. `);
  60. break;
  61. case 'vlognovel.com':
  62. chapSelector = '#showContent';
  63. preSelector = '.prevchap';
  64. nextSelector = '.nextchap';
  65. break;
  66. default:
  67. console.log('NovelHelper: Unknown host');
  68. }
  69.  
  70. const chapter = document.querySelector(chapSelector);
  71. chapter.scrollIntoView();
  72.  
  73. const navChap = (btnSelector) => {
  74. const button = document.querySelector(btnSelector);
  75. if (button === null) return;
  76. button.click();
  77. };
  78.  
  79. k('left', () => {
  80. if (typeof preSelector === 'string') {
  81. navChap(preSelector);
  82. } else {
  83. preSelector();
  84. }
  85. });
  86.  
  87. k('right', () => {
  88. if (typeof nextSelector === 'string') {
  89. navChap(nextSelector);
  90. } else {
  91. nextSelector();
  92. }
  93. });
  94.  
  95. const contentLineHeight = () => parseFloat(getComputedStyle(chapter).lineHeight);
  96.  
  97. k('up', () => {
  98. document.documentElement.scrollTop -= window.innerHeight - contentLineHeight() * 2;
  99. });
  100.  
  101. let endChapter = false;
  102. k('down', () => {
  103. if (endChapter) {
  104. k.trigger('right');
  105. return;
  106. }
  107.  
  108. document.documentElement.scrollTop += window.innerHeight - contentLineHeight() * 2;
  109.  
  110. const chapterRect = chapter.getBoundingClientRect();
  111. if (
  112. chapterRect.top + chapterRect.height - window.innerHeight + contentLineHeight() * 2 < 0 ||
  113. document.documentElement.scrollTop + window.innerHeight === document.documentElement.scrollHeight
  114. ) {
  115. endChapter = true;
  116. }
  117. });
  118.  
  119. document.addEventListener(
  120. 'touchstart',
  121. (e) => {
  122. if (e.changedTouches[0].clientX < (window.innerWidth / 100) * 40) {
  123. k.trigger('up');
  124. } else {
  125. k.trigger('down');
  126. }
  127. },
  128. true,
  129. );

QingJ © 2025

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