Grouping annotations through the AnnotationManager

Grouping annotations can be done in WebViewer both in the UI and programmatically. This can be useful for keeping annotations together and forming more meaningful commentary on your documents. Grouped annotations associate themselves to one primary annotation. Only the comment of the primary annotation will appear in the notes panel.

This is what grouped annotations look like represented in XFDF:

sh

1<square page="0" rect="92.533,616.387,228.861,717.911" color="#E44234" flags="print" name="f1b0896d-b173-c01e-27bf-eee16f33ae23" title="Guest" subject="Rectangle" rotation="345.166" date="D:20220411125212-07'00'" creationdate="D:20220411125149-07'00'" />
2<circle page="0" rect="141.590,547.820,264.010,660.970" color="#E44234" flags="print" inreplyto="f1b0896d-b173-c01e-27bf-eee16f33ae23" replyType="group" name="c245310b-3704-41ea-46ca-756bd66217ae" title="Guest" subject="Ellipse" date="D:20220411125212-07'00'" creationdate="D:20220411125152-07'00'"/>

Notice the replyType and inreplyto attributes of the circle annotation which refer to the square annotation as the primary.

Grouping annotations in the UI

Grouping annotations through the UI is straightforward. Simply selection the annotations you want to group and press the group button.

Apryse Docs Image

Ungrouping annotations in the UI

Likewise, ungrouping annotations will require first selecting the group and pressing the ungroup button.

Apryse Docs Image

Grouping annotations programmatically

Grouping annotations is done through the AnnotationManager. The API is called groupAnnotations and it takes a primary annotation along with an array of annotations that will be grouped with it.

1const { annotationManager } = instance.Core;
2
3const annotList = annotationManager.getAnnotationsList();
4const primaryAnnot = annotList[0];
5const primaryColor = primary.FillColor.toHexString();
6// Group annotations of the same color
7const secondaryAnnots = annotList.filter(annot => annot.FillColor.toHexString() === primaryColor);
8
9annotationManager.groupAnnotations(primary, secondary);

You can group annotations that are on different pages. However, the group's movement will still be constrained by their respective pages.

Grouping an annotation to a group will create another group instead of adding to it, so you must always group to the primary annotation to add a new annotation to the group.

Ungrouping annotations programmatically

Simlar to grouping annotations, the AnnotationManager also provides the ungroupAnnotations function. This function takes an array of annotations to be ungrouped (regardless of which group they belong in) and it will ungroup them without ungrouping other annotations of their respective groups.

1const { annotationManager } = instance.Core;
2
3const annotList = annotationManager.getAnnotationsList();
4const groupedAnnots = annotList.filter(annot => annot.isGrouped() && annot.PageNumber === 1);
5annotationManager.ungroupAnnotations(groupedAnnots);

Reading grouped annotations

A helpful API that will get you all the grouped annotations (both the primary and children) is the getGroupAnnotations API. By passing in any of the annotations that are part of the group, it will provide all the annotations in the group including that one that was passed in.

1const { annotationManager } = instance.Core;
2
3const annotList = annotationManager.getAnnotationsList();
4annotList.forEach(annot => {
5 const group = annotationManager.getGroupAnnotations(annot);
6 console.log(group);
7});

Although this will return both the primary and the children annotations, it may be helpful to be able to make a distinction between them. The next sections will cover this.

Using isGrouped

The isGrouped API on annotations will tell you whether the annotation is grouped with another. This will only get you secondary annotations that are grouped to a primary annotation. You can leverage this to determine both the parent and children.

1const { annotationManager } = instance.Core;
2
3const annotList = annotationManager.getAnnotationsList();
4annotList.forEach(annot => {
5 const group = annotationManager.getGroupAnnotations(annot);
6 const parent = group.find(annot => !annot.isGrouped());
7 const children = group.filter(annot => annot.isGrouped());
8
9 // Use annotations
10});

Getting the primary annotation with InReplyTo

Alternatively, you can make use of the InReplyTo property of a grouped secondary annotation along with getAnnotationById on the AnnotationManager to get the primary annotation.

1const primaryAnnotsMap = {};
2groupedAnnots.forEach(annot => {
3 const primary = annotationManager.getAnnotationById(annot.InReplyTo);
4 if (primaryAnnotsMap[primary.Id]) {
5 return;
6 }
7 primaryAnnotsMap[primary.Id] = primary;
8});
9const primaryAnnots = Object.values(primaryAnnotsMap);

Getting grouped children using the primary annotation

If you have the primary annotation of a group, you can use getGroupedChildren to get all the child annotations that are grouped with it. You could also use this to check for a primary annotation.

1const annotList = annotationManager.getAnnotationsList();
2annotList.forEach(primary => {
3 const children = primary.getGroupedChildren();
4 if (children.length > 0) {
5 // This is a primary annotation
6 }
7});

Next steps

Look into how you can create your own annotations!

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales