PDF Page Manipulation API - Showcase Demo Code Sample

Requirements
View Demo

Easily perform changes to PDF pages, including split, merge, append, replicate, reorder, and more.

This demo allows you to:

  • Choose your own PDF file
  • Perform programmatic page manipulation:
    • Split
    • Merge
    • Append
    • Replicate
    • Reorder
    • and more
  • Download edited document

Implementation steps

To add PDF Page Manipulation capability with WebViewer:
Step 1: Get started with WebViewer in your preferred web stack
Step 2: Add the ES6 JavaScript sample code provided in this guide

1
2// ES6 Compliant Syntax
3// GitHub Copilot - GPT-4 Model - October 16, 2025
4// File: pdf-page-manipulation-api/index.js
5
6import WebViewer from '@pdftron/webviewer';
7import { saveAs } from 'file-saver';
8// Global variables
9const element = document.getElementById('viewer');
10let instance = null;
11
12// Initialize WebViewer
13function initializeWebViewer() {
14 if (!element) {
15 console.error('Viewer div not found.');
16 return;
17 }
18 // Initialize WebViewer
19 WebViewer({
20 path: '/lib',
21 licenseKey: 'YOUR_LICENSE_KEY',
22 initialDoc: 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/WebviewerDemoDoc.pdf',
23 enableFilePicker: true, // Enable file picker to open files. In WebViewer -> menu icon -> Open File
24 }, element).then((inst) => {
25 instance = inst;
26 const { documentViewer} = instance.Core;
27 documentViewer.addEventListener('documentLoaded', () => {
28 const doc = documentViewer.getDocument();
29 console.log(`Document loaded with ${doc.getPageCount()} pages.`);
30 createUIElements().then(() => {
31 // Now initialize rotateAngle options values (after UI elements are created)
32 if (window.rotateAngle) {
33 window.rotateAngle.children[0].value = instance.Core.PageRotation.E_90;
34 window.rotateAngle.children[1].value = instance.Core.PageRotation.E_180;
35 window.rotateAngle.children[2].value = instance.Core.PageRotation.E_270;
36 } else {
37 console.error('rotateAngle element not found after UI creation');
38 }
39 // activate thumbnails panel
40 instance.UI.openElements(['tabPanel']);
41 instance.UI.setActiveTabInPanel({ tabPanel: 'tabPanel', tabName: 'thumbnailsPanel' });
42 });
43 });
44 });
45} // Close initializeWebViewer function
46
47// validate page number input
48const validPageNumber = (pageNum, doc) => {
49 if (pageNum > doc.getPageCount() || pageNum < 1) {
50 alert('Please enter a valid page number.');
51 return false;
52 }
53 return true;
54}
55
56// convert a string like "1,2,5-7" to an array of numbers [1,2,5,6,7]
57const parseStringToNumberArray = (val, maxVal) => {
58 // check for valid number, comma, or dash pattern
59 if (!/^[0-9]+([,-][0-9]+)*$/.test(val)) {
60 return [];
61 }
62 const numbers = [];
63 val.split(',').forEach((group) => {
64 const range = group.split('-');
65 const start = Number(range[0]);
66 let end = Number(range.length === 1 ? range[0] : range[1]);
67 if (end > maxVal) {
68 end = maxVal;
69 }
70 for (let i = start; i <= end; i++) {
71 numbers.push(i);
72 }
73 });
74 return numbers;
75}
76
77// delete specified pages from document
78const deletePages = () => {
79 const doc = instance.Core.documentViewer.getDocument();
80 const pageNumbers = pagesRange.value;
81 const result = parseStringToNumberArray(pageNumbers, doc.getPageCount());
82 if (!validPageNumber(pageNumbers, doc)) return;
83 if (result.length === doc.getPageCount()) {
84 alert('Cannot delete all pages in the document.');
85 return;
86 }
87 if (result.length > 0) {
88 doc.removePages(result);
89 } else {
90 alert('Please enter a comma or dash separated list of valid page numbers ex 1,2,3-5 for the first 5 pages');
91 }
92}
93
94// rotate specified pages in document
95const rotatePages = () => {
96 const pageNumbers = pagesRange.value;
97 const rotation = Number(rotateAngle.value);
98 const doc = instance.Core.documentViewer.getDocument();
99 if (!validPageNumber(pageNumbers, doc)) return;
100 let result = [];
101 if (pageNumbers) {
102 result = parseStringToNumberArray(pageNumbers, doc.getPageCount());
103 } else {
104 // No page numbers provided, rotating all pages
105 for (let i = 1; i <= doc.getPageCount(); i++) {
106 result.push(i);
107 }
108 }
109 if (result.length > 0) {
110 doc.rotatePages(result, rotation);
111 } else {
112 alert('Please enter a comma or dash separated list of valid page numbers ex 1,2,3-5 for the first 5 pages');
113 }
114}
115
116// move a page to a new location in the document
117const movePage = () => {
118 const doc = instance.Core.documentViewer.getDocument();
119 const pageOne = Number(pageInput.value);
120 let pageTwo = Number(locationInput.value);
121 if (!validPageNumber(pageOne, doc) || !validPageNumber(pageTwo, doc)) return;
122 if (pageOne < pageTwo) pageTwo++; // adjust for removing the "from" page
123 doc.movePages([pageOne], pageTwo);
124}
125
126// insert a blank page at the specified location
127const insertBlankPage = () => {
128 let pageNumber = Number(pageInput.value);
129 const doc = instance.Core.documentViewer.getDocument();
130 if (pageNumber === -1) { // append to end
131 pageNumber = doc.getPageCount() + 1;
132 } else if (!validPageNumber(pageNumber, doc)) return;
133 const pageSize = doc.getPageInfo(1);
134 doc.insertBlankPages([pageNumber], pageSize.width, pageSize.height);
135}
136
137// extract specified pages from document and save as a new file
138const extractPages = async () => {
139 const pageNumbers = pagesRange.value;
140 const doc = instance.Core.documentViewer.getDocument();
141 const pageCount = doc.getPageCount();
142 if (!validPageNumber(pageNumbers, doc)) return;
143 let pagesToExtract = [];
144 if (pageNumbers) {
145 pagesToExtract = parseStringToNumberArray(pageNumbers, pageCount);
146 } else {
147 for (let i = 1; i <= pageCount; i++) {
148 pagesToExtract.push(i);
149 }
150 }
151 if (pagesToExtract.length > 0) {
152 const annotList = instance.Core.annotationManager.getAnnotationsList().filter((annot) => pagesToExtract.indexOf(annot.PageNumber) > -1);
153 const xfdfString = await instance.Core.annotationManager.exportAnnotations({ annotationList: annotList });
154 doc.extractPages(pagesToExtract, xfdfString).then((data) => {
155 const arr = new Uint8Array(data);
156 const blob = new Blob([arr], { type: 'application/pdf' });
157 saveAs(blob, 'extracted.pdf');
158 });
159 } else {
160 alert('Please enter a comma or dash separated list of valid page numbers ex 1,2,3-5 for the first 5 pages');
161 }
162}
163
164// crop the specified page by the specified pixel amounts from 4 sides
165const cropPage = () => {
166 const pageNumber = Number(pageInput.value);
167 const doc = instance.Core.documentViewer.getDocument();
168 if (!validPageNumber(pageNumber, doc)) return;
169 const top = Number(cropTop.value);
170 const bottom = Number(cropBottom.value);
171 const left = Number(cropLeft.value);
172 const right = Number(cropRight.value);
173 doc.cropPages([pageNumber], top, bottom, left, right);
174}
175
176// merge an uploaded document into the current document at the specified location
177const mergeDocuments = () => {
178 if (!window.newDoc) {
179 alert('Please upload a document to merge first');
180 return;
181 }
182 const pageNumbers = pagesRange.value;
183 let pagesToInsert = [];
184 if (pageNumbers) {
185 pagesToInsert = parseStringToNumberArray(pageNumbers, window.newDoc.getPageCount());
186 } else {
187 for (let i = 1; i <= window.newDoc.getPageCount(); i++) {
188 pagesToInsert.push(i);
189 }
190 }
191 const locationToInsert = Number(locationInput.value);
192 if (pagesToInsert.length > 0) {
193 instance.Core.documentViewer.getDocument().insertPages(window.newDoc, pagesToInsert, locationToInsert);
194 } else {
195 alert('Please enter a comma or dash separated list of valid page numbers ex 1,2,3-5 for the first 5 pages');
196 }
197}
198
199// Expose functions to global scope for UI elements
200window.deletePages = deletePages;
201window.rotatePages = rotatePages;
202window.movePage = movePage;
203window.insertBlankPage = insertBlankPage;
204window.extractPages = extractPages;
205window.cropPage = cropPage;
206window.mergeDocuments = mergeDocuments;
207window.parseStringToNumberArray = parseStringToNumberArray;
208window.validPageNumber = validPageNumber;
209
210// UI Elements
211// Function to create and initialize UI elements
212function createUIElements() {
213 return new Promise((resolve) => {
214 // Create a container for all controls (label, dropdown, and buttons)
215 // Dynamically load ui-elements.js if not already loaded
216 if (typeof UIElements === 'undefined') {
217 const script = document.createElement('script');
218 script.src = '/showcase-demos/pdf-page-manipulation-api/ui-elements.js';
219 script.onload = () => {
220 console.log('ui-elements.js loaded successfully');
221 UIElements.init(instance);
222 resolve(); // Resolve when UI elements are created
223 };
224 script.onerror = () => {
225 console.error('Failed to load ui-elements.js');
226 resolve(); // Resolve even on error to prevent hanging
227 };
228 document.head.appendChild(script);
229 } else {
230 console.log('UIElements already available, initializing...');
231 UIElements.init(instance);
232 resolve(); // Resolve immediately if UIElements is already loaded
233 }
234 });
235}
236
237// Initialize WebViewer when the window loads
238initializeWebViewer();

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales