The History API includes methods to undo and redo annotation operations: creation, updates and deletions may be reverted and restored by means of this API.
The implementation does not fully revert an annotation to its previous state:
updatedAt field will have changed to the current time.id
than the original.updatedAt property are not tracked, and the updated
annotation is considered identical to the previous one in this case.The feature only accounts for annotations modified locally, wether using the API or the toolbar Undo and Redo buttons. If an annotation is modified externally, by another Instant client, for example, undoing will not revert the annotation state to the one just before the external change, but to the previous to that one: external annotation operations are not undone, but overridden.
Annotation operations performed while the History API is disabled can also be considered external for that effect. This is also the case for annotation operations that result from Instant Comments changes, like deleting the last comment of a comment thread, which results on the comment marker being deleted, and which cannot therefore be undone.
However, comment markers directly deleted with the API may be restored with its former comments.
Annotation presets are not restored by undo and redo operations.
Returns true if it's possible to redo a previously undone operation, false otherwise,
also if the History API is disabled.
Returns true if it's possible to undo a previous operation, false otherwise,
also if the History API is disabled.
Removes all undoable and redoable operations available.
Disables the History API: attempting to undo or redo previous operations with the API or the UI will not be possible, but the previous undoable and redoable operations will be preserved, and available if the History API is enabled again with NutrientViewer.Instance#history.enable.
Enables the History API, making undoing and redoing possible. If there were previous undoable or redoable operations, they will be now available.
When called, the last undone annotation operation will be performed again.
Note that if an annotation deletion has been undone, and then redone by calling this function, it will reappear in front of any other annotations, even if that was not its original stacking order.
Returns true if the operation has been redone successfully, false if there are no
redoable operations available or the History API is disabled.
await instance.create(new NutrientViewer.Annotations.RectangleAnnotation({
pageIndex: 0,
boundingBox: new NutrientViewer.Geometry.Rect({
left: 200,
top: 150,
width: 250,
height: 75
})
}));
console.log("Annotation created!");
await instance.delete();
console.log("Annotation deleted!");
await instance.history.undo();
console.log("Annotation creation undone: annotation deleted!");
await instance.history.redo();
console.log("Annotation creation redone: annotation created!");
When called, the last local annotation operation will be reverted. The outcome will vary depending on the type of that operation:
Note that if a deleted annotation is restored by calling this function, it will reappear in front of any other annotations, even if that was not its original stacking order.
Returns true if the operation has been undone successfully, false if there are no
undoable operations available or the History API is disabled.
await instance.create(new NutrientViewer.Annotations.RectangleAnnotation({
pageIndex: 0,
boundingBox: new NutrientViewer.Geometry.Rect({
left: 200,
top: 150,
width: 250,
height: 75
})
}));
console.log("Annotation created!");
await instance.history.undo();
console.log("Annotation creation undone: annotation deleted!");
The current annotation creator name. This is set using instance.setAnnotationCreatorName().
Returns a deep copy of the latest annotation presets. This value changes whenever the user interacts with NutrientViewer or whenever Instance.setAnnotationPresets is called.
Mutating this object will have no effect.
NOTE This method is only available with Nutrient Instant.
Use this method to obtain an up-to-date list of the current connected instance clients.
The return value is an Immutable.Map, which can be used like the regular ES2015 Map.
The "instant.connectedClients.change" event will be triggered, whenever a new client will connect to the document, or a current client will disconnect. The event will always include the full up-to-date list of the currently connected clients (the same that would be returned when you call this method).
An NutrientViewer.Immutable.Map of the connected clients.
Access the shadow root object of the Nutrient Web SDK's viewer. This can be used to quickly interact with elements (using our public CSS API) inside the viewer.
When the iframe fallback is set, this property provides access the document object of
the Nutrient Web SDK's viewer frame instead.
Access the window object of the Nutrient Web SDK's viewer frame. This can be used to quickly
interact with elements (using our public CSS API) inside the viewer.
Get the current active annotation preset ID
Returns a deep copy of the latest document editor footer items. This value changes whenever the user interacts with NutrientViewer or whenever Instance#setDocumentEditorFooterItems is called.
Mutating this array will have no effect.
A deep copy of the latest document editor footer items.
Returns a deep copy of the latest document editor toolbar items. This value changes whenever the user interacts with NutrientViewer or whenever Instance#setDocumentEditorToolbarItems is called.
Mutating this array will have no effect.
Returns a deep copy of the latest editableAnnotationTypes. This value changes whenever Instance.setEditableAnnotationTypes is called.
Mutating this object will have no effect.
Returns the current locale for the application.
The current locale for the application.
The maximum zoom level. This value depends on the current viewport and page dimensions.
Defaults to 10 but can be bigger so that the FIT_TO_WIDTH and FIT_TO_VIEWPORT
ZoomModes always fit.
The minimum zoom level. This value depends on the current viewport and page dimensions.
Defaults to 0.5 but can be bigger so that the FIT_TO_WIDTH and FIT_TO_VIEWPORT
ZoomModes always fit.
Returns the latest search state. This value changes whenever the user interacts with NutrientViewer or whenever Instance#setSearchState is called.
The search state can be used to finely control the current search UI.
Returns a deep copy of the latest stamp and image annotation templates. This value changes whenever NutrientViewer.Instance#setStampAnnotationTemplates is called.
Mutating this array will have no effect.
Returns a deep copy of the latest toolbar items. This value changes whenever the user interacts with NutrientViewer or whenever Instance#setToolbarItems is called.
Mutating this array will have no effect.
Returns the latest view state. This value changes whenever the user interacts with NutrientViewer or whenever Instance#setViewState is called.
When you want to keep a reference to the latest view state, you should always listen on the "viewState.change" to update your reference.
Registers an event listener for a specific event type.
Use this method to listen for changes and actions within the viewer, such as annotation updates, page navigation, form field changes, and more. Each supported event type is associated with a specific handler signature, ensuring type safety and clarity.
A list of all supported events can be found in NutrientViewer.EventName.
action parameter must be one of the supported event names listed above.listener parameter must match the corresponding event listener type for the event.If you attempt to register a listener for an unsupported event, a NutrientViewer.Error will be thrown.
The event name to listen for. Must be a key of Events.EventNameToHandlerMap.
The event name to listen for. See the table above for supported values.
The function to be called when the event is emitted.
Registering a listener for a view state change
instance.addEventListener("viewState.change", (viewState) => {
console.log(viewState.toJS());
});
Applies operations to the current document. If multiple operations are provided, each operation is performed on the resulting document from the previous operation. This API works only if you have the document editor component in your license.
Operations to be performed on the document.
Promise that resolves with an array of results.
Applies redactions to the current document. This will overwrite the document, removing content irreversibly.
In the process of redacting the content, all the redaction annotations will be removed. Any annotation that is either partially or completely covered by a redaction annotation will be deleted.
Promise that resolves when the redactions has been applied.
Creates and returns a new content editing session.
If called in a Server-backed instance, we will download the document and WASM in the background automatically.
Using this method requires a license that includes the Content Editor component.
A promise that resolves to a ContentEditing.Session object.
Takes a NutrientViewer.Annotations.TextAnnotation and returns a new NutrientViewer.Annotations.TextAnnotation where the bounding box is adjusted to fit the annotation and inside the page.
This is using the same calculations as the text annotation editor interface.
The text annotation that needs its bounding box adjusted.
The text annotation that has it's bounding box adjusted.
Compares documents based on the operation provided. It supports both standard text comparison and AI-powered analysis and tagging.
Descriptors of the original and changed documents.
The comparison operation to be applied (either standard text or AI).
A promise that resolves to the result of the comparison. The type depends on the operation: DocumentComparisonResult for text comparison, AIDocumentComparisonResult for AI operations.
Compare two documents
const operation = new NutrientViewer.ComparisonOperation("text", { numberOfContextWords: 2 });
const originalDocument = new NutrientViewer.DocumentDescriptor({ filePath: "path/to/original.pdf", pageIndexes: [0]});
const changedDocument = new NutrientViewer.DocumentDescriptor({ filePath: "path/to/changed.pdf", pageIndexes: [0]});
const comparisonDocuments = { originalDocument, changedDocument };
instance.compareDocuments(operation, comparisonDocuments)
.then((comparisonResults) => {
console.log(comparisonResults);
});
AI-powered analysis
const aiOperation = new NutrientViewer.ComparisonOperation(
NutrientViewer.ComparisonOperationType.AI,
{ operationType: NutrientViewer.AIComparisonOperationType.ANALYZE }
);
instance.compareDocuments(comparisonDocuments, aiOperation)
.then((result) => {
// For AI operations, check the result type
if (NutrientViewer.isAIDocumentComparisonResult(result)) {
console.log('AI Summary:', result.summary);
console.log('Categories:', result.categories);
}
});
AI-powered tagging with categories
const tagOperation = new NutrientViewer.ComparisonOperation(
NutrientViewer.ComparisonOperationType.AI,
{
operationType: NutrientViewer.AIComparisonOperationType.TAG,
categories: ["Legal", "Financial"]
}
);
instance.compareDocuments(comparisonDocuments, tagOperation)
.then((result) => {
// For AI operations, check the result type
if (NutrientViewer.isAIDocumentComparisonResult(result)) {
console.log('Tagged References:', result.references);
// result.changes contains the original DocumentComparisonResult
}
});
Creates new changes and assigns them IDs. If you need to ensure that changes are persisted by the backend, please refer to: NutrientViewer.Instance#ensureChangesSaved.
This method returns a promise that will resolve to an array of records with the local IDs set.
New changes will be made visible in the UI instantly.
A promise that resolves to an array of created changes or an error if some changes could not be created.
NutrientViewer.load(configuration).then(function(instance) {
const annotation = new NutrientViewer.Annotations.InkAnnotation({
pageIndex: 0,
lines: NutrientViewer.Immutable.List([
NutrientViewer.Immutable.List([
new NutrientViewer.Geometry.DrawingPoint({ x: 0, y: 0 }),
new NutrientViewer.Geometry.DrawingPoint({ x: 100, y: 100}),
])
])
});
instance.create(annotation).then(function(createdAnnotations) {
console.log(createdAnnotations);
});
})
@public
Searches in the PDF document and creates a redaction annotation for each search result. You can search for a text, regex or use one of the patterns we provide. See NutrientViewer.SearchPattern for the list of all the patterns we support.
Regex syntax:
Notice that matches included when using one of the NutrientViewer.SearchPattern options might overfit the criteria (i.e. include false positive results). This might happen since we strive for including all positive results and avoid data loss. Make sure to review the matches found.
Note for multiline regular expressions that document text lines end with CRLF (\r\n).
Regular expressions that follow the JavaScript syntax are matched in a similar way to the RegExp.prototype.exec() method (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec), but ignoring capturing groups, that is, this function only returns full string matches.
The text, regex or pattern you want to search for.
Optionaloptions: {Search options object.
OptionalannotationPreset?: RedactionAnnotationPresetRedaction annotation preset.
OptionalcaseSensitive?: booleanWhether the search will be case-sensitive or not. Default is false if searchType is NutrientViewer.SearchType.TEXT and true for other types of searches.
OptionalpageRange?: numberStarting from the start page, the number of pages to search. Default is to the end of the document.
OptionalsearchInAnnotations?: booleanSet to false if you don't want to search in annotations.
OptionalsearchType?: "text" | "preset" | "regex"Redactions Search Type.
OptionalstartPageIndex?: numberThe page number to start the search from.
Promise that resolves when the redaction annotations have been created. Returns a list of new Redaction Annotation IDs.
// Search and add redactions
instance.createRedactionsBySearch(NutrientViewer.SearchPattern.CREDIT_CARD_NUMBER, {
searchType: NutrientViewer.SearchType.PRESET,
searchInAnnotations: true,
annotationPreset: {
overlayText: 'Redacted'
}
}).then(function(ids) {
console.log("The following annotations have been added:", ids);
return instance.applyRedactions();
});
// We can add an "annotations.create" event listener and add custom logic based on the
// information for each of the newly created redaction annotations
const {RedactionAnnotation} = NutrientViewer.Annotations
instance.addEventListener("annotations.create", annotations => {
const redactions = annotations.filter(annot => annot instanceof RedactionAnnotation)
if (redactions.size > 0) {
console.log("Redactions: ", redactions.toJS())
}
});
Deletes a change. This can be called with a change ID.
If you need to ensure that changes are persisted by the backend, please refer to: Instance#ensureChangesSaved.
Deleted changes will be made visible in the UI instantly.
If the deleted change is a NutrientViewer.Annotations.WidgetAnnotation
(which can only be deleted if the Form Creator component is present in
the license, and the backend is using a Form Creator capable provider),
and the associated NutrientViewer.FormField only includes that annotation in
its annotationIds list, the form field will also be deleted.
If there are more widget annotations remaining in the annotationIds list,
as could be the case for radio buttons, for example, the form field's
annotationIds property will be updated by removing the deleted
annotation's id from it.
A single id or a list/array of ids of changes that should be deleted.
A promise that resolves to an array of deleted changes or an error if some changes could not be deleted.
If there are any annotations groups, this function will return all annotations groups. deleteAnnotationsGroup
The annotation group id.
Ensures that changes have been saved to the backend and returns the current persisted state of these changes.
This method returns a promise that will resolve to an array of Change.
A promise that resolves to an array of changes or an error if some changes could not be saved.
Instant JSON can be used to instantiate a viewer with a diff that is applied to the raw PDF. This format can be used to store annotation and form field value changes on your server and conveniently instantiate the viewer with the same content at a later time.
Instead of storing the updated PDF, this serialization only contains a diff that is applied on top of the existing PDF and thus allows you to cache the PDF and avoid transferring a potentially large PDF all the time.
This method is used to export the current annotations as Instant JSON. Use Configuration#instantJSON to load it.
annotations will follow the Instant Annotation JSON format specification.
formFieldValues will follow the Instant Form Field Value JSON format specification.
Optionally a version argument can be provided to specify the Instant JSON version to use for exported annotations.
For Server-Backed setups, only saved annotations will be exported.
Optionalversion: numberOptional Instant JSON version for annotations.
Instant JSON as a plain JavaScript object.
Exports the document converted to the specified output format as an ArrayBuffer. This can be used to download the resulting file.
An options object should be passed to the method with a format property
set to one of the supported conversion output formats: OfficeDocumentFormat.
Export options object.
The binary contents of the PDF.
Download as DOCX
instance.exportOffice({ format: NutrientViewer.OfficeDocumentFormat.docx })
.then(function (buffer) {
const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
const objectUrl = window.URL.createObjectURL(blob);
downloadPdf(objectUrl);
window.URL.revokeObjectURL(objectUrl);
});
function downloadPdf(blob) {
const a = document.createElement("a");
a.href = blob;
a.style.display = "none";
a.download = "download.docx";
a.setAttribute("download", "download.docx");
document.body.append(a);
a.click();
a.remove();
}
Exports the PDF contents as an ArrayBuffer. This can be used to download the PDF.
If the document is digitally signed and the license includes the Digital Signatures component, the method will export the document incrementally saved by default, so as not to corrupt signed data. Otherwise, it will be exported as fully saved by default.
It's not possible to use flatten and incremental both set to true at the same time,
as flattening is a destructive operation that will necessarily modify the provided document.
Please see guide article for more information and examples.
Export options object.
The binary contents of the PDF.
Export the PDF content
instance.exportPDF().then(function (buffer) {
buffer; // => ArrayBuffer
});
Export the PDF with password and permissions
instance.exportPDF({
permissions: {
userPassword: "123",
ownerPassword: "123",
documentPermissions: [NutrientViewer.DocumentPermissions.annotationsAndForms]
}
}).then(function (buffer) {
buffer; // => ArrayBuffer
});
Download the PDF by using an <a> tag
instance.exportPDF().then(function(buffer) {
const supportsDownloadAttribute = HTMLAnchorElement.prototype.hasOwnProperty(
"download"
);
const blob = new Blob([buffer], { type: "application/pdf" });
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, "download.pdf");
} else if (!supportsDownloadAttribute) {
const reader = new FileReader();
reader.onloadend = function() {
const dataUrl = reader.result;
downloadPdf(dataUrl);
};
reader.readAsDataURL(blob);
} else {
const objectUrl = window.URL.createObjectURL(blob);
downloadPdf(objectUrl);
window.URL.revokeObjectURL(objectUrl);
}
});
function downloadPdf(blob) {
const a = document.createElement("a");
a.href = blob;
a.style.display = "none";
a.download = "download.pdf";
a.setAttribute("download", "download.pdf");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
Exports the PDF contents after applying operations on the current document, which is not modified.
If multiple operations are provided, each operation is performed on the resulting document from the previous operation.
Returns an ArrayBuffer that can be used to download the PDF.
Operations to be performed on the document.
Promise that resolves with the binary contents of the modified PDF.
Export the modified PDF content
const operations = [
{
type: "rotatePages",
pageIndexes: [0],
rotateBy: 90
}
];
instance.exportPDFWithOperations(operations).then(function (buffer) {
buffer; // => ArrayBuffer
});
Download the modified PDF by using an <a> tag
const operations = [
{
type: "rotatePages",
pageIndexes: [0],
rotateBy: 90
}
];
instance.exportPDFWithOperations(operations).then(function(buffer) {
const supportsDownloadAttribute = HTMLAnchorElement.prototype.hasOwnProperty(
"download"
);
const blob = new Blob([buffer], { type: "application/pdf" });
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, "download.pdf");
} else if (!supportsDownloadAttribute) {
const reader = new FileReader();
reader.onloadend = function() {
const dataUrl = reader.result;
downloadPdf(dataUrl);
};
reader.readAsDataURL(blob);
} else {
const objectUrl = window.URL.createObjectURL(blob);
downloadPdf(objectUrl);
window.URL.revokeObjectURL(objectUrl);
}
});
function downloadPdf(blob) {
const a = document.createElement("a");
a.href = blob;
a.style.display = "none";
a.download = "download.pdf";
a.setAttribute("download", "download.pdf");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
XFDF can be used to instantiate a viewer with a diff that is applied to the raw PDF. This format can be used to store annotation and form field value changes on your server and conveniently instantiate the viewer with the same content at a later time.
Instead of storing the updated PDF, this serialization only contains a diff that is applied on top of the existing PDF and thus allows you to cache the PDF and avoid transferring a potentially large PDF all the time.
This method is used to export the current annotations as XFDF. Use Configuration#XFDF to load it.
For Server-Backed setups, only saved annotations will be exported.
Optional flag to ignore page rotation when exporting XFDF, by default false. This means that the exported XFDF will contain the annotations in the same orientation as the page and if you import this XFDF using Configuration#XFDFIgnorePageRotation the annotations will be imported in the same orientation no matter the page rotation.
XFDF as a plain text.
Returns a NutrientViewer.Immutable.List of NutrientViewer.Annotations.Annotation for the given
pageIndex.
The list contains an immutable snapshot of the currently available annotations in the UI for the page. This means, that the returned list could include invalid annotations. Think for example of the following workflow:
When you want to keep a reference to the latest annotations, you can listen for
If annotations for this page have not been loaded yet, the promise will resolve only after we have received all annotations.
The page index for the annotations you want.
pageIndex is zero-based and has a maximum value of totalPageCount - 1
Resolves to annotations for the given page.
instance.getAnnotations(0).then(function (annotations) {
annotations.forEach(annotation => {
console.log(annotation.pageIndex);
});
// Filter annotations by type
annotations.filter(annotation => {
return annotation instanceof NutrientViewer.Annotations.InkAnnotation;
})
// Filter annotations at a specific point
const pointInFirstPage = new NutrientViewer.Geometry.Point({ x: 20, y: 30 });
const annotationsAtPointInPage = annotationsOnFirstPage.filter(annotation => {
return annotation.boundingBox.isPointInside(pointInFirstPage);
});
// Get the number of currently loaded annotations
const totalAnnotations = annotations.size;
})
This function will return all annotations groups, if there are any annotations groups.
Annotations groups
Returns a NutrientViewer.Immutable.List of Bookmark for the current document.
The list contains an immutable snapshot of the currently available bookmarks in the UI for the page.
When you want to keep a reference to the latest bookmarks, you can listen for NutrientViewer.EventName.BOOKMARKS_CHANGE, NutrientViewer.EventName.BOOKMARKS_WILL_SAVE, or NutrientViewer.EventName.BOOKMARKS_DID_SAVE to update your reference.
Resolves to bookmarks for the given page.
Returns a NutrientViewer.Immutable.List of Comment for the current document.
The list contains an immutable snapshot of the currently available comments in the UI.
When you want to keep a reference to the latest comments, you can listen for NutrientViewer.EventName.COMMENTS_CHANGE.
An object to configure the comments retrieval - GetCommentsOptions
OptionalincludeDrafts?: booleanWhether to include draft comments in the returned list.
Resolves to comments.
Returns the document outline (table of content).
A promise that resolves to a NutrientViewer.Immutable.List of NutrientViewer.OutlineElement
Returns the current DocumentPermissions of the document.
A Promise resolving to an object containing the document permissions keys along with their status (true or false).
Returns a list containing the information of all the embedded files in the PDF.
If you want to get the content of a particular embedded file, you can use NutrientViewer.Instance#getAttachment
const embeddedFiles = await instance.getEmbeddedFiles()
const fileContent = await instance.getAttachment(embeddedFiles.get(0).attachmentId)
List of embedded files in the document with their individual information.
Returns a NutrientViewer.Immutable.List of all NutrientViewer.FormFields for this document.
Resolves to a list of all form fields.
instance.getFormFields().then(formFields => {
formFields.forEach(formField => {
console.log(formField.name);
});
// Filter form fields by type
formFields.filter(formField => (
formField instanceof NutrientViewer.FormFields.TextFormField
));
// Get the total number of form fields
const totalFormFields = formFields.size;
})
Returns a simplified object that contains all form fields currently loaded and maps to their values. This object can be used to serialize form field values.
Values can be of type null, string, or Array.<string>.
This method does not check if all the form fields have been loaded. If you want to make sure that the all the document's form field values are retrieved, you have to make sure that the form fields have been retrieved first.
A simplified object that contains all form field values.
Returns a copy of the available stored signatures. Signatures are ink and image annotations and therefore can be converted to JavaScript objects with NutrientViewer.Annotations.toSerializableObject.
When the application doesn't have signatures in store this method will invoke Configuration#populateStoredSignatures to retrieve the initial list of annotations.
Promise that resolves with an Immutable list of signatures
Returns the current OCG layers visibility state.
OCG layers are groups of content in the document, that can be shown or hidden independently.
This method returns the current visibility state of the layers in the document as an object
with a visibleLayerIds Array that contains the list of layers identified by their ocgId
number, which are currently visible.
A promise that resolves to a NutrientViewer.LayersVisibilityState
Extracts the text behind a NutrientViewer.Annotations.MarkupAnnotation. This can be useful to get the highlighted text.
Warning: This is only an approximation. Highlighted text might not always 100% represent the text, as we just look behind the absolute coordinates to see what text is beneath. PDF highlight annotations are not markers in the content itself.
The text markup annotation you want to extract the text behind.
The text behind the annotation.
Get the text of all text markup annotations on the first page:
const annotations = await instance.getAnnotations(0);
const markupAnnotations = annotations.filter(
annotation => annotation instanceof NutrientViewer.Annotations.MarkupAnnotation
);
const text = await Promise.all(
markupAnnotations.map(instance.getMarkupAnnotationText)
);
console.log(text);
Returns a NutrientViewer.Immutable.List of NutrientViewer.Annotations for the given form field or annotation.
The list contains an immutable snapshot of the currently overlapping annotations for the argument.
If annotations for this page have not been loaded yet, the promise will resolve only after we have received all annotations.
The annotation or the form field that needs to be checked for overlapping annotations.
Resolves to a list of the annotations that overlap the given argument.
Get signature overlapping a signature form field
// The name of the field you want to check.
const formFieldName = "signature";
// First get all `FormFields` in the `Document`.
const formFields = await instance.getFormFields();
// Get a signature form with the specific name you want.
const field = formFields.find(
(formField) =>
formField.name === formFieldName && formField instanceof NutrientViewer.FormFields.SignatureFormField
);
// Check if the signature form field has been signed
await instance.getOverlappingAnnotations(field);
// It will result in a list of annotations that overlaps the given signature form field.
// If no annotation overlaps the form field, the list will be empty.
Get annotations overlapping an ink annotation
const annotations = instance.getAnnotations(0);
const inkAnnotation = annotations.find(
(annotation) =>
annotation instanceof NutrientViewer.Annotation.InkAnnotation
);
await instance.getOverlappingAnnotations(inkAnnotation);
// It will result in a list of annotations that overlaps the given signature form field.
// If no annotation overlaps the form field, the list will be empty.
*** Standalone only ***
This method is used to retrieve the tab order of annotations in a given page.
The tab order will be returned as an array of annotation IDs.
In the case of widget annotations associated to a radio form field, all the widgets
associated to the same form field are rendered next to the first one found
in the provided Array of annotation IDs.
A promise that resolves to an ordered array of annotation IDs.
If multiple annotations are selected, this function will return the set of selected annotations.
Gets the digital signatures validation information for all the signatures present in the current document. See DigitalSignatures.SignaturesInfo.
Promise that resolves with a DigitalSignatures.SignaturesInfo.
Retrieve signatures information
instance.getSignaturesInfo()
.then(signaturesInfo => {
console.log(signaturesInfo.status)
if(signaturesInfo.signatures) {
const invalidSignatures = signaturesInfo.signatures
.filter(signature => signature.signatureValidationStatus !== NutrientViewer.SignatureValidationStatus.valid);
console.log(invalidSignatures);
}
});
Additional information can be found in this guide article.
Returns a copy of the available stored signatures. Signatures are ink and image annotations and therefore can be converted to JavaScript objects with NutrientViewer.Annotations.toSerializableObject.
When the application doesn't have signatures in store this method will invoke Configuration#populateStoredSignatures to retrieve the initial list of annotations.
Promise that resolves with an Immutable list of signatures
Given a list of rects and their page index, extracts the text intersecting them. This can be useful to get the text that overlaps a focused annotation to give more context to screen reader users.
Warning: The computed text might be partial as we just look behind the absolute coordinates of a rect to see what text it is intersecting.
The page index where the rects are located
An immutable list of rects
The text that intersect the rects.
Get the text of all ink annotations on the first page:
const annotations = await instance.getAnnotations(0);
const inkAnnotationsRects = annotations.filter(
annotation => annotation instanceof NutrientViewer.Annotations.InkAnnotation
).map(annotation => annotation.boundingBox);
const text = await instance.getTextFromRects(0, inkAnnotationsRects);
console.log(text);
Gets the current text selection in the document, if any.
A promise that resolves to the current text selection, or null if no text is selected.
Group annotations in the user interface.
OptionalannotationsOrAnnotationsId: NutrientViewer.Immutable.List<The annotations model or annotations IDs you want to be grouped. Annotations selected for grouping must be on the same page. Annotations that are already grouped will be removed from the previous group and added to the new one.
Returns true if any local changes are not yet saved. This can be used in combination with
Configuration.autoSaveMode to implement fine grained save controls.
Whenever changes are saved (for example, when calling NutrientViewer.Instance#save),
the method will return false again.
Whether unsaved changes are present or not.
Brings the rect (in PDF page coordinates) into the viewport. This function will also change the zoom level so that the rect is visible completely in the best way possible.
The index of the page you want to have information about. If none is provided, the first page (pageIndex 0) will be used.
The rect in PDF page coordinates that you want to jump to.
Brings the rect (in PDF page coordinates) into the viewport. This function will not change the zoom level.
This can be used to scroll to specific annotations or search results.
The index of the page you want to have information about. If none
is provided, the first page (pageIndex 0) will be used.
The rect in PDF page coordinates that you want to jump to.
Returns the PageInfo for the specified page index.
If there is no page at the given index, returns null.
The index of the page you want to have information about
The PageInfo or null.
Print the document programmatically.
Optionaloptions: Print options object.
OptionalexcludeAnnotations?: booleanWhether to exclude annotations from the printout.
Optionalmode?: IPrintMode | undefinedOptional print mode. See NutrientViewer.PrintMode
This method will throw when printing is disabled, currently in process or when an invalid NutrientViewer.PrintMode was supplied.
This method is used to remove an existing CustomOverlayItem.
The id of the item to remove.
Create and then remove a text node.
const id = "1";
const item = new NutrientViewer.CustomOverlayItem({
id: id,
node: document.createTextNode("Hello from Nutrient Web SDK."),
pageIndex: 0,
position: new NutrientViewer.Geometry.Point({ x: 100, y: 200 }),
});
instance.setCustomOverlayItem(item);
instance.removeCustomOverlayItem(id);
This method can be used to remove an event listener registered via Instance#addEventListener.
It requires the same reference to the function that was used when registering the function (equality will be verified the same way as it is in the DOM API).
The action you want to add an event listener to. See the list on Instance#addEventListener for possible event types.
A listener function.
Proper approach - Use the same reference for registering and removing
const callback = someFunction.bind(this)
instance.addEventListener("viewState.zoom.change", callback);
instance.removeEventListener("viewState.zoom.change", callback);
StandaloneProvided a dimension and pageIndex renders a page of a document and returns the
result as ArrayBuffer. This can be used as thumbnail.
You can specify a width or height (but not both at the same time) as the first dimension
argument, each accepts a value in the interval (0; 5000]. The other dimension will be
calculated based on the aspect ratio of the document.
This method can be used to provide thumbnail images for your document list. You can use it
in a <canvas> tag. The following example will load the cover of the loaded document with a
width of 400px. We set the width of the <canvas> tag to 200px, so the image will be
sharp on high DPI screens.
The size of the resulting image. Only accepts either width or
height, but not both. The other dimension will be calculated accordingly.
The width of the resulting image.
The height of the resulting image.
The index of the page you want to have information about.
The raw image as bitmap.
const pageWidth = instance.pageInfoForIndex(0).width;
const pageHeight = instance.pageInfoForIndex(0).height;
const width = 400;
const height = Math.round(width * pageHeight / pageWidth);
instance.renderPageAsArrayBuffer({ width }, 0).then(function(buffer) {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.style.transformOrigin = "0 0";
canvas.style.transform = "scale(0.5)";
const imageView = new Uint8Array(buffer);
const ctx = canvas.getContext("2d");
const imageData = ctx.createImageData(width, height);
imageData.data.set(imageView);
ctx.putImageData(imageData, 0, 0);
document.body.appendChild(canvas);
});
@standalone
Generates a URL to an image for the first page of a document or the page of the
provided pageIndex. This can be used as thumbnail.
You can specify a width or height (but not both at the same time) as the first dimension
argument, each accepts a value in the interval (0; 5000]. The other dimension will be
calculated based on the aspect ratio of the document.
This endpoint can be used to provide thumbnail images for your document list. You can use it
as a src for an img tag. The following example will load the cover of the loaded document with a
width of 400px.
The returned URL is a Blob URL.
In order to prevent memory leaks, it's recommended to revoke the returned object URL once the image is no longer needed, as in the example.
The size of the resulting image. Only accepts either width or
height, but not both. The other dimension will be calculated accordingly.
The width of the resulting image.
The height of the resulting image.
The index of the page you want to have information about.
The image url.
let objectURL
instance.renderPageAsImageURL({ width: 400 }, 0).then(function(src) {
const image = document.createElement('img');
image.src = src;
objectURL = src;
document.body.appendChild(image);
});
// Once the image is no longer needed, we revoke the URL so that the associated
// Blob is released.
function callWhenTheImageIsNoLongerNeeded() {
// Is it an object URL?
if (objectURL.split("://")[0] === "blob") {
URL.revokeObjectURL(objectURL);
}
}
This method can be used to change the default group back to original after it was changed to
something else using instance.setGroup.
This method is no-op if Collaboration Permissions is not enabled.
With NutrientViewer.AutoSaveMode it's possible to define when local changes get saved, but it's also possible to define the point to save changes yourself.
By choosing NutrientViewer.AutoSaveMode.DISABLED, nothing gets saved automatically, but
by calling save, it's possible to manually trigger save. This can be useful when you want
to have full control when new changes get saved to your backend.
Promise that resolves once all changes are saved on remote server (in case of server-based backend) or in local backend (in case of standalone). If changes could not be saved, rejects with NutrientViewer.SaveError.
NutrientViewer.load(configuration).then(async (instance) => {
const annotation = new NutrientViewer.Annotations.InkAnnotation({
pageIndex: 0,
lines: NutrientViewer.Immutable.List([
NutrientViewer.Immutable.List([
new NutrientViewer.Geometry.DrawingPoint({ x: 0, y: 0 }),
new NutrientViewer.Geometry.DrawingPoint({ x: 100, y: 100}),
])
])
});
await instance.create(annotation);
await instance.save(); // Now the annotation gets saved.
})
Queries the PDF backend for all search results of a given term. Search is case-insensitive and accented letters are ignored. The minimum query length for the term query to be performed can be retrieved from SearchState.minSearchQueryLength.
Shorter queries will throw an error.
The search term.
Parameters used for search operation.
OptionalcaseSensitive?: booleanWhether you want the search to be case-sensitive.
OptionalendPageIndex?: numberThe last page index to search (inclusive). options.startPageIndex must be provided if this parameter is given.
OptionalsearchInAnnotations?: booleanWhether you want to search in annotations.
OptionalsearchType?: "text" | "preset" | "regex"The search type which describes whether the query is a text, pattern or regex.
OptionalstartPageIndex?: numberThe page index to start searching from. options.endPageIndex must be provided if this parameter is given.
Resolves to an immutable list of search results.
Search for all occurrences of foo
instance.search("foo").then(results => {
console.log(results.size);
});
Search within a page range.
instance.search("foo", { startPageIndex: 1, endPageIndex: 4 }).then(results => {
console.log(results.size);
});
Search for a regex.
instance.search("Q[a-z]+ck\\sC.*[tT]", { searchType: NutrientViewer.SearchType.REGEX }).then(results => {
console.log(results.size);
});
Sets the annotation creator name. Each created annotation will have the creators name set in the author property.
OptionalannotationCreatorName: null | stringThis method is used to update the annotation presets.
It makes it possible to add new annotation presets and edit or remove existing ones.
When you pass in an object with keyed AnnotationPreset, the current annotation presets
will be immediately updated. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current annotation presets as argument. You can use this to modify the object based on its
current value. This type of update is guaranteed to be atomic - the value of currentAnnotationPresets can't change in between. See: AnnotationPresetCallback
When one of the supplied AnnotationPreset is invalid, this method will throw an Error that contains a detailed error message.
Since annotationPresets is a regular JavaScript object, it can be manipulated using standard Object
methods.
Either a
new AnnotationPresets object which would overwrite the existing one, or a callback that will get
invoked with the current annotation presets and is expected to return the new annotation presets object.
The new changes will be applied immediately
instance.setAnnotationPresets(newAnnotationPresets);
instance.annotationPresets === newAnnotationPresets; // => true
You can use this callback to set/modify the toolbar items present in the annotation toolbar after the document has loaded.
The callback will receive the annotation which is being created or selected and based on it, you can have different annotation toolbars for different annotations.
You can do the following modifications using this API:
You can also use the hasDesktopLayout to determine if the current UI is being rendered on
mobile or desktop. Based on that, you can implement different designs for Desktop and Mobile.
This callback gets called every time the annotation toolbar is mounted.
Add a new annotation toolbar item
instance.setAnnotationToolbarItems((annotation, { defaultAnnotationToolbarItems, hasDesktopLayout }) => {
const node = document.createElement('node')
node.innerText = "Custom Item"
const icon = `<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" /></svg>`
return [{
id: "custom",
type: "custom",
node: node,
icon: icon,
className: 'Custom-Node',
onPress: () => alert("Custom item pressed!")
}, ...defaultAnnotationToolbarItems];
});
This method is used to set the current active annotation preset.
It makes it possible to specify what annotation preset should be used when new annotations are created in the UI by passing the annotation preset key string as argument.
The current annotation preset is set when the toolbar annotation buttons are used to create
annotations. This method allows to set the current annotation preset programmatically, as well
as resetting it by passing null as argument.
When the supplied key does not correspond with an existing AnnotationPreset, this method will throw an Error that contains a detailed error message.
OptionalannotationPresetID: null | stringAnnotation preset name.
The new changes will be applied immediately
instance.setCurrentAnnotationPreset("ink");
instance.currentAnnotationPreset === "ink"; // => true
Setting an annotation preset for a closed arrow line annotation.
instance.setAnnotationPresets(annotationPresets => {
return {
...annotationPresets,
line: {
...annotationPresets.line,
lineCaps: {
end: "closedArrow"
}
}
}
});
instance.setCurrentAnnotationPreset("line");
instance.setViewState(viewState =>
viewState.set("interactionMode", NutrientViewer.InteractionMode.SHAPE_LINE),
);
This method is used to set a new CustomOverlayItem or update an existing one.
The item to create or update.
Sets the current custom renderers. When this function is called with a new CustomRenderers object, all visible custom rendered annotations are immediately updated.
Sets the current custom UI configuration. When this function is called with a new CustomUI object, all visible sidebars are immediately updated.
The custom UI configuration or the custom UI configuration setter.
Standalone only
Enables or disables the document comparison UI.
When a DocumentComparisonConfiguration object is passed, the document comparison UI is mounted and initialized with the provided settings.
When null is passed, the document comparison UI is hidden if it was being shown.
Initial document comparison configuration.
Promise that resolves when the document comparison UI is hidden.
This method is used to update the document editor footer of the PDF editor. It makes it possible to add new items and edit or remove existing ones.
When you pass in an array of DocumentEditorFooterItem, the current items will be immediately
updated. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
array of DocumentEditorFooterItem as argument. You can use this to modify the list based on its
current value. This type of update is guaranteed to be atomic - the value of currentDocumentEditorFooterItems
can't change in between.
When one of the supplied DocumentEditorFooterItem is invalid, this method will throw an Error that contains a detailed error message.
Since items is a regular JavaScript Array of object literals it can be manipulated using
standard array methods like forEach, map, reduce, splice and so on.
Additionally you can use any 3rd party library for array manipulation like lodash
or just.
Either a
new array of DocumentEditorFooterItem which would overwrite the existing one, or a callback that will get
invoked with the current footer items and is expected to return the new array of items.
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setDocumentEditorFooterItems(items => items.reverse());
The new changes will be applied immediately
instance.setDocumentEditorFooterItems(newItems);
instance.documentEditorFooterItems === newItems; // => true
This method is used to update the document editor toolbar of the PDF editor. It makes it possible to add new items and edit or remove existing ones.
When you pass in an array of DocumentEditorToolbarItem, the current items will be immediately
updated. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
array of DocumentEditorToolbarItem as argument. You can use this to modify the list based on its
current value. This type of update is guaranteed to be atomic - the value of currentDocumentEditorToolbarItems
can't change in between.
See: DocumentEditorToolbarItemsSetter
When one of the supplied DocumentEditorToolbarItem is invalid, this method will throw an Error that contains a detailed error message.
Since items is a regular JavaScript Array of object literals it can be manipulated using
standard array methods like forEach, map, reduce, splice and so on.
Additionally you can use any 3rd party library for array manipulation like https://lodash.com|lodash
or http://anguscroll.com/just|just.
Either a
new array of DocumentEditorToolbarItem which would overwrite the existing one, or a callback that will get
invoked with the current toolbar items and is expected to return the new array of items.
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setDocumentEditorToolbarItems(items => items.reverse());
The new changes will be applied immediately
instance.setDocumentEditorToolbarItems(newItems);
instance.documentEditorToolbarItems === newItems; // => true
StandaloneSets the document outline (table of content).
The outline to set.
A promise that resolves when the outline has been set.
This method is used to update the editable annotation types.
When one of the supplied NutrientViewer.Annotations.Annotation is invalid, this method will throw an Error that contains a detailed error message.
Selects an annotation in the user interface and enters edit mode. If annotationOrAnnotationId is empty, the
current selection will be cleared instead.
This method works with NutrientViewer.Annotations.TextAnnotation and NutrientViewer.Annotations.NoteAnnotation. When called with other annotation types that don't have any text it will simply select the annotation.
OptionalannotationOrAnnotationId: null | string | AnnotationsUnionThe annotation
model or annotation ID you want to set as selected. If null is used, the current selection
will be cleared instead.
OptionalautoSelectText: null | booleanWhether the text should be automatically selected.
Updates the values of form fields. It's possible to update multiple form fields at once.
The object must use the NutrientViewer.FormFields.FormField#name as a key and the
values must be of type null, string, or Array.<string>. A null value will reset
the form field to either null, or its default value if available.
This method returns a Promise that resolves when all the form fields have been updated, so it should be awaited whenever you need to get or modify form fields immediately to ensure the form field value is synchronized.
An object that contains the form field names that should be updated as keys and their value as values.
Resolves when the values have been set.
This method is used to update the group that will be used by default in all the newly created form-fields, comments and annotations. If you don't have permission to change the group, you will get error when you try to add an annotation, comment or form-field.
This method is no-op if Collaboration Permissions is not enabled.
The new group that you want to use for all the newly created form-fields, comments and annotations.
This method is used to update the signatures list. It makes it possible to add new signatures and edit or remove existing ones.
Ink Signatures are Ink Annotations whose pageIndex and boundingBox is calculated at creation time.
When selected via UI such annotations are used as template to create new NutrientViewer.Annotations.InkAnnotations and NutrientViewer.Annotations.ImageAnnotations.
When you pass in a List of NutrientViewer.Annotations.InkAnnotation and NutrientViewer.Annotations.ImageAnnotation, the current list of signatures will be immediately updated. Calling this method is also idempotent.
If you pass in a function, it will be invoked with the current List of NutrientViewer.Annotations.InkAnnotation and NutrientViewer.Annotations.ImageAnnotation as argument.
You can use this to modify the list based on its current value.
This type of update is guaranteed to be atomic - the value of getStoredSignatures() can't change in between.
When the application doesn't have signatures in store this method will invoke Configuration#populateStoredSignatures to retrieve the initial list of annotations and it will pass it to your function.
When the list is invalid, this method will throw an Error that contains a detailed error message.
a
new array of signatures which would overwrite the existing one, or a callback that will get
invoked with the current toolbar items and is expected to return the new array of items.
Fetch and set a list of signatures
const signatures = fetch("/signatures")
.then(r => r.json())
.then(a => (
new NutrientViewer.Immutable.List(
a.map(NutrientViewer.Annotations.fromSerializableObject)
)
)
);
signatures.then(signatures => { instance.setInkSignatures(signatures) });
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setInkSignatures(signatures => signatures.reverse());
Add a Ink Signature to the existing list
const signature = new NutrientViewer.Annotations.InkAnnotation({ lines: ..., boundingBox: ... });
instance.setInkSignatures(signatures => signatures.push(signature));
You can use this callback to set/modify the toolbar items present in the inline toolbar after the document has loaded.
The callback will receive the default items of the inline toolbar and the text that is currently selected NutrientViewer.TextSelection
You can do the following modifications using this API:
icon of the a default toolbar item.You can also use the hasDesktopLayout flag provided to the callback to determine if the current UI is being rendered on
mobile or desktop. Based on that, you can implement different designs for Desktop and Mobile.
This callback gets called every time the inline toolbar is mounted.
The callback to set the inline text selection toolbar items.
Add a custom button and a custom node to the toolbar.
instance.setInlineTextSelectionToolbarItems(({ defaultItems, hasDesktopLayout }, selection) => {
console.log(selection)
if (hasDesktopLayout) {
const node = document.createElement("div");
node.innerText = "Custom Item";
return [
...defaultItems,
{
type: "custom",
id: "custom-1",
node: node,
className: "Custom-Node",
onPress: () => alert("Custom node pressed!"),
},
{
type: "custom",
id: "custom-2",
title: "custom-button-2",
onPress: () => alert("Custom item pressed!"),
},
];
}
return defaultItems
});
This method is used to update the isEditableAnnotation callback
When the supplied callback is invalid it will throw a Error that contains a detailed error message.
This method is used to update the isEditableComment callback
When the supplied callback is invalid it will throw a Error that contains a detailed error message.
To learn more check this guide article.
Sets the OCG visibility state.
This method takes an OCGLayersVisibilityState object as an argument, which contains
a visibleLayerIds Array that contains the list of layers identified by their ocgId, and
makes them visible, hiding any other layers not included in the Array.
The OCG visibility state to set.
A promise that resolves when the OCG visibility state has been set.
Sets the locale for the application. When setting a locale that doesn't exist it tries to
fall back to the parent locale when available. For example en-US falls back to en.
See NutrientViewer.I18n.locales to get a list of all the available locales.
The locale to set the app to. It must be one of NutrientViewer.I18n.locales.
Returns a promise that resolves once the locale is set.
Set the default value of scale for all newly created measurement annotations.
Scale value
Allows the user to toggle the snapping behavior while creation of measurement annotations. The snapping points are the points are a combination of endpoints, midpoints and intersections.
Whether to enable/disable snapping behaviour for creation of measurement annotations.
ServerSet a list of users that can be mentioned in comments.
An array of MentionableUser objects.
instance.setMentionableUsers([
{ id: "1", name: "John Doe", displayName: "John", avatar: "https://example.com/avatar.png" },
{ id: "2", name: "Jane Doe", displayName: "Jane", avatar: "https://example.com/avatar.png" },
{ id: "3", name: "John Smith", displayName: "John", avatar: "https://example.com/avatar.png" },
]);
@server
This method is used to update the setOnAnnotationResizeStart callback
When the supplied callback is invalid it will throw a NutrientViewer.Error that contains a detailed error message.
You can programmatically modify the properties of the comment just before it is created.
The callback to set the values of created form fields programmatically.
You can programmatically modify the properties of the widget annotation and the associated form field just before it is created via the form creator UI.
The callback to set the values of created form fields programmatically.
Standalone*** Standalone only ***
This method is used to set or modify the tab order of annotations in a given page.
Using this method, it is possible to specify the order in which annotations are navigated when using the keyboard. The tab order should be provided as an array of annotation IDs, or determined by a callback function.
The method accepts a page index as the first argument, and a callback as the second. This callback will
be called with an array of annotations in the page sorted by their current tab order, and should return
an array of those annotations' ids following the new tab order.
In the case of widget annotations associated to a radio form field, all the widgets associated to the same form field will be rendered next to the first one found in the provided array of annotation IDs, and navigated accordingly.
The page index to set the tab order for.
A callback that will be invoked with the annotations in the current tab order, and is expected to return the annotation IDs in the new tab order.
Set the tab order of annotations in page 0
instance.setPageTabOrder(0, currentTabOrderedAnnotations =>
["annotation-id-1", "annotation-id-2"]
);
Set the tab order of annotations in page 0, with a radio form field
// 'radio-widget-id-2' will be rendered next to 'radio-widget-id-1', and navigated accordingly
instance.setPageTabOrder(0, currentTabOrderedAnnotations =>
["radio-widget-id-1", "annotation-id-1", "annotation-id-2", "radio-widget-id-2"]
);
This method is used to update the UI search state of the PDF editor.
When you pass in a SearchState, the current state will be immediately overwritten. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
SearchState as a property. You can use this to change state based on the
current value. This type of update is guaranteed to be atomic - the value of currentState
can't change in between.
When the supplied SearchState is invalid, this method will throw an Error that contains a detailed error message.
SearchState#minSearchQueryLength is a readonly property and cannot be changed.
If the provided SearchState object includes a modified minSearchQueryLength
property, a warning will be shown and only changes to other properties will be applied.
Either a new SearchState which would overwrite the existing one, or a callback that will get invoked with the current search state and is expected to return the new state.
Selects annotations in the user interface. If annotationOrAnnotationId is empty, the
current selection will be cleared instead.
OptionalannotationsOrAnnotationsIds: The annotations
model or annotations IDs you want to set as selected. If null is used, the current selection
will be cleared instead.
StandaloneAdds LTV (Long Term Validation) information to an existing signature. See DigitalSignatures.SignaturesInfo.
Optionalcertificates: string[] | ArrayBuffer[]Certificates used to sign the document.
Promise that resolves with a DigitalSignatures.SignaturesInfo.
Add LTV information to an existing signature
instance.setSignaturesLTV(certificates)
.then(signaturesInfo => {
console.log(signaturesInfo.status)
if(signaturesInfo.signatures) {
const invalidSignatures = signaturesInfo.signatures
.filter(signature => !signature.ltv);
console.log(invalidSignatures);
}
});
Additional information can be found in this guide article.
This method is used to update the stamp annotation templates.
It makes it possible to add new stamp and image annotation templates and edit or remove existing ones.
When you pass in an array with StampAnnotation, the current
templates will be immediately updated. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
Array<NutrientViewer.Annotations.StampAnnotation | NutrientViewer.Annotations.ImageAnnotation> Array as argument.
You can use this to modify the array based on its current value. This type of update is guaranteed
to be atomic - the value of currentStampAnnotationTemplates can't change in between.
When one of the supplied StampAnnotation or NutrientViewer.Annotations.ImageAnnotation is invalid, this method will throw a NutrientViewer.Error that contains a detailed error message.
Since stampAnnotationTemplates is a regular JavaScript Array, it can be manipulated
using standard Array methods.
Either a new StampAnnotationTemplates Array which would overwrite the existing one, or a callback that
will get invoked with the current stamp and image annotation templates and is expected to return
the new stamp annotation stamps Array.
The new changes will be applied immediately
instance.setStampAnnotationTemplates(newStampAnnotationTemplates);
instance.stampAnnotationTemplates === newStampAnnotationTemplates; // => true
Adding a stamp annotation template.
const myStampAnnotationTemplate = new NutrientViewer.Annotations.StampAnnotation({
stampType: "Custom",
title: "My custom template title",
subtitle: "Custom subtitle",
boundingBox: new NutrientViewer.Geometry.Rect({ left: 0, top: 0, width: 192, height: 64 })
});
instance.setStampAnnotationTemplates(stampAnnotationTemplates => [ ...stampAnnotationTemplates, myStampAnnotationTemplate ]);
This method is used to update the stored signatures list. It makes it possible to add new signatures and edit or remove existing ones.
Signatures are either ink or image annotations whose pageIndex and boundingBox is calculated at creation time.
When selected via UI such annotations are used as template to create new NutrientViewer.Annotations.InkAnnotations and NutrientViewer.Annotations.ImageAnnotations.
When you pass in a List of NutrientViewer.Annotations.InkAnnotation and NutrientViewer.Annotations.ImageAnnotation, the current list of signatures will be immediately updated. Calling this method is also idempotent.
If you pass in a function, it will be invoked with the current List of NutrientViewer.Annotations.InkAnnotation and NutrientViewer.Annotations.ImageAnnotation as argument.
You can use this to modify the list based on its current value.
This type of update is guaranteed to be atomic - the value of getStoredSignatures() can't change in between.
When the application doesn't have signatures in store this method will invoke Configuration#populateStoredSignatures to retrieve the initial list of annotations and it will pass it to your function.
When the list is invalid, this method will throw an NutrientViewer.Error that contains a detailed error message.
a new array of signatures which would overwrite the existing one, or a callback that will get
invoked with the current toolbar items and is expected to return the new array of items.
Fetch and set a list of signatures
const signatures = fetch("/signatures")
.then(r => r.json())
.then(a => (
new NutrientViewer.Immutable.List(
a.map(NutrientViewer.Annotations.fromSerializableObject)
)
)
);
signatures.then(signatures => { instance.setStoredSignatures(signatures) });
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setStoredSignatures(signatures => signatures.reverse());
Add a Signature to the existing list
const signature = new NutrientViewer.Annotations.InkAnnotation({ lines: ..., boundingBox: ... });
instance.setStoredSignatures(signatures => signatures.push(signature));
This method is used to update the main toolbar items of the PDF editor. It makes it possible to add new items and edit or remove existing ones.
When you pass in an array of ToolbarItem, the current items will be immediately
updated. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
array of ToolbarItem as argument. You can use this to modify the list based on its
current value. This type of update is guaranteed to be atomic - the value of currentToolbarItems
can't change in between.
When one of the supplied ToolbarItem is invalid, this method will throw an Error that contains a detailed error message.
Since items is a regular JavaScript Array of object literals it can be manipulated using
standard array methods like forEach, map, reduce, splice and so on.
Additionally you can use any 3rd party library for array manipulation like https://lodash.com|lodash
or http://anguscroll.com/just|just.
a new array of ToolbarItems which would overwrite the existing one, or a callback that will get
invoked with the current toolbar items and is expected to return the new array of items.
Reverse the order of the toolbar items
const items = instance.toolbarItems;
items.reverse();
instance.setToolbarItems(newState);
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setToolbarItems(items => items.reverse());
The new changes will be applied immediately
instance.setToolbarItems(newItems);
instance.toolbarItems === newItems; // => true
Adding a button that's always visible on the right hand side of the zoom-in button.
const myButton = {
type: "custom",
id: "my-button",
title: "Test Button",
icon: "https://example.com/icon.jpg",
onPress() {
alert("test");
}
// mediaQueries is not defined so it will always be shown
};
instance.setToolbarItems(items => {
items.forEach((item, index) => {
if (item.name === "spacer") {
items.splice(index + 1, 0, myButton);
}
});
return items;
});
Changing a property of a custom button
const myButton = {
type: "custom",
id: "my-button",
title: "Test Button",
icon: "https://example.com/icon.jpg",
disabled: true,
onPress() {
alert("test");
},
};
NutrientViewer.load({
toolbarItems: [...NutrientViewer.defaultToolbarItems, myButton],
// ...
}).then(instance => {
instance.setToolbarItems(items =>
items.map(item => {
if (item.id === "my-button") {
item.disabled = false;
}
return item;
})
);
});
FunctionSet the UI customization config. This method allows you to change the UI configuration of an already mounted instance. The provided configuration will replace the previous configuration entirely.
In case of partial updates, you should merge the previous configuration with new changes.
Refer to guide for more information and examples.
The new UI configuration to set.
This method is used to update the UI state of the PDF editor.
When you pass in a ViewState, the current state will be immediately overwritten. Calling this method is also idempotent.
If you pass in a function, it will be immediately invoked and will receive the current
ViewState as a property. You can use this to change state based on the
current value. This type of update is guaranteed to be atomic - the value of currentState
can't change in between.
Be aware that this behavior is different from a React component's setState, because
it will not be deferred but initially applied. If you want to, you can always add deferring
behavior yourself. The approach we choose (immediate applying) makes it possible to control
exactly when the changes are flushed, which will allow fine control to work with other
frameworks (e.g. runloop-based frameworks like Ember).
Whenever this method is called (and actually changes the view state), the instance will trigger an "viewState.change". However, if you use this method to change properties of the view state at once (e.g. zooming and currentPageIndex at the same time), the "viewState.change" will only be triggered once. The "viewState.change" will be triggered synchronously, that means that the code will be called before this function exits. This is true for both passing in the state directly and passing in an update function.
When the supplied ViewState is invalid, this method will throw an Error that contains a detailed error message.
Either a new ViewState which would overwrite the existing one, or a callback that will get invoked with the current view state and is expected to return the new state.
Update values for the immutable state object
const state = instance.viewState;
const newState = state.set("currentPageIndex", 2);
instance.setViewState(newState);
Use ES2015 arrow functions and the update callback to reduce boilerplate
instance.setViewState(state => state.set("currentPageIndex", 2));
The state will be applied immediately
instance.setViewState(newState);
instance.viewState === newState; // => true
When the state is invalid, it will throw a NutrientViewer.Error
try {
// Non existing page index
instance.setViewState(state => state.set("currentPageIndex", 2000));
} catch (error) {
error.message; // => "The currentPageIndex set on the new ViewState is out of bounds.
// The index is expected to be in the range from 0 to 5 (inclusive)"
}
Digitally signs the document. On Standalone it can make sign the document with the certificates and private key provided by the user in DigitalSignatures.SignaturePreparationData, or use the signing service optionally provided in the callback argument.
On Server, you can optionally specify additional data to be passed to the signing service.
Check the related guide article.
Properties to prepare the signature with.
OptionaltwoStepSignatureCallbackOrSigningServiceData: TwoStepSignatureCallback | SigningServiceDataEither a callback to be executed when the document is ready for signing (Standalone only) or optional data to be passed to the signing service.
Promise that resolves when the document is signed.
Sign document with CMS signature (Standalone)
instance.signDocument(null, function({ hash, fileContents }) {
return new Promise(function(resolve, reject) {
const PKCS7Container = getPKCS7Container(hash, fileContents);
if (PKCS7Container != null) {
return resolve(PKCS7Container)
}
reject(new Error("Could not retrieve the PKCS7 container."))
})
}).then(function() {
console.log("Document signed!");
})
Open the search box, fill in the search term, and start loading the search requests.
This will set the ViewState#interactionMode to NutrientViewer.InteractionMode.SEARCH so that the search box is visible.
Load all TextLines for the specified pageIndex. If there is no page
at the given index, the list will be empty.
The index of the page you want to extract text from.
A promise that resolves the text lines of the given page.
Enable actions like cut, copy, paste and duplicate for annotations using keyboard shortcuts Cmd/Ctrl+X, Cmd/Ctrl+C, Cmd/Ctrl+V and Cmd/Ctrl+D respectively.
Whether to enable/disable the clipboard actions.
Transforms a NutrientViewer.Geometry.Point or a NutrientViewer.Geometry.Rect from the client space inside the main frame to the PDF page space.
The client space is relative to your HTML viewport and the same coordinates that you receive
by DOM APIs like Element.getBoundingClientRect() or MouseEvent.clientX, etc.
Use this transform when you receive events inside the main frame (The document of your
application).
Note: If you apply a CSS scale transformation to the mounting node of Nutrient Web SDK, this calculation will not work. In this case make sure to manually scale afterwards.
The rectangle or point that needs to be transformed that needs to be transformed
The index of the page you want to have information about. If none is provided, the first page (pageIndex 0) will be used.
The transformed point or rectangle.
Transforms a NutrientViewer.Geometry.Point or a NutrientViewer.Geometry.Rect from the client space inside the content frame to the PDF page space.
The content client space is relative to the NutrientViewer mounting container and the same
coordinates that you receive by DOM APIs like Element.getBoundingClientRect() or
MouseEvent.clientX, etc. that originate within the Nutrient Web SDK's iframe.
Use this transform when you receive events inside the content frame.
The rectangle or point that needs to be transformed that needs to be transformed
The index of the page you want to have information about. If none is provided, the first page (pageIndex 0) will be used.
The transformed point or rectangle.
Transforms a NutrientViewer.Geometry.Point or a NutrientViewer.Geometry.Rect from the PDF page space to the client space inside the content frame.
The content client space is relative to the NutrientViewer mounting container and the same
coordinates that you receive by DOM APIs like Element.getBoundingClientRect() or
MouseEvent.clientX, etc. that originate within the Nutrient Web SDK's iframe.
Use this transform when you want to position elements inside the NutrientViewer content frame.
The rectangle or point that needs to be transformed that needs to be transformed
The index of the page you want to have information about. If none is provided, the first page (pageIndex 0) will be used.
The transformed point or rectangle.
Transforms a NutrientViewer.Geometry.Point or a NutrientViewer.Geometry.Rect from the PDF page space to the client space inside the main frame.
The client space is relative to your HTML viewport and the same coordinates that you receive
by DOM APIs like Element.getBoundingClientRect() or MouseEvent.clientX, etc.
Use this transform when you want to position elements inside the main frame.
Note: If you apply a CSS scale transformation to the mounting node of Nutrient Web SDK, this calculation will not work. In this case make sure to manually scale afterwards.
The rectangle or point that needs to be transformed that needs to be transformed
The index of the page you want to have information about. If none is provided, the first page (pageIndex 0) will be used.
The transformed point or rectangle.
Transforms a NutrientViewer page space bounding box to a raw PDF bounding rect.
A raw PDF bounding rect is an array of inset values: [left, bottom, right, top],
in PDF page space units (as opposted to NutrientViewer page units) where the top and bottom
coordinates are actually relative to the distance to the bottom of the page.
Use this transform when you want to manage document entities with external tools.
The rectangle to be transformed
The index of the page you want to have information about.
The resulting transformed rectangle as inset coordinates.
Transforms a raw PDF bounding rect from the PDF page space to NutrientViewer's page space.
Use this transform when you want to manage entities using their raw, original coordinates and dimensions according to the PDF spec (e.g. from a XFDF file).
The inset to be transformed
The index of the page you want to have information about.
The resulting transformed rectangle.
Updates object and changes its contents.
If you need to ensure that changes are persisted by the backend, please refer to: Instance#ensureChangesSaved.
New changes will be made visible in the UI instantly.
A promise that resolves to an array of changes or an error if some changes could not be updated.
const instance = await NutrientViewer.load(configuration);
// Get all annotations on the first page
const annotations = instance.getAnnotations(0);
// Grab the first one
const annotation = annotations.first();
const editedAnnotation = annotation.set("noPrint", true);
const updatedAnnotation = await instance.update(editedAnnotation);
editedAnnotation === updatedAnnotation; // => true
@public
A mounted document instance.
You can generate an instance by using NutrientViewer.load.