Lit is a simple library for building fast, lightweight web components. At Lit's core is a boilerplate-killing component base class that provides reactive state, scoped styles, and a declarative template system that's tiny, fast and expressive.
In this article, we are going to build a web component with LitElement to scan documents in an HTML website based on Dynamic Web TWAIN.
New Project
Although Lit can be used without a build system, in this article, we are going to use webpack with the following template (clone with git):
git clone https://github.com/wbkd/webpack-starter
Install Dependencies
- Install Lit.
npm install lit
- Install Dynamic Web TWAIN.
npm install dwt
In addition, we need to copy the resources of Dynamic Web TWAIN to the public folder.
-
Install
ncp
.
npm install --save-dev ncp
-
Modify
package.json
to copy the resources for the build and start commands.
"scripts": { "lint": "npm run lint:styles; npm run lint:scripts", "lint:styles": "stylelint src", "lint:scripts": "eslint src", "build": "cross-env NODE_ENV=production webpack --config webpack/webpack.config.prod.js", "start": "webpack serve --config webpack/webpack.config.dev.js" + "build": "ncp node_modules/dwt/dist public/dwt-resources && cross-env NODE_ENV=production webpack --config webpack/webpack.config.prod.js", + "start": "ncp node_modules/dwt/dist public/dwt-resources && webpack serve --config webpack/webpack.config.dev.js" },
-
Modify
webpack.common.js
to copy the files in thepublic
folder to the output folder instead of thepublic
folder inside the output folder.
new CopyWebpackPlugin({ - patterns: [{ from: Path.resolve(__dirname, '../public'), to: 'public' }], + patterns: [{ from: Path.resolve(__dirname, '../public'), to: '' }], }),
Write a Document Scanner Component
- Create a new
documentscanner.js
file undersrc\scripts
with the following template.
import {LitElement, html, css} from 'lit';
export class DocumentScanner extends LitElement {
static properties = {
};
DWObject;
static styles = css`
:host {
display: block;
}
`;
constructor() {
super();
}
render() {
return html``;
}
}
customElements.define('document-scanner', DocumentScanner);
- Add a
div
element as the container for the controls of Dynamic Web TWAIN (mainly to view documents).
render() {
return html`<div id="dwtcontrolContainer"></div>`;
}
- Configure Dynamic Web TWAIN in the
constructor
. You need a license to use Dynamic Web TWAIN. You can apply for a license here.
constructor() {
super();
Dynamsoft.DWT.AutoLoad = false;
Dynamsoft.DWT.ResourcesPath = "/dwt/dist";
Dynamsoft.DWT.ProductKey = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial
}
- Initialize Dynamic Web TWAIN in the
firstUpdated
lifecycle after the dom is first updated and bind it to the container in the previous step. In addition, dispatch a custom event with the object of Dynamic Web TWAIN so that we can control it in a parent node.
DWObject;
firstUpdated() {
let pThis = this;
let dwtContainer = this.renderRoot.getElementById("dwtcontrolContainer");
Dynamsoft.DWT.CreateDWTObjectEx(
{
WebTwainId: 'dwtcontrol'
},
function(obj) {
pThis.DWObject = obj;
pThis.DWObject.Viewer.bind(dwtContainer);
pThis.DWObject.Viewer.show();
pThis.DWObject.Viewer.width = "100%";
pThis.DWObject.Viewer.height = "100%";
const event = new CustomEvent('initialized', {
detail: {
DWObject: pThis.DWObject
}
});
pThis.dispatchEvent(event);
},
function(err) {
console.log(err);
}
);
}
- Add one button to scan documents and one button to save the document images as a PDF file.
render() {
return html`
<div class="buttons">
<button @click=${this.scan}>Scan</button>
<button @click=${this.save}>Save</button>
</div>
<div id="dwtcontrolContainer"></div>`;
}
scan(){
let pThis = this;
if (pThis.DWObject) {
pThis.DWObject.SelectSource(function () {
pThis.DWObject.OpenSource();
pThis.DWObject.AcquireImage();
},
function () {
console.log("SelectSource failed!");
}
);
}
}
save(){
if (this.DWObject) {
this.DWObject.SaveAllAsPDF("Scanned.pdf");
}
}
- Add a reactive property named
total
to reflect how many documents are scanned. We can update its value in theOnBufferChanged
event of Web TWAIN.
export class DocumentScanner extends LitElement {
static properties = {
total: {},
};
constructor() {
super();
this.total = 0;
//...
}
render() {
return html`
<div class="buttons">
<button @click=${this.scan}>Scan</button>
<button @click=${this.save}>Save</button>
</div>
<div id="dwtcontrolContainer"></div>
<div class="status">Total: ${this.total}</div>`;
}
firstUpdated() {
//...
Dynamsoft.DWT.CreateDWTObjectEx(
{
WebTwainId: 'dwtcontrol'
},
function(obj) {
//...
pThis.DWObject.RegisterEvent('OnBufferChanged',function () {
pThis.total = pThis.DWObject.HowManyImagesInBuffer;
});
//...
},
function(err) {
console.log(err);
}
);
}
}
- Set the styles for the component.
static styles = css`
:host {
display: block;
}
.buttons {
height: 25px;
}
#dwtcontrolContainer {
width: 100%;
height: calc(100% - 50px);
}
.status {
height: 25px;
}
`;
Use the Document Scanner Component
- Import the component in the
index.js
file.
import { DocumentScanner } from './documentscanner'; // eslint-disable-line
- Add the component in the
index.html
.
<document-scanner
style="width:320px;height:480px;"
></document-scanner>
All right, we can now scan documents from the browser.
Source Code
Get the source code of the demo to have a try:
Top comments (0)