前端页面文件拖拽上传模块js代码示例
作者:codeplay_guo 发布时间:2023-09-20 02:15:30
标签:js,文件上传,拖拽
最近给卫生局做一个表格上传/可视化系统,算是小有成果。今天把项目中的文件拖拽上传模块分离出来,做了一个独立的小demo,并把相关代码打包上传到了我的github中,为了其他学习者和开发者提供拙见。
gitHub地址:https://github.com/codeplay2015/dragToUpload
由于代码中我的注释很详尽,所以具体逻辑实现及不介绍了,大家直接看代码及能明白。现在简单列一个功能清单和一些用到的知识点清单:
模态框
文件的批量上传
使用formData API 封装数据 并通过ajax方法提交
读取拖放文件,ondrop事件 dataTransfer对象
清空所有文件
知识点:
单例模式:构建一个单例模式的formData容器
事件冒泡,事件委托:动态添加删除单个文件的方法
css各种布局,BFC
CSS 伪类 link vistied hover active
html 离线操作文档:创建fragment 离线操作,提高性能,减少浏览器的重绘和回流
原型链,原型方法:为formData对象添加一个删除所有文件的方法
CSS伪对象,结合after伪对象画一个‘X'号,放在模态框右上角表示退出按钮
截图:
整体界面
点击‘拖拽上传'按钮
拖拽文件到虚线框,文件拖入会边框变红提示
上传成功,弹出提示
代码:
1. html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="demo.css" rel="external nofollow" >
</head>
<body>
<!--遮罩-->
<div class="overlay"></div>
<!--模态框-->
<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>拖拽文件至此</b></p>
<div class="content" id="content">
<table class="table">
<tbody class="tbody"></tbody>
</table>
</div>
<div class="footer">
<button class="btn" onclick="upload()">开始上传</button>
</div>
<a href='#' onclick='clearAll()' style='position:absolute;bottom:10px;right:30px;'>清空所有</a>
</div>
</div>
</div>
<!--页面内容-->
<div style="margin-top:40vh;text-align: center;">
<p>拖拽上传演示模板。点击下方按钮,弹出模态框</p>
<button class="btn" onclick="showModal()">点击上传</button>
</div>
<!--嵌入脚本-->
<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
}
/*画一个叉号,表示推出界面*/
.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{
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代码:
function showModal() { //打开上传框
var modal = document.getElementById('modal');
var overlay = document.getElementsByClassName('overlay')[0];
overlay.style.display = 'block';
modal.style.display = 'block';
}
function closeModal() { //关闭上传框
var modal = document.getElementById('modal');
var overlay = document.getElementsByClassName('overlay')[0];
overlay.style.display = 'none';
modal.style.display = 'none';
}
//用DOM2级方法为右上角的叉号和黑色遮罩层添加事件:点击后关闭上传框
document.getElementsByClassName('overlay')[0].addEventListener('click', closeModal, false);
document.getElementById('close').addEventListener('click', closeModal, false);
//利用html5 FormData() API,创建一个接收文件的对象,因为可以多次拖拽,这里采用单例模式创建对象Dragfiles
var Dragfiles=(function (){
var instance;
return function(){
if(!instance){
instance = new FormData();
}
return instance;
}
}());
//为Dragfiles添加一个清空所有文件的方法
FormData.prototype.deleteAll=function () {
var _this=this;
this.forEach(function(value,key){
_this.delete(key);
})
}
//添加拖拽事件
var dz = document.getElementById('content');
dz.ondragover = function (ev) {
//阻止浏览器默认打开文件的操作
ev.preventDefault();
//拖入文件后边框颜色变红
this.style.borderColor = 'red';
}
dz.ondragleave = function () {
//恢复边框颜色
this.style.borderColor = 'gray';
}
dz.ondrop = function (ev) {
//恢复边框颜色
this.style.borderColor = 'gray';
//阻止浏览器默认打开文件的操作
ev.preventDefault();
var files = ev.dataTransfer.files;
var len=files.length,
i=0;
var frag=document.createDocumentFragment(); //为了减少js修改dom树的频度,先创建一个fragment,然后在fragment里操作
var tr,time,size;
var newForm=Dragfiles(); //获取单例
var it=newForm.entries(); //创建一个迭代器,测试用
while(i<len){
tr=document.createElement('tr');
//获取文件大小
size=Math.round(files[i].size * 100 / 1024) / 100 + 'KB';
//获取格式化的修改时间
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>删除</td>';
console.log(size+' '+time);
frag.appendChild(tr);
//添加文件到newForm
newForm.append(files[i].name,files[i]);
//console.log(it.next());
i++;
}
this.childNodes[1].childNodes[1].appendChild(frag);
//为什么是‘1'?文档里几乎每一样东西都是一个节点,甚至连空格和换行符都会被解释成节点。而且都包含在childNodes属性所返回的数组中.不同于jade模板
}
function blink()
{
document.getElementById('content').style.borderColor = 'gray';
}
//ajax上传文件
function upload(){
if(document.getElementsByTagName('tbody')[0].hasChildNodes()==false){
document.getElementById('content').style.borderColor = 'red';
setTimeout(blink,200);
return false;
}
var data=Dragfiles(); //获取formData
$.ajax({
url: 'upload',
type: 'POST',
data: data,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (data) {
alert('succeed!') //可以替换为自己的方法
closeModal();
data.deleteAll(); //清空formData
$('.tbody').empty(); //清空列表
},
error: function (returndata) {
alert('failed!') //可以替换为自己的方法
}
});
}
// 用事件委托的方法为‘删除'添加点击事件,使用jquery中的on方法
$(".tbody").on('click','tr td:last-child',function(){
//删除拖拽框已有的文件
var temp=Dragfiles();
var key=$(this).prev().prev().prev().text();
console.log(key);
temp.delete(key);
$(this).parent().remove();
});
//清空所有内容
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(); //清空formData
//$('.tbody').empty(); 等同于以下方法
document.getElementsByTagName('tbody')[0].innerHTML='';
}


猜你喜欢
- jQuery源码里自己也有很多用到each方法。其实jQuery里的each方法是通过js里的call方法来实现的。下面简单介绍一下call
- 一:区别:1、var声明的变量属于函数作用域,而let和const声明的变量属于块级作用域;(js作用域在上篇文章) 2、var声
- 表单的验证是开发WEB应用程序中常遇到的一关。有时候我们必须保证表单的某些项必须填写、必须为数字、必须是指定的位数等等,这时候就要用到表单验
- 记得以前的windows 任务定时是可以的正常使用的,今天试了下,发现不能正常使用了,任务计划总是挂起。接下来记录下python 爬虫定时任
- cuda上tensor的定义a = torch.ones(1000,1000,3).cuda()某一gpu上定义cuda1 = torch.
- super()函数可以用于继承父类的方法,语法如下:super(type[, object-or-type])虽然super()函数的使用比
- 🌟 写在前面专栏介绍:凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技术文章,Vue 框架目
- <html> <head> <title>获取ACCESS数据库表名 -&
- #!/usr/bin/env python import os, sys, time while True: time.sleep(3) t
- 我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用
- 一.概述:Selenium是一个用于Web应用程序测试的工具,本文使用的是Selenium 2。Selenium就是一套类库,不依赖于任何测
-   这篇博客讲的是SQL server的分页方法,用的SQL server 2012版本。下面都用pag
- 本文实例讲述了JS实现json数组排序操作。分享给大家供大家参考,具体如下:有时需要根据json对象的某个属性排序json数组,javasc
- 对有自增长字段的表导入数据注意事项: 1、把自增长字段暂时设置成非自增长的;导入数据成功后,再设置成自增长字段。 2、导出、导入数据时,注意
- MAC地址也叫物理地址、硬件地址,由网络设备制造商生产时烧录在网卡(Network lnterface Card)的EPROM(一种闪存芯片
- 最近看到一个内部项目的插件加载机制,非常赞。当然这里说的插件并不是指的golang原生的可以在buildmode中加载指定so文件的那种加载
- Protobuf是google开发的一个序列化和反序列化的协议库,我们可以自己设计传递数据的格式,通过.proto文件定义我们的要传递的数据
- 一、TensorFlow介绍1、简介 TensorFlow是一个基于数据流编程(dataflow programming)的符号数学系统,
- 在上一个文章里写了关于左(右)侧定宽右(左)侧自动缩放的两列浮动,这个文章就要说一下三列浮动的问题了。在之前说过,两列浮动是其他多列浮动的基
- 首先官网上的树形控件教程地址为Element - The world's most popular Vue UI framework