前端頁面文件拖拽上傳模塊js代碼示例
最近給衛(wèi)生局做一個表格上傳/可視化系統(tǒng),算是小有成果。今天把項(xiàng)目中的文件拖拽上傳模塊分離出來,做了一個獨(dú)立的小demo,并把相關(guān)代碼打包上傳到了我的github中,為了其他學(xué)習(xí)者和開發(fā)者提供拙見。
gitHub地址:https://github.com/codeplay2015/dragToUpload
由于代碼中我的注釋很詳盡,所以具體邏輯實(shí)現(xiàn)及不介紹了,大家直接看代碼及能明白?,F(xiàn)在簡單列一個功能清單和一些用到的知識點(diǎn)清單:
- 模態(tài)框
- 文件的批量上傳
- 使用formData API 封裝數(shù)據(jù) 并通過ajax方法提交
- 讀取拖放文件,ondrop事件 dataTransfer對象
- 清空所有文件
知識點(diǎn):
- 單例模式:構(gòu)建一個單例模式的formData容器
- 事件冒泡,事件委托:動態(tài)添加刪除單個文件的方法
- css各種布局,BFC
- CSS 偽類 link vistied hover active
- html 離線操作文檔:創(chuàng)建fragment 離線操作,提高性能,減少瀏覽器的重繪和回流
- 原型鏈,原型方法:為formData對象添加一個刪除所有文件的方法
- CSS偽對象,結(jié)合after偽對象畫一個‘X'號,放在模態(tài)框右上角表示退出按鈕
截圖:
整體界面
點(diǎn)擊‘拖拽上傳'按鈕
拖拽文件到虛線框,文件拖入會邊框變紅提示
上傳成功,彈出提示
代碼:
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> <!--模態(tài)框--> <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> <!--頁面內(nèi)容--> <div style="margin-top:40vh;text-align: center;"> <p>拖拽上傳演示模板。點(diǎn)擊下方按鈕,彈出模態(tài)框</p> <button class="btn" onclick="showModal()">點(diǎn)擊上傳</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() { //關(guān)閉上傳框 var modal = document.getElementById('modal'); var overlay = document.getElementsByClassName('overlay')[0]; overlay.style.display = 'none'; modal.style.display = 'none'; } //用DOM2級方法為右上角的叉號和黑色遮罩層添加事件:點(diǎn)擊后關(guān)閉上傳框 document.getElementsByClassName('overlay')[0].addEventListener('click', closeModal, false); document.getElementById('close').addEventListener('click', closeModal, false); //利用html5 FormData() API,創(chuàng)建一個接收文件的對象,因?yàn)榭梢远啻瓮献?,這里采用單例模式創(chuàng)建對象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) { //阻止瀏覽器默認(rèn)打開文件的操作 ev.preventDefault(); //拖入文件后邊框顏色變紅 this.style.borderColor = 'red'; } dz.ondragleave = function () { //恢復(fù)邊框顏色 this.style.borderColor = 'gray'; } dz.ondrop = function (ev) { //恢復(fù)邊框顏色 this.style.borderColor = 'gray'; //阻止瀏覽器默認(rèn)打開文件的操作 ev.preventDefault(); var files = ev.dataTransfer.files; var len=files.length, i=0; var frag=document.createDocumentFragment(); //為了減少js修改dom樹的頻度,先創(chuàng)建一個fragment,然后在fragment里操作 var tr,time,size; var newForm=Dragfiles(); //獲取單例 var it=newForm.entries(); //創(chuàng)建一個迭代器,測試用 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'?文檔里幾乎每一樣?xùn)|西都是一個節(jié)點(diǎn),甚至連空格和換行符都會被解釋成節(jié)點(diǎn)。而且都包含在childNodes屬性所返回的數(shù)組中.不同于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!') //可以替換為自己的方法 } }); } // 用事件委托的方法為‘刪除'添加點(diǎn)擊事件,使用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(); }); //清空所有內(nèi)容 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=''; }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解微信小程序開發(fā)聊天室—實(shí)時聊天,支持圖片預(yù)覽
這篇文章主要介紹了微信小程序?qū)崟r聊天支持圖片預(yù)覽,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05使用JS在瀏覽器中判斷當(dāng)前網(wǎng)絡(luò)連接狀態(tài)的幾種方法
本篇文章主要介紹了使用JS在瀏覽器中判斷當(dāng)前網(wǎng)絡(luò)狀態(tài)的幾種方法,非常具有實(shí)用價值,需要的朋友可以參考下2017-05-05Bootstrap組件學(xué)習(xí)之導(dǎo)航、標(biāo)簽、面包屑導(dǎo)航(精品)
這篇文章主要介紹了Bootstrap組件學(xué)習(xí)之導(dǎo)航、標(biāo)簽、面包屑導(dǎo)航(精品)的相關(guān)資料,需要的朋友可以參考下2016-05-05JavaScript 解析數(shù)學(xué)表達(dá)式的過程詳解
這篇文章主要介紹了JavaScript 解析數(shù)學(xué)表達(dá)式的過程詳解,本文以一個的解題思路,來分享如何解決問題,解決的過程,可以作為解決工作中一般問題的通用思路,對js解析表達(dá)式相關(guān)知識感興趣的朋友一起看看吧2022-06-06利用Js的console對象,在控制臺打印調(diào)式信息測試Js的實(shí)現(xiàn)
下面小編就為大家?guī)硪黄肑s的console對象,在控制臺打印調(diào)式信息測試Js的實(shí)現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11javascript通過元素id和name直接取得元素的方法
這篇文章主要介紹了javascript通過元素id和name直接取得元素的方法,涉及javascript獲取元素的相關(guān)技巧,非常具有實(shí)用價值,需要的朋友可以參考下2015-04-04php和js對數(shù)據(jù)庫圖片進(jìn)行等比縮放示例
這篇文章主要介紹了php和js如何對數(shù)據(jù)庫圖片進(jìn)行等比縮放,需要的朋友可以參考下2014-04-04基于iframe實(shí)現(xiàn)類似于ajax的頁面無刷新
本方法是基于iframe實(shí)現(xiàn)的,需求是form表單提交帶有文件上傳的input標(biāo)簽,示例如下,感興趣的朋友可以參考下2014-05-05讓網(wǎng)頁根據(jù)不同IE版本顯示不同的內(nèi)容
在上一篇blog 《IE8里判斷當(dāng)前網(wǎng)頁顯示模式》里面提到IE有不同的顯示模式以及如何用Javascript 來動態(tài)判定。 Web開發(fā)者可以根據(jù)不同顯示模式導(dǎo)入不同的內(nèi)容。2009-02-02