Skip to content

Instantly share code, notes, and snippets.

@jeshuaborges
Last active December 12, 2015 04:58
(function() {
var meta, store;
// Base
Ember.UploadStoreMixin = Ember.Mixin.create({
url: '/uploads',
success: W.noop,
progress: W.noop,
init: function() {
this._super();
this.set('data', {file: this.get('file')});
},
filename: function() {
return this.get('file.name');
}.property('file'),
save: function() {
var ajax = W.AJAX(this.get('url'), this.get('data')),
success = _.bind(this.success, this),
progress = _.bind(this.progress, this);
ajax.onSuccess(success);
ajax.onProgress(progress);
ajax.save();
return this.get('filename');
}
});
// Extensions
Ember.UploadStoreMixin.Local = {};
Ember.UploadStoreMixin.AWS = {
init: function() {
this._super();
this.set('fields', this.getFields());
this.set('url', meta('upload-store-url'));
this.set('path', meta('upload-store-path'));
this.set('data', _.extend(this.get('fields'), {file: this.get('file')}));
},
getFields: function() {
var tupal = _.map($('[name^="upload-store-field"]'), function(el) {
el = $(el);
return [el.attr('name').substr(19), el.attr('content')];
});
return _.object(tupal);
},
filename: function() {
return this.get('path') +'/'+ this.get('file.name');
}.property('file.name', 'path')
};
// Setup proper data store extensions for mixin.
meta = function(name) {
return $('meta[name="'+ name +'"]').attr('content');
};
store = function(name) {
var proto = Ember.UploadStoreMixin[name];
if( !_.isString(name) ) {
throw 'No upload store defined. Make sure to set <meta name="upload-store" content="anything">.';
}
if( !_.isObject(proto) ) {
throw 'Pototype for "'+ name +"' is not defined.";
}
return {
extend: function(mixin) {
mixin.reopen(proto);
}
};
};
store(meta('upload-store')).extend(Ember.UploadStoreMixin);
})();
(function() {
W = {
noop: function(){}
};
W.AJAX = function(url, data) {
// TODO: setup better data size calculation
var dataSize = data.file.size,
req = new XMLHttpRequest(),
form = new FormData();
_.each(data, function(v, k) {
form.append(k, v);
});
var _m = {
success: W.noop,
progress: W.noop,
error: W.noop,
// Native incoming events
progressProxy: function(e) {
if( e.lengthComputable ) {
var bytesLoaded = e.loaded,
percentComplete = Math.round(dataSize / bytesLoaded * 100);
_m.progress(percentComplete);
} else {
_m.progress();
}
},
completeProxy: function(e) {
if( e.target.status >= 200 && e.target.status < 300 ) {
_m.success();
} else {
_m.error();
}
},
errorProxy: function(e) {
_m.error();
},
// Consuming agent binding
onProgress: function(cb) {
_m.progress = cb;
},
onSuccess: function(cb) {
_m.success = cb;
},
onError: function(cb) {
_m.error = cb;
},
// Public actions
save: function() {
req.open('POST', url);
req.send(form);
}
}
req.addEventListener('load', _m.completeProxy, false);
req.addEventListener('error', _m.errorProxy, false);
req.upload.addEventListener('progress', _m.progressProxy, false);
return _m;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment