Skip to content

Commit

Permalink
JS -- add support for page property in field
Browse files Browse the repository at this point in the history
  • Loading branch information
calixteman committed May 3, 2021
1 parent f081701 commit df88997
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 31 deletions.
49 changes: 44 additions & 5 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,34 @@ class AnnotationFactory {
* instance.
*/
static create(xref, ref, pdfManager, idFactory, collectFields) {
return pdfManager.ensureCatalog("acroForm").then(acroForm => {
return pdfManager.ensure(this, "_create", [
return Promise.all([
pdfManager.ensureCatalog("acroForm"),
collectFields ? this._getPageIndex(xref, ref, pdfManager) : -1,
]).then(([acroForm, pageIndex]) =>
pdfManager.ensure(this, "_create", [
xref,
ref,
pdfManager,
idFactory,
acroForm,
collectFields,
]);
});
pageIndex,
])
);
}

/**
* @private
*/
static _create(xref, ref, pdfManager, idFactory, acroForm, collectFields) {
static _create(
xref,
ref,
pdfManager,
idFactory,
acroForm,
collectFields,
pageIndex = -1
) {
const dict = xref.fetchIfRef(ref);
if (!isDict(dict)) {
return undefined;
Expand All @@ -108,6 +120,7 @@ class AnnotationFactory {
pdfManager,
acroForm: acroForm instanceof Dict ? acroForm : Dict.empty,
collectFields,
pageIndex,
};

switch (subtype) {
Expand Down Expand Up @@ -196,6 +209,26 @@ class AnnotationFactory {
return new Annotation(parameters);
}
}

static async _getPageIndex(xref, ref, pdfManager) {
try {
const annotDict = await xref.fetchIfRefAsync(ref);
if (!isDict(annotDict)) {
return -1;
}
const pageRef = annotDict.getRaw("P");
if (!isRef(pageRef)) {
return -1;
}
const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [
pageRef,
]);
return pageIndex;
} catch (ex) {
warn(`_getPageIndex: "${ex}".`);
return -1;
}
}
}

function getRgbColor(color) {
Expand Down Expand Up @@ -373,6 +406,7 @@ class Annotation {
AnnotationActionEventType
);
this.data.fieldName = this._constructFieldName(dict);
this.data.pageIndex = params.pageIndex;
}

this._fallbackFontDict = null;
Expand Down Expand Up @@ -681,6 +715,7 @@ class Annotation {
name: this.data.fieldName,
type: "",
kidIds: this.data.kidIds,
page: this.data.pageIndex,
};
}
return null;
Expand Down Expand Up @@ -1775,6 +1810,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
name: this.data.fieldName,
rect: this.data.rect,
actions: this.data.actions,
page: this.data.pageIndex,
type: "text",
};
}
Expand Down Expand Up @@ -2106,6 +2142,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
rect: this.data.rect,
hidden: this.data.hidden,
actions: this.data.actions,
page: this.data.pageIndex,
type,
};
}
Expand Down Expand Up @@ -2186,6 +2223,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
hidden: this.data.hidden,
actions: this.data.actions,
items: this.data.options,
page: this.data.pageIndex,
type,
};
}
Expand All @@ -2205,6 +2243,7 @@ class SignatureWidgetAnnotation extends WidgetAnnotation {
return {
id: this.data.id,
value: null,
page: this.data.pageIndex,
type: "signature",
};
}
Expand Down
13 changes: 10 additions & 3 deletions src/core/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class Catalog {
this.builtInCMapCache = new Map();
this.globalImageCache = new GlobalImageCache();
this.pageKidsCountCache = new RefSetCache();
this.pageIndexCache = new RefSetCache();
this.nonBlendModesSet = new RefSet();
}

Expand Down Expand Up @@ -983,6 +984,7 @@ class Catalog {
clearPrimitiveCaches();
this.globalImageCache.clear(/* onlyData = */ manuallyTriggered);
this.pageKidsCountCache.clear();
this.pageIndexCache.clear();
this.nonBlendModesSet.clear();

const promises = [];
Expand Down Expand Up @@ -1112,6 +1114,11 @@ class Catalog {
}

getPageIndex(pageRef) {
const cachedPageIndex = this.pageIndexCache.get(pageRef);
if (cachedPageIndex !== undefined) {
return Promise.resolve(cachedPageIndex);
}

// The page tree nodes have the count of all the leaves below them. To get
// how many pages are before we just have to walk up the tree and keep
// adding the count of siblings to the left of the node.
Expand Down Expand Up @@ -1191,16 +1198,16 @@ class Catalog {
}

let total = 0;
function next(ref) {
return pagesBeforeRef(ref).then(function (args) {
const next = ref =>
pagesBeforeRef(ref).then(args => {
if (!args) {
this.pageIndexCache.put(pageRef, total);
return total;
}
const [count, parentRef] = args;
total += count;
return next(parentRef);
});
}

return next(pageRef);
}
Expand Down
46 changes: 24 additions & 22 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,8 @@ class Page {
annotationRef,
this.pdfManager,
this._localIdFactory,
/* collectFields */ false
/* collectFields */ false,
null
).catch(function (reason) {
warn(`_parsedAnnotations: "${reason}".`);
return null;
Expand Down Expand Up @@ -1241,29 +1242,30 @@ class PDFDocument {
return shadow(this, "fieldObjects", Promise.resolve(null));
}

const allFields = Object.create(null);
const fieldPromises = new Map();
for (const fieldRef of this.catalog.acroForm.get("Fields")) {
this._collectFieldObjects("", fieldRef, fieldPromises);
}
const fieldObjectsPromise = this.pdfManager
.ensureCatalog("toplevelPagesDict")
.then(pages => {
const allFields = Object.create(null);
const fieldPromises = new Map();
for (const fieldRef of this.catalog.acroForm.get("Fields")) {
this._collectFieldObjects("", fieldRef, fieldPromises);
}

const allPromises = [];
for (const [name, promises] of fieldPromises) {
allPromises.push(
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
if (fields.length > 0) {
allFields[name] = fields;
}
})
);
}
const allPromises = [];
for (const [name, promises] of fieldPromises) {
allPromises.push(
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
if (fields.length > 0) {
allFields[name] = fields;
}
})
);
}
return Promise.all(allPromises).then(() => allFields);
});

return shadow(
this,
"fieldObjects",
Promise.all(allPromises).then(() => allFields)
);
return shadow(this, "fieldObjects", fieldObjectsPromise);
}

get hasJSActions() {
Expand Down
10 changes: 9 additions & 1 deletion src/scripting_api/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class Field extends PDFObject {
this.multiline = data.multiline;
this.multipleSelection = !!data.multipleSelection;
this.name = data.name;
this.page = data.page;
this.password = data.password;
this.print = data.print;
this.radiosInUnison = data.radiosInUnison;
Expand Down Expand Up @@ -78,6 +77,7 @@ class Field extends PDFObject {
this._fillColor = data.fillColor || ["T"];
this._isChoice = Array.isArray(data.items);
this._items = data.items || [];
this._page = data.page || 0;
this._strokeColor = data.strokeColor || ["G", 0];
this._textColor = data.textColor || ["G", 0];
this._value = data.value || "";
Expand Down Expand Up @@ -180,6 +180,14 @@ class Field extends PDFObject {
this.strokeColor = color;
}

get page() {
return this._page;
}

set page(_) {
throw new Error("field.page is read-only");
}

get textColor() {
return this._textColor;
}
Expand Down
40 changes: 40 additions & 0 deletions test/integration/scripting_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -762,4 +762,44 @@ describe("Interaction", () => {
);
});
});

describe("Check field properties", () => {
let pages;

beforeAll(async () => {
pages = await loadAndWait("evaljs.pdf", "#\\35 5R");
});

afterAll(async () => {
await closePages(pages);
});

it("must check page index", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);

await clearInput(page, "#\\35 5R");
await page.type(
"#\\35 5R",
`
['Text1', 'Text2', 'Text4',
'List Box7', 'Group6'].map(x => this.getField(x).page).join(',')
`
);

// Click on execute button to eval the above code.
await page.click("[data-annotation-id='57R']");
await page.waitForFunction(
`document.querySelector("#\\\\35 6R").value !== ""`
);

const text = await page.$eval("#\\35 6R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("0,0,1,1,1");
})
);
});
});
});
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
!issue12418_reduced.pdf
!annotation-freetext.pdf
!annotation-line.pdf
!evaljs.pdf
!annotation-line-without-appearance.pdf
!bug1669099.pdf
!annotation-square-circle.pdf
Expand Down
Binary file added test/pdfs/evaljs.pdf
Binary file not shown.

0 comments on commit df88997

Please sign in to comment.