   # If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
   getFallbackForm: ->
     fields = o """<div class="fallback-elements"><input type="file" name="#{@options.paramName}" multiple="multiple" /><button type="submit">Upload!</button></div>"""
-    if @elementTagName isnt "FORM"
+    if @element.tagName isnt "FORM"
       fields = o("""<form action="#{@options.url}" enctype="multipart/form-data" method="post"></form>""").append fields
     else
       # Make sure that the enctype and method attributes are set properly

      @element.attr "method", "post" unless @element.attr "method"
    fields

  setupEventListeners: (initial = yes) ->

    if initial
      # First setup all event listeners on the dropzone object itself.
      @on eventName, @options[eventName] for eventName in @events

    noPropagation = (e) ->
      e.stopPropagation()
      e.preventDefault()

    @element.on "dragstart.dropzone", (e) =>
      @emit "dragstart", e

    @element.on "dragenter.dropzone", (e) =>
      noPropagation e
      @emit "dragenter", e

    @element.on "dragover.dropzone", (e) =>
      noPropagation e
      @emit "dragover", e

    @element.on "dragleave.dropzone", (e) =>
      @emit "dragleave", e

    @element.on "drop.dropzone", (e) =>
      noPropagation e
      @drop e
      @emit "drop", e
    
    @element.on "dragend.dropzone", (e) =>
      @emit "dragend", e

    if @options.clickable
      @element.addClass "clickable"
      @element.on "click.dropzone", (evt) =>
        target = o evt.target
        # Only the actual dropzone or the message element should trigger file selection
        if target.is(@element) or target.is(@element.find(".message"))
          @hiddenFileInput.click() # Forward the click
      @hiddenFileInput.on "change", =>
        files = @hiddenFileInput.get(0).files
        @emit "selectedfiles", files
        @handleFiles files if files.length


  removeEventListeners: ->
    @element.off ".dropzone"
    if @options.clickable
      @element.removeClass "clickable"
      @hiddenFileInput.off()

  # Removes all event listeners and clears the arrays.
  disable: ->
    @removeEventListeners()
    @filesProcessing = [ ]
    @filesQueue = [ ]

  enable: ->
    @setupEventListeners no # not initial

  # Returns a nicely formatted filesize
  filesize: (size) ->



    # Those are self explanatory and simply concern the DragnDrop.
    drop: (e) -> @element.classList.remove "drag-hover"
    dragstart: noop
    dragend: (e) -> @element.classList.remove "drag-hover"
    dragenter: (e) -> @element.classList.add "drag-hover"
    dragover: (e) -> @element.classList.add "drag-hover"
    dragleave: (e) -> @element.classList.remove "drag-hover"
    
    # Called whenever files are dropped or selected
    selectedfiles: (files) ->
      @element.classList.add "started" if @element == @previewsContainer

    # Called whenever there are no files left in the dropzone anymore, and the
    # dropzone should be displayed as if in the initial state.
    reset: ->
      @element.classList.remove "started"

    # Called when a file is added to the queue
    # Receives `file`
    addedfile: (file) ->
      file.previewTemplate = createElement @options.previewTemplate
      @previewsContainer.appendChild file.previewTemplate
      file.previewTemplate.querySelector(".filename span").textContent = file.name
      file.previewTemplate.querySelector(".details").appendChild createElement """<div class="size">#{@filesize file.size}</div>"""


    # Called whenever a file is removed.
    removedfile: (file) ->
      file.previewTemplate.parentNode.removeChild file.previewTemplate

    # Called when a thumbnail has been generated
    # Receives `file` and `dataUrl`
    thumbnail: (file, dataUrl) ->
      file.previewTemplate.classList.remove "file-preview"
      file.previewTemplate.classList.add "image-preview"
      file.previewTemplate.querySelector(".details").appendChild createElement """<img alt="#{file.name}" src="#{dataUrl}"/>"""

    
    # Called whenever an error occurs
    # Receives `file` and `message`
    error: (file, message) ->
      file.previewTemplate.classList.add "error"
      file.previewTemplate.querySelector(".error-message span").textContent = message
    
    
    # Called when a file gets processed. Since there is a cue, not all added
    # files are processed immediately.
    # Receives `file`
    processingfile: (file) ->
      file.previewTemplate.classList.add "processing"
    
    # Called whenever the upload progress gets updated.
    # You can be sure that this will be called with the percentage 100% when the file is finished uploading.
    # Receives `file` and `progress` (percentage)
    uploadprogress: (file, progress) ->
      file.previewTemplate.querySelector(".progress .upload").style.width = "#{progress}%"

    # Called just before the file is sent. Gets the `xhr` object as second
    # parameter, so you can modify it (for example to add a CSRF token) and a
    # `formData` object to add additional information.
    sending: noop
    
    # When the complete upload is finished and successfull
    # Receives `file`
    success: (file) ->
      file.previewTemplate.classList.add "success"

    # When the upload is finished, either with success or an error.
    # Receives `file`
    complete: noop



