Skip to content

Instantly share code, notes, and snippets.

@melito
Created March 18, 2012 05:20
Show Gist options
  • Save melito/2069113 to your computer and use it in GitHub Desktop.
Save melito/2069113 to your computer and use it in GitHub Desktop.
Coffee Script html5 uploader
class HTML5Uploader
constructor:(obj, options) ->
@method = options['method'] ||= "POST"
@url = options['url'] ||= "/"
@params = options['params']
@obj = $(obj)
@files = []
@alerted = false
_.bindAll(this, 'dragEnter', 'dragOver', 'drop')
@obj.bind('dragenter', this.dragEnter)
@obj.bind('dragover', this.dragOver)
@obj.bind('drop', this.drop)
dragEnter:(event) ->
event.stopPropagation()
event.preventDefault()
return false
dragOver:(event) ->
event.stopPropagation()
event.preventDefault()
return false
drop:(event) ->
event.stopPropagation()
event.preventDefault()
dataTransfer = event.originalEvent.dataTransfer
self = this
$("#drag_assets_here_msg").hide()
# If we have some files in the drop event
if dataTransfer.files.length > 0
# Iterate over each of them and send them to the server
$.each dataTransfer.files, (i, file) ->
# Only allow the user to upload 40 files per apartment
if self.files.length >= 40
unless self.alerted
alert "You are only allowed to upload 40 photos"
self.alerted = true
return true
# Build an ajax request
xhr = new XMLHttpRequest()
upload = xhr.upload
# Add the file to the files array
self.files.push file
# Render the file template into the drop zone
$(self.obj).append(JST['file']( {cnt: _.indexOf(self.files, file)} ))
# Action to take on upload progress
upload.onprogress = (x) ->
if x.lengthComputable
percentComplete = Math.round(x.loaded * 100 / x.total)
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-text").html(percentComplete.toString() + "%")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-progress").css('width', percentComplete.toString()+"%")
# Action to take on upload abort
upload.onabort = (x) ->
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-text").html("Aborted")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-text").attr("class", "aborted")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-progress").css('width', "100%")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-progress").css('background-color', "red")
# Action to take on upload error
upload.onerror = (x) ->
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-text").html("Error")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-text").attr("class", "error")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-progress").css('width', "100%")
$(self.obj).find("#file_"+_.indexOf(self.files, file)+" .meter-progress").css('background-color', "red")
# Build a form object for building the request
fd = new FormData()
if self.params != undefined
_.each _.keys(self.params), (key) ->
fd.append(key, self.params[key])
# Append the file to the asset object in the request
fd.append('asset[photo]', file)
# Configure how to handle ajax complete,errors,etc
xhr.onreadystatechange = (x) ->
if xhr.readyState == 4
if xhr.status >= 200 && xhr.status <= 300
resp = JSON.parse(xhr.responseText)
new_img = JST['rendered_file'] ('resp':resp)
$(self.obj).find("#file_"+_.indexOf(self.files, file)).html(new_img)
# Fire it up
xhr.open(self.method, self.url, true)
xhr.setRequestHeader('X-Filename', file.fileName)
xhr.send(fd)
return false
$.fn.html5Uploader = (method) ->
return new HTML5Uploader(this, method)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment