class FileUpload
constructor: (@parse,@scope,controllers,model,override,@element)-> [@ngModel,@ngCallback] = controllers modelName = (override || model) if parts = modelName.match(/(.+)\[(.+)\]/) @modelName = parts[1] @atomName = @parse(parts[2])() else [@modelName,@atomName] = modelName.split('.') @override = !!override uploadFile: (file)-> @scope.progress = 0 @element.addClass('covered') id = @scope.$eval(@modelName).id route = Routes[@modelName + '_path'](id: id) + '.json' formData = new FormData() formData.append @modelName + '[id]', id formData.append @modelName + '[' + @atomName + ']', file xhr = new XMLHttpRequest() xhr.upload.addEventListener "progress", (event) => if event.lengthComputable @scope.$apply => @scope.progress = Math.round(event.loaded * 100 / event.total) , true xhr.addEventListener "readystatechange", (event) => if event.target.readyState == 4 && !(event.target.status > 399) data = JSON.parse(event.target.response) @scope.$apply => @scope[@modelName][@atomName] = data[@atomName] @scope[@modelName].thumb = data.thumb @scope.progress = 100 @element.removeClass('covered') @ngCallback.evaluate(data) if !!@ngCallback else if event.target.readyState == 4 && event.target.status > 399 failed() , false xhr.addEventListener "error", (event) -> failed() , false failed = -> @element.addClass('failed') timeout -> @element.removeClass('failed') @element.removeClass('covered') , 2000 xhr.open("PUT", route) csrf = null for tag in document.getElementsByTagName('meta') csrf = tag.content if tag.name == 'csrf-token' xhr.setRequestHeader('X-CSRF-Token', csrf) xhr.send(formData) fileData: -> data = {} if @scope[@modelName] if @scope[@modelName][@atomName] data.path = @scope[@modelName][@atomName].url data.name = @scope[@modelName][@atomName].name data.thumb = @scope[@modelName].thumb.url if @scope[@modelName].thumb return data
class NgUploadEvents
constructor: (@element,@file_upload,@disabled) -> @element.children().bind 'click', (event) => return if @disabled() return if event.target.tagName == 'A' event.target.parentElement.getElementsByTagName('input')[0].click() @element.children('input').bind 'change', (event) => return if @disabled() file = event.target.files[0] @file_upload.uploadFile(file)
class NgDropFileEvents
constructor: (@element,@file_upload) -> dragHovered = 0 el = angular.element("<div class='hovered-cover'>Drop Files Here</div>") @element.bind 'dragenter', (event) => dragHovered += 1 @element.addClass('hovered') if dragHovered == 1 @element.append el if dragHovered == 1 height = window.getComputedStyle(@element[0]).height el.css('height', height) el.css('line-height',height) el.css('margin-top', '-' + height) @element.bind 'dragleave', (event) => dragHovered -= 1 @element.removeClass('hovered') if dragHovered == 0 el.remove() if dragHovered == 0 @element.bind 'dragover', (event) => event.preventDefault() event.stopPropagation() @element.bind 'drop', (event) => event.preventDefault() event.stopPropagation() @element.removeClass('hovered') el.remove() dragHovered = 0 file = (event.originalEvent || event).dataTransfer.files[0] @file_upload.uploadFile(file)
angular.module('NgUpload', [])
.directive 'ngDropFile', ($timeout,$parse) -> restrict: 'A' require: ['ngModel','?ngCallback'] link: (scope, element, attributes,controllers) -> file_upload = new FileUpload($parse,scope,controllers,attributes.ngModel,attributes.ngOverride,element) new NgDropFileEvents(element,file_upload) scope.file_upload_data = -> file_upload.fileData() .directive 'ngUpload', ($timeout, $parse) -> restrict: 'E' replace: true, require: ['ngModel','?ngCallback'], template: (element,attributes) -> disabled = typeof(attributes.disabled) != 'undefined' '<span class="ng-upload" style="outline: none"> <div class="ng-progress-bar"> <span class="bar" style="width: {{progress || 0}}%;"></span><span class="text" style="margin-left: -{{uploadProgress() || 0}}%;">{{uploadProgress()}}%</span> </div> <input accept="{{accept()}}" ng-model="ngModel" type="file" ng-class="{image: file_upload_show('image')}" ' + (if disabled then 'disabled ') + '/><img ng-show="file_upload_show('image')" ng-src="{{file_upload_data().thumb}}" /> <div class="button" ng-show="file_upload_show('button')"> Select File </div> <a download="" href="{{file_upload_data().path}}" ng-show="file_upload_show('text')" target="_blank">{{file_upload_data().name}}</a></span>' link: (scope, element, attributes,controllers) -> file_upload = new FileUpload($parse,scope,controllers,attributes.ngModel,attributes.ngOverride,element) options = $parse(attributes.ngUploadOptions)() scope.file_upload_show = (type) -> options[type] scope.file_upload_data = -> file_upload.fileData() scope.accept = -> attributes.accept || '*' disabled = -> el = element[0] until !el.parentElement return true if el.getAttribute('disabled') el = el.parentElement new NgUploadEvents(element,file_upload,disabled)