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.

Once you generate your license key, it will automatically be included in your sample code below.

License Key

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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales