initial commit, added caret-read-progress.js
This commit is contained in:
commit
49689c8225
2 changed files with 124 additions and 0 deletions
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
* `caret-read-progress.js` - highlights the line/position while reading a text - move back/forth with left/right arrows.
|
123
caret-read-progress.js
Normal file
123
caret-read-progress.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
// ==UserScript==
|
||||
// @name Caret Read Progress
|
||||
// @namespace http://tampermonkey.net/
|
||||
// @version 1.5
|
||||
// @description Moves caret with arrow keys, highlights read text, works across paragraphs and divs
|
||||
// @author You
|
||||
// @match *://*/*
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
let highlightDiv = document.createElement("div");
|
||||
highlightDiv.style.position = "absolute";
|
||||
highlightDiv.style.background = "rgba(255, 255, 0, 0.3)"; // Yellow highlight
|
||||
highlightDiv.style.height = "1.5em";
|
||||
highlightDiv.style.pointerEvents = "none";
|
||||
highlightDiv.style.zIndex = "9999";
|
||||
highlightDiv.style.width = "0px"; // Start with no highlight
|
||||
document.body.appendChild(highlightDiv);
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key !== "ArrowRight" && event.key !== "ArrowLeft") return;
|
||||
|
||||
let sel = window.getSelection();
|
||||
if (!sel.rangeCount) return;
|
||||
|
||||
let range = sel.getRangeAt(0);
|
||||
let moved = moveCaret(event.key === "ArrowRight" ? 1 : -1);
|
||||
|
||||
if (moved) updateHighlight();
|
||||
});
|
||||
|
||||
function moveCaret(direction) {
|
||||
let sel = window.getSelection();
|
||||
if (!sel.rangeCount) return false;
|
||||
|
||||
let range = sel.getRangeAt(0);
|
||||
let node = range.startContainer;
|
||||
let offset = range.startOffset;
|
||||
|
||||
// Move within the same text node
|
||||
if (direction === 1 && offset < node.length) {
|
||||
offset++;
|
||||
} else if (direction === -1 && offset > 0) {
|
||||
offset--;
|
||||
}
|
||||
// If at the end of a node, move to the next text node
|
||||
else if (direction === 1) {
|
||||
let nextNode = findNextTextNode(node);
|
||||
if (nextNode) {
|
||||
node = nextNode;
|
||||
offset = 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If at the start of a node, move to the previous text node
|
||||
else if (direction === -1) {
|
||||
let prevNode = findPreviousTextNode(node);
|
||||
if (prevNode) {
|
||||
node = prevNode;
|
||||
offset = prevNode.length;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update selection range
|
||||
let newRange = document.createRange();
|
||||
newRange.setStart(node, offset);
|
||||
newRange.collapse(true);
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(newRange);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function findNextTextNode(node) {
|
||||
while (node) {
|
||||
if (node.nextSibling) {
|
||||
node = node.nextSibling;
|
||||
while (node && node.nodeType !== Node.TEXT_NODE) {
|
||||
node = node.firstChild || node.nextSibling;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findPreviousTextNode(node) {
|
||||
while (node) {
|
||||
if (node.previousSibling) {
|
||||
node = node.previousSibling;
|
||||
while (node && node.nodeType !== Node.TEXT_NODE) {
|
||||
node = node.lastChild || node.previousSibling;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function updateHighlight() {
|
||||
let sel = window.getSelection();
|
||||
if (!sel.rangeCount) return;
|
||||
|
||||
let range = sel.getRangeAt(0);
|
||||
let rect = range.getBoundingClientRect();
|
||||
|
||||
if (rect.width === 0 && rect.height === 0) {
|
||||
return; // Ignore empty selections
|
||||
}
|
||||
|
||||
highlightDiv.style.top = `${rect.top + window.scrollY}px`;
|
||||
highlightDiv.style.left = `0px`; // Always start from the left
|
||||
highlightDiv.style.width = `${rect.right}px`; // Expand highlight only to where you've read
|
||||
}
|
||||
})();
|
Loading…
Add table
Reference in a new issue