Display Files in the Document Viewer - NodeJS and TypeScript

This tutorial shows how to create a NodeJS Web application with TypeScript that uses the LEADTOOLS SDK to load a document in the HTML5 JavaScript Document Viewer.

Overview  
Summary This tutorial covers how to use LEADTOOLS Document Viewer SDK technology in a NodeJS Web Application with TypeScript.
Completion Time 15 minutes
Visual Studio Project Download tutorial project (30 KB)
Platform NodeJS NPM Project
IDE Visual Studio Code - Client
Runtime License Download LEADTOOLS
Try it in another language

Required Knowledge

Get familiar with the basic steps of creating a project by reviewing the Add References and Set a License - NodeJS and TypeScript tutorial before working on the Display Files in the Document Viewer - NodeJS and TypeScript tutorial.

The tutorial uses a text editor such as Visual Studio Code to create and modify the necessary script files.

Execute commands in this tutorial using PowerShell/CommandPrompt (if using Windows) or a terminal window (if using a Unix-based system).

Create the Project and Install Required Dev Dependencies

Start with a copy of the project created in the Add References and Set a License - NodeJS and TypeScript tutorial. If that project is unavailable, follow the steps in that tutorial to create it.

Make sure that the required dependencies are installed by running the npm install command.

Rename lt.MyModule in the .\ts\App\SetLicense.ts and the .\ts\Index.ts scripts to lt.DocumentViewer.

Add LEADTOOLS References

The references needed depend upon the purpose of the project. References can be added by .js files located at <INSTALL_DIR>\LEADTOOLS23\Bin\JS.

For this project, the following references are needed:

Copy these files to the project's .\site\Common folder.

For a complete list of which JS files are required for your application, refer to Files to be Included with your Application

In addition, the following type definition files are needed for use with TypeScript:

These can be found in the same folder as the .js files at <INSTALL_DIR>\LEADTOOLS23\Bin\JS

Copy these files to the project's .\leadtools_modules\@types folder.

The Leadtools.Document.d.ts type definition script also requires jQuery type definitions, these are included in the toolkit at <INSTALL_DIR>\LEADTOOLS23\Bin\JS\ThirdParty\jquery. Copy the jquery.d.ts file to the project's .\leadtools_modules\@types folder and place it in a ThirdParty\jquery sub-folder.

After copying the type definition script files, edit the .\ts\tsconfig.json file and add the files to the types value:

{ 
   "compilerOptions": { 
      "target": "es5", 
      "module": "none", 
      "outDir": "../site", 
      "types": [ 
         "../leadtools_modules/@types/Leadtools.Annotations.Automation", 
         "../leadtools_modules/@types/Leadtools.Annotations.Designers", 
         "../leadtools_modules/@types/Leadtools.Annotations.Engine", 
         "../leadtools_modules/@types/Leadtools.Controls", 
         "../leadtools_modules/@types/Leadtools", 
         "../leadtools_modules/@types/Leadtools.Document", 
         "../leadtools_modules/@types/Leadtools.Document.Viewer", 
         "../leadtools_modules/@types/ThirdParty/jquery/jquery" 
      ] 
   } 
} 

Add and Set the license files

The License unlocks the features needed for the project. It must be set before any toolkit function is called. For details including tutorials for different platforms, refer to Setting a Runtime License.

There are two types of runtime licenses:

Copy and paste the LEADTOOLS.lic.txt license file into the .\site\LEADTOOLS folder. Note that the licenses ending in .txt are for JavaScript. The license files that do not end in .txt are for server and desktop applications. The license files can be found in the following directory: <INSTALL_DIR>\LEADTOOLS23\Support\Common\License

Replace the key value from the LEADTOOLS.lic.key.txt file in the .\ts\App\SetLicense.ts script.

Add the Document Viewer HTML Elements

With the project created, dependencies added, and the license set, coding can begin.

Open the .\site\Index.html file in an editor. Use the following lines to import the JS files and attach the dependencies to the Index.html page.

<!-- External .js files --> 
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> 
<!-- Leadtools .js files --> 
<script src="Common/Leadtools.js"></script> 
<script src="Common/Leadtools.Controls.js"></script> 
<script src="Common/Leadtools.Annotations.Engine.js"></script> 
<script src="Common/Leadtools.Annotations.Designers.js"></script> 
<script src="Common/Leadtools.Annotations.Rendering.JavaScript.js"></script> 
<script src="Common/Leadtools.Annotations.Automation.js"></script> 
<script src="Common/Leadtools.Document.js"></script> 
<script src="Common/Leadtools.Document.Viewer.js"></script> 
<!-- DocumentViewer .js fies --> 
<script src="App/SetLicense.js"></script> 
<script src="App/DocumentViewerApp.js"></script> 
<script src="Index.js"></script> 

Add the HTML elements that will be used as containers for the following components of the document viewer:

In addition, add a navigationbar element that will contain buttons to toggle between the thumbnail and bookmark containers.

<div id="navigationbar" class="navigationbar"> 
    <button id="showThumbnails" class="navigationbarBtn"> 
        <span class="icon thumbnailsIcon"></span> 
    </button> 
    <button id="showBookmarks" class="navigationbarBtn"> 
        <span class="icon bookmarksIcon"></span> 
    </button> 
</div> 
 
<div id="thumbnailsControl" class="affectedContainers"> 
    <div class="controlHeader"> 
        <label>Pages</label> 
    </div> 
    <div id="thumbnails"> 
    </div> 
</div> 
 
<div id="bookmarksControl" class="affectedContainers"> 
    <div class="controlHeader"> 
        <label>Bookmarks</label> 
    </div> 
    <div id="bookmarks"> 
    </div> 
</div> 
 
<div id="imageViewerContainer" class="affectedContainers"> 
    <!-- The viewer will be dynamically created inside imageViewerDiv --> 
    <div id="imageViewerDiv"> 
    </div> 
</div> 

The affectedContainers class is used for selecting elements that will adjust their display according to the size of the browser window. The navigationbar class is used in a similar way to adjust the display of the imageViewerContainer when the bookmark or thumbnails controls are toggled.

Modify the StyleSheet file

Create a CSS folder in the site directory and create a new style sheet CSS file called documentViewer.css.

Use this file to specify the display styles for the HTML elements of the document viewer using the code below:

/* Document Viewer styles 
-------------------------------------------------- */ 
body { 
   height: 100%; 
   background: white; 
   overflow: hidden; 
   color: #4D5F82; 
   height: 100%; 
   margin: 0; 
   -webkit-text-size-adjust: none; 
   font-family: helvetica; 
   font-size: 10pt; 
   margin-bottom: 60px; 
   display: block; 
} 
 
.navigationbar { 
   overflow: hidden; 
   position: fixed; 
   background-color: #DFE1E5; 
   display: block; 
   width: 40px; 
   left: 0px; 
   bottom: 0px; 
   top: 0px; 
   border-right: 1px solid; 
   border-right-color: #D4D6DB; 
   -webkit-box-shadow: 2px 0px 7px rgba(0, 0, 0, 0.3); 
   box-shadow: 2px 0px 7px rgba(0, 0, 0, 0.3); 
   z-index: 1; 
} 
 
   .navigationbar .icon { 
      width: 34px; 
   } 
 
.navigationbarBtn { 
   padding: 7px 0px 8px 0px; 
   width: 100%; 
   background-color: transparent; 
   border: 1px solid transparent; 
   border-right: 0; 
   outline: none; 
   width: 39px; 
   height: 45px; 
   -webkit-box-sizing: border-box; 
   -moz-box-sizing: border-box; 
   box-sizing: border-box; 
} 
 
.activeNavigationbarBtn { 
   background-color: #D4D6DB; 
   border-color: darkgray; 
} 
 
.icon { 
   position: relative; 
   display: inline-block; 
   background-repeat: no-repeat; 
   background-position: center; 
   width: 35px; 
   height: 25px; 
   top: 3px; 
} 
 
.thumbnailsIcon { 
   background-image: url("../resources/images/icons/Thumbnails.png"); 
} 
 
.bookmarksIcon { 
   background-image: url("../resources/images/icons/Bookmarks.png"); 
} 
 
 
#imageViewerContainer { 
   overflow: hidden; 
   position: fixed; 
   display: block; 
   left: 0px; 
   right: 0px; 
   bottom: 0px; 
   top: 0px; 
} 
 
#imageViewerDiv { 
   position: relative; 
   width: 100%; 
   height: 100%; 
   background-color: #C2C2C2; 
} 
 
#thumbnailsControl, #bookmarksControl { 
   width: 195px; 
   background-color: #D4D6DB; 
   z-index: 1; 
   position: fixed; 
   left: 39px; 
   bottom: 0px; 
   top: 0px; 
   -webkit-box-shadow: 5px 4px 5px -5px #333; 
   box-shadow: 5px 4px 5px -5px #333; 
   border: 1px solid darkgray; 
   display: none; 
} 
 
   #thumbnailsControl > .controlHeader, #bookmarksControl > .controlHeader { 
      padding: inherit; 
      text-align: inherit; 
      padding-top: 13px; 
      padding-left: 5px; 
   } 
 
#thumbnails, #bookmarks { 
   overflow: hidden; 
   top: 43px; 
   left: 5px; 
   right: 5px; 
   bottom: 5px; 
   position: absolute !important; 
   border: 1px solid darkgray; 
} 
 
#thumbnails { 
   background-color: #fafdff; 
} 
 
#bookmarks { 
   background-color: white; 
   overflow: auto !important; 
   font: normal normal 12px/20px Helvetica, Arial, sans-serif; 
} 

Link this CSS file to be used in the Pages/index.chtml file:

<!-- DocumentViewer stylesheet --> 
<link rel="stylesheet" href="~/CSS/documentviewer.css" /> 

Add the Icon Image Resources

The navigationbar element uses an icon image for each button contained for toggling the display of the thumbnail or bookmark containers.

Create a Resources folder under the site directory of the project then create the Images\Icons sub-folders.

Add the Bookmarks.png and Thumbnails.png icon images to this folder. These images can be found at <INSTALL_DIR>\LEADTOOLS23\Examples\Common\JS\Resources\Images\Icons

Add the Document Viewer App Code

Create a DocumentViewerApp.ts file in the .\ts\App folder.

Declare and export a new DocumentViewerApp class which will contain the properties and functions used for the configuration and operation of the document viewer web app.

Use the code below to define the public and private properties of the DocumentViewerApp as well as configure the constructor.

module lt.DocumentViewer { 
   export class DocumentViewerApp { 
      // Document viewer 
      private _documentViewer: lt.Document.Viewer.DocumentViewer = null; 
 
      // HTML Elements 
      public navigationbarContainer: HTMLElement = document.getElementById("navigationbar"); 
      public navigationbar = { 
         showThumbnailsBtn: <HTMLButtonElement>document.getElementById("showThumbnails"), 
         showBookmarksBtn: <HTMLButtonElement>document.getElementById("showBookmarks") 
      }; 
      public imageViewerContainerDiv: HTMLElement = document.getElementById("imageViewerContainer"); 
      public thumbnailsContainer: HTMLElement = document.getElementById("thumbnailsControl"); 
      public bookmarksContainer: HTMLElement = document.getElementById("bookmarksControl"); 
      public affectedContainers: NodeListOf<HTMLElement> = document.querySelectorAll(".affectedContainers"); 
 
      constructor() { 
         window.onunload = ((e: Event) => this.onUnload(e)); 
         window.onresize = ((e: Event) => this.onResize(e)); 
      } 
 
      private onUnload(e: Event): void { 
         if (this._documentViewer != null) { 
            this._documentViewer.dispose(); 
         } 
      } 

Add onResize() Code to Configure Container Display

Use the code below to dynamically update the display of the document viewer elements according to the browser window size in relation to the header and footer elements in the project.

This code also adjusts the display of the view container if the thumbnail or bookmark containers are visible.

private onResize(e: Event) { 
   this.updateContainers(); 
} 
 
public updateContainers(): void { 
   // Check visibility 
   let visibleThumbnails: boolean = window.getComputedStyle(this.thumbnailsContainer).display !== "none"; 
   let visibleBookmarks: boolean = window.getComputedStyle(this.bookmarksContainer).display !== "none"; 
 
   let navigationbarContainerWidth: number = this.navigationbarContainer.offsetWidth; 
   // Thumbnails, bookmarks and attachments Containers has same width 
   // Use thumbnails container as common 
   let containerWidth: number = parseInt(window.getComputedStyle(this.thumbnailsContainer).width); 
 
   // Now update viewer container 
   let imageViewerContainerDivLeft: number = navigationbarContainerWidth; 
   if (visibleThumbnails || visibleBookmarks) 
      imageViewerContainerDivLeft += containerWidth; 
   this.imageViewerContainerDiv.style.left = imageViewerContainerDivLeft.toString() + "px"; 
 
   // The viewer container size might be changed; call onSizeChanged 
   this._documentViewer.view.imageViewer.onSizeChanged(); 
   if (this._documentViewer.thumbnails != null) { 
      this._documentViewer.thumbnails.imageViewer.onSizeChanged(); 
      this._documentViewer.thumbnails.imageViewer.invalidate(lt.LeadRectD.empty); 
   } 
} 

Add the run() Code to Initialize the DocumentViewer App

Use the code below for the DocumentViewer.run() which will initialize the viewer, verify the service connection, and load a PDF document.

The PDF document that will be loaded is a sample Leadtools.pdf file that is available at https://demo.leadtools.com/images/pdf/leadtools.pdf

public run(): void { 
   // Initialize the Navigation Bar Buttons 
   this.navigationbar.showThumbnailsBtn.addEventListener("click", () => this.showContainer(this.thumbnailsContainer, true)); 
   this.navigationbar.showBookmarksBtn.addEventListener("click", () => this.showContainer(this.bookmarksContainer, true)); 
 
   // Initialize the document viewer 
   this.initDocumentViewer(); 
 
   // Initialize the UI 
   this.updateAppUIState(); 
 
   // Verify Service Connection 
   lt.Document.DocumentFactory.serviceHost = "http://localhost:40000"; 
   lt.Document.DocumentFactory.servicePath = ""; 
   lt.Document.DocumentFactory.serviceApiPath = "api"; 
 
   lt.Document.DocumentFactory.verifyService() 
         .done(() => { 
            lt.LTHelper.log("Service connection verified!"); 
 
         }) 
         .fail(() => { 
            lt.LTHelper.log("Service connection unavailable."); 
         }); 
 
   // Load a Document 
   const url = "https://demo.leadtools.com/images/pdf/leadtools.pdf"; 
   lt.Document.DocumentFactory.loadFromUri(url, null) 
         .done((doc) => { 
            this.setDocument(doc); 
            this.updateAppUIState(); 
         }); 
} 

Add the showContainer() Code

Use the code below for the navigation bar buttons to use for controlling the visibility of the thumbnails and bookmarks containers.

// Toggle the visibility of the thumbnails/bookmarks containers 
public showContainer(container, flipState: boolean): void { 
   let visibleThumbnails: boolean = window.getComputedStyle(this.thumbnailsContainer).display !== "none"; 
   let visibleBookmarks: boolean = window.getComputedStyle(this.bookmarksContainer).display !== "none"; 
 
   // Show Thumbnails 
   if (container == this.thumbnailsContainer) { 
         if (!visibleThumbnails) { 
            if (visibleBookmarks) { 
               this.bookmarksContainer.style.display = "none"; 
               this.navigationbar.showBookmarksBtn.classList.remove("activeNavigationbarBtn"); 
            } 
            this.navigationbar.showThumbnailsBtn.classList.add("activeNavigationbarBtn"); 
            this.thumbnailsContainer.style.display = "block"; 
         } else { 
            if (flipState) { 
               this.navigationbar.showThumbnailsBtn.classList.remove("activeNavigationbarBtn"); 
               this.thumbnailsContainer.style.display = "none"; 
            } 
         } 
 
         this.updateContainers(); 
         return; 
   } 
 
   // Show Bookmarks 
   if (container == this.bookmarksContainer) { 
         if (!visibleBookmarks) { 
            // Hide others 
            if (visibleThumbnails) { 
               this.thumbnailsContainer.style.display = "none"; 
               this.navigationbar.showThumbnailsBtn.classList.remove("activeNavigationbarBtn"); 
            } 
            this.navigationbar.showBookmarksBtn.classList.add("activeNavigationbarBtn"); 
            this.bookmarksContainer.style.display = "block"; 
         } else { 
            if (flipState) { 
               this.navigationbar.showBookmarksBtn.classList.remove("activeNavigationbarBtn"); 
               this.bookmarksContainer.style.display = "none"; 
            } 
         } 
         this.updateContainers(); 
         return; 
   } 
} 

Initialize and Create the Document Viewer

Use the following code to configure the document viewer. The createOptions object configures the creation of the viewer and hooks the HTML elements.

After the document viewer is created by the DocumentViewerFactory object, the document viewer settings can also be configured. In this tutorial, the following settings are applied:

// Create the document viewer 
private initDocumentViewer(): void { 
    // Document Viewer Creation Options 
    let createOptions: lt.Document.Viewer.DocumentViewerCreateOptions = new lt.Document.Viewer.DocumentViewerCreateOptions(); 
    createOptions.viewCreateOptions.useElements = false; 
    createOptions.thumbnailsCreateOptions.useElements = false; 
 
    // Set the UI part where the main view is displayed 
    createOptions.viewContainer = document.getElementById("imageViewerDiv"); 
    // Set the UI part where the thumbnails are displayed 
    createOptions.thumbnailsContainer = document.getElementById("thumbnails"); 
    // Set the UI part where the bookmarks are displayed (Set bookmarks container will show them in simple list) 
    createOptions.bookmarksContainer = document.getElementById("bookmarks"); 
 
    createOptions.useAnnotations = false; 
 
    // Create the viewer 
    try { 
        this._documentViewer = lt.Document.Viewer.DocumentViewerFactory.createDocumentViewer(createOptions); 
 
        // Document viewer settings 
 
        // SVG Preference for Display 
        this._documentViewer.view.preferredItemType = lt.Document.Viewer.DocumentViewerItemType.svg 
 
        // Lazy Loading 
        this._documentViewer.view.lazyLoad = true; 
        if (this._documentViewer.thumbnails) 
            this._documentViewer.thumbnails.lazyLoad = true; 
 
        // Log Rendering Errors 
        let imageViewer: lt.Controls.ImageViewer = this._documentViewer.view.imageViewer; 
 
        let logRenderErrors: lt.Controls.ImageViewerRenderEventHandler = function (sender: any, e: lt.Controls.ImageViewerRenderEventArgs) { 
            let item: number = e.item != null ? e.item.imageViewer.items.indexOf(e.item) : -1; 
            let message: string = "Error during render item " + item + " part " + (e.part) + ": " + (e.error.message); 
            lt.LTHelper.logError({ message: message, error: e.error }); 
        } 
 
        imageViewer.renderError.add(logRenderErrors); 
        if (this._documentViewer.thumbnails && this._documentViewer.thumbnails.imageViewer) 
            this._documentViewer.thumbnails.imageViewer.renderError.add(logRenderErrors); 
    } 
    catch (e) { 
        alert("DocumentViewer creation failed"); 
        lt.LTHelper.logError(e); 
        return; 
    } 
} 

Initialize the Document Viewer App UI

Use the code below to initialize the display of the document viewer app's user interface.

// Update the UI state of the app 
private updateAppUIState(): void { 
    let hasDocument: boolean = this._documentViewer.hasDocument; 
    if (hasDocument) { 
        if (window.getComputedStyle(this.imageViewerContainerDiv).display === "none") { 
            this.imageViewerContainerDiv.style.display = "block"; 
            this._documentViewer.view.imageViewer.updateTransform(); 
        } 
 
        if (this.navigationbar.showThumbnailsBtn.matches(":disabled")) 
            this.navigationbar.showThumbnailsBtn.disabled = false; 
 
 
        if (this._documentViewer.document.isStructureSupported) { 
            if (this.navigationbar.showBookmarksBtn.matches(":disabled")) 
                this.navigationbar.showBookmarksBtn.disabled = false; 
        } else { 
            this.navigationbar.showBookmarksBtn.classList.remove("activeNavigationbarBtn"); 
            if (!(this.navigationbar.showBookmarksBtn.matches(":disabled"))) 
                this.navigationbar.showBookmarksBtn.disabled = true; 
            if (this.bookmarksContainer.style.display === "block") 
                this.bookmarksContainer.style.display = "none"; 
        } 
    } else { 
        if (window.getComputedStyle(this.imageViewerContainerDiv).display === "block") { 
            this.imageViewerContainerDiv.style.display = "none"; 
        } 
 
        this.navigationbar.showThumbnailsBtn.classList.remove("activeNavigationbarBtn"); 
        if (!(this.navigationbar.showThumbnailsBtn.matches(":disabled"))) 
            this.navigationbar.showThumbnailsBtn.disabled = true; 
        if (this.thumbnailsContainer.style.display === "block") 
            this.thumbnailsContainer.style.display = "none"; 
 
        this.navigationbar.showBookmarksBtn.classList.remove("activeNavigationbarBtn"); 
        if (!(this.navigationbar.showBookmarksBtn.matches(":disabled"))) 
            this.navigationbar.showBookmarksBtn.disabled = true; 
        if (this.bookmarksContainer.style.display === "block") 
            this.bookmarksContainer.style.display = "none"; 
    } 
    this.updateContainers(); 
} 

Add the setDocument() Code

The following code checks if the loaded document is parsed, parses the document if needed, and sets the loaded document into the document viewer.

      public setDocument(document: lt.Document.LEADDocument): void { 
         // See if we need to parse the document structure 
         if (document.structure.isParsed) { 
               this.finishSetDocument(document); 
         } 
         else 
               this.parseStructure(document); 
      } 
 
      private parseStructure(document: lt.Document.LEADDocument): void { 
         document.structure.parse() 
               .done((document: lt.Document.LEADDocument): void => { 
                  this.finishSetDocument(document); 
               }) 
               .fail((): void => { 
                  lt.LTHelper.log("Error parsing the document structure."); 
               }); 
      } 
 
      public finishSetDocument(document: lt.Document.LEADDocument): void { 
         if (this._documentViewer.view != null) { 
               // Use SVG Back Image 
               this._documentViewer.view.useSvgBackImage = true; 
         } 
 
         // Set the loaded document in the document viewer 
         this._documentViewer.setDocument(document); 
 
         // Update the UI 
         this.updateAppUIState(); 
         // Call onResize so the DIV sizes get updated 
         this.onResize(null); 
 
         // Fit page to display 
         this._documentViewer.commands.run(lt.Document.Viewer.DocumentViewerCommands.viewFitPage, null); 
      } 
   } 
} 

Call run() from Index Script

Add a call to the run() method in the Index.ts script.

document.addEventListener("DOMContentLoaded", () => { 
   (new lt.DocumentViewer.SetLicense()).run(); 
   (new lt.DocumentViewer.DocumentViewerApp()).run(); 
}); 

Run the Project

Before running the front-end Document Viewer, run the Document Service. The LEADTOOLS SDK installation provides three examples of the Document Service for the following platforms:

For instructions on how to set up and configure the Document Service, in the three platforms previously listed, refer to the steps in the Get Started with the Document Viewer Demo - HTML5 JavaScript tutorial.

For the purposes of this tutorial, the .NET Framework Document Service is used and it can be found here: \LEADTOOLS23\Examples\Document\JS\DocumentServiceDotNet\fx.

Once you have the back-end Document Service running, execute the build script to transpile the TS scripts to the output site folder:

npm run build

Once done, execute the start script to start the server and automatically open the hosted site in the default browser.

npm run start
Document Viewer Running in Browser

Wrap-up

This tutorial showed how to initialize, load, and display a document in a NodeJS TypeScript Document Viewer Web application.

See Also

Help Version 23.0.2024.5.22
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2024 LEAD Technologies, Inc. All Rights Reserved.

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.