[JS] Make the date parser less strict
and display the expected date formt as a tooltip.
This commit is contained in:
parent
5653458b51
commit
2541d96bf5
@ -61,6 +61,7 @@ import {
|
||||
parseAppearanceStream,
|
||||
parseDefaultAppearance,
|
||||
} from "./default_appearance.js";
|
||||
import { DateFormats, TimeFormats } from "../shared/scripting_utils.js";
|
||||
import { Dict, isName, isRefsEqual, Name, Ref, RefSet } from "./primitives.js";
|
||||
import { Stream, StringStream } from "./stream.js";
|
||||
import { BaseStream } from "./base_stream.js";
|
||||
@ -2780,6 +2781,25 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
||||
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
||||
this.data.maxLen !== 0;
|
||||
this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);
|
||||
|
||||
// Check if we have a date or time.
|
||||
const {
|
||||
data: { actions },
|
||||
} = this;
|
||||
for (const keystrokeAction of actions?.Keystroke || []) {
|
||||
const m = keystrokeAction
|
||||
.trim()
|
||||
.match(/^AF(Date|Time)_Keystroke(?:Ex)?\(['"]?([^'"]+)['"]?\);$/);
|
||||
if (m) {
|
||||
let format = m[2];
|
||||
const num = parseInt(format, 10);
|
||||
if (!isNaN(num) && Math.floor(Math.log10(num)) + 1 === m[2].length) {
|
||||
format = (m[1] === "Date" ? DateFormats : TimeFormats)[num] ?? format;
|
||||
}
|
||||
this.data[m[1] === "Date" ? "dateFormat" : "timeFormat"] = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get hasTextContent() {
|
||||
|
||||
@ -1293,6 +1293,10 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
element.disabled = this.data.readOnly;
|
||||
element.name = this.data.fieldName;
|
||||
element.tabIndex = 0;
|
||||
const format = this.data.dateFormat || this.data.timeFormat;
|
||||
if (format) {
|
||||
element.title = format;
|
||||
}
|
||||
|
||||
this._setRequired(element, this.data.required);
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DateFormats, TimeFormats } from "../shared/scripting_utils.js";
|
||||
import { GlobalConstants } from "./constants.js";
|
||||
|
||||
class AForm {
|
||||
@ -21,23 +22,6 @@ class AForm {
|
||||
this._app = app;
|
||||
this._util = util;
|
||||
this._color = color;
|
||||
this._dateFormats = [
|
||||
"m/d",
|
||||
"m/d/yy",
|
||||
"mm/dd/yy",
|
||||
"mm/yy",
|
||||
"d-mmm",
|
||||
"d-mmm-yy",
|
||||
"dd-mmm-yy",
|
||||
"yy-mm-dd",
|
||||
"mmm-yy",
|
||||
"mmmm-yy",
|
||||
"mmm d, yyyy",
|
||||
"mmmm d, yyyy",
|
||||
"m/d/yy h:MM tt",
|
||||
"m/d/yy HH:MM",
|
||||
];
|
||||
this._timeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"];
|
||||
|
||||
// The e-mail address regex below originates from:
|
||||
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
|
||||
@ -52,17 +36,14 @@ class AForm {
|
||||
return event.target ? `[ ${event.target.name} ]` : "";
|
||||
}
|
||||
|
||||
_parseDate(cFormat, cDate, strict = false) {
|
||||
_parseDate(cFormat, cDate) {
|
||||
let date = null;
|
||||
try {
|
||||
date = this._util._scand(cFormat, cDate, strict);
|
||||
date = this._util._scand(cFormat, cDate, /* strict = */ false);
|
||||
} catch {}
|
||||
if (date) {
|
||||
return date;
|
||||
}
|
||||
if (strict) {
|
||||
return null;
|
||||
}
|
||||
|
||||
date = Date.parse(cDate);
|
||||
return isNaN(date) ? null : new Date(date);
|
||||
@ -277,9 +258,7 @@ class AForm {
|
||||
}
|
||||
|
||||
AFDate_Format(pdf) {
|
||||
if (pdf >= 0 && pdf < this._dateFormats.length) {
|
||||
this.AFDate_FormatEx(this._dateFormats[pdf]);
|
||||
}
|
||||
this.AFDate_FormatEx(DateFormats[pdf] ?? pdf);
|
||||
}
|
||||
|
||||
AFDate_KeystrokeEx(cFormat) {
|
||||
@ -293,7 +272,7 @@ class AForm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._parseDate(cFormat, value, /* strict = */ true) === null) {
|
||||
if (this._parseDate(cFormat, value) === null) {
|
||||
const invalid = GlobalConstants.IDS_INVALID_DATE;
|
||||
const invalid2 = GlobalConstants.IDS_INVALID_DATE2;
|
||||
const err = `${invalid} ${this._mkTargetName(
|
||||
@ -305,8 +284,8 @@ class AForm {
|
||||
}
|
||||
|
||||
AFDate_Keystroke(pdf) {
|
||||
if (pdf >= 0 && pdf < this._dateFormats.length) {
|
||||
this.AFDate_KeystrokeEx(this._dateFormats[pdf]);
|
||||
if (pdf >= 0 && pdf < DateFormats.length) {
|
||||
this.AFDate_KeystrokeEx(DateFormats[pdf]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,9 +596,7 @@ class AForm {
|
||||
}
|
||||
|
||||
AFTime_Format(pdf) {
|
||||
if (pdf >= 0 && pdf < this._timeFormats.length) {
|
||||
this.AFDate_FormatEx(this._timeFormats[pdf]);
|
||||
}
|
||||
this.AFDate_FormatEx(TimeFormats[pdf] ?? pdf);
|
||||
}
|
||||
|
||||
AFTime_KeystrokeEx(cFormat) {
|
||||
@ -627,8 +604,8 @@ class AForm {
|
||||
}
|
||||
|
||||
AFTime_Keystroke(pdf) {
|
||||
if (pdf >= 0 && pdf < this._timeFormats.length) {
|
||||
this.AFDate_KeystrokeEx(this._timeFormats[pdf]);
|
||||
if (pdf >= 0 && pdf < TimeFormats.length) {
|
||||
this.AFDate_KeystrokeEx(TimeFormats[pdf]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -227,7 +227,7 @@ class Util extends PDFObject {
|
||||
ddd: data => this._days[data.dayOfWeek].substring(0, 3),
|
||||
dd: data => data.day.toString().padStart(2, "0"),
|
||||
d: data => data.day.toString(),
|
||||
yyyy: data => data.year.toString(),
|
||||
yyyy: data => data.year.toString().padStart(4, "0"),
|
||||
yy: data => (data.year % 100).toString().padStart(2, "0"),
|
||||
HH: data => data.hours.toString().padStart(2, "0"),
|
||||
H: data => data.hours.toString(),
|
||||
|
||||
@ -105,4 +105,22 @@ class ColorConverters {
|
||||
}
|
||||
}
|
||||
|
||||
export { ColorConverters };
|
||||
const DateFormats = [
|
||||
"m/d",
|
||||
"m/d/yy",
|
||||
"mm/dd/yy",
|
||||
"mm/yy",
|
||||
"d-mmm",
|
||||
"d-mmm-yy",
|
||||
"dd-mmm-yy",
|
||||
"yy-mm-dd",
|
||||
"mmm-yy",
|
||||
"mmmm-yy",
|
||||
"mmm d, yyyy",
|
||||
"mmmm d, yyyy",
|
||||
"m/d/yy h:MM tt",
|
||||
"m/d/yy HH:MM",
|
||||
];
|
||||
const TimeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"];
|
||||
|
||||
export { ColorConverters, DateFormats, TimeFormats };
|
||||
|
||||
@ -1065,8 +1065,8 @@ describe("Scripting", function () {
|
||||
id: refId,
|
||||
value: "",
|
||||
actions: {
|
||||
Format: [`AFDate_FormatEx("mmddyyyy");`],
|
||||
Keystroke: [`AFDate_KeystrokeEx("mmddyyyy");`],
|
||||
Format: [`AFDate_FormatEx("mm.dd.yyyy");`],
|
||||
Keystroke: [`AFDate_KeystrokeEx("mm.dd.yyyy");`],
|
||||
},
|
||||
type: "text",
|
||||
},
|
||||
@ -1080,7 +1080,7 @@ describe("Scripting", function () {
|
||||
sandbox.createSandbox(data);
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
value: "12062023",
|
||||
value: "12.06.2023",
|
||||
name: "Keystroke",
|
||||
willCommit: true,
|
||||
});
|
||||
@ -1088,14 +1088,14 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
siblings: null,
|
||||
value: "12062023",
|
||||
formattedValue: "12062023",
|
||||
value: "12.06.2023",
|
||||
formattedValue: "12.06.2023",
|
||||
});
|
||||
send_queue.delete(refId);
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
value: "1206202",
|
||||
value: "12.06.202",
|
||||
name: "Keystroke",
|
||||
willCommit: true,
|
||||
});
|
||||
@ -1103,16 +1103,15 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
siblings: null,
|
||||
value: "",
|
||||
formattedValue: null,
|
||||
selRange: [0, 0],
|
||||
value: "12.06.202",
|
||||
formattedValue: "12.06.0202",
|
||||
});
|
||||
send_queue.delete(refId);
|
||||
|
||||
sandbox.createSandbox(data);
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
value: "02062023",
|
||||
value: "02.06.2023",
|
||||
name: "Keystroke",
|
||||
willCommit: true,
|
||||
});
|
||||
@ -1120,8 +1119,24 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
siblings: null,
|
||||
value: "02062023",
|
||||
formattedValue: "02062023",
|
||||
value: "02.06.2023",
|
||||
formattedValue: "02.06.2023",
|
||||
});
|
||||
send_queue.delete(refId);
|
||||
|
||||
sandbox.createSandbox(data);
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
value: "2.6.2023",
|
||||
name: "Keystroke",
|
||||
willCommit: true,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
siblings: null,
|
||||
value: "2.6.2023",
|
||||
formattedValue: "02.06.2023",
|
||||
});
|
||||
send_queue.delete(refId);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user