update
This commit is contained in:
@@ -515,6 +515,9 @@ export class DeesPdfViewer extends DeesElement {
|
||||
textLayerDiv.style.width = `${viewport.width}px`;
|
||||
textLayerDiv.style.height = `${viewport.height}px`;
|
||||
|
||||
// Set the scale factor CSS variable - required by PDF.js text layer
|
||||
textLayerDiv.style.setProperty('--scale-factor', String(viewport.scale));
|
||||
|
||||
const textLayerRenderTask = pdfjs.renderTextLayer({
|
||||
textContentSource: textContent,
|
||||
container: textLayerDiv,
|
||||
@@ -529,14 +532,80 @@ export class DeesPdfViewer extends DeesElement {
|
||||
endOfContent.className = 'endOfContent';
|
||||
textLayerDiv.appendChild(endOfContent);
|
||||
|
||||
// Selection class handling
|
||||
textLayerDiv.addEventListener('mousedown', () => {
|
||||
textLayerDiv.classList.add('selecting');
|
||||
const onMouseUp = () => {
|
||||
// Custom drag selection for Shadow DOM compatibility
|
||||
// caretRangeFromPoint doesn't pierce shadow DOM, so we find spans manually
|
||||
let isDragging = false;
|
||||
let anchorNode: Node | null = null;
|
||||
let anchorOffset = 0;
|
||||
|
||||
const getTextPositionFromPoint = (x: number, y: number): { node: Node; offset: number } | null => {
|
||||
// Find span at coordinates by checking bounding rects
|
||||
const spans = Array.from(textLayerDiv.querySelectorAll('span'));
|
||||
for (const span of spans) {
|
||||
const rect = span.getBoundingClientRect();
|
||||
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
||||
const textNode = span.firstChild;
|
||||
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
|
||||
// Calculate character offset based on x position
|
||||
const text = textNode.textContent || '';
|
||||
const charWidth = rect.width / text.length;
|
||||
const relativeX = x - rect.left;
|
||||
const offset = Math.min(Math.round(relativeX / charWidth), text.length);
|
||||
return { node: textNode, offset };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
if (isDragging) {
|
||||
isDragging = false;
|
||||
anchorNode = null;
|
||||
textLayerDiv.classList.remove('selecting');
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
}
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
};
|
||||
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!isDragging || !anchorNode) return;
|
||||
|
||||
e.preventDefault();
|
||||
const pos = getTextPositionFromPoint(e.clientX, e.clientY);
|
||||
if (pos) {
|
||||
const selection = window.getSelection();
|
||||
if (selection) {
|
||||
try {
|
||||
selection.setBaseAndExtent(anchorNode, anchorOffset, pos.node, pos.offset);
|
||||
} catch (err) {
|
||||
// Ignore errors from invalid selections
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
textLayerDiv.addEventListener('mousedown', (e: MouseEvent) => {
|
||||
if (e.button !== 0) return;
|
||||
|
||||
const pos = getTextPositionFromPoint(e.clientX, e.clientY);
|
||||
if (pos) {
|
||||
// Prevent native selection behavior
|
||||
e.preventDefault();
|
||||
|
||||
isDragging = true;
|
||||
anchorNode = pos.node;
|
||||
anchorOffset = pos.offset;
|
||||
textLayerDiv.classList.add('selecting');
|
||||
|
||||
// Clear existing selection
|
||||
const selection = window.getSelection();
|
||||
selection?.removeAllRanges();
|
||||
|
||||
// Add document-level listeners for drag
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
}
|
||||
});
|
||||
|
||||
pageInfo.textLayerRendered = true;
|
||||
|
||||
@@ -289,12 +289,14 @@ export const viewerStyles = [
|
||||
.text-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: clip;
|
||||
overflow: visible;
|
||||
line-height: 1;
|
||||
text-size-adjust: none;
|
||||
forced-color-adjust: none;
|
||||
transform-origin: 0 0;
|
||||
z-index: 1;
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
.text-layer span,
|
||||
@@ -304,6 +306,8 @@ export const viewerStyles = [
|
||||
white-space: pre;
|
||||
cursor: text;
|
||||
transform-origin: 0% 0%;
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
.text-layer ::selection {
|
||||
|
||||
Reference in New Issue
Block a user