title: HTML5 Drag-And-Drop DataTransfer: Drag data sometimes in files sometimes in items
body: <p>I wrote up a script and html page to test out some drag-and-drop features with files from the file system dragged into the browser drop target I defined.</p>
  
  <p>In this environment i was always able to access <code>event.dataTransfer.files</code></p>
  
  <p>However, I have since integrated this into a JSF servlet and suddenly the behavior is not as consistent.</p>
  
  <p>I now see that in the dragover event the file is listed under <code>event.dataTransfer.items</code> but <code>event.dataTransfer.files</code> is empty. <code>DataTransferItem</code> object seems to reference the mimeType but not the data itself nor the filename like a <code>File</code> does. Yet on the drop event, <code>event.dataTransfer.files</code> contains the file.</p>
  
  <p>Also, all of the getAs methods on <code>DataTransferItem</code> are returning null. I can work around a bit since I'm only really trying to figure out the file type at the dragover event, but I'd at least like to figure out these idiosyncratic behaviors.</p>
  
  <p>I'm not sure what this change is caused by. The actual script hadn't changed and the related markup is all plain HTML and not JSF components. Why has the behavior changed?</p>
  
  <p>Edit: It may be worth noting that the JSF implementation I am using is Primefaces and it contains a version of jQuery, which maybe older than the latest one I pulled from jQuery's site this week. </p>
  
  <p>JS:</p>
  
  <pre><code>var CSVParser = (function($) {
    "use strict";
  
    var module = {
  
      /**
       * Inspects the file's name and mime-type to determine if it is a CSV file. Does not inspect
       * contents.
       * supports any mime type that contains csv, is comma-separated-values, or is application/vnd.ms-excel
       * @param file - javascript file
       */
      isCSV: function(file) {
        if(file) {
          var mimeType = file.type;
          var name = file.name || ".csv";  //Deal with possibly getting a DataTransferItem instead of File object. Just assume .csv
  
          var matchStandardMime = mimeType.match(/.*\/csv.*/) !== null || mimeType.match(/comma-separated-values/) !== null;
          var matchExcelMime = mimeType.match(/application\/vnd.ms-excel/) !== null;
          matchExcelMime = matchExcelMime &amp;&amp; name.match(/.*\.csv/) !== null;
  
          return matchStandardMime || matchExcelMime;
        }
      }
    };
  
    return module;
  
  }(jQuery));
  
  (function($){
  
    /* Deal with drop-files */
  
    function getDropbox() {
      return $('.csvDropTarget');
    }
  
    function getEventFiles(e) {
      var files = e.originalEvent.dataTransfer.files || [];  //jQuery seems to wrap the original event
      var items = e.originalEvent.dataTransfer.items || [];  //jQuery seems to wrap the original event
      e.originalEvent.dataTransfer.dropEffect = 'copy';
  
      if(files.length &gt; 0) {
          return files;
      } else if (items.length &gt; 0) {
          return items;
      }
  
      return files;
    }
  
    function onDragEnter(e) {
      e.stopPropagation();
      e.preventDefault();
    }
  
    function onDragOver(e) {
      var files = getEventFiles(e);
      var validDrop = false;
  
      e.stopPropagation();
      e.preventDefault();
  
      for(var i = 0; i &lt; files.length; i++) {
        if(files[i] &amp;&amp; CSVParser.isCSV(files[i])) {
          validDrop = true;
        } else {
          validDrop = false;
          break;
        }
      }
    }
  
    function onDragLeave(e) { 
      e.stopPropagation();
      e.preventDefault();
    }
  
    function onDrop(e) {
      var files = getEventFiles(e);
      var file = null;
  
      e.stopPropagation();
      e.preventDefault();
  
      // Loop through list of files user dropped.
      for (var i = 0; i &lt; files.length; i++) {
        file = files[i];
        console.log("File type: " + file.type);
  
        console.log("Is CSV: " + CSVParser.isCSV(file));
      }
    }
  
    /* Register events and determine functionality */
  
    $(document).ready(function() {
      var dropbox = getDropbox();
  
      dropbox.bind("dragenter", onDragEnter);
      dropbox.bind("dragover", onDragOver);
      dropbox.bind("dragleave", onDragLeave);
      dropbox.bind("drop", onDrop);
    });
  
  }(jQuery));
  </code></pre>
  
  <p>HTML snippet:</p>
  
  <pre><code>&lt;div class="csvDropTarget mainDropTarget"&gt;
    &lt;span class="dragDropText"&gt;${resourceBundle.csv_drag_prompt}&lt;/span&gt;
    &lt;span class="validDropText hidden"&gt;${resourceBundle.csv_valid_drag}&lt;/span&gt;
    &lt;span class="invalidDropText hidden"&gt;${resourceBundle.csv_invalid_drag}&lt;/span&gt;
  &lt;/div&gt;
  </code></pre>