網頁閱讀模式

[ALT+R] 將任何一個網頁中影響您閱讀的圖片,視頻,廣告等無關內容過濾,僅查看最關注的那一部分內容。特別適合各種內容閱讀型網頁。同時提供將所選區域的 HTML 代碼導出的功能。

目前為 2017-01-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Page Read Mode
  3. // @name:zh-CN 网页阅读模式
  4. // @name:zh-TW 網頁閱讀模式
  5. // @description [ALT+R] Content reader on any page, selecting the text area automatically or manually.
  6. // @description:zh-CN [ALT+R] 将任何一个网页中影响您阅读的图片,视频,广告等无关内容过滤,仅查看最关注的那一部分内容。特别适合各种内容阅读型网页。同时提供将所选区域的 HTML 代码导出的功能。
  7. // @description:zh-TW [ALT+R] 將任何一個網頁中影響您閱讀的圖片,視頻,廣告等無關內容過濾,僅查看最關注的那一部分內容。特別適合各種內容閱讀型網頁。同時提供將所選區域的 HTML 代碼導出的功能。
  8.  
  9. // @authuer Moshel
  10. // @namespace https://hzy.pw
  11. // @homepageURL https://gf.qytechs.cn/zh-CN/scripts/26709
  12. // @supportURL https://github.com/h2y/link-fix
  13. // @icon https://wiki.greasespot.net/images/f/f3/Book.png
  14. // @license GPL-3.0
  15.  
  16. // @include *
  17. // @grant GM_setClipboard
  18. // *run-at context-menu
  19. // @require https://cdn.staticfile.org/keymaster/1.6.1/keymaster.min.js
  20. // @resource useageIMG https://github.com/h2y/link-fix/raw/master/read_mode/useage.png
  21.  
  22. // @date 12/17/2015
  23. // @modified 01/23/2016
  24. // @version 1.1.2
  25. // ==/UserScript==
  26.  
  27.  
  28. /*
  29. global var
  30. */
  31. let mode = 0, //状态标记
  32. topNode = null, //顶层节点
  33. styleNode = null,
  34. butNodes = null,
  35. useageNode = null;
  36.  
  37.  
  38. /*
  39. Tool functions
  40. */
  41. function isNodeShow(node) {
  42. const styles = window.getComputedStyle(node);
  43.  
  44. if(styles.display=='none' || styles.visibility=='hidden')
  45. return false;
  46.  
  47. if(!parseInt(styles.height) || !parseInt(styles.height))
  48. return false;
  49.  
  50. return true;
  51. }
  52.  
  53.  
  54. /*
  55. main functions
  56. */
  57. function enterCliping(e) {
  58. mode = 1;
  59. e.preventDefault();
  60.  
  61. //add style
  62. if(!styleNode) {
  63. styleNode = document.createElement('style');
  64. styleNode.innerHTML = `.cliper-top-node {
  65. box-shadow: 0 0 20px #777 !important;
  66. border: 3px solid red !important;
  67. } .read-mode-reading {
  68. position: fixed !important;
  69. z-index: 9999970 !important;
  70. top: 0 !important;
  71. left: 0 !important;
  72. height: 100% !important;
  73. width: 100% !important;
  74. background-color: white !important;
  75. overflow: scroll !important;
  76. padding: 0 !important;
  77. border: 0 !important;
  78. margin: 0 !important;
  79. } .read-mode-buts {
  80. position: fixed;
  81. z-index: 9999985;
  82. top: 2rem; right: 1rem;
  83. } .read-mode-button {
  84. width: 54px;
  85. height: 54px;
  86. margin: 0 .5rem;
  87. padding: 10px 15px;
  88. color: #fff;
  89. opacity: .5;
  90. transition: 500ms;
  91. border-radius: 5px;
  92. background-color: black;
  93. } .read-mode-button:hover {
  94. background-color: white;
  95. border-radius: 0;
  96. box-shadow: 0 0 10px #000;
  97. color: #000;
  98. } img.read-mode-useage {
  99. position: fixed;
  100. right: 3rem;
  101. bottom: 2rem;
  102. z-index: 9999975;
  103. opacity: .7;
  104. }`;
  105. //styleNode.id = 'read_mode';
  106. document.body.appendChild(styleNode);
  107. }
  108.  
  109. // useage image
  110. if(!useageNode) {
  111. useageNode = document.createElement('img');
  112. useageNode.src = 'https://github.com/h2y/link-fix/raw/master/read_mode/useage.png';
  113. useageNode.className = 'read-mode-useage';
  114. document.body.appendChild(useageNode);
  115. }
  116.  
  117. useageNode.style.display = '';
  118.  
  119. //choose the init node
  120. topNode = document.body;
  121. let preNode = null;
  122.  
  123. do {
  124. preNode = topNode;
  125. onDown(e);
  126. }while(preNode!=topNode && preNode.clientHeight*0.9 < topNode.clientHeight);
  127. }
  128.  
  129. function quitCliping(e) {
  130. mode = 0;
  131. e.preventDefault();
  132.  
  133. useageNode.style.display = 'none';
  134.  
  135. changeTopNode(null);
  136.  
  137. if(butNodes)
  138. butNodes.style.display = 'none';
  139.  
  140. topNode.classList.remove('read-mode-reading');
  141. }
  142.  
  143.  
  144. function buildButNodes() {
  145. butNodes = document.createElement('div');
  146. butNodes.className = 'read-mode-buts';
  147.  
  148. let buts = [
  149. {
  150. text: "Exit read mode",
  151. handler: quitCliping,
  152. icon: '✘'
  153. }, {
  154. text: "Save HTML data",
  155. handler: onSaveHTML,
  156. icon: '❖'
  157. }
  158. ];
  159.  
  160. for(let but of buts) {
  161. let newBut = document.createElement('a');
  162. newBut.className = 'read-mode-button';
  163. newBut.innerHTML = but.icon;
  164. newBut.title = but.text;
  165. newBut.onclick = but.handler;
  166. butNodes.appendChild(newBut);
  167. }
  168.  
  169. document.body.appendChild(butNodes);
  170. }
  171.  
  172.  
  173. function changeTopNode(newNode) {
  174. if(topNode)
  175. topNode.classList.remove('cliper-top-node');
  176.  
  177. if(newNode)
  178. newNode.classList.add('cliper-top-node');
  179. else
  180. return;
  181.  
  182. topNode = newNode;
  183.  
  184. //scroll
  185. var winH = window.screen.availHeight,
  186. winY = window.scrollY,
  187. domH = topNode.clientHeight,
  188. domY = topNode.getBoundingClientRect().top + winY;
  189. //console.log(winH,winY,domH,domY);
  190.  
  191. if(domH>winH)
  192. window.scrollTo(0, domY - 50 );
  193. else
  194. window.scrollTo(0, domY - (winH-domH)/2 );
  195. }
  196.  
  197.  
  198. /*
  199. Event handler
  200. */
  201. function onSaveHTML(e) {
  202. let htmlStr = '';
  203.  
  204. htmlStr += topNode.outerHTML.split('\n').join('')
  205. .replace(/(id|class)=(\'.*?\'|\".*?\")/ig, '')
  206. .replace(/<!--.*?-->/g, '')
  207. .replace(/>[\t ]+?</g, '><')
  208. .replace(/<(link|meta).*?>/ig, '')
  209. .replace(/<style.*?>.*?<\/style>/ig, '')
  210. .replace(/<script.*?>.*?<\/script>/ig, '');
  211.  
  212. GM_setClipboard(htmlStr);
  213.  
  214. alert('Copied into clipboard.');
  215. }
  216.  
  217.  
  218. function onUp(e) {
  219. if(!mode) return;
  220. e.preventDefault();
  221.  
  222. if(topNode.parentElement)
  223. changeTopNode(topNode.parentNode);
  224. }
  225.  
  226. function onDown(e) {
  227. if(!mode) return;
  228. e.preventDefault();
  229.  
  230. if(!topNode.childElementCount)
  231. return;
  232.  
  233. var scanNodes = topNode.children,
  234. maxNode = null;
  235. var maxHeight = -1;
  236.  
  237. for(let node of scanNodes)
  238. if(isNodeShow(node) && node.clientHeight > maxHeight) {
  239. maxHeight = node.clientHeight;
  240. maxNode = node;
  241. }
  242.  
  243. if(maxNode)
  244. changeTopNode(maxNode);
  245. }
  246.  
  247. function onLeft(e) {
  248. if(!mode) return;
  249. e.preventDefault();
  250.  
  251. let nowNode = topNode;
  252. for(let node=nowNode; node.previousElementSibling;) {
  253. node = node.previousElementSibling;
  254. if(isNodeShow(node)) {
  255. nowNode = node;
  256. break;
  257. }
  258. }
  259.  
  260. if(nowNode!=topNode)
  261. changeTopNode(nowNode);
  262. //else: up
  263. else if (topNode.parentNode) {
  264. let bakNode = nowNode = topNode;
  265.  
  266. onUp(e);
  267. nowNode = topNode;
  268.  
  269. onLeft(e);
  270. if(nowNode==topNode)
  271. changeTopNode(bakNode);
  272. else
  273. onDown(e);
  274. }
  275. }
  276.  
  277. function onRight(e) {
  278. if(!mode) return;
  279. e.preventDefault();
  280.  
  281. let nowNode = topNode;
  282. for(let node=nowNode; node.nextElementSibling;) {
  283. node = node.nextElementSibling;
  284. if(isNodeShow(node)) {
  285. nowNode = node;
  286. break;
  287. }
  288. }
  289.  
  290. if(nowNode!=topNode)
  291. changeTopNode(nowNode);
  292. //else: up
  293. else if (topNode.parentNode) {
  294. let bakNode = nowNode = topNode;
  295.  
  296. onUp(e);
  297. nowNode = topNode;
  298.  
  299. onRight(e);
  300. if(nowNode==topNode)
  301. changeTopNode(bakNode);
  302. else
  303. onDown(e);
  304. }
  305. }
  306.  
  307.  
  308. function onEnter(e) {
  309. if(!mode) return;
  310. e.preventDefault();
  311.  
  312. quitCliping(e);
  313.  
  314. topNode.classList.add('read-mode-reading');
  315.  
  316. //buttons
  317. if(butNodes)
  318. butNodes.style.display = '';
  319. else
  320. buildButNodes();
  321. }
  322.  
  323.  
  324. /*
  325. Main
  326. */
  327. key('alt+r', function(){
  328. if(mode)
  329. quitCliping(new MouseEvent("main"));
  330. else
  331. enterCliping(new MouseEvent("main"));
  332. });
  333.  
  334.  
  335. /*
  336. bind action
  337. */
  338. key('up', onUp);
  339. key('down', onDown);
  340. key('left', onLeft);
  341. key('right', onRight);
  342.  
  343. key('enter', onEnter);
  344. key('esc', quitCliping);

QingJ © 2025

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