Skip to content

Commit 95edd01

Browse files
authored
Enhance text-selection behavior on simple viewer (#94)
1 parent ebc8ddc commit 95edd01

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

examples/simple-viewer/style.css

+12-3
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,29 @@ div.page canvas {
189189
user-select: none;
190190
}
191191

192-
div.text span {
192+
svg.text {
193+
width: 100%;
194+
height: 100%;
195+
}
196+
197+
svg.text text {
193198
white-space: pre;
194199
line-height: 1;
195-
color: transparent;
200+
fill: transparent;
196201
}
197202

198-
div.text ::selection {
203+
svg.text ::selection {
199204
background: hsla(220, 100%, 50%, 0.2);
200205
}
201206

202207
div.link a:hover {
203208
border: 1px dotted blue;
204209
}
205210

211+
#pages.do-content-select div.link {
212+
pointer-events: none;
213+
}
214+
206215
div.search > div {
207216
pointer-events: none;
208217
border: 1px solid hotpink;

examples/simple-viewer/viewer.js

+28-27
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ class PageView {
206206
this.rootNode.appendChild(this.canvasNode)
207207

208208
this.textData = null
209-
this.textNode = document.createElement("div")
210-
this.textNode.className = "text"
209+
this.textNode = document.createElementNS("http://www.w3.org/2000/svg", "svg")
210+
this.textNode.classList.add("text")
211211
this.rootNode.appendChild(this.textNode)
212212

213213
this.linkData = null
@@ -341,44 +341,29 @@ class PageView {
341341
}
342342

343343
_showText() {
344-
this.textNode.zoom = this.zoom
345-
this.textNode.replaceChildren()
346-
347-
let nodes = []
348-
let pdf_w = []
349-
let html_w = []
350-
let text_len = []
344+
let frag = document.createDocumentFragment()
351345
let scale = this.zoom / 72
352346

353347
for (let block of this.textData.blocks) {
354348
if (block.type === "text") {
355349
for (let line of block.lines) {
356-
let text = document.createElement("span")
357-
text.style.left = line.bbox.x * scale + "px"
358-
text.style.top = (line.y - line.font.size * 0.8) * scale + "px"
359-
text.style.height = line.bbox.h * scale + "px"
350+
let text = document.createElementNS("http://www.w3.org/2000/svg", "text")
351+
text.setAttribute("x", line.bbox.x * scale + "px")
352+
text.setAttribute("y", line.y * scale + "px")
360353
text.style.fontSize = line.font.size * scale + "px"
361354
text.style.fontFamily = line.font.family
362355
text.style.fontWeight = line.font.weight
363356
text.style.fontStyle = line.font.style
357+
text.setAttribute("textLength", line.bbox.w * scale + "px")
358+
text.setAttribute("lengthAdjust", "spacingAndGlyphs")
364359
text.textContent = line.text
365-
this.textNode.appendChild(text)
366-
nodes.push(text)
367-
pdf_w.push(line.bbox.w * scale)
368-
text_len.push(line.text.length - 1)
360+
frag.appendChild(text)
369361
}
370362
}
371363
}
372364

373-
for (let i = 0; i < nodes.length; ++i) {
374-
if (text_len[i] > 0)
375-
html_w[i] = nodes[i].clientWidth
376-
}
377-
378-
for (let i = 0; i < nodes.length; ++i) {
379-
if (text_len[i] > 0)
380-
nodes[i].style.letterSpacing = (pdf_w[i] - html_w[i]) / text_len[i] + "px"
381-
}
365+
this.textNode.zoom = this.zoom
366+
this.textNode.replaceChildren(frag)
382367
}
383368

384369
_showLinks() {
@@ -543,7 +528,12 @@ window.addEventListener("keydown", function (event) {
543528
case 96:
544529
zoom_to(100)
545530
break
546-
531+
// 'A'
532+
case 65:
533+
// Ctrl-A full selection
534+
document.getSelection().selectAllChildren(document.getElementById("pages"))
535+
event.preventDefault()
536+
break
547537
// 'F'
548538
case 70:
549539
show_search_panel()
@@ -574,6 +564,17 @@ function toggle_fullscreen() {
574564
document.documentElement.requestFullscreen()
575565
}
576566

567+
// Mark TEXT-SELECTION State
568+
function remove_selection_state(e) {
569+
document.getElementById("pages").classList.remove("do-content-select")
570+
document.removeEventListener("mouseup", remove_selection_state)
571+
}
572+
573+
document.addEventListener("selectstart", function (event) {
574+
document.getElementById("pages").classList.add("do-content-select")
575+
document.addEventListener("mouseup", remove_selection_state)
576+
})
577+
577578
// SEARCH
578579

579580
let search_panel = document.getElementById("search-panel")

0 commit comments

Comments
 (0)