', {class: 'mercury-uploader-overlay', style: 'display:none'})
@element.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
@overlay.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
bindEvents: ->
Mercury.on 'resize', => @position()
appear: ->
@fillDisplay()
@position()
@overlay.show()
@overlay.animate {opacity: 1}, 200, 'easeInOutSine', =>
@element.show()
@element.animate {opacity: 1}, 200, 'easeInOutSine', =>
@visible = true
@loadImage()
position: ->
width = @element.outerWidth()
height = @element.outerHeight()
@element.css {
top: (Mercury.displayRect.height - height) / 2
left: (Mercury.displayRect.width - width) / 2
}
fillDisplay: ->
details = [
Mercury.I18n('Name: %s', @file.name),
Mercury.I18n('Size: %s', @file.readableSize),
Mercury.I18n('Type: %s', @file.type)
]
@element.find('.mercury-uploader-details').html(details.join('
'))
loadImage: ->
@file.readAsDataURL (result) =>
@element.find('.mercury-uploader-preview b').html(jQuery('
', {src: result}))
@upload()
upload: ->
xhr = new XMLHttpRequest
jQuery.each ['onloadstart', 'onprogress', 'onload', 'onabort', 'onerror'], (index, eventName) =>
xhr.upload[eventName] = (event) => @uploaderEvents[eventName].call(@, event)
xhr.onload = (event) =>
if (event.currentTarget.status >= 400)
@updateStatus('Error: Unable to upload the file')
Mercury.notify('Unable to process response: %s', event.currentTarget.status)
@hide()
else
try
response =
if Mercury.config.uploading.handler
Mercury.config.uploading.handler(event.target.responseText)
else
jQuery.parseJSON(event.target.responseText)
src = response.url || response.image.url
throw 'Malformed response from server.' unless src
Mercury.trigger('action', {action: 'insertImage', value: {src: src}})
@hide()
catch error
@updateStatus('Error: Unable to upload the file')
Mercury.notify('Unable to process response: %s', error)
@hide()
xhr.open('post', Mercury.config.uploading.url, true)
xhr.setRequestHeader('Accept', 'application/json, text/javascript, text/html, application/xml, text/xml, */*')
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
xhr.setRequestHeader(Mercury.config.csrfHeader, Mercury.csrfToken)
@file.readAsBinaryString (result) =>
# build the multipart post string
multipart = new Mercury.uploader.MultiPartPost(Mercury.config.uploading.inputName, @file, result)
# update the content size so we can calculate
@file.updateSize(multipart.delta)
# set the content type and send
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + multipart.boundary)
xhr.sendAsBinary(multipart.body)
updateStatus: (message, loaded) ->
@element.find('.mercury-uploader-progress span').html(Mercury.I18n(message).toString())
if loaded
percent = Math.floor(loaded * 100 / @file.size) + '%'
@element.find('.mercury-uploader-indicator div').css({width: percent})
@element.find('.mercury-uploader-indicator b').html(percent).show()
hide: (delay = 0) ->
setTimeout delay * 1000, =>
@element.animate {opacity: 0}, 200, 'easeInOutSine', =>
@overlay.animate {opacity: 0}, 200, 'easeInOutSine', =>
@overlay.hide()
@element.hide()
@reset()
@visible = false
Mercury.trigger('focus:frame')
reset: ->
@element.find('.mercury-uploader-preview b').html('')
@element.find('.mercury-uploader-indicator div').css({width: 0})
@element.find('.mercury-uploader-indicator b').html('0%').hide()
@updateStatus('Processing...')
uploaderEvents:
onloadstart: -> @updateStatus('Uploading...')
onprogress: (event) -> @updateStatus('Uploading...', event.loaded)
onabort: ->
@updateStatus('Aborted')
@hide(1)
onload: ->
@updateStatus('Successfully uploaded...', @file.size)
onerror: ->
@updateStatus('Error: Unable to upload the file')
@hide(3)
class Mercury.uploader.File
constructor: (@file) ->
@size = @file.size
@fullSize = @file.size
@readableSize = @file.size.toBytes()
@name = @file.fileName
@name ||= @file.name
@type = @file.type
# add any errors if we need to
errors = []
errors.push(Mercury.I18n('Too large')) if @size >= Mercury.config.uploading.maxFileSize
errors.push(Mercury.I18n('Unsupported format')) unless Mercury.config.uploading.allowedMimeTypes.indexOf(@type) > -1
@errors = errors.join(' / ') if errors.length
readAsDataURL: (callback = null) ->
reader = new FileReader()
reader.readAsDataURL(@file)
reader.onload = => callback(reader.result) if callback
readAsBinaryString: (callback = null) ->
reader = new FileReader()
reader.readAsBinaryString(@file)
reader.onload = => callback(reader.result) if callback
updateSize: (delta) ->
@fullSize = @size + delta
class Mercury.uploader.MultiPartPost
constructor: (@inputName, @file, @contents, @formInputs = {}) ->
@boundary = 'Boundaryx20072377098235644401115438165x'
@body = ''
@buildBody()
@delta = @body.length - @file.size
buildBody: ->
boundary = '--' + @boundary
for own name, value of @formInputs
@body += "#{boundary}\r\nContent-Disposition: form-data; name=\"#{name}\"\r\n\r\n#{unescape(encodeURIComponent(value))}\r\n"
@body += "#{boundary}\r\nContent-Disposition: form-data; name=\"#{@inputName}\"; filename=\"#{@file.name}\"\r\nContent-Type: #{@file.type}\r\nContent-Transfer-Encoding: binary\r\n\r\n#{@contents}\r\n#{boundary}--"