This sample demonstrates how to implement WebViewer with a Node.js backend and enable save and load user bookmarks.
WebViewer provides a slick out-of-the-box responsive UI that enables you to view, annotate and manipulate PDFs and other document types inside any web project.
Click the button below to view the full project in GitHub.
1var viewerElement = document.getElementById('viewer');
2var DOCUMENT_ID = 'webviewer-demo-1';
3
4WebViewer({
5 path: 'lib',
6 initialDoc: './webviewer-demo.pdf',
7 // ui: 'legacy',
8}, viewerElement).then((instance) => {
9
10 instance.UI.addEventListener('userBookmarksChanged', e => {
11 const bookmarks = e.detail;
12 const bookmarksString = JSON.stringify(bookmarks);
13 saveBookmarksString(DOCUMENT_ID, bookmarksString).then(() => {
14 console.log('Bookmarks saved successfully.');
15 });
16 });
17
18 const onSaveBookmarks = () => {
19 const bookmarks = instance.UI.exportBookmarks();
20 const bookmarksString = JSON.stringify(bookmarks);
21 saveBookmarksString(DOCUMENT_ID, bookmarksString).then(() => {
22 alert('Bookmarks saved successfully.');
23 });
24 };
25
26 /** Legacy UI: Uncomment this to add a save button to the header */
27 // instance.UI.enableElements(['bookmarksPanel', 'bookmarksPanelButton']);
28 // instance.UI.setHeaderItems((header) => {
29 // header.push({
30 // type: 'actionButton',
31 // img: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
32 // onClick: onSaveBookmarks,
33 // });
34 // });
35 /** End of Legacy UI */
36
37
38 /** Modular UI: Add a save button to the header */
39 // Comment this out on legacy UI
40 const saveButton = new instance.UI.Components.CustomButton({
41 dataElement: 'customButton',
42 title: 'Save Bookmarks',
43 onClick: onSaveBookmarks,
44 img: 'icon-save',
45 });
46 const defaultHeader = instance.UI.getModularHeader('default-top-header');
47 defaultHeader.setItems([...defaultHeader.getItems(), saveButton]);
48 /** End of Modular UI */
49
50
51 // Load bookmarks when document is loaded
52 instance.Core.documentViewer.addEventListener('documentLoaded', () => {
53 loadBookmarksString(DOCUMENT_ID).then((bookmarksString = '') => {
54 const bookmarks = JSON.parse(bookmarksString);
55 instance.UI.importBookmarks(bookmarks);
56 });
57 });
58});
59
60
61// Make a POST request with bookmarks string
62const saveBookmarksString = (documentId, bookmarksString) => {
63 return new Promise((resolve) => {
64 fetch(`/server/bookmarksHandler.js?documentId=${documentId}`, {
65 method: 'POST',
66 body: bookmarksString
67 }).then((response) => {
68 if (response.status === 200) {
69 resolve();
70 }
71 });
72 });
73};
74
75// Make a GET request to get bookmarks string
76const loadBookmarksString = (documentId) => {
77 return new Promise((resolve) => {
78 fetch(`/server/bookmarksHandler.js?documentId=${documentId}`, {
79 method: 'GET'
80 }).then((response) => {
81 if (response.status === 200) {
82 response.text().then((bookmarksString) => {
83 resolve(bookmarksString);
84 })
85 }
86 });
87 });
88};
89
1const path = require('path');
2const fs = require('fs');
3
4module.exports = (app) => {
5 // Create xfdf folder if it doesn't exist
6 if (!fs.existsSync('server/bookmarks')) {
7 fs.mkdirSync('server/bookmarks');
8 }
9
10 // Handle POST request sent to '/server/bookmarksHandler.js'
11 app.post('/server/bookmarksHandler.js', (request, response) => {
12 const bookmarksFile = path.resolve(__dirname, `./bookmarks/${request.query.documentId}.json`);
13
14 try {
15 // Write XFDF string into an XFDF file
16 response.status(200).send(fs.writeFileSync(bookmarksFile, request.body));
17 } catch(e) {
18 response.status(500).send(`Error writing bookmarks data to ${bookmarksFile}`);
19 }
20 response.end();
21 });
22
23 // Handle GET request sent to '/server/bookmarksHandler.js'
24 app.get('/server/bookmarksHandler.js', (request, response) => {
25 const bookmarksFile = path.resolve(__dirname, `./bookmarks/${request.query.documentId}.json`);
26
27 if (fs.existsSync(bookmarksFile)) {
28 response.header('Content-Type', 'text/xml');
29 // Read from the XFDF file and send the string as a response
30 response.status(200).send(fs.readFileSync(bookmarksFile));
31 } else {
32 response.status(204).send(`${bookmarksFile} is not found.`);
33 }
34 response.end();
35 });
36}
37
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales