Recently, a form upload/visualization system has been developed for the Health Bureau, which is a little fruitful. Today, I separated the file drag and upload module from the project, made a small independent demo, and uploaded the relevant code packages to my github, for the sake of other learners and developers.
gitHub address: https://github.com/codeplay2015/dragToUpload
Because my comments in the code are very detailed, so the specific logic implementation and not introduced, you can directly see the code and understand. Now make a simple list of functions and some knowledge points used:
- Modal frame
- Batch upload of documents
- Encapsulating data using the formData API and submitting it through the ajax method
- Read the drag-and-drop file, ondrop event dataTransfer object
- Clean up all documents
Knowledge Points:
- Singleton pattern: Build a formData container for a singleton pattern
- Event Bubble, Event Delegation: Dynamic Addition and Deletion of a Single File
- css layout, BFC
- CSS pseudoclass link vistied hover active
- html offline operation document: create fragment offline operation, improve performance, reduce redrawing and reflow of browser
- Prototype Chain, Prototype Method: Add a method to delete all files for the formData object
- CSS pseudo-object, drawing an `X'number with after pseudo-object, and putting it in the upper right corner of the modal box to indicate the exit button
Screenshot:
Integral interface
Click on the drag-and-upload button
Drag the file to the dotted line box. Drag the file into the dotted line box will cause the border to turn red.
Successful upload, pop-up prompt
----—-,
Code
1. html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="demo.css">
</head>
<body>
<!--Mask-->
<div class="overlay"></div>
<!--Modal frame-->
<div id="modal" class="dropbox">
<div class="items-container">
<div id="close" style="cursor:pointer;float: right;width:20px">
<span class="css-close"></span>
</div>
<div>
<p class="head"><b>Drag files to this point</b></p>
<div class="content" id="content">
<table class="table">
<tbody class="tbody"></tbody>
</table>
</div>
<div class="footer">
<button class="btn" onclick="upload()">Start uploading</button>
</div>
<a href='#' onclick='clearAll()' style='position:absolute;bottom:10px;right:30px;'>Empty all</a>
</div>
</div>
</div>
<!--Page content-->
<div style="margin-top:40vh;text-align: center;">
<p>Drag and upload the demo template. Click the button below to pop up the modal box</p>
<button class="btn" onclick="showModal()">Click Upload</button>
</div>
<!--Embedded script-->
<script src="jquery-1.10.2.js" type="text/javascript"></script>
<script src="demo.js" type="text/javascript"></script>
</body>
</html>
CSS
.overlay{
z-index: 99;
position:fixed;
display: none;
top:0;
left:0;
width: 100%;
height: 100%;
background-color: #333;
opacity:0.5;
}
.dropbox{
z-index: 100;
display: none;
position: fixed;
width:500px;
height:520px;
margin:auto;
top:0;
right:0;
bottom: 0;
left:0;
background-color: #fff;
border-radius:6px;
transition-duration: 0.9s;
-webkit-transition-duration: 0.9s;
overflow:hidden;
text-align: center;
}
.items-container{
padding: 10px;
}
.content{
border: 3px dashed gray;
border-radius: 10px;
margin: 10px 20px;
height:400px;
overflow: auto;
padding:2px 8px;
}
.head{
margin:0px;
font-size:30px;
color:#aaa;
}
.footer{
margin:5px auto
}
.btn{
border-radius: 20px;
box-sizing: border-box;
border-width: 2px;
background-color: transparent;
font-size: 14px;
font-weight: 500;
padding: 7px 18px
}
/*Draw a cross to indicate the push-out interface*/
.css-close{display:inline-block; width:15px; height:2px; background:#000; font-size:0; line-height:0;vertical-align:middle;-webkit-transform: rotate(45deg);}
.css-close:after { content:'.'; display:block; width:15px; height:2px; background:#000;-webkit-transform: rotate(90deg);}
/*Table Style*/
.table{
width:100%;
border-collapse: collapse;
}
#content tr:first-child td{
border-top-width: 0px;
}
#content tr td:last-child{
cursor: pointer;
color: red;
}
#content tr td{
padding: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
border-top:1px solid #9A9A9A;
}
#content tr:hover{
background-color: #d5d5d5;
}
#content tr:active{
background-color: #9A9A9A;
}
a:link{
color:blue;
}
a:visited{
color:blue;
}
a:hover{
color:blue;
}
a:active{
color:red;
}
js code:
function showModal() { //Open the upload box
var modal = document.getElementById('modal');
var overlay = document.getElementsByClassName('overlay')[0];
overlay.style.display = 'block';
modal.style.display = 'block';
}
function closeModal() { //Close the upload box
var modal = document.getElementById('modal');
var overlay = document.getElementsByClassName('overlay')[0];
overlay.style.display = 'none';
modal.style.display = 'none';
}
//Add Events to the Fork and Black Mask Layer in the Upper Right corner with DOM2 Level Method: Close Upload Box after Clicking
document.getElementsByClassName('overlay')[0].addEventListener('click', closeModal, false);
document.getElementById('close').addEventListener('click', closeModal, false);
//Using the html5 FormData() API, create an object that receives files, because it can be dragged and dropped many times. Here we use the singleton mode to create object Dragfiles.
var Dragfiles=(function (){
var instance;
return function(){
if(!instance){
instance = new FormData();
}
return instance;
}
}());
//Add a way to empty all files for Dragfiles
FormData.prototype.deleteAll=function () {
var _this=this;
this.forEach(function(value,key){
_this.delete(key);
})
}
//Add drag events
var dz = document.getElementById('content');
dz.ondragover = function (ev) {
//Prevent browsers from opening files by default
ev.preventDefault();
//Drag the file and the border turns red
this.style.borderColor = 'red';
}
dz.ondragleave = function () {
//Restore border color
this.style.borderColor = 'gray';
}
dz.ondrop = function (ev) {
//Restore border color
this.style.borderColor = 'gray';
//Prevent browsers from opening files by default
ev.preventDefault();
var files = ev.dataTransfer.files;
var len=files.length,
i=0;
var frag=document.createDocumentFragment(); //In order to reduce the frequency of js modifying dom tree, first create a fragment, and then operate in the fragment
var tr,time,size;
var newForm=Dragfiles(); //Getting singletons
var it=newForm.entries(); //Create an iterator for testing
while(i<len){
tr=document.createElement('tr');
//Get file size
size=Math.round(files[i].size * 100 / 1024) / 100 + 'KB';
//Get the formatting modification time
time = files[i].lastModifiedDate.toLocaleDateString() + ' '+files[i].lastModifiedDate.toTimeString().split(' ')[0];
tr.innerHTML='<td>'+files[i].name+'</td><td>'+time+'</td><td>'+size+'</td><td>delete</td>';
console.log(size+' '+time);
frag.appendChild(tr);
//Add files to newForm
newForm.append(files[i].name,files[i]);
//console.log(it.next());
i++;
}
this.childNodes[1].childNodes[1].appendChild(frag);
//Why is it `1'? Almost everything in a document is a node, and even spaces and newline characters are interpreted as nodes. And they are all included in the array returned by the child Nodes attribute. Unlike the jade template
}
function blink()
{
document.getElementById('content').style.borderColor = 'gray';
}
//ajax upload file
function upload(){
if(document.getElementsByTagName('tbody')[0].hasChildNodes()==false){
document.getElementById('content').style.borderColor = 'red';
setTimeout(blink,200);
return false;
}
var data=Dragfiles(); //Get formData
$.ajax({
url: 'upload',
type: 'POST',
data: data,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (data) {
alert('succeed!') //Can be replaced by your own method
closeModal();
data.deleteAll(); //Clear formData
$('.tbody').empty(); //clear list
},
error: function (returndata) {
alert('failed!') //Can be replaced by your own method
}
});
}
// Add click events for deletion by event delegation, using on Method in jquery
$(".tbody").on('click','tr td:last-child',function(){
//Delete existing files in drag-and-drop boxes
var temp=Dragfiles();
var key=$(this).prev().prev().prev().text();
console.log(key);
temp.delete(key);
$(this).parent().remove();
});
//Clear everything up
function clearAll(){
if(document.getElementsByTagName('tbody')[0].hasChildNodes()==false){
document.getElementById('content').style.borderColor = 'red';
setTimeout(blink,300);
return false;
}
var data=Dragfiles();
data.deleteAll(); //Clear formData
//$('. tbody').empty(); equivalent to the following method
document.getElementsByTagName('tbody')[0].innerHTML='';
}