{% extends "_templates/base.html" %}
{% set page_title = "Drag and Drop" %}
{% block sidebar %}
{{ api_links(options=['dragAndDrop-ui',], methods=['addExtraDropzone', 'removeExtraDropzone', 'getDropTarget-ui']) }}
{% endblock %}
{% block content %}
{% markdown %}

# Drag and Drop {: .page-header }

{{ alert("If you want the contents of any drop zone to be invisible until an item enters the drop zone,
simply ensure a `qq-hide-dropzone` attribute is present on the drop zone container.") }}

Fine Uploader's UI mode has drag & drop support built in.  The following contains information about that built-in
support.  Near the middle of this page, you can find instructions that will allow you to easily integrate Fine Uploader's
standalone drag & drop module into your project if you are using Fine Uploader's core mode only.

{{ alert("While dragging and dropping of _files_ is supported in many browsers,
Dragging and dropping of _folders_ is currently only supported in Chrome 21+ & Opera 15+", "default", "Note") }}

# Drag and Drop Standalone Module

If you are integrating Fine Uploader and utilizing FineUploaderBasic mode,
you are likely building you own UI entirely. In case you want to support drag
and drop of folders and files, you probably don't want to re-invent the wheel, since
Fine Uploader already has code to handle this in Fine Uploader mode.
Fine Uploader's drag & drop code has been moved into a standalone module, so
it can be easily integrated into your Fine Uploader Core mode app
(or even any non-Fine Uploader app). This following will explain how to utilize
this module.

{{
alert("This module is aimed at Fine Uploader Core mode integrators only. If
you are running this in UI mode, then take a look at the `dragAndDrop` options defined above.", "info")
}}

## Options

{% endmarkdown %}

{{ api_option("allowMultipleItems", "allowMultipleItems", "Set to `false` if you would to prevent the user from dropping more than one item at once.", "boolean", "`true`",)}}
{{ api_option("dropZoneElements", "dropZoneElements", "Specify all container elements that should be treated as drop zones.", "Array", "`[ ]`",)}}

{{api_parent_option("classes", "classes", "",
    (
        ("classes.dropActive", "dropActive", "Specify a CSS class to apply to drop zone(s) when a file has entered it.", "String", "''",),
    )
)}}

{% markdown %}
## Events

{% endmarkdown %}

{{
api_event("processingDroppedFiles", "processingDroppedFiles",
"Invoked when the module has started processing the set of dropped files.", [], [])
}}

{{
api_event("processingDroppedFilesComplete", "processingDroppedFilesComplete",
"""Invoked when the module has finished processing.
""",
[
    {
        "name": "files",
        "type": "Array",
        "description": "An array of processed files.  Note that a `qqPath` property will be added
        to each `File` object that was dropped as part of a directory drop.  The value of this property
        will be the path of the file starting with the dropped top-level directory."
    },
    {
        "name": "dropTarget",
        "type": "HTMLElement",
        "description": "The target where this event originated from."
    },
])
}}

{{
api_event("dropError", "dropError",
"""Called when processing the drop fails for any reason.
""",
[
    {
        "name": "errorCode",
        "type": "String",
        "description": "The specific error code"
    },
    {
        "name": "errorRelatedData",
        "type": "String",
        "description": "Data related to the error."
    },
])
}}

{{
api_event("dropLog", "dropLog",
"""Invoked when a message is logged.
""",
[
    {
        "name": "message",
        "type": "String",
        "description": "The message to log."
    },
])
}}

{% markdown %}
### Methods
{% endmarkdown %}

{{ api_method("dispose", "dispose", "Tears down all drop zones associated with the dnd instance.") }}
{{ api_method("setupExtraDropzone", "setupExtraDropzone", "Call this to add an additional drop zone to the DnD instance. Not available if using the jQuery plug-in wrapper.",
[
    {
        "name": "element",
        "type": "HTMLElement",
        "description": "THe HTMLElement where the dropzone will be rendered inside of."
    }
])}}
{{ api_method("removeDropzone", "removeDropzone", "Call this to remove a drop zone from the DnD instance. Not available if using the jQuery plug-in wrapper.",
[
    {
        "name": "element",
        "type": "HTMLElement",
        "description": "THe HTMLElement where the dropzone will be remove from."
    }

]) }}

{% markdown %}
## jQuery Example

For jQuery users, a jQuery-wrapped DnD module is also available in the combined and minified Fine Uplpoader javascript file.
This jQuery wrapper follows the same conventions as the jQuery plug-in that wraps the uploader library.  To read more
about these conventions, please see the [Using jQuery plug-in]({{ URL_ROOT }}/integrating/modes/using-jquery-plugin.html) readme document.

There are a couple things to be aware of when using the DnD standalone module via the jQuery plug-in wrapper:
* The only API method available is `dispose`.  This restriction is in place since the other API functions don't really make sense in the context of a jQuery plug-in.
* The target of your plug-in instance takes the place of the `dropZoneElements` option.  Do not pass a `dropZoneElements` option, it will be ignored.

Here is the above example rewritten using the jQuery plug-in wrappers:

```javascript
$('#myDropZone').fineUploaderDnd({
    classes: {
        dropActive: "cssClassToAddToDropZoneOnEnter"
    }
})
    .on('processingDroppedFiles', function(event) {
        //TODO: display some sort of a "processing" or spinner graphic
    })
    .on('processingDroppedFilesComplete', function(event, files, dropTarget) {
        //TODO: hide spinner/processing graphic

        $('#fineUploaderBasicContainer').fineUploader('addFiles', files); //this submits the dropped files to Fine Uploader
    });

$('#fineUploaderBasicContainer').fineUploader({
    request: {
        endpoint: "server/uploadHandler"
    }
});
```

{{ alert("jQuery 1.7+ is required to use the `on` function.") }}

## Non-jQuery Example

If you are not utilizing jQuery, you can use the plain javascript DnD module.  Here is a simple example:

```javascript
var dragAndDropModule = new qq.DragAndDrop({
        dropZoneElements: [document.getElementById('myDropZone')],
        classes: {
          dropActive: "cssClassToAddToDropZoneOnEnter"
        },
        callbacks: {
          processingDroppedFiles: function() {
            //TODO: display some sort of a "processing" or spinner graphic
          },
          processingDroppedFilesComplete: function(files, dropTarget) {
            //TODO: hide spinner/processing graphic

            fineUploaderBasicInstance.addFiles(files); //this submits the dropped files to Fine Uploader
          }
        }
      }),

    fineUploaderBasicInstance = new qq.FineUploaderBasic({
    request: {
        endpoint: "server/uploadHandler"
    }
  });
```

[For more information, see the associated blog post](http://blog.fineuploader.com/2013/04/05/standalone-file-drag-drop-module-in-3-5/)

{% endmarkdown %}
{% endblock %}
