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

来源:互联网 发布:有什么育儿软件 编辑:程序博客网 时间:2024/05/21 16:55

最近给卫生局做一个表格上传/可视化系统,算是小有成果。今天把项目中的文件拖拽上传模块分离出来,做了一个独立的小demo,并把相关代码打包上传到了我的github中,为了其他学习者和开发者提供拙见。

gitHub地址:https://github.com/codeplay2015/dragToUpload


由于代码中我的注释很详尽,所以具体逻辑实现及不介绍了,大家直接看代码及能明白。现在简单列一个功能清单和一些用到的知识点清单:

  1. 模态框
  2. 文件的批量上传
  3. 使用formData API 封装数据 并通过ajax方法提交
  4. 读取拖放文件,ondrop事件 dataTransfer对象
  5. 清空所有文件

知识点:

  1. 单例模式:构建一个单例模式的formData容器
  2. 事件冒泡,事件委托:动态添加删除单个文件的方法
  3. css各种布局,BFC
  4. CSS 伪类 link vistied hover active
  5. html 离线操作文档:创建fragment 离线操作,提高性能,减少浏览器的重绘和回流
  6. 原型链,原型方法:为formData对象添加一个删除所有文件的方法
  7. CSS伪对象,结合after伪对象画一个‘X’号,放在模态框右上角表示退出按钮

截图:
整体界面
整体界面
点击‘拖拽上传’按钮
点击‘拖拽上传’按钮
拖拽文件到虚线框,文件拖入会边框变红提示
这里写图片描述
上传成功,弹出提示
这里写图片描述

—————————-、
代码
1. html:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <link rel="stylesheet" href="demo.css"></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,创建一个接收文件的对象,因为可以多次拖拽,这里采用单例模式创建对象Dragfilesvar 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='';}
原创粉丝点击