Document Scanner

Add a document scanning button to your web pages with Dynamic Web TWAIN.

当前为 2023-02-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Document Scanner
  3. // @namespace https://www.dynamsoft.com
  4. // @version 0.3
  5. // @description Add a document scanning button to your web pages with Dynamic Web TWAIN.
  6. // @author Lihang Xu
  7. // @include *
  8. // @license MIT
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. let modal;
  14. let DWObject;
  15.  
  16. const CSS = /* css */ `
  17. .dwt-fab {
  18. position:fixed;
  19. bottom:0;
  20. width: 50px;
  21. height: 50px;
  22. left: 0;
  23. margin: 10px;
  24. border-radius: 50%;
  25. background: #2196f3;
  26. pointer-events: auto;
  27. z-index: 9999;
  28. }
  29.  
  30. .dwt-fab:hover {
  31. background: #7db1d4;
  32. }
  33.  
  34. .dwt-fab img {
  35. padding: 10px;
  36. }
  37.  
  38. .dwt-modal {
  39. position:fixed;
  40. left: 20px;
  41. top: 20px;
  42. width: calc(100% - 40px);
  43. height: calc(100% - 40px);
  44. border: 1px solid gray;
  45. border-radius: 5px;
  46. background: white;
  47. z-index: 9999;
  48. }
  49.  
  50. .dwt-header {
  51. height: 25px;
  52. }
  53.  
  54. .dwt-close-btn {
  55. float: right;
  56. margin-right: 5px;
  57. }
  58.  
  59. .dwt-body {
  60. text-align: center;
  61. height: calc(100% - 25px);
  62. }
  63.  
  64. .dwt-controls {
  65. text-align: center;
  66. height: 50px;
  67. }
  68.  
  69. #dwtcontrolContainer {
  70. width: 100%;
  71. height: calc(100% - 50px);
  72. }
  73. `;
  74.  
  75. (function() {
  76. 'use strict';
  77. GM_addStyle(CSS);
  78. console.log("DWT userscript loaded");
  79. init();
  80. // Your code here...
  81. })();
  82.  
  83. async function init(){
  84. await loadLibrary("https://unpkg.com/dwt@18.0.0/dist/dynamsoft.webtwain.min.js","text/javascript");
  85. Dynamsoft.DWT.AutoLoad = false;
  86. Dynamsoft.DWT.ResourcesPath = "https://unpkg.com/dwt@18.0.0/dist";
  87. addButton();
  88. }
  89.  
  90. function addButton(){
  91. const button = document.createElement("div");
  92. button.className = "dwt-fab";
  93. const a = document.createElement("a")
  94. a.href = "javascript:void(0)";
  95. const icon = document.createElement("img")
  96. icon.src = "https://tony-xlh.github.io/document-scanner-userscript/scanner-scan.svg"
  97. a.appendChild(icon);
  98. button.appendChild(a);
  99. document.body.appendChild(button);
  100. button.addEventListener("click", () => {
  101. showModal();
  102. });
  103. }
  104.  
  105. function showModal(){
  106. if (!modal) {
  107. modal = document.createElement("div");
  108. modal.className = "dwt-modal";
  109. document.body.appendChild(modal);
  110. const header = document.createElement("div");
  111. const closeBtn = document.createElement("div");
  112. closeBtn.className = "dwt-close-btn";
  113. closeBtn.innerText = "x";
  114. header.appendChild(closeBtn);
  115. header.className = "dwt-header";
  116. closeBtn.addEventListener("click", () => {
  117. hideModal();
  118. });
  119. const body = document.createElement("div");
  120. body.className = "dwt-body";
  121. const viewer = document.createElement("div");
  122. viewer.id = "dwtcontrolContainer";
  123. const controls = document.createElement("div");
  124. controls.className = "dwt-controls";
  125. const scanBtn = document.createElement("button");
  126. scanBtn.innerText = "Scan";
  127. scanBtn.addEventListener("click", () => {
  128. scan();
  129. });
  130. const copyBtn = document.createElement("button");
  131. copyBtn.innerText = "Copy selected";
  132. copyBtn.addEventListener("click", () => {
  133. copy();
  134. });
  135.  
  136. const saveBtn = document.createElement("button");
  137. saveBtn.innerText = "Save";
  138. saveBtn.addEventListener("click", () => {
  139. save();
  140. });
  141.  
  142. const status = document.createElement("div");
  143. status.className="dwt-status";
  144.  
  145. controls.appendChild(scanBtn);
  146. controls.appendChild(copyBtn);
  147. controls.appendChild(saveBtn);
  148. controls.appendChild(status);
  149.  
  150. body.appendChild(viewer);
  151. body.appendChild(controls);
  152. modal.appendChild(header);
  153. modal.appendChild(body);
  154. if (!DWObject) {
  155. initDWT();
  156. }
  157. }
  158. document.querySelector(".dwt-fab").style.display = "none";
  159. modal.style.display = "";
  160. }
  161.  
  162. function hideModal(){
  163. modal.style.display = "none";
  164. document.querySelector(".dwt-fab").style.display = "";
  165. }
  166.  
  167. function scan(){
  168. if (DWObject) {
  169. if (Dynamsoft.Lib.env.bMobile) {
  170. DWObject.Addon.Camera.scanDocument();
  171. }else {
  172. DWObject.SelectSource(function () {
  173. DWObject.OpenSource();
  174. DWObject.AcquireImage();
  175. },
  176. function () {
  177. console.log("SelectSource failed!");
  178. }
  179. );
  180. }
  181. }
  182. }
  183.  
  184. function copy(){
  185. if (DWObject) {
  186. if (Dynamsoft.Lib.env.bMobile) {
  187. DWObject.ConvertToBlob(
  188. [DWObject.CurrentImageIndexInBuffer],
  189. Dynamsoft.DWT.EnumDWT_ImageType.IT_PNG,
  190. function(result) {
  191. CopyBlobToClipboard(result);
  192. },
  193. function(errorCode,errorString) {
  194. console.log("convert failed");
  195. console.log(errorString);
  196. alert("Failed");
  197. });
  198. }else{
  199. DWObject.CopyToClipboard(DWObject.CurrentImageIndexInBuffer);
  200. alert("Copied");
  201. }
  202. }
  203. }
  204.  
  205. function CopyBlobToClipboard(blob) {
  206. var data = [new ClipboardItem({ "image/png": blob})];
  207. navigator.clipboard.write(data).then(function() {
  208. alert("Copied");
  209. }, function() {
  210. alert("Failed");
  211. });
  212. }
  213.  
  214. function save(){
  215. if (DWObject) {
  216. DWObject.SaveAllAsPDF("Scanned");
  217. }
  218. }
  219.  
  220. function initDWT(){
  221. console.log("initDWT");
  222. const status = document.querySelector(".dwt-status");
  223. Dynamsoft.DWT.Containers = [{ ContainerId: 'dwtcontrolContainer',Width: 270, Height: 350 }];
  224. Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', function () {
  225. console.log("ready");
  226. status.innerText = "";
  227. DWObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer');
  228. DWObject.Viewer.width = "100%";
  229. DWObject.Viewer.height = "100%";
  230. DWObject.SetViewMode(2,2);
  231. });
  232. status.innerText = "Loading...";
  233. Dynamsoft.DWT.Load();
  234. }
  235.  
  236. function loadLibrary(src,type){
  237. return new Promise(function (resolve, reject) {
  238. let scriptEle = document.createElement("script");
  239. scriptEle.setAttribute("type", type);
  240. scriptEle.setAttribute("src", src);
  241. document.body.appendChild(scriptEle);
  242. scriptEle.addEventListener("load", () => {
  243. console.log(src+" loaded")
  244. resolve(true);
  245. });
  246. scriptEle.addEventListener("error", (ev) => {
  247. console.log("Error on loading "+src, ev);
  248. reject(ev);
  249. });
  250. });
  251. }