Skip to content

Commit 3a97b63

Browse files
author
Giovani Guizzo
authored
feat: implement selection saving and restoring functionality in layout (#115)
1 parent 8d88562 commit 3a97b63

2 files changed

Lines changed: 92 additions & 1 deletion

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// DEV: This file was generated by Claude Sonnet 4.5 and it works :)
2+
// Honestly, I didn't want to write this myself because it's boring af
3+
4+
let savedSelection = null;
5+
6+
// Function to save selection
7+
window.saveSelection = function saveSelection() {
8+
const selection = window.getSelection();
9+
if (selection.rangeCount > 0 && selection.toString().length > 0) {
10+
const range = selection.getRangeAt(0);
11+
12+
savedSelection = {
13+
text: selection.toString(),
14+
startOffset: range.startOffset,
15+
endOffset: range.endOffset,
16+
startContainerPath: getNodePath(range.startContainer),
17+
endContainerPath: getNodePath(range.endContainer),
18+
};
19+
}
20+
};
21+
22+
// Function to get path to a node for later reconstruction
23+
function getNodePath(node) {
24+
const path = [];
25+
let current = node;
26+
const root = document.body; // Use body as the root instead of job-details
27+
28+
while (current && current !== root && current !== document.documentElement) {
29+
const parent = current.parentNode;
30+
if (!parent) break;
31+
32+
const siblings = Array.from(parent.childNodes);
33+
const index = siblings.indexOf(current);
34+
path.unshift({ index, nodeType: current.nodeType });
35+
current = parent;
36+
}
37+
38+
return path;
39+
}
40+
41+
// Function to get node from path
42+
function getNodeFromPath(path) {
43+
const root = document.body; // Use body as the root instead of job-details
44+
if (!root || !path) return null;
45+
46+
let current = root;
47+
for (const step of path) {
48+
const children = Array.from(current.childNodes);
49+
if (step.index >= children.length) return null;
50+
current = children[step.index];
51+
if (current.nodeType !== step.nodeType) return null;
52+
}
53+
54+
return current;
55+
}
56+
57+
// Function to restore selection
58+
window.restoreSelection = function restoreSelection() {
59+
if (!savedSelection) return;
60+
61+
try {
62+
const startContainer = getNodeFromPath(savedSelection.startContainerPath);
63+
const endContainer = getNodeFromPath(savedSelection.endContainerPath);
64+
65+
if (startContainer && endContainer) {
66+
const range = document.createRange();
67+
range.setStart(startContainer, savedSelection.startOffset);
68+
range.setEnd(endContainer, savedSelection.endOffset);
69+
70+
const selection = window.getSelection();
71+
selection.removeAllRanges();
72+
selection.addRange(range);
73+
}
74+
} catch (e) {
75+
// Selection restoration failed, try fallback with text search
76+
console.debug("Could not restore selection:", e);
77+
}
78+
79+
savedSelection = null;
80+
};
81+
82+
// We don't do a htmx:afterSwap restore here because we do it in layout.ejs after hljs.highlightAll()
83+
document.addEventListener("htmx:beforeSwap", () => {
84+
window.saveSelection();
85+
});

packages/dashboard/src/views/layout.ejs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<script src="/public/js/highlight.js"></script>
1111
<script src="/public/js/chart.js"></script>
1212
<script src="/public/js/scroll.js"></script>
13+
<script src="/public/js/selection.js"></script>
1314
</head>
1415
<body class="h-full bg-base-100 text-base-content">
1516
<div class="flex h-full">
@@ -28,7 +29,6 @@
2829
v0.1.0 — OSS Edition
2930
</div>
3031
</aside>
31-
3232

3333
<!-- Main content -->
3434
<main id="main-section" class="flex-1 p-6 overflow-y-auto"><%- body %></main>
@@ -37,7 +37,13 @@
3737
<script>
3838
function loadLibs() {
3939
feather.replace();
40+
41+
// Save selection before highlighting (which destroys DOM nodes)
42+
window.saveSelection();
43+
// Highlights all code blocks
4044
hljs.highlightAll();
45+
// Restore selection after highlighting
46+
window.restoreSelection();
4147
}
4248
4349
document.addEventListener("htmx:afterSwap", loadLibs);

0 commit comments

Comments
 (0)