前端页面文件拖拽上传模块js代码示例


Posted in Javascript onMay 19, 2017

最近给卫生局做一个表格上传/可视化系统,算是小有成果。今天把项目中的文件拖拽上传模块分离出来,做了一个独立的小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'号,放在模态框右上角表示退出按钮

截图:

整体界面

前端页面文件拖拽上传模块js代码示例

点击‘拖拽上传'按钮

前端页面文件拖拽上传模块js代码示例

拖拽文件到虚线框,文件拖入会边框变红提示

前端页面文件拖拽上传模块js代码示例

上传成功,弹出提示

前端页面文件拖拽上传模块js代码示例

代码:

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='';
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript下通过的XMLHttpRequest发送请求的代码
Jun 28 Javascript
使用CSS3的scale实现网页整体缩放
Mar 18 Javascript
搭建pomelo 开发环境
Jun 24 Javascript
jquery访问ashx文件示例代码
Aug 11 Javascript
浅谈JavaScript Date日期和时间对象
Dec 29 Javascript
谈谈对offsetleft兼容性的理解
Nov 11 Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
Apr 13 Javascript
微信小程序开发的四十个技术窍门总结(推荐)
Jan 23 Javascript
vue中的event bus非父子组件通信解析
Oct 27 Javascript
初识 Vue.js 中的 *.Vue文件
Nov 22 Javascript
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
Apr 28 Javascript
Layer组件多个iframe弹出层打开与关闭及参数传递的方法
Sep 25 Javascript
jQuery操作之效果详解
May 19 #jQuery
AngularJS中的promise用法分析
May 19 #Javascript
几种响应式文字详解
May 19 #Javascript
关于Bootstrap按钮组件消除黄框的方法
May 19 #Javascript
vue.js动态数据绑定学习笔记
May 19 #Javascript
Node.JS利用PhantomJs抓取网页入门教程
May 19 #Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
May 19 #Javascript
You might like
一个简洁的多级别论坛
2006/10/09 PHP
php SQL防注入代码集合
2008/04/25 PHP
ThinkPHP中redirect用法分析
2014/12/05 PHP
php+jQuery+Ajax实现点赞效果的方法(附源码下载)
2020/07/21 PHP
php等比例缩放图片及剪切图片代码分享
2016/02/13 PHP
PHP中echo与print区别点整理
2021/03/09 PHP
jQuery语法总结和注意事项小结
2012/11/11 Javascript
IE关闭时判断及AJAX注销案例学习
2013/02/18 Javascript
JavaScript创建闭包的两种方式的优劣与区别分析
2015/06/22 Javascript
jQuery实现form表单基于ajax无刷新提交方法详解
2015/12/08 Javascript
javascript点击按钮实现隐藏显示切换效果
2016/02/03 Javascript
swiper动态改变滑动内容的实现方法
2018/01/17 Javascript
Vue.js实现图片的随意拖动方法
2018/03/08 Javascript
vue2.x集成百度UEditor富文本编辑器的方法
2018/09/21 Javascript
使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)
2018/10/23 Javascript
如何使用Node.js爬取任意网页资源并输出PDF文件到本地
2019/06/17 Javascript
jquery添加div实现消息聊天框
2020/02/08 jQuery
JS删除对象中某一属性案例详解
2020/09/08 Javascript
javascript实现打砖块小游戏(附完整源码)
2020/09/18 Javascript
Python自动重试HTTP连接装饰器
2015/04/28 Python
python实现中文转换url编码的方法
2016/06/14 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Python中%是什么意思?python中百分号如何使用?
2018/03/20 Python
Django app配置多个数据库代码实例
2019/12/17 Python
python实现超级马里奥
2020/03/18 Python
Python趣味入门教程之循环语句while
2020/08/26 Python
详解Python中的文件操作
2021/01/14 Python
大学生职业规划前言模板
2013/12/27 职场文书
大学生创业计划书的用途
2014/01/08 职场文书
淘宝活动总结范文
2014/06/26 职场文书
公司劳动纪律管理制度
2015/08/04 职场文书
2016年政治理论学习心得体会
2016/01/25 职场文书
Pytorch 中net.train 和 net.eval的使用说明
2021/05/22 Python
解决Pytorch dataloader时报错每个tensor维度不一样的问题
2021/05/28 Python
spring boot中nativeQuery的用法
2021/07/26 Java/Android
PostgreSQL常用字符串分割函数整理汇总
2022/07/07 PostgreSQL