diff --git a/src/core/annotation.js b/src/core/annotation.js index e642b3d83..f4c58e50e 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -2461,6 +2461,10 @@ class TextWidgetAnnotation extends WidgetAnnotation { this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL); } + get hasTextContent() { + return !!this.appearance; + } + _getCombAppearance( defaultAppearance, font, diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index ae5a873a3..e8755c502 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -1049,7 +1049,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { const storedData = storage.getValue(id, { value: this.data.fieldValue, }); - let textContent = storedData.formattedValue || storedData.value || ""; + let textContent = storedData.value || ""; const maxLen = storage.getValue(id, { charLimit: this.data.maxLen, }).charLimit; @@ -1057,23 +1057,29 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { textContent = textContent.slice(0, maxLen); } + let fieldFormattedValues = + storedData.formattedValue || this.data.textContent?.join("\n") || null; + if (fieldFormattedValues && this.data.comb) { + fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, ""); + } + const elementData = { userValue: textContent, - formattedValue: null, + formattedValue: fieldFormattedValues, lastCommittedValue: null, commitKey: 1, }; if (this.data.multiLine) { element = document.createElement("textarea"); - element.textContent = textContent; + element.textContent = fieldFormattedValues ?? textContent; if (this.data.doNotScroll) { element.style.overflowY = "hidden"; } } else { element = document.createElement("input"); element.type = "text"; - element.setAttribute("value", textContent); + element.setAttribute("value", fieldFormattedValues ?? textContent); if (this.data.doNotScroll) { element.style.overflowX = "hidden"; } diff --git a/src/scripting_api/event.js b/src/scripting_api/event.js index 6a2047bc3..ba0aa8967 100644 --- a/src/scripting_api/event.js +++ b/src/scripting_api/event.js @@ -98,8 +98,9 @@ class EventDispatcher { // errors in the case where a formatter is using one of those named // actions (see #15818). this._document.obj._initActions(); - // Before running the Open event, we format all the fields - // (see bug 1766987). + // Before running the Open event, we run the format callbacks but + // without changing the value of the fields. + // Acrobat does the same thing. this.formatAll(); } if ( @@ -232,13 +233,7 @@ class EventDispatcher { const event = (globalThis.event = new Event({})); for (const source of Object.values(this._objects)) { event.value = source.obj.value; - if (this.runActions(source, source, event, "Format")) { - source.obj._send({ - id: source.obj._id, - siblings: source.obj._siblings, - formattedValue: event.value?.toString?.(), - }); - } + this.runActions(source, source, event, "Format"); } } diff --git a/src/scripting_api/field.js b/src/scripting_api/field.js index 869822222..cfd37da0f 100644 --- a/src/scripting_api/field.js +++ b/src/scripting_api/field.js @@ -13,7 +13,7 @@ * limitations under the License. */ -import { createActionsMap, FieldType, getFieldType } from "./common.js"; +import { createActionsMap, getFieldType } from "./common.js"; import { Color } from "./color.js"; import { PDFObject } from "./pdf_object.js"; @@ -247,29 +247,15 @@ class Field extends PDFObject { return; } - if (value === "") { - this._value = ""; - } else if (typeof value === "string") { - switch (this._fieldType) { - case FieldType.none: { - this._originalValue = value; - const _value = value.trim().replace(",", "."); - this._value = !isNaN(_value) ? parseFloat(_value) : value; - break; - } - case FieldType.number: - case FieldType.percent: { - const _value = value.trim().replace(",", "."); - const number = parseFloat(_value); - this._value = !isNaN(number) ? number : 0; - break; - } - default: - this._value = value; - } - } else { + if (value === "" || typeof value !== "string") { + this._originalValue = undefined; this._value = value; + return; } + + this._originalValue = value; + const _value = value.trim().replace(",", "."); + this._value = !isNaN(_value) ? parseFloat(_value) : value; } _getValue() { diff --git a/test/integration/scripting_spec.js b/test/integration/scripting_spec.js index 77b7b277d..b4afc9eac 100644 --- a/test/integration/scripting_spec.js +++ b/test/integration/scripting_spec.js @@ -1897,4 +1897,70 @@ describe("Interaction", () => { ); }); }); + + describe("in bug1825002.pdf", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("bug1825002.pdf", getSelector("23R")); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check that a field has the correct formatted value", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await page.waitForFunction( + "window.PDFViewerApplication.scriptingReady === true" + ); + + let text = await page.$eval(getSelector("23R"), el => el.value); + expect(text) + .withContext(`In ${browserName}`) + .toEqual("ABCDEFGHIJKLMN"); + + await page.click(getSelector("23R")); + await page.waitForFunction( + `${getQuerySelector("23R")}.value !== "ABCDEFGHIJKLMN"` + ); + + text = await page.$eval(getSelector("23R"), el => el.value); + expect(text).withContext(`In ${browserName}`).toEqual("123,45.7A"); + }) + ); + }); + + it("must check that a field is empty", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await page.waitForFunction( + "window.PDFViewerApplication.scriptingReady === true" + ); + + let text = await page.$eval(getSelector("26R"), el => el.value); + expect(text).withContext(`In ${browserName}`).toEqual(""); + + await page.click(getSelector("26R")); + await page.type(getSelector("26R"), "abcde", { delay: 10 }); + + await page.click(getSelector("23R")); + await page.waitForTimeout(10); + await page.click(getSelector("26R")); + + await page.keyboard.down("Control"); + await page.keyboard.press("A"); + await page.keyboard.up("Control"); + await page.keyboard.press("Backspace"); + + await page.click(getSelector("23R")); + await page.waitForTimeout(10); + + text = await page.$eval(getSelector("26R"), el => el.value); + expect(text).withContext(`In ${browserName}`).toEqual(""); + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 98d799d1b..96ac967d7 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -591,3 +591,4 @@ !issue16316.pdf !issue14565.pdf !multiline.pdf +!bug1825002.pdf diff --git a/test/pdfs/bug1825002.pdf b/test/pdfs/bug1825002.pdf new file mode 100755 index 000000000..abe08e51c Binary files /dev/null and b/test/pdfs/bug1825002.pdf differ