Drag & Drop

Dropping files onto an XUL application

It's possible to setup drag and drop events to handle dropping files from external applications or OS file managers onto your XUL-based application. First, you need to hook up the basic drag event handlers:

elem.addEventListener("dragover", _dragOver, true);
elem.addEventListener("dragdrop", _dragDrop, true);

Here, elem could be a window or an XUL element. Next, setup the handlers so that files can be dropped on the application:

  function _dragOver(aEvent) {
    var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);
    var dragSession = dragService.getCurrentSession();

    var supported = dragSession.isDataFlavorSupported("text/x-moz-url");
    if (!supported)
      supported = dragSession.isDataFlavorSupported("application/x-moz-file");

    if (supported)
      dragSession.canDrop = true;
  }

  function _dragDrop(aEvent) {
    var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);
    var dragSession = dragService.getCurrentSession();
    var _ios = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
    var uris = new Array();


    // If sourceNode is not null, then the drop was from inside the application
    if (dragSession.sourceNode)
      return;

    // Setup a transfer item to retrieve the file data
    var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
    trans.addDataFlavor("text/x-moz-url");
    trans.addDataFlavor("application/x-moz-file");

    for (var i=0; i<dragSession.numDropItems; i++) {
      var uri = null;

      dragSession.getData(trans, i);
      var flavor = {}, data = {}, length = {};
      trans.getAnyTransferData(flavor, data, length);
      if (data) {
        try {
          var str = data.value.QueryInterface(Components.interfaces.nsISupportsString);
        }
        catch(ex) {
        }

        if (str) {
          uri = _ios.newURI(str.data.split("\n")[0], null, null);
        }
        else {
          var file = data.value.QueryInterface(Components.interfaces.nsIFile);
          if (file)
            uri = _ios.newFileURI(file);
        }
      }

      if (uri)
        uris.push(uri);
    }

    // Use the array of file URIs
  }

The _dragOver function checks the drag data to see if a simple text file or general purpose file types are available. If the file types are present in the drag data, the function returns that dropping the data is allowed. The _dragDrop function retrieves the file URI data from the drag session and creates an array of file URIs that the XUL application can use.