How to Drag and Drop to Reorder Scanned Document Images with JavaScript
Drag and drop is a useful feature for managing scanned document images. It allows users to move items from one location to another using a mouse or touch gesture.
Dynamsoft Document Viewer is an SDK which provides a set of viewers for document images. In this article, we are going to demonstrate how to use it to display images and use drag and drop to reorder images. In addition, we will also explore how to implement it from scratch with JavaScript using the drag and drop API.
Use Dynamsoft Document Viewer to Drag and Drop Images
-
Create a new HTML file with the following template.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>Drag and Drop</title> <style> </style> </head> <body> </body> <script> </script> </html>
-
Include Dynamsoft Document Viewer’s files.
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.0.0/dist/ddv.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.0.0/dist/ddv.css">
-
Initialize Dynamsoft Document Viewer with a license. You can apply for one here.
Dynamsoft.DDV.Core.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.0.0/dist/engine";// Lead to a folder containing the distributed WASM files await Dynamsoft.DDV.Core.init();
-
Create a new document instance.
const docManager = Dynamsoft.DDV.documentManager; const doc = docManager.createDocument();
-
Create an instance of browse viewer, bind it to a container and use it to view the document we just created.
HTML:
<div id="viewer"></div>
JavaScript:
let browseViewer = new Dynamsoft.DDV.BrowseViewer({ container: document.getElementById("viewer"), }); browseViewer.openDocument(doc.uid);
CSS:
#viewer { width: 320px; height: 480px; }
-
Use
input
to select image or PDF files and load them into the document instance so that we can use the browse viewer to view the files.HTML:
<label> Select an image: <br/> <input type="file" id="files" name="files" onchange="filesSelected()"/> </label>
JavaScript:
async function filesSelected(){ let filesInput = document.getElementById("files"); let files = filesInput.files; if (files.length>0) { const file = files[0]; const blob = await readFileAsBlob(file); await doc.loadSource(blob); // load image } } function readFileAsBlob(file){ return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = async function(e){ const response = await fetch(e.target.result); const blob = await response.blob(); resolve(blob); }; fileReader.onerror = function () { reject('oops, something went wrong.'); }; fileReader.readAsDataURL(file); }) }
We can then drap and drop to reorder the images in the viewer.
Implement Drag and Drop from Scratch
HTML5 has the Drag and Drop API out of the box.
In the previous article, we’ve written a page to view and select multiple images.
We are now going to add the drap and drop feature to it. It works by dragging the selected images into another image to adjust the image order.
-
Set the draggable attribute to true for the selected image elements.
function toggleSelection(thumbnail) { thumbnail.classList.toggle('selected'); + if (thumbnail.classList.contains('selected')) { + thumbnail.getElementsByTagName("img")[0].setAttribute("draggable",true); + }else{ + thumbnail.getElementsByTagName("img")[0].setAttribute("draggable",false); + } } function selectOne(thumbnail) { thumbnail.classList.add('selected'); + thumbnail.getElementsByTagName("img")[0].setAttribute("draggable",true); } function clearSelection() { let thumbnails = document.querySelectorAll(".thumbnail"); - thumbnails.forEach(thumbnail => thumbnail.classList.remove('selected')); + thumbnails.forEach(thumbnail => { + thumbnail.classList.remove('selected') + thumbnail.getElementsByTagName("img")[0].setAttribute("draggable",false); + }); + }
-
Add
dragenter
anddragleave
events to add effects to the image dragged into. Meanwhile, keep track of the image dragged into astargetImg
.let targetImg; img.addEventListener("dragenter",function(){ img.classList.add("dragHover"); targetImg = img; }) img.addEventListener("dragleave",function(){ img.classList.remove("dragHover"); })
CSS:
.dragHover { opacity: 0.5; }
-
Add the
dragover
event to set the drop effect.img.addEventListener("dragover",function(e){ e.dataTransfer.dropEffect = "move"; })
-
Add the
dragend
event to remove the dragging effect and perform reordering. First, we get all the selected images, the first selected image’s index and the target image’s index. Then, if the target index is bigger than the selected index, useinsertBefore
to insert the images before the next image of the target image. Otherwize, insert the images right before the target image.img.addEventListener("dragend",function(){ img.classList.remove("dragHover"); if (img.classList.contains("selected") === false) { reorder(); } }) function reorder(){ const targetThumbnailContainer = targetImg.parentNode; targetImg.classList.remove("dragHover"); const thumbnails = document.getElementsByClassName("thumbnail"); const selected = []; let targetIndex = -1; let selectedIndex = -1; for (let index = thumbnails.length - 1; index >=0 ; index--) { const item = thumbnails[index]; if (item.classList.contains("selected")) { selected.push(item); selectedIndex = index; if (item === targetThumbnailContainer) { //abort if the target image is also selected return; } } if (item === targetThumbnailContainer) { targetIndex = index; } } const viewer = document.getElementById("viewer"); if (selectedIndex>targetIndex) { selected.reverse(); } selected.forEach(function(one) { if (selectedIndex<targetIndex) { viewer.insertBefore(one,targetThumbnailContainer.nextSibling); }else{ viewer.insertBefore(one,targetThumbnailContainer); } }) }
-
The drag and drop API does not work on touch devices. We can enable it using a polyfill by including the following line in our page.
<script src="https://drag-drop-touch-js.github.io/dragdroptouch/dist/drag-drop-touch.esm.min.js?autoload" type="module"></script>
All right, we’ve implemented the drag and drop feature with JavaScript.
Source Code
https://github.com/tony-xlh/document-viewer-samples/tree/main/drag-and-drop