Only call the focus/blur callbacks when it's necessary (bug 1851517)
Focus callback must be called only when the element has been blurred. For example, blur callback (which implies some potential validation) is not called because the newly focused element is an other tab, an alert dialog, ... so consequently the focus callback mustn't be called when the element gets its focus back.
This commit is contained in:
parent
92792a8215
commit
d03494eeff
@ -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"],
|
||||
|
@ -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");
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user