Easy Web PDF Viewer With jQuery And pdf.js - pdfjs-viewer

File Size: 46.6 KB
Views Total: 5872
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Easy Web PDF Viewer With jQuery And pdf.js - pdfjs-viewer

As web developers, we are always on the lookout for new ways to improve our user's experience. That's why I'm excited to share with you a new jQuery plugin called pdfjs-viewer.

This plugin is based on mozilla's pdf.js library, and provides a simple way for your users to view PDF documents directly in their web browser.

In this tutorial, I'll show you how to install and use the pdfjs-viewer jQuery plugin, as well as some of its features. So let's get started!

How to use it:

1. Load the necessary jQuery and pdf.js libraries in the document.

<script src="/path/to/cdn/jquery.min.js"></script>
<script src="/path/to/cdn/pdf.min.js"></script>

2. Load the OPTIONAL Material Icons.

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet">

3. Load the pdfjs-viewer plugin's files.

<!-- Core -->
<script src="/js/pdfjs-viewer.js"></script>
<link rel="stylesheet" href="/css/pdfjs-viewer.css">
<!-- Optional Toolbar Stylesheet -->
<link rel="stylesheet" href="/css/pdftoolbar.css">

4. Initialize the pdf.js library.

// Let's initialize the PDFjs library
var pdfjsLib = window['pdfjs-dist/build/pdf'];

// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';

5. Emebd a PDF viewer in an HTML element you specify.

<div class="pdfpages">
  <div class="pdfpage placeholder">
    <p>No file loaded</p>
  </div>
</div>
// override the PDF path
let PDFFILE="test.pdf";

let pdfViewer = new PDFjsViewer($('.pdfpages'));
pdfViewer.loadDocument(PDFFILE).then(function() {
  pdfViewer.setZoom("fit");
});

5. Add a custom toolbar to the PDF viewer.

<div class="pdftoolbar">
  <button class="btn-first" onclick="pdfViewer.first()"><i class="material-icons-outlined">skip_previous</i></button>
  <button class="btn-prev" onclick="pdfViewer.prev(); return false;"><i class="material-icons-outlined">navigate_before</i></button>
  <span class="pageno"></span>
  <button class="btn-next" onclick="pdfViewer.next(); return false;"><i class="material-icons-outlined">navigate_next</i></button>
  <button class="btn-last" onclick="pdfViewer.last()"><i class="material-icons-outlined">skip_next</i></button>

  <button onclick="pdfViewer.setZoom('out')"><i class="material-icons-outlined">zoom_out</i></button>
  <span class="zoomval">100%</span>
  <button onclick="pdfViewer.setZoom('in')"><i class="material-icons-outlined">zoom_in</i></button>
  <button class="ms-3" onclick="pdfViewer.setZoom('width')"><i class="material-icons-outlined">swap_horiz</i></button>
  <button onclick="pdfViewer.setZoom('height')"><i class="material-icons-outlined">swap_vert</i></button>
  <button onclick="pdfViewer.setZoom('fit')"><i class="material-icons-outlined">fit_screen</i></button>
</div>
let pdfViewer = new PDFjsViewer($('.pdfjs-viewer'), {
    onZoomChange: function(zoom) {
        zoom = parseInt(zoom * 10000) / 100;
        $('.zoomval').text(zoom + '%');
    },
    onActivePageChanged: function(page, pageno) {
        $('.pageno').text(pageno + '/' + this.getPageCount());
    },
});
pdfViewer.loadDocument("test.pdf").then(function() {
    pdfViewer.setZoom('fit');
});

6. This example shows how to create a fullscreen PDF viewer with thumbnail support.

<!-- Toolbar -->
<div class="pdftoolbar">
  <button class="" onclick="pdfViewer.prev();"><i class="material-icons-outlined">arrow_upward</i></button>
  <div class="v-sep"></div>
  <button class="" onclick="pdfViewer.next();"><i class="material-icons-outlined">arrow_downward</i></button>
  <input id="pageno" class="pageno" type="number" class="form-control form-control-sm d-inline w-auto" value="1" min="1" max="1000" onchange="pdfViewer.scrollToPage(parseInt(this.value))">
  <span id="pagecount" class="pageno"></span>
  <div class="divider"></div>
  <button onclick="setZoom('in')"><i class="material-icons-outlined">add</i></button>
  <div class="v-sep"></div>
  <button onclick="setZoom('out')"><i class="material-icons-outlined">remove</i></button>
  <div class="dropdown">
    <div class="dropdown-value" onclick="this.parentNode.classList.toggle('show');">
      <span class="zoomval">100%</span>
      <i class="material-icons-outlined">
        keyboard_arrow_down
      </i>                    
    </div>
    <div class="dropdown-content" onclick="this.parentNode.classList.toggle('show');">
      <a href="#" data-zoom="width" onclick='setZoom(this); return false;'>Adjust width</a>
      <a href="#" data-zoom="height" onclick='setZoom(this); return false;'>Adjust height</a>
      <a href="#" data-zoom="fit" onclick='setZoom(this); return false;'>Fit page</a>
      <a href="#" data-zoom="0.5" onclick='setZoom(this); return false;'>50%</a>
      <a href="#" data-zoom="0.75" onclick='setZoom(this); return false;'>75%</a>
      <a href="#" data-zoom="1" onclick='setZoom(this); return false;'>100%</a>
      <a href="#" data-zoom="1.25" onclick='setZoom(this); return false;'>125%</a>
      <a href="#" data-zoom="1.5" onclick='setZoom(this); return false;'>150%</a>
      <a href="#" data-zoom="2" onclick='setZoom(this); return false;'>200%</a>
      <a href="#" data-zoom="3" onclick='setZoom(this); return false;'>300%</a>
      <a href="#" data-zoom="4" onclick='setZoom(this); return false;'>400%</a>
    </div>                    
  </div>
  <div class="divider"></div>
  <button class="btn-first" onclick="window.open(PDFFILE, '_blank')"><i class="material-icons-outlined">file_download</i></button>
  <div class="dropdown dropdown-right">
    <div onclick="this.parentNode.classList.toggle('show');">
      <button><i class="material-icons-outlined">keyboard_double_arrow_right</i></button>
    </div>
    <div class="dropdown-content" onclick="this.parentNode.classList.toggle('show');">
      <a href="#" onclick='pdfViewer.scrollToPage(1); return false;'><i class="material-icons-outlined">vertical_align_top</i>First page</a>
      <a href="#" onclick='pdfViewer.scrollToPage(pdfViewer.pdf.numPages); return false;'><i class="material-icons-outlined">vertical_align_bottom</i>Last page</a>
      <div class="h-sep"></div>
      <a href="#" onclick='document.querySelector(".pdfpages").classList.remove("horizontal-scroll"); pdfViewer.refreshAll();'><i class="material-icons-outlined">more_vert</i>Vertical scroll</a>
      <a href="#" onclick='setHorizontal()'><i class="material-icons-outlined">more_horiz</i>Horizontal scroll</a>
    </div>                    
  </div>                
</div>
<!-- Thumbnail -->
<div class="thumbnails">
</div>
<div class="hider">
  <a class="my-auto fold" href="#" onclick="hidethumbs(); return false;">
    <i class="material-icons-outlined">keyboard_double_arrow_left</i>
  </a>
  <a class="my-auto unfold" href="#" onclick="showthumbs(); return false;">
    <i class="material-icons-outlined">keyboard_double_arrow_right</i>
  </a>
</div>

<!-- PDF viewer -->
<div class="pdfpages">
  <div class="pdfpage placeholder">
    <p>No file loaded</p>
  </div>
</div>  
let PDFFILE="test.pdf";
function dataURItoBinArray(data) {
    // taken from: https://stackoverflow.com/a/11954337/14699733
    var binary = atob(data);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Uint8Array(array);
}
/** Function to load a PDF file using the input=file API */
document.querySelector("#opendoc").addEventListener("change", function(e) {
    let file = e.target;
    let reader = new FileReader();
    reader.onload = async function() {
        await pdfViewer.loadDocument({data: dataURItoBinArray(reader.result.replace(/^data:.*;base64,/,""))});
        await pdfThumbnails.loadDocument({data: dataURItoBinArray(reader.result.replace(/^data:.*;base64,/,""))}).then(() => pdfThumbnails.setZoom("fit"));
    }
    if (file.files.length > 0) {
        reader.readAsDataURL(file.files[0]);
        document.querySelector('#filedownload').download = document.querySelector('#opendoc').files[0].name;
    }
});
/** Sets the document in horizontal scroll by changing the class for the pages container and refreshing the document 
 *    so that the pages may be displayed in horizontal scroll if they were not visible before */
function setHorizontal() {
    document.querySelector(".maindoc").classList.add("horizontal-scroll"); 
    pdfViewer.refreshAll();    
}
/** Toggles the visibility of the thumbnails */
function togglethumbs(el) {
    if (el.classList.contains('pushed')) {
        el.classList.remove('pushed');
        document.querySelector('.thumbnails').classList.add('hide');
    } else {
        el.classList.add('pushed');
        document.querySelector('.thumbnails').classList.remove('hide');
    }
}
/** Now create the PDFjsViewer object in the DIV */
let pdfViewer = new PDFjsViewer($('.maindoc'), {
    zoomValues: [ 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4 ],

    /** Update the zoom value in the toolbar */
    onZoomChange: function(zoom) {
        zoom = parseInt(zoom * 10000) / 100;
        $('.zoomval').text(zoom + '%');
    },

    /** Update the active page */
    onActivePageChanged: function(page) {
        let pageno = $(page).data('page');
        let pagetotal = this.getPageCount();

        pdfThumbnails.setActivePage(pageno);
        $('#pageno').val(pageno);
        $('#pageno').attr('max', pagetotal);
        $('#pagecount').text('de ' + pagetotal);
    },

    /** zoom to fit when the document is loaded and create the object if wanted to be downloaded */
    onDocumentReady: function () {
        pdfViewer.setZoom('fit');
        pdfViewer.pdf.getData().then(function(data) {
            document.querySelector('#filedownload').href = URL.createObjectURL(new Blob([data], {type: 'application/pdf'}));
            document.querySelector('#filedownload').target = '_blank';
        });
    }
});

/** Load the initial PDF file */
pdfViewer.loadDocument(PDFFILE).then(function() {
    document.querySelector('#filedownload').download = PDFFILE;
});

/** Create the thumbnails */
let pdfThumbnails = new PDFjsViewer($('.thumbnails'), {
    zoomFillArea: 0.7,
    onNewPage: function(page) {
        page.on('click', function() {
            if (!pdfViewer.isPageVisible(page.data('page'))) {
                pdfViewer.scrollToPage(page.data('page'));
            }
        })
    },
    onDocumentReady: function() {
        this.setZoom('fit');
    }
});

pdfThumbnails.setActivePage = function(pageno) {
    this.$container.find('.pdfpage').removeClass('selected');
    let $npage = this.$container.find('.pdfpage[data-page="' + pageno + '"]').addClass('selected');
    if (!this.isPageVisible(pageno)) {
        this.scrollToPage(pageno);
    }
}.bind(pdfThumbnails);

pdfThumbnails.loadDocument(PDFFILE);

7. All default options.

let pdfViewer = new PDFjsViewer($('.pdfpages'), {
    visibleThreshold: .5,
    extraPagesToLoad: 3,
    pageClass: "pdfpage",
    zoomValues: [ .25, .5, .75, 1, 1.25, 1.5, 2, 4, 8 ],
    zoomFillArea: .95,
    contentClass: "content-wrapper",
    // callbacks
    onDocumentReady: () => {},
    onNewPage: (page, i) => {},
    onPageRender: (page, i) => {},
    errorPage: () => {
      $(`<div class="placeholder"></div>`).addClass(this.settings.pageClass).append($(`<p class="m-auto"></p>`).text("could not load document"));
    },
    onZoomChange: zoomlevel => {},
    onActivePageChanged: (page, i) => {},
    // function to handle empty content
    emptyContent: () => $('<div class="loader"></div>')
});

8. API methods.

// load a PDF file and returns a promise
// the document can be either an url or a bin array.
pdfViewer.loadDocument(document);

// force re-init
pdfViewer.forceViewerInitialization();

// refresh all pages
pdfViewer.refreshAll();

// get the active page
pdfViewer.getActivePage();

// go to the first page
pdfViewer.first();

// go to the last page
pdfViewer.last();

// go to the next page
pdfViewer.next();

// back to the previous page
pdfViewer.prev();

// get the number of pages
pdfViewer.getPageCount();

// retrieve all the pages of the document
pdfViewer.getPages();

// go to a specific page
pdfViewer.scrollToPage(i);

// check if the page is visible
isPageVisible(i);

// set zoom level
// it is possible to use a float value which represents a fraction or a keyword 'in', 'out', 'width', 'height' or 'fit'
pdfViewer.setZoom(zoom);

// get the current zoom level
pdfViewer.getZoom();

// rotate the pages
pdfViewer.rotate(deg, accumulate = false);

Changelog:

2021-12-24

  • v1.0.0

This awesome jQuery plugin is developed by dealfonso. For more Advanced Usages, please check the demo page or visit the official website.