Draggable Reference Line

Designed for reading long articles, it helps remember the current reading progress.

当前为 2021-09-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Draggable Reference Line
  3. // @description Designed for reading long articles, it helps remember the current reading progress.
  4. // @version 1.0
  5. // @author Rui LIU (@liurui39660)
  6. // @match *://*/*
  7. // @icon https://icons.duckduckgo.com/ip2/example.com.ico
  8. // @run-at document-body
  9. // @namespace https://greasyfork.org/users/193469
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. const height = 2; // px, height of the visible line
  16. const padding = 2; // px, additional draggable area above and below the line, not the sum of them
  17. const color = 'red'; // or #-string
  18.  
  19. const body = document.getElementsByTagName('body')[0];
  20. const line = document.createElement('div');
  21. line.textContent = '#DraggableReferenceLine';
  22. line.style = `margin: 0; padding: ${padding}px 0; cursor: n-resize; font-size: 0; color: #fff0; background: ${color}; background-clip: content-box; width: 100vw; height: ${height}px; position: absolute; top: ${localStorage[`DraggableLine_${window.location.pathname}${window.location.search}`] || -padding - height / 2}px; z-index: 10;`;
  23. let callbackMouseMove = ev => {
  24. line.style.top = `${ev.pageY - padding - height / 2}px`;
  25. };
  26. let callbackMouseUp = ev => {
  27. if (ev.detail === 1) { // Don't overwrite dblclick
  28. body.releasePointerCapture(ev.pointerId);
  29. body.style.cursor = null;
  30. const top = Math.max(-padding, parseFloat(line.style.top)); // So you can't move it out of page
  31. line.style.top = `${top}px`;
  32. localStorage[`DraggableLine_${window.location.pathname}${window.location.search}`] = top;
  33. [onmouseup, onmousemove, callbackMouseUp, callbackMouseMove] = [callbackMouseUp, callbackMouseMove, onmouseup, onmousemove];
  34. }
  35. };
  36. line.addEventListener('mousedown', ev => {
  37. if (ev.detail === 1) {
  38. ev.preventDefault(); // Don't select text
  39. body.setPointerCapture(ev.pointerId); // The cursor won't change back to pointer when out of browser
  40. body.style.cursor = 'n-resize';
  41. [onmouseup, onmousemove, callbackMouseUp, callbackMouseMove] = [callbackMouseUp, callbackMouseMove, onmouseup, onmousemove];
  42. }
  43. });
  44. line.addEventListener('dblclick', () => {
  45. line.style.top = `${-padding - height / 2}px`;
  46. localStorage.removeItem(`DraggableLine_${window.location.pathname}${window.location.search}`);
  47. });
  48. body.appendChild(line);
  49. })();