From 4bc7184d2a2206d1acfdb5a2e65e6100ffcb10c1 Mon Sep 17 00:00:00 2001 From: Wojciech Maj Date: Thu, 10 Nov 2022 18:11:50 +0100 Subject: [PATCH] Improve text selection behavior Adds an element behind text items that expands on mouse down. This especially improves text selection behavior on Firefox where elements with user-select: none prevent selection from being updated. Closes #1034 --- src/Page/TextLayer.css | 3 ++- src/Page/TextLayer.jsx | 41 ++++++++++++++++++++++++++++++++++--- src/Page/TextLayer.spec.jsx | 2 +- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/Page/TextLayer.css b/src/Page/TextLayer.css index f5226a327..2a762be5f 100644 --- a/src/Page/TextLayer.css +++ b/src/Page/TextLayer.css @@ -37,6 +37,7 @@ white-space: pre; cursor: text; transform-origin: 0% 0%; + z-index: 1; } /* Only necessary in Google Chrome, see issue 14205, and most unfortunately @@ -85,7 +86,7 @@ top: 100%; right: 0; bottom: 0; - z-index: -1; + z-index: 0; cursor: default; user-select: none; } diff --git a/src/Page/TextLayer.jsx b/src/Page/TextLayer.jsx index ed5e01454..2a398c16e 100644 --- a/src/Page/TextLayer.jsx +++ b/src/Page/TextLayer.jsx @@ -18,6 +18,8 @@ export class TextLayerInternal extends PureComponent { layerElement = createRef(); + endElement = createRef(); + componentDidMount() { const { page } = this.props; @@ -92,6 +94,26 @@ export class TextLayerInternal extends PureComponent { if (onRenderTextLayerError) onRenderTextLayerError(error); }; + onMouseDown = () => { + const end = this.endElement.current; + + if (!end) { + return; + } + + end.classList.add('active'); + }; + + onMouseUp = () => { + const end = this.endElement.current; + + if (!end) { + return; + } + + end.classList.remove('active'); + }; + get viewport() { const { page, rotate, scale } = this.props; @@ -120,16 +142,18 @@ export class TextLayerInternal extends PureComponent { return null; } + const container = this.layerElement.current; + const { viewport } = this; const { customTextRenderer } = this.props; // If another rendering is in progress, let's cancel it cancelRunningTask(this.runningTask); - this.layerElement.current.innerHTML = ''; + container.innerHTML = ''; const parameters = { - container: this.layerElement.current, + container, textContent, viewport, }; @@ -139,6 +163,11 @@ export class TextLayerInternal extends PureComponent { cancellable.promise .then(() => { + const end = document.createElement('div'); + end.className = 'endOfContent'; + container.append(end); + this.endElement.current = end; + if (customTextRenderer) { textContent.items.forEach((item, itemIndex) => { const child = this.layerElement.current.children[itemIndex]; @@ -161,7 +190,13 @@ export class TextLayerInternal extends PureComponent { render() { return ( -
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions +
{this.renderTextLayer()}
); diff --git a/src/Page/TextLayer.spec.jsx b/src/Page/TextLayer.spec.jsx index 9911e65ab..2a5f1f0f7 100644 --- a/src/Page/TextLayer.spec.jsx +++ b/src/Page/TextLayer.spec.jsx @@ -94,7 +94,7 @@ describe('TextLayer', () => { return onRenderTextLayerSuccessPromise.then(() => { const textItems = [...container.firstChild.children]; - expect(textItems).toHaveLength(desiredTextItems.length); + expect(textItems).toHaveLength(desiredTextItems.length + 1); }); });