From fb3c21dd06a30e9cda4213e50d09da455ef82143 Mon Sep 17 00:00:00 2001 From: yihan_dai Date: Mon, 20 Apr 2026 12:22:53 +0800 Subject: [PATCH] fix:add conditions in textInputChecker. If a page containing pdf.js,som PASSWORD TYPE INPUTS will be prevented from DEFAULT ACTIONS(like deleting). Co-authored-by: Calixte Denizet --- src/display/editor/tools.js | 26 ++++++-- test/integration/freetext_editor_spec.mjs | 78 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/src/display/editor/tools.js b/src/display/editor/tools.js index 491b65a837ad3..3de263d2a548c 100644 --- a/src/display/editor/tools.js +++ b/src/display/editor/tools.js @@ -45,6 +45,23 @@ function bindEvents(obj, element, names) { } } +// The `type` values of the `` elements which don't hold editable text. +// The keyboard events must only be handled by the editor when the focused +// element isn't a text input, hence any type not listed here (text, number, +// password, email, ...) is treated as a text input. +const NON_TEXT_INPUT_TYPES = new Set([ + "button", + "checkbox", + "color", + "file", + "hidden", + "image", + "radio", + "range", + "reset", + "submit", +]); + /** * Class to store current pointers used by the editor to be able to handle * multiple pointers (e.g. two fingers, a pen, a mouse, ...). @@ -861,13 +878,8 @@ class AnnotationEditorUIManager { document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl(); - const textInputChecker = (_self, { target: el }) => { - if (el instanceof HTMLInputElement) { - const { type } = el; - return type !== "text" && type !== "number"; - } - return true; - }; + const textInputChecker = (_self, { target: el }) => + !(el instanceof HTMLInputElement) || NON_TEXT_INPUT_TYPES.has(el.type); const small = this.TRANSLATE_SMALL; const big = this.TRANSLATE_BIG; diff --git a/test/integration/freetext_editor_spec.mjs b/test/integration/freetext_editor_spec.mjs index 28240b5acd127..ce8947f74f01e 100644 --- a/test/integration/freetext_editor_spec.mjs +++ b/test/integration/freetext_editor_spec.mjs @@ -2750,6 +2750,84 @@ describe("FreeText Editor", () => { }) ); }); + + it("must check that the shortcuts depend on the focused input type", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await switchToFreeText(page); + + const rect = await getRect(page, ".annotationEditorLayer"); + + // Add two editors so that the "select all" shortcut has something to + // select. + await createFreeTextEditor({ + page, + x: rect.x + 100, + y: rect.y + 100, + data: "Hello", + }); + await createFreeTextEditor({ + page, + x: rect.x + 100, + y: rect.y + 200, + data: "PDF.js World", + }); + + // Nothing must be selected before triggering the shortcut. + await page.keyboard.press("Escape"); + await page.waitForFunction( + () => !document.querySelector(".freeTextEditor.selectedEditor") + ); + + const addInput = type => + page.evaluate(inputType => { + const input = document.createElement("input"); + input.type = inputType; + input.id = "testInputForShortcuts"; + input.value = "abc"; + document.body.append(input); + input.focus(); + }, type); + const removeInput = () => + page.evaluate(() => { + document.getElementById("testInputForShortcuts").remove(); + }); + const countSelectedEditors = () => + page.$$eval(".freeTextEditor.selectedEditor", els => els.length); + + // When the focus is in a text input, the editor mustn't handle the + // "select all" shortcut, hence no editor must be selected. + for (const type of ["text", "number", "password", "email"]) { + await addInput(type); + await page.waitForSelector("#testInputForShortcuts:focus"); + await kbSelectAll(page); + expect(await countSelectedEditors()) + .withContext(`In ${browserName} for type=${type}`) + .toEqual(0); + await removeInput(); + } + + // When the focus is in a non-text input, the editor must handle the + // "select all" shortcut, hence all the editors must be selected. + for (const type of ["checkbox", "button"]) { + await addInput(type); + await page.waitForSelector("#testInputForShortcuts:focus"); + await kbSelectAll(page); + await page.waitForFunction( + () => + !document.querySelector(".freeTextEditor:not(.selectedEditor)") + ); + await removeInput(); + + // Reset the selection for the next iteration. + await page.keyboard.press("Escape"); + await page.waitForFunction( + () => !document.querySelector(".freeTextEditor.selectedEditor") + ); + } + }) + ); + }); }); describe("Delete a freetext in using the delete button", () => {