selection update
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { escapeChar } from "./html.js";
|
||||
|
||||
function bufferColToDomOffset(lineText, col) {
|
||||
let offset = 0;
|
||||
for (let i = 0; i < col && i < lineText.length; i++)
|
||||
offset += escapeChar(lineText[i]).length;
|
||||
return offset;
|
||||
}
|
||||
|
||||
function findTextNode(parent, targetOffset) {
|
||||
let remaining = targetOffset;
|
||||
const walker = document.createTreeWalker(parent, NodeFilter.SHOW_TEXT);
|
||||
let node;
|
||||
while ((node = walker.nextNode())) {
|
||||
if (remaining <= node.textContent.length)
|
||||
return { node, offset: remaining };
|
||||
remaining -= node.textContent.length;
|
||||
}
|
||||
return { node: parent, offset: parent.childNodes.length };
|
||||
}
|
||||
|
||||
function posToElement(line, col, buffer) {
|
||||
const spans = document.querySelectorAll("#text > span");
|
||||
if (line >= spans.length) return null;
|
||||
const span = spans[line];
|
||||
const range = document.createRange();
|
||||
const lineText = buffer[line] || "";
|
||||
const offset = bufferColToDomOffset(lineText, col);
|
||||
const tn = findTextNode(span, offset);
|
||||
range.setStart(tn.node, tn.offset);
|
||||
range.collapse(true);
|
||||
const rect = range.getBoundingClientRect();
|
||||
return { x: rect.left, y: rect.top, height: rect.height };
|
||||
}
|
||||
|
||||
export function elementToPos(x, y, buffer) {
|
||||
const spans = document.querySelectorAll("#text > span");
|
||||
let bestLine = 0;
|
||||
let bestDistY = Infinity;
|
||||
|
||||
for (let i = 0; i < spans.length; i++) {
|
||||
const rect = spans[i].getBoundingClientRect();
|
||||
const midY = rect.top + rect.height / 2;
|
||||
const distY = Math.abs(y - midY);
|
||||
if (distY < bestDistY) {
|
||||
bestDistY = distY;
|
||||
bestLine = i;
|
||||
}
|
||||
}
|
||||
|
||||
let bestCol = 0;
|
||||
let bestDistX = Infinity;
|
||||
const lineText = buffer[bestLine] || "";
|
||||
for (let c = 0; c <= lineText.length; c++) {
|
||||
const pos = posToElement(bestLine, c, buffer);
|
||||
if (!pos) continue;
|
||||
const dist = Math.abs(x - pos.x);
|
||||
if (dist < bestDistX) {
|
||||
bestDistX = dist;
|
||||
bestCol = c;
|
||||
}
|
||||
}
|
||||
|
||||
return { line: bestLine, col: bestCol };
|
||||
}
|
||||
Reference in New Issue
Block a user