Merge pull request #16905 from calixteman/bug1851517

Only call the focus/blur callbacks when it's necessary (bug 1851517)
This commit is contained in:
calixteman 2023-09-05 15:19:36 +02:00 committed by GitHub
commit 03eabae613
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 5 deletions

View File

@ -1013,7 +1013,7 @@ class WidgetAnnotationElement extends AnnotationElement {
return (isWin && event.ctrlKey) || (isMac && event.metaKey);
}
_setEventListener(element, baseName, eventName, valueGetter) {
_setEventListener(element, elementData, baseName, eventName, valueGetter) {
if (baseName.includes("mouse")) {
// Mouse events
element.addEventListener(baseName, event => {
@ -1029,8 +1029,24 @@ class WidgetAnnotationElement extends AnnotationElement {
});
});
} else {
// Non mouse event
// Non-mouse events
element.addEventListener(baseName, event => {
if (baseName === "blur") {
if (!elementData.focused || !event.relatedTarget) {
return;
}
elementData.focused = false;
} else if (baseName === "focus") {
if (elementData.focused) {
return;
}
elementData.focused = true;
}
if (!valueGetter) {
return;
}
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
source: this,
detail: {
@ -1043,10 +1059,25 @@ class WidgetAnnotationElement extends AnnotationElement {
}
}
_setEventListeners(element, names, getter) {
_setEventListeners(element, elementData, names, getter) {
for (const [baseName, eventName] of names) {
if (eventName === "Action" || this.data.actions?.[eventName]) {
this._setEventListener(element, baseName, eventName, getter);
if (eventName === "Focus" || eventName === "Blur") {
elementData ||= { focused: false };
}
this._setEventListener(
element,
elementData,
baseName,
eventName,
getter
);
if (eventName === "Focus" && !this.data.actions?.Blur) {
// Ensure that elementData will have the correct value.
this._setEventListener(element, elementData, "blur", "Blur", null);
} else if (eventName === "Blur" && !this.data.actions?.Focus) {
this._setEventListener(element, elementData, "focus", "Focus", null);
}
}
}
}
@ -1178,6 +1209,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
formattedValue: fieldFormattedValues,
lastCommittedValue: null,
commitKey: 1,
focused: false,
};
if (this.data.multiLine) {
@ -1238,12 +1270,16 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
if (this.enableScripting && this.hasJSActions) {
element.addEventListener("focus", event => {
if (elementData.focused) {
return;
}
const { target } = event;
if (elementData.userValue) {
target.value = elementData.userValue;
}
elementData.lastCommittedValue = target.value;
elementData.commitKey = 1;
elementData.focused = true;
});
element.addEventListener("updatefromsandbox", jsEvent => {
@ -1349,9 +1385,10 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const _blurListener = blurListener;
blurListener = null;
element.addEventListener("blur", event => {
if (!event.relatedTarget) {
if (!elementData.focused || !event.relatedTarget) {
return;
}
elementData.focused = false;
const { value } = event.target;
elementData.userValue = value;
if (elementData.lastCommittedValue !== value) {
@ -1431,6 +1468,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
this._setEventListeners(
element,
elementData,
[
["focus", "Focus"],
["blur", "Blur"],
@ -1540,6 +1578,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
this._setEventListeners(
element,
null,
[
["change", "Validate"],
["change", "Action"],
@ -1630,6 +1669,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
this._setEventListeners(
element,
null,
[
["change", "Validate"],
["change", "Action"],
@ -1894,6 +1934,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
this._setEventListeners(
selectElement,
null,
[
["focus", "Focus"],
["blur", "Blur"],

View File

@ -2154,4 +2154,50 @@ describe("Interaction", () => {
);
});
});
describe("Textfields and focus", () => {
let pages;
let otherPages;
beforeAll(async () => {
otherPages = await Promise.all(
global.integrationSessions.map(async session =>
session.browser.newPage()
)
);
pages = await loadAndWait("evaljs.pdf", getSelector("55R"));
});
afterAll(async () => {
await closePages(pages);
await Promise.all(otherPages.map(page => page.close()));
});
it("must check that focus/blur callbacks aren't called", async () => {
await Promise.all(
pages.map(async ([browserName, page], i) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await page.click(getSelector("55R"));
await page.type(getSelector("55R"), "Hello", { delay: 10 });
await page.click(getSelector("56R"));
await page.waitForTimeout(10);
await page.click(getSelector("55R"));
await page.type(getSelector("55R"), " World", { delay: 10 });
await page.waitForTimeout(10);
await otherPages[i].bringToFront();
await otherPages[i].waitForTimeout(100);
await page.bringToFront();
await page.waitForTimeout(100);
const text = await page.$eval(getSelector("55R"), el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("Hello World");
})
);
});
});
});