Hi everyone, in this blog, we will learn how to show a PDF document on a web page. We will not only load a PDF file into a web page but also create pagination if it is a multi-page PDF document and also display an error message if a PDF file not found. In this little project, we will use pdf.js to create our custom pdf view interface and pagination using javascript. We will be using modern syntaxes such as arrow functions and promises. So we will keep it very very simple, we will create our script, our HTML, and a little bit of CSS for the file navigation part and showing error messages. So let's get started and create a project structure as listed below.
PDF_viewer (project root)
and that should be for our structure.
We will also use font-awesome so you can quickly grab the CDN.
Now head over to your index.html and add the following code.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous" /> <link rel="stylesheet" href="css/style.css" /> <title>PDF Viewer</title> </head> <body> <div class="top-bar"> <button class="btn" id="prev-page"> <i class="fas fa-arrow-circle-left"></i> Prev Page </button> <button class="btn" id="next-page"> Next Page <i class="fas fa-arrow-circle-right"></i> </button> <span class="page-info"> Page <span id="page-num"></span> of <span id="page-count"></span> </span> </div> <canvas id="pdf-render"></canvas> <script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script> <script src="js/main.js"></script> </body> </html>
At this point, we have not added any CSS. We will do that last. So let's jump into our main.js and add the following code.
const url = '../docs/pdf.pdf'; let pdfDoc = null, pageNum = 1, ageIsRendering = false, pageNumIsPending = null; const scale = 1.5, canvas = document.querySelector('#pdf-render'), ctx = canvas.getContext('2d'); // Render the page const renderPage = num => { pageIsRendering = true; // Get page pdfDoc.getPage(num).then(page => { // Set scale const viewport = page.getViewport({ scale }); canvas.height = viewport.height; canvas.width = viewport.width; const renderCtx = { canvasContext: ctx, viewport }; page.render(renderCtx).promise.then(() => { pageIsRendering = false; if (pageNumIsPending !== null) { renderPage(pageNumIsPending); pageNumIsPending = null; } }); // Output current page document.querySelector('#page-num').textContent = num; }); }; // Check for pages rendering const queueRenderPage = num => { if (pageIsRendering) { pageNumIsPending = num; } else { renderPage(num); } }; // Show Prev Page const showPrevPage = () => { if (pageNum <= 1) { return; } pageNum--; queueRenderPage(pageNum); }; // Show Next Page const showNextPage = () => { if (pageNum >= pdfDoc.numPages) { return; } pageNum++; queueRenderPage(pageNum); }; // Get Document pdfjsLib .getDocument(url) .promise.then(pdfDoc_ => { pdfDoc = pdfDoc_; document.querySelector('#page-count').textContent = pdfDoc.numPages; renderPage(pageNum); }) .catch(err => { // Display error const div = document.createElement('div'); div.className = 'error'; div.appendChild(document.createTextNode(err.message)); document.querySelector('body').insertBefore(div, canvas); // Remove top bar document.querySelector('.top-bar').style.display = 'none'; }); // Button Events document.querySelector('#prev-page').addEventListener('click', showPrevPage); document.querySelector('#next-page').addEventListener('click', showNextPage);
So at this point, everything will be working well. Now we will move on to our styling, so let's head over to your style.css and add the following rules.
* { margin: 0; padding: 0; } .top-bar { background: #333; color: #fff; padding: 1rem; } .btn { background: coral; color: #fff; border: none; outline: none; cursor: pointer; padding: 0.7rem 2rem; } .btn:hover { opacity: 0.9; } .page-info { margin-left: 1rem; } .error { background: orangered; color: #fff; padding: 1rem; }
So from now on, if you have to include a pdf on your website or on your application, you can embed it however you want and have a UI of whatever kind you want which comes in really handy. So that's it for now, I hope you find it useful to implement in a real website or application.