public
Last active

This directive uses the HTML5 drag and drop spec as well as the FileReader to base64 encode the dropped files. This allows for easy client/server transfer via REST protocol.

  • Download Gist
dropzone.coffee
CoffeeScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
'use strict';
 
angular.module('reusableThings')
.directive('fileDropzone', () ->
restrict: 'A'
scope: {
file: '='
fileName: '='
}
link: (scope, element, attrs) ->
 
# function to prevent default behavior (browser loading image)
processDragOverOrEnter = (event) ->
event?.preventDefault()
event.dataTransfer.effectAllowed = 'copy'
false
 
validMimeTypes = attrs.fileDropzone
 
# if the max file size is provided and the size of dropped file is greater than it,
# it's an invalid file and false is returned
checkSize = (size) ->
if attrs.maxFileSize in [undefined, ''] or (size / 1024) / 1024 < attrs.maxFileSize
true
else
alert "File must be smaller than #{attrs.maxFileSize} MB"
false
 
isTypeValid = (type) ->
if validMimeTypes in [undefined, ''] or validMimeTypes.indexOf(type) > -1
true
else
# return true if no mime types are provided
alert "Invalid file type. File must be one of following types #{validMimeTypes}"
false
 
# for dragover and dragenter (IE) we stop the browser from handling the
# event and specify copy as the allowable effect
element.bind 'dragover', processDragOverOrEnter
element.bind 'dragenter', processDragOverOrEnter
 
# on drop events we stop browser and read the dropped file via the FileReader
# the resulting droped file is bound to the image property of the scope of this directive
element.bind 'drop', (event) ->
event?.preventDefault()
reader = new FileReader()
reader.onload = (evt) ->
 
if checkSize(size) and isTypeValid(type)
scope.$apply ->
scope.file = evt.target.result
scope.fileName = name if angular.isString scope.fileName
 
file = event.dataTransfer.files[0]
name = file.name
type = file.type
size = file.size
reader.readAsDataURL(file)
return false
)

Sample Usage:

<div file-dropzone="[image/png, image/jpeg, image/gif]" file="ctrlBoundImage", file-name="ctrlBoundFileName"
         data-max-file-size="3" style="width: 150px; height: 150px; border: 1px solid">
  <span>Drop Background Images Here</span>
</div>
<div>
  <img ng-src={{ctrlBoundImage}} />
  <span>{{ctrlBoundFileName}}</span>
</div>

creating a module requires a second argument, in this case, an empty array should do fine.

angular.module('reusableThings', [])

A copy of this directive can be incorporated into your app via bower install angular-file-dnd

See the repo here: https://github.com/onemightyroar/angular-file-dnd

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.