Example: Multiple Files Uploader with HTML5 Drag-and-Drop Support

In this example, the Uploader is used to send multiple images or videos to the server and monitor their upload progress with individual counters. If the Uploader is used in a browser with HTML5 support, it is progressively enhanced to enable dragging-and-dropping files into the browser window.

Please note: This example will not work when run from a local filesystem because of security restrictions in the transport protocols used. If you’d like to run this example locally, set up a local web server and launch it from there.

Also note: The uploader is not supported on iOS devices (iPhone and iPad), because they lack file upload capability. This example provides a graceful degradation message for all such systems.

Also note: The backend script used in these examples does not store any information it receives. Nevertheless, do not submit any sensitive or private data and keep your tests to a few small files to avoid overloading the system.

File nameFile sizePercent uploaded
No files selected.

Progressive Enhancement with a Drag-and-Drop Area

The base functionality in this example is the same as in the Simple Multiple Files Uploader, but we are conditionally adding support for a drag-and-drop area for cases where the HTML5 uploader is being used:

if (Y.Uploader.TYPE == "html5") {
   uploader.set("dragAndDropArea", "body");
   Y.one("#ddmessage").setHTML("<strong>Drag and drop files here.</strong>");   
 
   uploader.on(["dragenter", "dragover"], function (event) {
       var ddmessage = Y.one("#ddmessage");
       if (ddmessage) {
         ddmessage.setHTML("<strong>Files detected, drop them here!</strong>");
         ddmessage.addClass("yellowBackground");
       }
    });

    uploader.on(["dragleave", "drop"], function (event) {
       var ddmessage = Y.one("#ddmessage");
       if (ddmessage) {
         ddmessage.setHTML("<strong>Drag and drop files here.</strong>");
         ddmessage.removeClass("yellowBackground");
       }
    });
}

Note that we are setting the entire page <body> as the drag-and-drop area, so the user can drop the files anywhere onto the page. We also add a visual response to the files being dragged over the page by listening to the dragenter, dragover, dragleave and drop events.

Full Source Code For this Example

<style>
#filelist {
    margin-top: 15px;
}

#uploadFilesButtonContainer, #selectFilesButtonContainer, #overallProgress {
    display: inline-block;
}

#overallProgress {
    float: right;
}

.yellowBackground {
  background: #F2E699;
}
</style>

<div id="exampleContainer">
<div id="uploaderContainer"> 
    <div id="selectFilesButtonContainer">
    </div> 
    <div id="uploadFilesButtonContainer">
      <button type="button" id="uploadFilesButton" 
              class="yui3-button" style="width:250px; height:35px;">Upload Files</button>
    </div> 
    <div id="overallProgress">
    </div>
</div> 

<div id="filelist">
  <table id="filenames">
    <thead>
       <tr><th>File name</th><th>File size</th><th>Percent uploaded</th></tr>
       <tr id="nofiles">
        <td colspan="3" id="ddmessage">
            <strong>No files selected.</strong>
        </td>
       </tr>
    </thead>
    <tbody>
    </tbody>
  </table>  
</div>
</div>

<script>

YUI({filter:"raw"}).use("uploader", function(Y) {
Y.one("#overallProgress").set("text", "Uploader type: " + Y.Uploader.TYPE);
   if (Y.Uploader.TYPE != "none" && !Y.UA.ios) { 
       var uploader = new Y.Uploader({width: "250px", 
                                      height: "35px", 
                                      multipleFiles: true,
                                      swfURL: "../../build/uploader/assets/flashuploader.swf?t=" + Math.random(),
                                      uploadURL: "http://www.yswfblog.com/upload/simpleupload.php",
                                      simLimit: 2,
                                      withCredentials: false
                                     });    
       var uploadDone = false;

       if (Y.Uploader.TYPE == "html5") {
          uploader.set("dragAndDropArea", "body");

          Y.one("#ddmessage").setHTML("<strong>Drag and drop files here.</strong>");   

          uploader.on(["dragenter", "dragover"], function (event) {
              var ddmessage = Y.one("#ddmessage");
              if (ddmessage) {
                ddmessage.setHTML("<strong>Files detected, drop them here!</strong>");
                ddmessage.addClass("yellowBackground");
              }
           });
    
           uploader.on(["dragleave", "drop"], function (event) {
              var ddmessage = Y.one("#ddmessage");
              if (ddmessage) {
                ddmessage.setHTML("<strong>Drag and drop files here.</strong>");
                ddmessage.removeClass("yellowBackground");
              }
           });
       }

       uploader.render("#selectFilesButtonContainer");

       uploader.after("fileselect", function (event) {

          var fileList = event.fileList;
          var fileTable = Y.one("#filenames tbody");
          if (fileList.length > 0 && Y.one("#nofiles")) {
            Y.one("#nofiles").remove();
          }

          if (uploadDone) {
            uploadDone = false;
            fileTable.setHTML("");
          }
          
          Y.each(fileList, function (fileInstance) {
              fileTable.append("<tr id='" + fileInstance.get("id") + "_row" + "'>" + 
                                    "<td class='filename'>" + fileInstance.get("name") + "</td>" + 
                                    "<td class='filesize'>" + fileInstance.get("size") + "</td>" + 
                                    "<td class='percentdone'>Hasn't started yet</td>"); 
                             });
       });

       uploader.on("uploadprogress", function (event) {
            var fileRow = Y.one("#" + event.file.get("id") + "_row");
                fileRow.one(".percentdone").set("text", event.percentLoaded + "%");
       });

       uploader.on("uploadstart", function (event) {
            uploader.set("enabled", false);
            Y.one("#uploadFilesButton").addClass("yui3-button-disabled");
            Y.one("#uploadFilesButton").detach("click");
       });

       uploader.on("uploadcomplete", function (event) {
            var fileRow = Y.one("#" + event.file.get("id") + "_row");
                fileRow.one(".percentdone").set("text", "Finished!");
       });

       uploader.on("totaluploadprogress", function (event) {
                Y.one("#overallProgress").setHTML("Total uploaded: <strong>" + 
                                                     event.percentLoaded + "%" + 
                                                     "</strong>");
       });

       uploader.on("alluploadscomplete", function (event) {
                     uploader.set("enabled", true);
                     uploader.set("fileList", []);
                     Y.one("#uploadFilesButton").removeClass("yui3-button-disabled");
                     Y.one("#uploadFilesButton").on("click", function () {
                          if (!uploadDone && uploader.get("fileList").length > 0) {
                             uploader.uploadAll();
                          }
                     });
                     Y.one("#overallProgress").set("text", "Uploads complete!");
                     uploadDone = true;
       });

       Y.one("#uploadFilesButton").on("click", function () {
         if (!uploadDone && uploader.get("fileList").length > 0) {
            uploader.uploadAll();
         }
       });      
   } 
   else {
       Y.one("#uploaderContainer").set("text", "We are sorry, but to use the uploader, you either need a browser that support HTML5 or have the Flash player installed on your computer.");
   }


});

</script>