Przeciąganie plików, czyli wczytywanie za pomocą metody drag&drop
Wczytywanie różnego rodzaju plików (zdjęć, dokumentów PDF itp) jest podstawową funkcją niemal każdego serwisu (niezależnie czy chodzi o backend, czy frontend). Jeszcze niedawno operacja ta była dostępna tylko za pomocą znacznika <input type=”file” /> (pomijam wykorzystanie Flasha i Javy), ale taki sposób nie był nigdy ani wygodny, ani estetyczny. Na szczęście, wraz z nadejściem HTML5 mamy takie zdarzenia JS jak drop i dragover.
Dzięki tym zdarzeniom oraz obiektowi XMLHttpRequest możemy przeciągać i wysyłać pliki tak łatwo jak w aplikacjach deskopowych. Spójrzmy na kod.
<!doctype html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script> <style> body{ font-size: 12px; font-family: Arial; color: #000000; } #drop_zone{ padding: 20px; width:150px; border: 1px dashed #000000; text-align: center; } </style> </head> <body> <form method="post" action="upload.php" enctype="multipart/form-data"> <div id="drop_zone">Przeciągnij tutaj plik</div> <output id="list"><ul></ul></output> </form> <script type="text/javascript"> function handleFileSelect(evt) { xhr = new XMLHttpRequest(); evt.stopPropagation(); evt.preventDefault(); var files = evt.dataTransfer.files; // FileList object. // files is a FileList of File objects. List some properties. var output = ''; f = files[0]; output += '<li><strong>' + escape(f.name) + '</strong> (' + f.type + ') - '; output += f.size + ' bytes, last modified: '; output += '<span class="info"></span></li>'; $("#list ul").append(output); xhr.open("post", "upload.php", true); xhr.upload.onprogress = function(e) { if (e.lengthComputable) { var percentComplete = (e.loaded / e.total) * 100; console.log(percentComplete + '% uploaded'); $("#list li:last .info").html("Wgrywanie..." + parseInt(percentComplete) + " %"); $("#drop_zone").html("Proszę czekać..."); } }; xhr.onload = function() { // do something to response console.log(this.responseText); $("#list li:last").css("color", "#008416"); $("#list li:last .info").html("Wczytano plik!"); $("#drop_zone").html("Przeciągnij tutaj plik"); }; var formData = new FormData(); formData.append('file', f); xhr.send(formData); } function handleDragOver(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } // Setup the dnd listeners. var dropZone = document.getElementById('drop_zone'); dropZone.addEventListener('dragover', handleDragOver, false); dropZone.addEventListener('drop', handleFileSelect, false); </script> </body> </html>
W funkcji handleFileSelect() za pomocą evt.dataTransfer.files pobieramy tablicę przeciągniętych plików. Następnie, za pomocą XMLHttpRequest przesyłamy plik na serwer. Dodatkowo dodałem komunikaty dla użytkownika informujące o „postępach” wysyłania plików.
Działanie skryptu możecie zobaczyć na tej stronie. Zachęcam do podejrzenia konsoli w Fireburgu :).