mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-06-22 16:05:56 +02:00
fix: prevent search highlights from interfering with drag-selection
This commit is contained in:
parent
62ac1b844a
commit
f01e4d477e
@ -432,6 +432,80 @@ describe("Text layer", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when selecting text with find highlights active", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
pages = await loadAndWait("find_all.pdf", ".textLayer", 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't jump when selection anchor is inside a highlight element", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
// Highlight all occurrences of the letter A (case insensitive).
|
||||||
|
await page.click("#viewFindButton");
|
||||||
|
await page.waitForSelector("#findInput", { visible: true });
|
||||||
|
await page.type("#findInput", "a");
|
||||||
|
await page.click("#findHighlightAll + label");
|
||||||
|
await page.waitForSelector(".textLayer .highlight");
|
||||||
|
|
||||||
|
// find_all.pdf contains 'AB BA' in a monospace font. These are
|
||||||
|
// the glyph metrics at 100% zoom, extracted from the PDF.
|
||||||
|
const glyphWidth = 15.98;
|
||||||
|
const expectedFirstAX = 30;
|
||||||
|
|
||||||
|
// Compute the drag coordinates to select exactly "AB". The
|
||||||
|
// horizontal positions use the page origin and PDF glyph
|
||||||
|
// metrics; the vertical center comes from the highlight.
|
||||||
|
const pageDiv = await page.$(".page canvas");
|
||||||
|
const pageBox = await pageDiv.boundingBox();
|
||||||
|
const firstHighlight = await page.$(".textLayer .highlight");
|
||||||
|
const highlightBox = await firstHighlight.boundingBox();
|
||||||
|
|
||||||
|
// Drag from beginning of first 'A' to end of second 'B'
|
||||||
|
const aStart = pageBox.x + expectedFirstAX;
|
||||||
|
const startY = Math.round(
|
||||||
|
highlightBox.y + highlightBox.height / 2
|
||||||
|
);
|
||||||
|
const bEnd = Math.round(aStart + glyphWidth * 2);
|
||||||
|
|
||||||
|
await page.mouse.move(aStart, startY);
|
||||||
|
await page.mouse.down();
|
||||||
|
await moveInSteps(
|
||||||
|
page,
|
||||||
|
{ x: aStart, y: startY },
|
||||||
|
{ x: bEnd, y: startY },
|
||||||
|
20
|
||||||
|
);
|
||||||
|
await page.mouse.up();
|
||||||
|
|
||||||
|
const selection = await page.evaluate(() =>
|
||||||
|
window.getSelection().toString()
|
||||||
|
);
|
||||||
|
expect(selection).withContext(`In ${browserName}`).toEqual("AB");
|
||||||
|
|
||||||
|
// The selectionchange handler in TextLayerBuilder walks up
|
||||||
|
// from .highlight to its parent span before placing
|
||||||
|
// endOfContent (see text_layer_builder.js). Without that
|
||||||
|
// fix, endOfContent would be inserted inside the text span
|
||||||
|
// (as a sibling of the .highlight) instead of as a direct
|
||||||
|
// child of .textLayer. Verify the correct DOM structure.
|
||||||
|
const endOfContentIsDirectChild = await page.evaluate(() => {
|
||||||
|
const eoc = document.querySelector(".textLayer .endOfContent");
|
||||||
|
return eoc?.parentElement?.classList.contains("textLayer");
|
||||||
|
});
|
||||||
|
expect(endOfContentIsDirectChild)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toBeTrue();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("using selection carets", () => {
|
describe("using selection carets", () => {
|
||||||
|
|||||||
@ -307,6 +307,9 @@ class TextLayerBuilder {
|
|||||||
if (anchor.nodeType === Node.TEXT_NODE) {
|
if (anchor.nodeType === Node.TEXT_NODE) {
|
||||||
anchor = anchor.parentNode;
|
anchor = anchor.parentNode;
|
||||||
}
|
}
|
||||||
|
if (anchor.classList?.contains("highlight")) {
|
||||||
|
anchor = anchor.parentNode;
|
||||||
|
}
|
||||||
if (!modifyStart && range.endOffset === 0) {
|
if (!modifyStart && range.endOffset === 0) {
|
||||||
do {
|
do {
|
||||||
while (!anchor.previousSibling) {
|
while (!anchor.previousSibling) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user