前端页面文件拖拽上传模块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 相关文章推荐
js post方式传递提交的实现代码
May 31 Javascript
别了 JavaScript中的isXX系列
Aug 01 Javascript
JS实现图片预加载无需等待
Dec 21 Javascript
jquery 实现窗口的最大化不论什么情况
Sep 03 Javascript
js动态设置鼠标事件示例代码
Oct 30 Javascript
js使用DOM操作实现简单留言板的方法
Apr 10 Javascript
jquery实现的仿天猫侧导航tab切换效果
Aug 24 Javascript
javascript 判断页面访问方式电脑或者移动端
Sep 19 Javascript
bootstrap与Jquery UI 按钮样式冲突的解决办法
Sep 23 Javascript
JavaScript中正则表达式判断匹配规则及常用方法
Aug 03 Javascript
JS实现简单的点赞与踩功能示例
Dec 05 Javascript
用Vue.js在浏览器中实现裁剪图像功能
Jun 18 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 SEO优化之URL优化方法
2011/04/21 PHP
php实现遍历目录并删除指定文件中指定内容
2015/01/21 PHP
PHP中实现获取IP和地理位置类分享
2015/02/10 PHP
PHP基于phpqrcode生成带LOGO图像的二维码实例
2015/07/10 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
2016/11/15 PHP
php面向对象程序设计入门教程
2019/06/22 PHP
redis+php实现微博(一)注册与登录功能详解
2019/09/23 PHP
jQuery中需要注意的细节问题小结
2011/12/06 Javascript
CodeMirror2 IE7/IE8 下面未知运行时错误的解决方法
2012/03/29 Javascript
JavaScript中读取和保存文件实例
2014/05/08 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
在JavaScript应用中实现延迟加载的方法
2015/06/25 Javascript
浅谈javascript中关于日期和时间的基础知识
2016/07/13 Javascript
vue+axios实现登录拦截的实例代码
2017/05/22 Javascript
bootstrap 通过加减按钮实现输入框组功能
2017/11/15 Javascript
H5+C3+JS实现五子棋游戏(AI篇)
2020/05/28 Javascript
微信小程序搜索功能(附:小程序前端+PHP后端)
2019/02/28 Javascript
原生js实现随机点名功能
2019/11/05 Javascript
Nuxt v-bind绑定img src不显示的解决
2019/12/05 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
2020/07/30 Javascript
解决Vue项目中tff报错的问题
2020/10/21 Javascript
Python中使用插入排序算法的简单分析与代码示例
2016/05/04 Python
Python错误提示:[Errno 24] Too many open files的分析与解决
2017/02/16 Python
python3.7 sys模块的具体使用
2019/07/22 Python
Python3爬虫关于代理池的维护详解
2020/07/30 Python
网吧最新创业计划书范文
2014/03/27 职场文书
报关报检委托书
2014/04/08 职场文书
幼儿园运动会口号
2014/06/07 职场文书
收费员岗位职责
2015/02/14 职场文书
好员工观后感
2015/06/17 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js
python cv2图像质量压缩的算法示例
2021/06/04 Python
Java中使用Filter过滤器的方法
2021/06/28 Java/Android
vue+element ui实现锚点定位
2021/06/29 Vue.js
深入解析MySQL索引数据结构
2021/10/16 MySQL
Vue router配置与使用分析讲解
2022/12/24 Vue.js