前端页面文件拖拽上传模块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 相关文章推荐
HTML中不支持静态Expando的元素的问题
Mar 08 Javascript
flexigrid 参数说明
Nov 23 Javascript
在JavaScript并非所有的一切都是对象
Apr 11 Javascript
Jquery实现点击切换图片并隐藏显示内容(2种方法实现)
Apr 11 Javascript
用js控制组织结构图可以任意拖拽到指定位置
Jan 17 Javascript
学习JavaScript设计模式(多态)
Nov 25 Javascript
详解Angular 自定义结构指令
Jun 21 Javascript
基于vue+canvas的excel-like组件实例详解
Nov 28 Javascript
对angularJs中$sce服务安全显示html文本的实例
Sep 30 Javascript
vue移动端屏幕适配详解
Apr 30 Javascript
Element InfiniteScroll无限滚动的具体使用方法
Jul 27 Javascript
Vue绑定用户接口实现代码示例
Nov 04 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
php5.2时间相差8小时
2007/01/15 PHP
攻克CakePHP系列二 表单数据显示
2008/10/22 PHP
PHP中将网页导出为Word文档的代码
2012/05/25 PHP
使用php伪造referer的方法 利用referer防止图片盗链
2014/01/20 PHP
PHP模板引擎Smarty之配置文件在模板变量中的使用方法示例
2016/04/11 PHP
Extjs EditorGridPanel中ComboBox列的显示问题
2011/07/04 Javascript
基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
2013/04/26 Javascript
JavaScript创建对象的写法
2013/08/29 Javascript
js实现图片在未加载完成前显示加载中字样
2014/09/03 Javascript
jquery ztree实现树的搜索功能
2016/02/25 Javascript
使用Jasmine和Karma对AngularJS页面程序进行测试
2016/03/05 Javascript
javascript对浅拷贝和深拷贝的详解
2016/10/14 Javascript
可输入文字查找ajax下拉框控件 ComBox的实现方法
2016/10/25 Javascript
微信小程序  action-sheet详解及实例代码
2016/11/09 Javascript
jQuery html表格排序插件tablesorter使用方法详解
2017/02/10 Javascript
关于jquery layui弹出层的使用方法
2018/04/21 jQuery
jQuery实现获取选中复选框的值实例详解
2018/06/28 jQuery
JavaScript中为事件指定处理程序的五种方式分析
2018/07/27 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
2018/08/22 Javascript
详解在网页上通过JS实现文本的语音朗读
2019/03/28 Javascript
JavaScript使用面向对象实现的拖拽功能详解
2019/06/12 Javascript
Vue3.0数据响应式原理详解
2019/10/09 Javascript
如何实现js拖拽效果及原理解析
2020/05/08 Javascript
举例讲解Python设计模式编程的代理模式与抽象工厂模式
2016/01/16 Python
Python使用combinations实现排列组合的方法
2018/11/13 Python
解决py2exe打包后,总是多显示一个DOS黑色窗口的问题
2019/06/21 Python
对django layer弹窗组件的使用详解
2019/08/31 Python
MNIST数据集转化为二维图片的实现示例
2020/01/10 Python
Pycharm2020.1安装无法启动问题即设置中文插件的方法
2020/08/07 Python
亚历山大·王官网:Alexander Wang
2017/06/23 全球购物
领先的英国注册在线药房 :Simply Meds Online
2019/03/28 全球购物
Intersport西班牙:在线体育商店
2019/11/06 全球购物
2014端午节活动策划方案
2014/01/27 职场文书
预备党员学习十八届三中全会精神思想汇报
2014/09/13 职场文书
用Python进行栅格数据的分区统计和批量提取
2021/05/27 Python
利用Pycharm连接服务器的全过程记录
2021/07/01 Python