Skip to content

Commit d0b0064

Browse files
committed
[Editor] When editing mode is disabled, allow to double click on a added annotation to edit it
It's already possible but only when double clicking outside the the text layer. This patach adds the possibility to click on the text layer.
1 parent 5653458 commit d0b0064

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed

src/display/editor/annotation_editor_layer.js

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
// eslint-disable-next-line max-len
2626
/** @typedef {import("../src/display/struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */
2727

28-
import { AnnotationEditorType, FeatureTest } from "../../shared/util.js";
28+
import {
29+
AnnotationEditorPrefix,
30+
AnnotationEditorType,
31+
FeatureTest,
32+
} from "../../shared/util.js";
2933
import { AnnotationEditor } from "./editor.js";
3034
import { FreeTextEditor } from "./freetext.js";
3135
import { HighlightEditor } from "./highlight.js";
@@ -85,6 +89,10 @@ class AnnotationEditorLayer {
8589

8690
#textSelectionAC = null;
8791

92+
#textLayerDblClickAC = null;
93+
94+
#lastPointerDownTimestamp = -1;
95+
8896
#uiManager;
8997

9098
static _initialized = false;
@@ -238,6 +246,8 @@ class AnnotationEditorLayer {
238246
this.#isEnabling = true;
239247
this.div.tabIndex = 0;
240248
this.togglePointerEvents(true);
249+
this.#textLayerDblClickAC?.abort();
250+
this.#textLayerDblClickAC = null;
241251
const annotationElementIds = new Set();
242252
for (const editor of this.#editors.values()) {
243253
editor.enableEditing();
@@ -280,6 +290,52 @@ class AnnotationEditorLayer {
280290
this.#isDisabling = true;
281291
this.div.tabIndex = -1;
282292
this.togglePointerEvents(false);
293+
if (this.#textLayer && !this.#textLayerDblClickAC) {
294+
this.#textLayerDblClickAC = new AbortController();
295+
const signal = this.#uiManager.combinedSignal(this.#textLayerDblClickAC);
296+
this.#textLayer.div.addEventListener(
297+
"pointerdown",
298+
e => {
299+
// It's the default value in Fenix:
300+
// https://searchfox.org/mozilla-central/rev/beba5cde846f944c4d709e75cbe499d17af880a4/modules/libpref/init/StaticPrefList.yaml#19064
301+
// and in Chrome and Windows:
302+
// https://source.chromium.org/chromium/chromium/src/+/main:ui/events/event_constants.h;drc=f0f5f3ceebb00da9363ccc7a1e2c0f17b6b383ba;l=115
303+
const DBL_CLICK_THRESHOLD = 500;
304+
const { clientX, clientY, timeStamp } = e;
305+
const lastPointerDownTimestamp = this.#lastPointerDownTimestamp;
306+
if (timeStamp - lastPointerDownTimestamp > DBL_CLICK_THRESHOLD) {
307+
this.#lastPointerDownTimestamp = timeStamp;
308+
return;
309+
}
310+
this.#lastPointerDownTimestamp = -1;
311+
const { classList } = this.div;
312+
classList.toggle("getElements", true);
313+
const elements = document.elementsFromPoint(clientX, clientY);
314+
classList.toggle("getElements", false);
315+
if (!this.div.contains(elements[0])) {
316+
return;
317+
}
318+
let id;
319+
const regex = new RegExp(`^${AnnotationEditorPrefix}[0-9]+$`);
320+
for (const element of elements) {
321+
if (regex.test(element.id)) {
322+
id = element.id;
323+
break;
324+
}
325+
}
326+
if (!id) {
327+
return;
328+
}
329+
const editor = this.#editors.get(id);
330+
if (editor?.annotationElementId === null) {
331+
e.stopPropagation();
332+
e.preventDefault();
333+
editor.dblclick();
334+
}
335+
},
336+
{ signal, capture: true }
337+
);
338+
}
283339
const changedAnnotations = new Map();
284340
const resetAnnotations = new Map();
285341
for (const editor of this.#editors.values()) {

test/integration/freetext_editor_spec.mjs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3357,4 +3357,56 @@ describe("FreeText Editor", () => {
33573357
);
33583358
});
33593359
});
3360+
3361+
describe("Edit added Freetext annotation", () => {
3362+
let pages;
3363+
3364+
beforeEach(async () => {
3365+
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
3366+
});
3367+
3368+
afterEach(async () => {
3369+
await closePages(pages);
3370+
});
3371+
3372+
it("must check that an added Freetext can be edited in double clicking on it", async () => {
3373+
await Promise.all(
3374+
pages.map(async ([browserName, page]) => {
3375+
await switchToFreeText(page);
3376+
3377+
const rect = await getRect(page, ".annotationEditorLayer");
3378+
const editorSelector = getEditorSelector(0);
3379+
3380+
const data = "Hello PDF.js World !!";
3381+
await page.mouse.click(
3382+
rect.x + rect.width / 2,
3383+
rect.y + rect.height / 2
3384+
);
3385+
await page.waitForSelector(editorSelector, { visible: true });
3386+
await page.type(`${editorSelector} .internal`, data);
3387+
await commit(page);
3388+
await waitForSerialized(page, 1);
3389+
3390+
await switchToFreeText(page, /* disable */ true);
3391+
3392+
const modeChangedHandle = await createPromise(page, resolve => {
3393+
window.PDFViewerApplication.eventBus.on(
3394+
"annotationeditormodechanged",
3395+
resolve,
3396+
{ once: true }
3397+
);
3398+
});
3399+
const editorRect = await getRect(page, editorSelector);
3400+
await page.mouse.click(
3401+
editorRect.x + editorRect.width / 2,
3402+
editorRect.y + editorRect.height / 2,
3403+
{ count: 2 }
3404+
);
3405+
3406+
await page.waitForSelector(".annotationEditorLayer.freetextEditing");
3407+
await awaitPromise(modeChangedHandle);
3408+
})
3409+
);
3410+
});
3411+
});
33603412
});

web/annotation_editor_layer_builder.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@
134134
&.drawing * {
135135
pointer-events: none !important;
136136
}
137+
138+
&.getElements {
139+
pointer-events: auto !important;
140+
> div {
141+
pointer-events: auto !important;
142+
}
143+
}
137144
}
138145

139146
.annotationEditorLayer.waiting {

0 commit comments

Comments
 (0)