From bae32b4fd25ff06e056fce8cb6eb6d83ede67953 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 9 Sep 2024 18:53:16 +0200 Subject: [PATCH] [JS] Let AFSpecial_KeystrokeEx match a format without 'decoration' (bug 1916714) It'll let the user enter 1234567 instead of 123-4567 for example. It works like this in other pdf viewers. --- src/scripting_api/aform.js | 34 ++++++++-- test/unit/scripting_spec.js | 122 ++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 5 deletions(-) diff --git a/src/scripting_api/aform.js b/src/scripting_api/aform.js index 74cd5a7c535b7..355fc8450f976 100644 --- a/src/scripting_api/aform.js +++ b/src/scripting_api/aform.js @@ -560,6 +560,22 @@ class AForm { } AFSpecial_KeystrokeEx(cMask) { + const event = globalThis.event; + + // Simplify the format string by removing all characters that are not + // specific to the format because the user could enter 1234567 when the + // format is 999-9999. + const simplifiedFormatStr = cMask.replaceAll(/[^9AOX]/g, ""); + this.#AFSpecial_KeystrokeEx_helper(simplifiedFormatStr, false); + if (event.rc) { + return; + } + + event.rc = true; + this.#AFSpecial_KeystrokeEx_helper(cMask, true); + } + + #AFSpecial_KeystrokeEx_helper(cMask, warn) { if (!cMask) { return; } @@ -605,20 +621,26 @@ class AForm { const err = `${GlobalConstants.IDS_INVALID_VALUE} = "${cMask}"`; if (value.length > cMask.length) { - this._app.alert(err); + if (warn) { + this._app.alert(err); + } event.rc = false; return; } if (event.willCommit) { if (value.length < cMask.length) { - this._app.alert(err); + if (warn) { + this._app.alert(err); + } event.rc = false; return; } if (!_checkValidity(value, cMask)) { - this._app.alert(err); + if (warn) { + this._app.alert(err); + } event.rc = false; return; } @@ -631,7 +653,9 @@ class AForm { } if (!_checkValidity(value, cMask)) { - this._app.alert(err); + if (warn) { + this._app.alert(err); + } event.rc = false; } } @@ -651,7 +675,7 @@ class AForm { case 2: const value = this.AFMergeChange(event); formatStr = - value.length > 8 || value.startsWith("(") + value.startsWith("(") || (value.length > 7 && /^\p{N}+$/.test(value)) ? "(999) 999-9999" : "999-9999"; break; diff --git a/test/unit/scripting_spec.js b/test/unit/scripting_spec.js index 505a990ff37ad..12c7161c21c9c 100644 --- a/test/unit/scripting_spec.js +++ b/test/unit/scripting_spec.js @@ -1571,6 +1571,67 @@ describe("Scripting", function () { send_queue.delete(refId); }); + it("should validate a US phone number with digits only (long) on a keystroke event", async () => { + const refId = getId(); + const data = { + objects: { + field: [ + { + id: refId, + value: "", + actions: { + Keystroke: [`AFSpecial_Keystroke(2);`], + }, + type: "text", + }, + ], + }, + appInfo: { language: "en-US", platform: "Linux x86_64" }, + calculationOrder: [], + dispatchEventName: "_dispatchMe", + }; + sandbox.createSandbox(data); + + let value = ""; + const changes = "1234567890"; + let i = 0; + + for (; i < changes.length; i++) { + const change = changes.charAt(i); + await sandbox.dispatchEventInSandbox({ + id: refId, + value, + change, + name: "Keystroke", + willCommit: false, + selStart: i, + selEnd: i, + }); + expect(send_queue.has(refId)).toEqual(true); + send_queue.delete(refId); + value += change; + } + + await sandbox.dispatchEventInSandbox({ + id: refId, + value, + change: "A", + name: "Keystroke", + willCommit: false, + selStart: i, + selEnd: i, + }); + expect(send_queue.has(refId)).toEqual(true); + expect(send_queue.get(refId)).toEqual({ + id: refId, + siblings: null, + value, + selRange: [i, i], + }); + + send_queue.delete(refId); + }); + it("should validate a US phone number (short) on a keystroke event", async () => { const refId = getId(); const data = { @@ -1631,6 +1692,67 @@ describe("Scripting", function () { send_queue.delete(refId); }); + + it("should validate a US phone number with digits only (short) on a keystroke event", async () => { + const refId = getId(); + const data = { + objects: { + field: [ + { + id: refId, + value: "", + actions: { + Keystroke: [`AFSpecial_Keystroke(2);`], + }, + type: "text", + }, + ], + }, + appInfo: { language: "en-US", platform: "Linux x86_64" }, + calculationOrder: [], + dispatchEventName: "_dispatchMe", + }; + sandbox.createSandbox(data); + + let value = ""; + const changes = "1234567"; + let i = 0; + + for (; i < changes.length; i++) { + const change = changes.charAt(i); + await sandbox.dispatchEventInSandbox({ + id: refId, + value, + change, + name: "Keystroke", + willCommit: false, + selStart: i, + selEnd: i, + }); + expect(send_queue.has(refId)).toEqual(true); + send_queue.delete(refId); + value += change; + } + + await sandbox.dispatchEventInSandbox({ + id: refId, + value, + change: "A", + name: "Keystroke", + willCommit: false, + selStart: i, + selEnd: i, + }); + expect(send_queue.has(refId)).toEqual(true); + expect(send_queue.get(refId)).toEqual({ + id: refId, + siblings: null, + value, + selRange: [i, i], + }); + + send_queue.delete(refId); + }); }); describe("eMailValidate", function () {