How to use and extend Mozilla's PDF.js Viewer

For the past few weeks, I've been working on adding PDF support to our Mediathread media analysis and annotation tool. Mediathread already works with images, video, and audio files, and we've been talking about making a PDF annotator within this tool for at least 5 years.

Screenshot of Mediathread's PDF annotator
Mediathread's new PDF annotator

At the moment, Mozilla maintains the state of the art for rendering PDF files in JavaScript: PDF.js. This is what's used when you open a PDF file in Firefox. You can embed this viewer in any web application. I haven't found much documentation, but the pieces are all here in Mozilla's repository: https://github.com/mozilla/pdf.js

There is some documentation on how to use the PDF.js library in a web application, but I haven't found much on embedding and using Mozilla's viewer along with it. These are my notes I've discovered along the way, through sorting all this out.

If you're embedding this viewer inside a surrounding layout, it's best to use an iframe embed instead of just throwing these DOM elements inside the view. The viewer relies on some styling that makes it difficult to embed otherwise: https://github.com/mozilla/pdf.js/issues/11626

Here's an overview of the pieces you'll need:

And then you'll need the compiled PDF.js files from the latest pdfjs-dist.zip, or build PDF.js yourself:

You need to connect all these pieces in your customized viewer.html template. See Mediathread's viewer template for a working example.

You'll need to tell pdf.js which PDF to load:

<script>
 window.PDFViewerApplication.baseUrl = window.ASSET_URL;
</script>

I'm creating an annotation tool on top of PDF.js, so I need to run initialization code after the PDF.js viewer is done starting up and loading the PDF. You can use the PDFViewerApplication.initializedPromise and the viewer's eventBus like this, to start any custom code at the right time:

// Wait for the PDFViewerApplication to initialize
// https://stackoverflow.com/a/68489111/173630
PDFViewerApplication.initializedPromise.then(function() {
    PDFViewerApplication.eventBus.on('pagerendered', function(e) {
        // The viewer is done loading, put custom init code here.
    });
});

This should be enough to get you started. I hope to eventually get a guide into Mozilla's documentation to make this PDF Viewer more approachable.