前端页面文件拖拽上传模块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中的History历史对象
Jan 16 Javascript
jquery 为a标签绑定click事件示例代码
Jun 23 Javascript
自定义Angular指令与jQuery实现的Bootstrap风格数据双向绑定的单选与多选下拉框
Dec 12 Javascript
总结jQuery插件开发中的一些要点
May 16 Javascript
浅析JavaScript中的对象类型Object
May 26 Javascript
angularJS 发起$http.post和$http.get请求的实现方法
May 18 Javascript
Bootstrap弹出框(Popover)被挤压的问题小结
Jul 11 Javascript
基于Vue生产环境部署详解
Sep 15 Javascript
jquery登录的异步验证操作示例
May 09 jQuery
详解javascript中var与ES6规范中let、const区别与用法
Jan 11 Javascript
JS实现纵向轮播图(初级版)
Jan 18 Javascript
js回到页面指定位置的三种方式
Dec 17 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
php Try Catch异常测试
2009/03/01 PHP
简单的php 验证图片生成函数
2009/05/21 PHP
php面向对象全攻略 (三)特殊的引用“$this”的使用
2009/09/30 PHP
无法载入 mcrypt 扩展,请检查 PHP 配置终极解决方案
2011/07/18 PHP
PHP使用数组实现队列
2012/02/05 PHP
php读取文件内容至字符串中,同时去除换行、空行、行首行尾空格(Zjmainstay原创)
2012/07/31 PHP
linux下编译安装memcached服务
2014/08/03 PHP
PHP进阶学习之依赖注入与Ioc容器详解
2019/06/19 PHP
JavaScript 页面编码与浏览器类型判断代码
2010/06/03 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
枚举的实现求得1-1000所有出现1的数字并计算出现1的个数
2013/09/10 Javascript
动态加载JS文件的三种方法
2013/11/08 Javascript
JavaScript中实现sprintf、printf函数
2015/01/27 Javascript
jquery通过closest选择器修改上级元素的方法
2015/03/17 Javascript
js生成随机数(指定范围)的实例代码
2016/07/10 Javascript
AngularJs 利用百度地图API 定位当前位置 获取地址信息
2017/01/18 Javascript
vue router demo详解
2017/10/13 Javascript
基于JavaScript实现抽奖系统
2018/01/16 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
2020/09/21 Javascript
Python命名空间详解
2014/08/18 Python
Python实现删除文件但保留指定文件
2015/06/21 Python
python搭建虚拟环境的步骤详解
2016/09/27 Python
python中numpy.zeros(np.zeros)的使用方法
2017/11/07 Python
Python中import机制详解
2017/11/14 Python
python实现简单颜色识别程序
2020/02/19 Python
浅谈Python __init__.py的作用
2020/10/28 Python
产品销售员岗位职责
2013/12/18 职场文书
《小猪家的桃花树》教学反思
2014/04/11 职场文书
二年级小学生评语
2014/04/21 职场文书
工作求职自荐信
2014/06/13 职场文书
交通事故赔偿协议书怎么写
2014/10/04 职场文书
元宵节晚会主持词
2015/07/01 职场文书
vue项目两种方式实现竖向表格的思路分析
2021/04/28 Vue.js
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python
Python安装使用Scrapy框架
2022/04/12 Python
vue组件vue-esign实现电子签名
2022/04/21 Vue.js