Custom PDF viewer using javascript

Posted By :Jayant Singh Parmar |28th February 2019

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)

  • index.html
  • docs
    • sample.pdf
  • css
    • style.css
  • js
    • main.js

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. 

 


About Author

Jayant Singh Parmar

Jayant has more than 5+ years of industry experience as a frontend developer. He has good knowledge of technologies like Angular, reactJS, HTML, CSS, javascript etc. He is proficient in building complex UI designs, implentation of complex logics on frontend, API integrations, development and deployments and have been part of successfully delivering services on various client projects like Virgin Media, Hp1t and Jabburr He is a quick learner and keen to learn new technologies.

Request For Proposal

[contact-form-7 404 "Not Found"]

Ready to innovate ? Let's get in touch

Chat With Us