Skip to content

Commit

Permalink
Improve text selection behavior
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wojtekmaj committed Nov 15, 2022
1 parent 7859c0f commit 4bc7184
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/Page/TextLayer.css
Expand Up @@ -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
Expand Down Expand Up @@ -85,7 +86,7 @@
top: 100%;
right: 0;
bottom: 0;
z-index: -1;
z-index: 0;
cursor: default;
user-select: none;
}
Expand Down
41 changes: 38 additions & 3 deletions src/Page/TextLayer.jsx
Expand Up @@ -18,6 +18,8 @@ export class TextLayerInternal extends PureComponent {

layerElement = createRef();

endElement = createRef();

componentDidMount() {
const { page } = this.props;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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,
};
Expand All @@ -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];
Expand All @@ -161,7 +190,13 @@ export class TextLayerInternal extends PureComponent {

render() {
return (
<div className="react-pdf__Page__textContent textLayer" ref={this.layerElement}>
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div
className="react-pdf__Page__textContent textLayer"
onMouseUp={this.onMouseUp}
onMouseDown={this.onMouseDown}
ref={this.layerElement}
>
{this.renderTextLayer()}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/Page/TextLayer.spec.jsx
Expand Up @@ -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);
});
});

Expand Down

0 comments on commit 4bc7184

Please sign in to comment.