How to Make Dynamic Web TWAIN Work with Polymer Shadow DOM

In the past, Dynamic Web TWAIN was tightly correlated with HTML elements. It only allowed developers to use HTML element ID to initialize the image container. In the meantime, shadow DOM elements were not supported, which failed Polymer projects. Starting from the latest version 16.1, the SDK has a lower coupling. Developers can use either HTML element ID or HTML element object to initialize a Dynamic Web TWAIN object. In this article, I will share how to integrate Dynamic Web TWAIN SDK to a Polymer project for scanning documents in web browsers.

Dynamic Web TWAIN Quick Start

Install the SDK.

Copy Dynamic Web TWAIN SDK 16.1\Resources to your project root directory.

Create an HTML file and get the full sample code from GitHub:

<!DOCTYPE html>
<html>
<head>
    <title>Hello World</title>
    <script type="text/javascript" src="Resources/dynamsoft.webtwain.initiate.js"></script>
    <script type="text/javascript" src="Resources/dynamsoft.webtwain.config.js"></script>
</head>
<body>
    <div id="dwtcontrolContainer" ></div>
    <input type="button" value="Scan" onclick="AcquireImage();" />
    <script type="text/javascript">
    function AcquireImage() {
	var DWObject = Dynamsoft.WebTwainEnv.GetWebTwain('dwtcontrolContainer');
	if (DWObject) {		
		DWObject.SelectSource(function () {		
		var OnAcquireImageSuccess = OnAcquireImageFailure = function () {
		    DWObject.CloseSource();
		};
		DWObject.OpenSource();
		DWObject.IfDisableSourceAfterAcquire = true;
		DWObject.AcquireImage(OnAcquireImageSuccess, OnAcquireImageFailure);
            }, function () {
		console.log('SelectSource failed!');
            });
        }
    }
    </script>
</body>
</html>

A simple web document management app is done. Double-click the HTML file to run the web scanner app.

web document scan

When you use an HTML element ID to initialize the Dynamic Web TWAIN object, it will internally use DOM to find the element. However, it cannot work with shadow DOM. Let’s substitute ID with an HTML element object as a warmup:

<script type="text/javascript">
        // Get a free trial license key from https://www.dynamsoft.com/CustomerPortal/Portal/Triallicense.aspx
        Dynamsoft.WebTwainEnv.ProductKey = 'LICENSE-KEY';
        Dynamsoft.WebTwainEnv.RegisterEvent('OnWebTwainReady', onReady);
        var DWObject;

        function onReady() {
            Dynamsoft.WebTwainEnv.CreateDWTObject(document.getElementById('doc-image'), function (obj) {
                DWObject = obj;
            }, function (errorString) {
                console.log(errorString)
            });
        }
    </script>

If you don’t have a trial license key, visit https://www.dynamsoft.com/CustomerPortal/Portal/Triallicense.aspx.

A Polymer Project for Scanning Documents

Install the Polymer CLI:

npm i -g polymer-cli

Initialize the Polymer project with a template and run the project:

mkdir polymer-document-scan
cd polymer-document-scan
polymer init polymer-3-starter-kit
npm start
Polymer project

Integrating Dynamic Web TWAIN into Polymer Project

In index.html file, we create an HTML DIV element in memory for initializing Dynamic Web TWAIN object:

<my-app></my-app>

  <script type="text/javascript">
    var DWObject;
    // Get a free trial license key from https://www.dynamsoft.com/CustomerPortal/Portal/Triallicense.aspx
    // Dynamsoft.WebTwainEnv.ProductKey = 'LICENSE-KEY';
    Dynamsoft.WebTwainEnv.RegisterEvent('OnWebTwainReady', onReady);

    function onReady() {
      Dynamsoft.WebTwainEnv.CreateDWTObject(document.createElement('div'), function (obj) {
        DWObject = obj;
      }, function (errorString) {
        console.log(errorString)
      });
    }
  </script>

Next, add a <div> and a <button> elements to the HTML template in src/my-view.js:

class MyView1 extends PolymerElement {
  static get template() {
    return html`
      <style include="shared-styles">
        :host {
          display: block;
 
          padding: 10px;
        }
      </style>
 
      <div class="card">
      <div id="dwtcontrolContainer"></div>
      <button on-click="handleClick">scan</button>
      </div>
    `;
  }
 
  handleClick() {
    if (DWObject) {
      
    }
  }
}

Refresh the web page to check the effect:

Add scan module to Polymer project

How can we scan documents and display images to the DIV element? If we open the developer console, we can see it is a shadow DOM element:

The JS code to get the element is as follows:

document.querySelector("body > my-app").shadowRoot.querySelector("app-drawer-layout > app-header-layout > iron-pages > my-view1").shadowRoot.querySelector("#dwtcontrolContainer")

Don’t be scared. We can beautify the code in src/my-view.js :

let container = this.shadowRoot.querySelector('# dwtcontrolContainer');

To render the document, add an <img> element to the <div> element:

<div class="card">
        <h1>Web Document Scan</h1>
        <div><img id="image"></div>
        <button on-click="handleClick">scan</button>
</div>

Then implement the scan and display logic:

handleClick() {
    if (DWObject) {
      let image = this.shadowRoot.querySelector('#image');
      DWObject.SelectSource(function () {
          var onSuccess, onFailure;
          onSuccess = onFailure = function () {
              DWObject.CloseSource();
              image.src = DWObject.GetImageURL(DWObject.CurrentImageIndexInBuffer, 640, 480);
          };
          DWObject.OpenSource();
          DWObject.IfDisableSourceAfterAcquire = true;
          DWObject.AcquireImage(onSuccess, onFailure);
      }, function () {
          console.log('SelectSource failed!');
      });
    }

Now the web document scan app can normally work in the Polymer project.

Polymer Shadow DOM document scan

Source Code

https://github.com/yushulx/web-twain-document-scan