Skip to content

Commit 549aae6

Browse files
committed
JS -- add support for page property in field
1 parent f081701 commit 549aae6

File tree

6 files changed

+104
-9
lines changed

6 files changed

+104
-9
lines changed

src/core/annotation.js

+44-5
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,34 @@ class AnnotationFactory {
7171
* instance.
7272
*/
7373
static create(xref, ref, pdfManager, idFactory, collectFields) {
74-
return pdfManager.ensureCatalog("acroForm").then(acroForm => {
75-
return pdfManager.ensure(this, "_create", [
74+
return Promise.all([
75+
pdfManager.ensureCatalog("acroForm"),
76+
collectFields ? this._getPageIndex(xref, ref, pdfManager) : -1,
77+
]).then(([acroForm, pageIndex]) =>
78+
pdfManager.ensure(this, "_create", [
7679
xref,
7780
ref,
7881
pdfManager,
7982
idFactory,
8083
acroForm,
8184
collectFields,
82-
]);
83-
});
85+
pageIndex,
86+
])
87+
);
8488
}
8589

8690
/**
8791
* @private
8892
*/
89-
static _create(xref, ref, pdfManager, idFactory, acroForm, collectFields) {
93+
static _create(
94+
xref,
95+
ref,
96+
pdfManager,
97+
idFactory,
98+
acroForm,
99+
collectFields,
100+
pageIndex = -1
101+
) {
90102
const dict = xref.fetchIfRef(ref);
91103
if (!isDict(dict)) {
92104
return undefined;
@@ -108,6 +120,7 @@ class AnnotationFactory {
108120
pdfManager,
109121
acroForm: acroForm instanceof Dict ? acroForm : Dict.empty,
110122
collectFields,
123+
pageIndex,
111124
};
112125

113126
switch (subtype) {
@@ -196,6 +209,26 @@ class AnnotationFactory {
196209
return new Annotation(parameters);
197210
}
198211
}
212+
213+
static async _getPageIndex(xref, ref, pdfManager) {
214+
try {
215+
const annotDict = await xref.fetchIfRefAsync(ref);
216+
if (!isDict(annotDict)) {
217+
return -1;
218+
}
219+
const pageRef = annotDict.getRaw("P");
220+
if (!isRef(pageRef)) {
221+
return -1;
222+
}
223+
const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [
224+
pageRef,
225+
]);
226+
return pageIndex;
227+
} catch (ex) {
228+
warn(`_getPageIndex: "${ex}".`);
229+
return -1;
230+
}
231+
}
199232
}
200233

201234
function getRgbColor(color) {
@@ -373,6 +406,7 @@ class Annotation {
373406
AnnotationActionEventType
374407
);
375408
this.data.fieldName = this._constructFieldName(dict);
409+
this.data.pageIndex = params.pageIndex;
376410
}
377411

378412
this._fallbackFontDict = null;
@@ -681,6 +715,7 @@ class Annotation {
681715
name: this.data.fieldName,
682716
type: "",
683717
kidIds: this.data.kidIds,
718+
page: this.data.pageIndex,
684719
};
685720
}
686721
return null;
@@ -1775,6 +1810,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
17751810
name: this.data.fieldName,
17761811
rect: this.data.rect,
17771812
actions: this.data.actions,
1813+
page: this.data.pageIndex,
17781814
type: "text",
17791815
};
17801816
}
@@ -2106,6 +2142,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
21062142
rect: this.data.rect,
21072143
hidden: this.data.hidden,
21082144
actions: this.data.actions,
2145+
page: this.data.pageIndex,
21092146
type,
21102147
};
21112148
}
@@ -2186,6 +2223,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
21862223
hidden: this.data.hidden,
21872224
actions: this.data.actions,
21882225
items: this.data.options,
2226+
page: this.data.pageIndex,
21892227
type,
21902228
};
21912229
}
@@ -2205,6 +2243,7 @@ class SignatureWidgetAnnotation extends WidgetAnnotation {
22052243
return {
22062244
id: this.data.id,
22072245
value: null,
2246+
page: this.data.pageIndex,
22082247
type: "signature",
22092248
};
22102249
}

src/core/catalog.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class Catalog {
7070
this.builtInCMapCache = new Map();
7171
this.globalImageCache = new GlobalImageCache();
7272
this.pageKidsCountCache = new RefSetCache();
73+
this.pageIndexCache = new RefSetCache();
7374
this.nonBlendModesSet = new RefSet();
7475
}
7576

@@ -983,6 +984,7 @@ class Catalog {
983984
clearPrimitiveCaches();
984985
this.globalImageCache.clear(/* onlyData = */ manuallyTriggered);
985986
this.pageKidsCountCache.clear();
987+
this.pageIndexCache.clear();
986988
this.nonBlendModesSet.clear();
987989

988990
const promises = [];
@@ -1112,6 +1114,11 @@ class Catalog {
11121114
}
11131115

11141116
getPageIndex(pageRef) {
1117+
const cachedPageIndex = this.pageIndexCache.get(pageRef);
1118+
if (cachedPageIndex !== undefined) {
1119+
return Promise.resolve(cachedPageIndex);
1120+
}
1121+
11151122
// The page tree nodes have the count of all the leaves below them. To get
11161123
// how many pages are before we just have to walk up the tree and keep
11171124
// adding the count of siblings to the left of the node.
@@ -1191,16 +1198,16 @@ class Catalog {
11911198
}
11921199

11931200
let total = 0;
1194-
function next(ref) {
1195-
return pagesBeforeRef(ref).then(function (args) {
1201+
const next = ref =>
1202+
pagesBeforeRef(ref).then(args => {
11961203
if (!args) {
1204+
this.pageIndexCache.put(pageRef, total);
11971205
return total;
11981206
}
11991207
const [count, parentRef] = args;
12001208
total += count;
12011209
return next(parentRef);
12021210
});
1203-
}
12041211

12051212
return next(pageRef);
12061213
}

src/scripting_api/field.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class Field extends PDFObject {
4949
this.multiline = data.multiline;
5050
this.multipleSelection = !!data.multipleSelection;
5151
this.name = data.name;
52-
this.page = data.page;
5352
this.password = data.password;
5453
this.print = data.print;
5554
this.radiosInUnison = data.radiosInUnison;
@@ -78,6 +77,7 @@ class Field extends PDFObject {
7877
this._fillColor = data.fillColor || ["T"];
7978
this._isChoice = Array.isArray(data.items);
8079
this._items = data.items || [];
80+
this._page = data.page || 0;
8181
this._strokeColor = data.strokeColor || ["G", 0];
8282
this._textColor = data.textColor || ["G", 0];
8383
this._value = data.value || "";
@@ -180,6 +180,14 @@ class Field extends PDFObject {
180180
this.strokeColor = color;
181181
}
182182

183+
get page() {
184+
return this._page;
185+
}
186+
187+
set page(_) {
188+
throw new Error("field.page is read-only");
189+
}
190+
183191
get textColor() {
184192
return this._textColor;
185193
}

test/integration/scripting_spec.js

+40
Original file line numberDiff line numberDiff line change
@@ -762,4 +762,44 @@ describe("Interaction", () => {
762762
);
763763
});
764764
});
765+
766+
describe("Check field properties", () => {
767+
let pages;
768+
769+
beforeAll(async () => {
770+
pages = await loadAndWait("evaljs.pdf", "#\\35 5R");
771+
});
772+
773+
afterAll(async () => {
774+
await closePages(pages);
775+
});
776+
777+
it("must check page index", async () => {
778+
await Promise.all(
779+
pages.map(async ([browserName, page]) => {
780+
await page.waitForFunction(
781+
"window.PDFViewerApplication.scriptingReady === true"
782+
);
783+
784+
await clearInput(page, "#\\35 5R");
785+
await page.type(
786+
"#\\35 5R",
787+
`
788+
['Text1', 'Text2', 'Text4',
789+
'List Box7', 'Group6'].map(x => this.getField(x).page).join(',')
790+
`
791+
);
792+
793+
// Click on execute button to eval the above code.
794+
await page.click("[data-annotation-id='57R']");
795+
await page.waitForFunction(
796+
`document.querySelector("#\\\\35 6R").value !== ""`
797+
);
798+
799+
const text = await page.$eval("#\\35 6R", el => el.value);
800+
expect(text).withContext(`In ${browserName}`).toEqual("0,0,1,1,1");
801+
})
802+
);
803+
});
804+
});
765805
});

test/pdfs/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@
403403
!issue12418_reduced.pdf
404404
!annotation-freetext.pdf
405405
!annotation-line.pdf
406+
!evaljs.pdf
406407
!annotation-line-without-appearance.pdf
407408
!bug1669099.pdf
408409
!annotation-square-circle.pdf

test/pdfs/evaljs.pdf

54.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)