Skip to content

Commit df1b166

Browse files
committed
feat: add auto navigate signature fields option
1 parent 329b062 commit df1b166

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import type {
2+
ImageAnnotation,
3+
InkAnnotation,
4+
Instance,
5+
Rect,
6+
WidgetAnnotation,
7+
} from "@nutrient-sdk/viewer";
8+
import { baseOptions } from "../../shared/base-options";
9+
10+
let globalInstance: Instance | null = null;
11+
12+
function scrollToNextSignatureField(index: number, rect: Rect) {
13+
if (!globalInstance) return;
14+
15+
const page = (
16+
globalInstance.contentDocument.getRootNode() as Document
17+
).querySelector(`[data-page-index="${index}"]`);
18+
19+
const arrow = document.createElement("span");
20+
arrow.classList.add("blob");
21+
arrow.style.cssText += `
22+
background: url(https://cdn-icons-png.flaticon.com/512/545/545682.png) 50% no-repeat;
23+
content: "";
24+
height: 1.2em;
25+
left: -2rem;
26+
position: absolute;
27+
top: 0;
28+
width: 1rem;
29+
`;
30+
31+
const item = new window.NutrientViewer.CustomOverlayItem({
32+
id: "arrow",
33+
node: arrow,
34+
pageIndex: index,
35+
position: new window.NutrientViewer.Geometry.Point({
36+
x: rect.left + 15,
37+
y: rect.top,
38+
}),
39+
});
40+
41+
globalInstance.setCustomOverlayItem(item);
42+
43+
window.requestAnimationFrame(() => {
44+
page?.scrollIntoView({
45+
block: "end",
46+
inline: "nearest",
47+
behavior: "smooth",
48+
});
49+
});
50+
}
51+
52+
localStorage.setItem("signature-field-counter", "0");
53+
54+
window.NutrientViewer.load({
55+
...baseOptions,
56+
}).then(async (instance: Instance) => {
57+
globalInstance = instance;
58+
59+
const formFields = await instance.getFormFields();
60+
61+
const signatureFormFields = formFields.filter(
62+
(field) =>
63+
field instanceof window.NutrientViewer.FormFields.SignatureFormField,
64+
);
65+
66+
const signatureNameIds = new Set(
67+
signatureFormFields.map((field) => field.name),
68+
);
69+
70+
const signatureFields = (
71+
await Promise.all(
72+
Array.from({ length: instance.totalPageCount }).map((_, pageIndex) =>
73+
instance.getAnnotations(pageIndex),
74+
),
75+
)
76+
).flatMap((annotations) =>
77+
annotations
78+
.filter((annotation) =>
79+
signatureNameIds.has(
80+
(annotation as WidgetAnnotation).formFieldName ?? "",
81+
),
82+
)
83+
.toJS(),
84+
);
85+
86+
setTimeout(() => {
87+
if (signatureFields.length > 0) {
88+
scrollToNextSignatureField(
89+
signatureFields[0].pageIndex,
90+
signatureFields[0].boundingBox,
91+
);
92+
}
93+
}, 1000);
94+
95+
instance.addEventListener("annotations.willChange", (event) => {
96+
const { annotations, reason } = event;
97+
const counter = Number.parseInt(
98+
localStorage.getItem("signature-field-counter") ?? "0",
99+
10,
100+
);
101+
102+
const firstAnnotation = annotations.first() as
103+
| InkAnnotation
104+
| ImageAnnotation
105+
| undefined;
106+
if (!firstAnnotation) return;
107+
108+
if (
109+
firstAnnotation.isSignature &&
110+
reason === window.NutrientViewer.AnnotationsWillChangeReason.SELECT_END
111+
) {
112+
instance.removeCustomOverlayItem("arrow");
113+
114+
const newCounter = counter + 1;
115+
localStorage.setItem("signature-field-counter", newCounter.toString());
116+
117+
if (newCounter < signatureFields.length) {
118+
const nextSignatureField = signatureFields[newCounter];
119+
const nextPageIndex = nextSignatureField.pageIndex;
120+
121+
const onViewStateChange = () => {
122+
setTimeout(() => {
123+
scrollToNextSignatureField(
124+
nextSignatureField.pageIndex,
125+
nextSignatureField.boundingBox,
126+
);
127+
}, 100);
128+
129+
instance.removeEventListener("viewState.change", onViewStateChange);
130+
};
131+
132+
instance.addEventListener("viewState.change", onViewStateChange);
133+
134+
instance.setViewState((viewState) =>
135+
viewState.set("currentPageIndex", nextPageIndex),
136+
);
137+
}
138+
}
139+
});
140+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: signatures
3+
title: Automatically Navigate to Next Signature Field
4+
description: Automatically scrolls to and highlights the next signature field after a user signs, guiding them through multiple signature fields in a document.
5+
keywords: [signature, navigation, scroll, form fields, custom overlay, electronic signatures, workflow]
6+
---

0 commit comments

Comments
 (0)