[Annotations] charLimit === 0 means unlimited (bug 1782564)

Changing the charLimit in JS had no impact, so this patch aims to fix
that and add an integration test for it.
This commit is contained in:
Calixte Denizet 2022-08-18 19:27:53 +02:00
parent b05010c3eb
commit c06c5f7cbd
8 changed files with 122 additions and 12 deletions

View File

@ -2255,7 +2255,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
// Determine the maximum length of text in the field.
let maximumLength = getInheritableProperty({ dict, key: "MaxLen" });
if (!Number.isInteger(maximumLength) || maximumLength < 0) {
maximumLength = null;
maximumLength = 0;
}
this.data.maxLen = maximumLength;
@ -2266,7 +2266,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
!this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
this.data.maxLen !== null;
this.data.maxLen !== 0;
this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);
}

View File

@ -1000,7 +1000,14 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const storedData = storage.getValue(id, {
value: this.data.fieldValue,
});
const textContent = storedData.formattedValue || storedData.value || "";
let textContent = storedData.formattedValue || storedData.value || "";
const maxLen = storage.getValue(id, {
charLimit: this.data.maxLen,
}).charLimit;
if (maxLen && textContent.length > maxLen) {
textContent = textContent.slice(0, maxLen);
}
const elementData = {
userValue: textContent,
formattedValue: null,
@ -1030,6 +1037,10 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
this._setRequired(element, this.data.required);
if (maxLen) {
element.maxLength = maxLen;
}
element.addEventListener("input", event => {
storage.setValue(id, { value: event.target.value });
this.setPropertyOnSiblings(
@ -1088,6 +1099,36 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
selRange(event) {
event.target.setSelectionRange(...event.detail.selRange);
},
charLimit: event => {
const { charLimit } = event.detail;
const { target } = event;
if (charLimit === 0) {
target.removeAttribute("maxLength");
return;
}
target.setAttribute("maxLength", charLimit);
let value = elementData.userValue;
if (!value || value.length <= charLimit) {
return;
}
value = value.slice(0, charLimit);
target.value = elementData.userValue = value;
storage.setValue(id, { value });
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
source: this,
detail: {
id,
name: "Keystroke",
value,
willCommit: true,
commitKey: 1,
selStart: target.selectionStart,
selEnd: target.selectionEnd,
},
});
},
};
this._dispatchEventFromSandbox(actions, jsEvent);
});
@ -1225,13 +1266,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
element.addEventListener("blur", blurListener);
}
if (this.data.maxLen !== null) {
element.maxLength = this.data.maxLen;
}
if (this.data.comb) {
const fieldWidth = this.data.rect[2] - this.data.rect[0];
const combWidth = fieldWidth / this.data.maxLen;
const combWidth = fieldWidth / maxLen;
element.classList.add("comb");
element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`;

View File

@ -29,7 +29,6 @@ class Field extends PDFObject {
this.buttonScaleHow = data.buttonScaleHow;
this.ButtonScaleWhen = data.buttonScaleWhen;
this.calcOrderIndex = data.calcOrderIndex;
this.charLimit = data.charLimit;
this.comb = data.comb;
this.commitOnSelChange = data.commitOnSelChange;
this.currentValueIndices = data.currentValueIndices;
@ -69,6 +68,7 @@ class Field extends PDFObject {
this._browseForFileToSubmit = data.browseForFileToSubmit || null;
this._buttonCaption = null;
this._buttonIcon = null;
this._charLimit = data.charLimit;
this._children = null;
this._currentValueIndices = data.currentValueIndices || 0;
this._document = data.doc;
@ -151,6 +151,17 @@ class Field extends PDFObject {
this.fillColor = color;
}
get charLimit() {
return this._charLimit;
}
set charLimit(limit) {
if (typeof limit !== "number") {
throw new Error("Invalid argument value");
}
this._charLimit = Math.max(0, Math.floor(limit));
}
get numItems() {
if (!this._isChoice) {
throw new Error("Not a choice widget");

View File

@ -1492,4 +1492,65 @@ describe("Interaction", () => {
);
});
});
describe("in bug1782564.pdf", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait("bug1782564.pdf", getSelector("7R"));
});
afterAll(async () => {
await closePages(pages);
});
it("must check that charLimit is correctly set", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await clearInput(page, getSelector("7R"));
// By default the charLimit is 0 which means that the input
// length is unlimited.
await page.type(getSelector("7R"), "abcdefghijklmnopq", {
delay: 10,
});
let value = await page.$eval(getSelector("7R"), el => el.value);
expect(value)
.withContext(`In ${browserName}`)
.toEqual("abcdefghijklmnopq");
// charLimit is set to 1
await page.click(getSelector("9R"));
await page.waitForFunction(
`document.querySelector('${getSelector(
"7R"
)}').value !== "abcdefgh"`
);
value = await page.$eval(getSelector("7R"), el => el.value);
expect(value).withContext(`In ${browserName}`).toEqual("a");
await clearInput(page, getSelector("7R"));
await page.type(getSelector("7R"), "xyz", { delay: 10 });
value = await page.$eval(getSelector("7R"), el => el.value);
expect(value).withContext(`In ${browserName}`).toEqual("x");
// charLimit is set to 2
await page.click(getSelector("9R"));
await clearInput(page, getSelector("7R"));
await page.type(getSelector("7R"), "xyz", { delay: 10 });
value = await page.$eval(getSelector("7R"), el => el.value);
expect(value).withContext(`In ${browserName}`).toEqual("xy");
})
);
});
});
});

View File

@ -535,3 +535,4 @@
!issue15092.pdf
!bug1782186.pdf
!tracemonkey_a11y.pdf
!bug1782564.pdf

BIN
test/pdfs/bug1782564.pdf Executable file

Binary file not shown.

View File

@ -1454,7 +1454,7 @@ describe("annotation", function () {
);
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
expect(data.textAlignment).toEqual(null);
expect(data.maxLen).toEqual(null);
expect(data.maxLen).toEqual(0);
expect(data.readOnly).toEqual(false);
expect(data.hidden).toEqual(false);
expect(data.multiLine).toEqual(false);
@ -1478,7 +1478,7 @@ describe("annotation", function () {
);
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
expect(data.textAlignment).toEqual(null);
expect(data.maxLen).toEqual(null);
expect(data.maxLen).toEqual(0);
expect(data.readOnly).toEqual(false);
expect(data.hidden).toEqual(false);
expect(data.multiLine).toEqual(false);

View File

@ -1390,7 +1390,7 @@ describe("api", function () {
defaultValue: "",
multiline: false,
password: false,
charLimit: null,
charLimit: 0,
comb: false,
editable: true,
hidden: false,