How to Manipulate Annotations Programmatically in Cordova

We provide various wrappers for our SDK, and Cordova is no exception. We are continuously improving our wrapper, so we are glad to announce that we’ve just updated our Cordova plugin to include support for programmatic annotations. You can now add, remove, and query annotations using our Instant JSON format or import and export annotations using an XFDF file.

In this article, we’ll discuss how to programmatically manipulate annotations in your JavaScript code in your Cordova app.

So let’s get started!

Instant JSON

Instant JSON is our approach to bringing annotations into a modern format. Instant JSON stores PDF changes like annotations in a cross-platform compatible and external JSON format. This means that a PDF document will only need to be transferred once and all changes will be added as an overlay to the existing PDF. This approach significantly reduces the bandwidth since you only need to transfer this JSON instead of the full PDF.

Adding Annotations

This is how you can add a single annotation to your document using the Instant JSON Annotation API:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const annotationJSON = {
  bbox: [89.0, 98.0, 143.0, 207.0],
  isDrawnNaturally: false,
  lineWidth: 5,
  lines: {
    intensities: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5]],
    points: [
      [[92.0, 101.0], [92.0, 202.0], [138.0, 303.0]],
      [[184.0, 101.0], [184.0, 202.0], [230.0, 303.0]]
    ]
  },
  opacity: 1,
  pageIndex: 0,
  name: "A167811E-6D10-4546-A147-B7AD775FE8AC",
  strokeColor: "#AA47BE",
  type: "pspdfkit/ink",
  v: 1
};

PSPDFKit.addAnnotation(annotationJSON, function(success, error) {
  if (success) {
    // The annotation has been successfully added.
  }
});

Removing an Annotation

And this is how you can remove an annotation:

Copy
1
2
3
4
5
6
const annotationJSON = ...// Instant JSON annotation payload.
PSPDFKit.removeAnnotation(annotationJSON, function(success, error) {
	if (success) {
		// The annotation has been successfully removed.
	}
});

Querying Annotations

You can get all annotations on a page of a specific type, like so:

Copy
1
2
3
4
5
6
PSPDFKit.getAnnotation(0, "pspdfkit/ink", function(success, error) {
  if (success) {
    // Get all ink annotations on the first page.
    const inkAnnotations = success;
  }
});

If you want to get all annotations on the page, you can pass null as the annotation type parameter:

Copy
1
2
3
4
5
6
PSPDFKit.getAnnotations(0, null, function(success, error) {
  if (success) {
    // Get all annotations on the first page.
    const annotations = success;
  }
});

To get all unsaved annotations on all pages, you can call getAllUnsavedAnnotations, as seen below:

Copy
1
2
3
4
5
6
PSPDFKit.getAllUnsavedAnnotations(function(success, error) {
  if (success) {
    // Get all unsaved annotations in the document.
    const allUnsavedAnnotations = success;
  }
});

As a result, you will get an Instant JSON Document API payload.

Applying the Document Instant JSON Payload

You can apply document changes using the Instant JSON Document API, like so:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const documentJSON = {
  annotations: [
    {
      v: 1,
      createdAt: "2018-07-30T15:34:48Z",
      bbox: [89.0, 98.0, 143.0, 207.0],
      type: "pspdfkit/ink",
      lines: {
        points: [
          [[92.0, 101.0], [92.0, 202.0], [138.0, 303.0]],
          [[184.0, 101.0], [184.0, 202.0], [230.0, 303.0]]
        ],
        intensities: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5]]
      },
      isDrawnNaturally: false,
      strokeColor: "#AA47BE",
      name: "A167811E-6D10-4546-A147-B7AD775FE8AC",
      updatedAt: "2018-07-30T15:34:48Z",
      pageIndex: 0,
      opacity: 1,
      lineWidth: 5,
      blendMode: "normal",
      id: "01CKNX7TVEGWMJDPTS9BN3RH9M"
    },
    {
      v: 1,
      createdAt: "2018-07-30T15:29:54Z",
      creatorName: "John Appleseed",
      lines: {
        points: [
          [
            [243.0, 510.0],
            [244.0, 510.0],
            [258.0, 506.0],
            [295.0, 496.0],
            [349.0, 489.0],
            [365.0, 489.0],
            [393.0, 489.0],
            [406.0, 489.0],
            [411.0, 496.0],
            [411.0, 526.0],
            [389.0, 578.0],
            [375.0, 602.0],
            [364.0, 618.0],
            [354.0, 631.0],
            [349.0, 639.0],
            [351.0, 645.0],
            [392.0, 661.0],
            [477.0, 672.0],
            [557.0, 673.0],
            [591.0, 673.0],
            [616.0, 669.0],
            [635.0, 665.0],
            [642.0, 661.0],
            [642.0, 657.0],
            [638.0, 654.0],
            [632.0, 652.0],
            [625.0, 652.0]
          ]
        ],
        intensities: [
          [
            1,
            1,
            0.78,
            0.43,
            0.19,
            0.77,
            0.58,
            0.82,
            0.86,
            0.56,
            0.16,
            0.59,
            0.72,
            0.75,
            0.86,
            0.9,
            0.38,
            0,
            0,
            0.5,
            0.62,
            0.71,
            0.88,
            0.95,
            0.93,
            0.9,
            0.9
          ]
        ]
      },
      isDrawnNaturally: true,
      strokeColor: "#1E59FF",
      updatedAt: "2018-07-30T15:29:54Z",
      pageIndex: 0,
      name: "1F291E11-0696-436B-A8E5-0386371E07B7",
      opacity: 1,
      note: "",
      lineWidth: 4,
      blendMode: "normal",
      type: "pspdfkit/ink",
      bbox: [243.0, 486.0, 397.0, 188.0],
      id: "01CKNX7TVF7ESF8Z4FR5Q4APEJ"
    }
  ],
  format: "https://pspdfkit.com/instant-json/v1"
};

PSPDFKit.applyInstantJSON(documentJSON, function(success, error) {
  if (success) {
    // The Instant JSON has been successfully applied.
  }
});

This function also allows you to apply multiple annotations at once.

XFDF

XFDF is an XML-like standard from Adobe XFDF for encoding annotations and forms. It is compatible with Adobe Acrobat and PSPDFKit. For more details, please take a look at our XFDF Support documentation.

In the latest version of our Cordova plugin, we’ve added the ability to import and export annotations from XFDF files.

Importing from an XFDF File

You can import annotations from an existing XFDF file like this:

Copy
1
2
3
4
5
PSPDFKit.importXFDF("path/to/your/XFDFFile.xfdf", function(success, error) {
  if (success) {
    // The annotations have been successfully imported.
  }
});

Exporting to an XFDF File

This is how you can export annotations from your document to an XFDF file:

Copy
1
2
3
4
5
PSPDFKit.exportXFDF("path/to/your/XFDFFile.xfdf", function(success, error) {
  if (success) {
    // The annotations have been successfully exported.
  }
});

Conclusion

We’re very excited about the new API additions! If you come across any missing APIs that you think would be useful to have, feel free to contact us or open an issue on the Cordova plugins repositories. You are also very welcome to submit pull requests to help improve our plugins, as they are open source.

PSPDFKit Newsletter

Subscribe to our newsletter for more articles like this.