HTML5 Drag&Drop 同瀏覽器跨文件拖拉
Sat, 09 Oct 2010 19:42:41 +0800除了跨應用軟體間的drag&drop,另外一個可以測試的是同一瀏覽器但是不同視窗不同文件之間的drag&drop。其實使用的方式跟前面兩篇文章:HTML5 Drag&Drop + 純AJAX檔案上傳以及一個簡單的HTML5 Drag & Drop試作差不多。目前測試到比較可用的方式,是過濾Event.dataTransfer.types,看看裡面是否有一筆資料為'text/uri-list',然後用Event.dataTransfer.getData('text/uri-list')就可以取得拖拉檔案的網址,接下來就可以使用這個資料來做一些處理。
如果要讓網頁可以同時處理其他應用軟體與跨文件drag&drop,我想到比較好的方式是先透過Event.dataTransfer.types裡面是否有'Files'字串來判斷(DataTransfer.types)。但是這時發現Firefox4 Beta6有一個問題...Orz。在從另一個Firefox視窗拖曳圖檔進來時,並沒有在Event.dataTransfer.files設定檔案資料,但是Event.dataTransfer.types卻有一筆資料是'Files',這樣會造成原本的程式邏輯有問題。所以只好額外用Event.dataTransfer.files.length來判斷是否有檔案資料。
利用這樣的判斷方式,就可以在有圖檔的File物件收到時,上傳檔案並且顯示上傳後的檔案。如果收到的資料是圖檔的url,就利用這個url來顯示圖檔。以下是從前兩篇文章再做修改的測試:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style> span#panel { display: inline-block; background: #336699; width: 140px; height: 180px; border: solid black 2px; border-radius: 10px; padding: 5px; text-align: center; color: white; vertical-align: middle; } span { display: inline-block; vertical-align: middle; } div.msg { display: block; background: #6699CC; width: 480px; height: 50px; border: solid black 2px; border-radius: 10px; padding: 5px; text-align: center; color: white; margin: 1px; vertical-align: middle; } div#container { vertical-align: baseline; border: solid 1px white; padding: 5px; text-align: center; } </style> <script src="fwajax3.js"></script> </head> <body> <div style="text-align:center"><h4>HTML5 Drag&Drop with pure AJAX file upload test.</h4></div> <div id="container"><span id="panel">Drop image here.<br></span> <span><div class="msg" id="msg1"></div><div class="msg" id="msg2"></div><div class="msg" id="msg3"></div></span></div> </body> </html> <script> document.ondragenter = function(e){e.preventDefault();} document.ondragover = function(e){e.preventDefault();} document.getElementById('panel').addEventListener('dragenter', function(e){ e.preventDefault(); if(window.console) console.log('dragenter'); e.effectAllowed = ['move']; },false); document.getElementById('panel').addEventListener('dragover', function(e){ e.preventDefault(); if(window.console) console.log('dragover'); e.dataTransfer.dropEffect = 'move'; },false); document.getElementById('panel').addEventListener('drop', function(e){ e.preventDefault(); e.dataTransfer.dropEffect = 'move'; if(window.console) console.log('drop'); if(window.console) console.log(e.dataTransfer); if(e.dataTransfer.types && e.dataTransfer.types.length>0) { var isFile = false; for(var i=0; i<e.dataTransfer.types.length; i++) { if(e.dataTransfer.types[i] === 'Files' && e.dataTransfer.files.length>0) isFile = true; } for(var i=0; i<e.dataTransfer.types.length; i++) { if(window.console) console.log(e.dataTransfer.types[i]); if(e.dataTransfer.types[i]==='Files') { if(e.dataTransfer.files.length>0) { for(var j=0; j<e.dataTransfer.files.length; j++) { switch(e.dataTransfer.files[j].type) { case 'image/jpeg': case 'image/gif': case 'image/png': case 'image/bmp': document.getElementById('msg1').innerHTML = 'File name: <br>'+e.dataTransfer.files[j].name; document.getElementById('msg2').innerHTML = ''; document.getElementById('msg3').innerHTML = ''; setTimeout(function(blob){ return function() { var fileReader = new FileReader(); fileReader.onload = function() { if(window.console) console.log('got an image file.'); //if(window.console) console.log(this.result); var uploader = new fwH5AjaxUploader( 'save_ajax.php', function(_txt,_xml) { if(window.console) console.log(_txt); var msg = JSON.parse(_txt); if(msg.state == 'success') { document.getElementById('msg3').innerHTML = 'File uploaded: <br>'+blob.name; var img = document.createElement('img'); img.src = msg.path; img.width = '110'; img.style = "text-align:center"; document.getElementById('panel').innerHTML = 'Drop Here.<p>'; document.getElementById('panel').appendChild(img); img = null; } } ); uploader.addFile( 'fileupload', {'name':blob.name,'type':blob.type,'data':this.result.slice(this.result.indexOf(",")+1)}, 'base64' ); document.getElementById('msg2').innerHTML = 'Start uploading: <br>'+blob.name; uploader.send(); }; try { fileReader.readAsDataURL(blob); } catch(e) { alert(e); } }; }(e.dataTransfer.files[j]),100); break; default: alert('Only image file allowed.\nIncluding: jpeg, png, gif and bmp.'); break; } } } } if(!isFile && e.dataTransfer.types[i]!=='Files') { var type = e.dataTransfer.types[i]; if(window.console) console.log(type); if('text/uri-list' === type || 'text/x-moz-url' === type) { var msg = e.dataTransfer.getData(type); if(window.console) console.log(msg); var filename = msg.split('/')[msg.split('/').length-1].split('?')[0]; var allowed = ['jpg','gif','png','bmp']; var isAllowed = false; for(var m=0; m<allowed.length; m++) { if(filename.toLowerCase().indexOf(allowed[m])>-1) { isAllowed = true; break; } } if(isAllowed) { var img = document.createElement('img'); img.src = msg; img.width = '110'; var panel = document.getElementById('panel'); panel.innerHTML = 'Drop Here.<p>'; panel.appendChild(img); document.getElementById('msg1').innerHTML = 'File name: <br>' + msg.split('/')[msg.split('/').length-1]; document.getElementById('msg2').innerHTML = 'Linked from: <br>' + msg; document.getElementById('msg3').innerHTML = 'Linked.'; } else { alert('Only image file allowed.\nIncluding: jpeg, png, gif and bmp.'); } } } } } },false); </script>save_ajax.php以及fwajax3.js請參考前篇,程式是一樣的。
接下來看一下操作的截圖:
這是跨文件拖拉圖檔,會直接使用url |
這是從系統拖拉圖檔上傳的結果 |
2010-10-9 19:56 補充:
仔細觀察了一下DataTransfer物件,發現從Chrome7拖拉網頁中的圖檔到Firefox4時,會收到的資料主要是'text/uri-list',但是從Firefox4拖拉網頁中的圖檔到Chrome7時,會收到File物件及'text/uri-list'。我測試程式的邏輯有一點混亂,不過我不想再調整了...不過同時收到File物件及'text/uri-list'時,還是做一下判斷比較好,在不需要上傳檔案的情況下,也許直接使用url就可以了。