Compare commits

..

2 Commits

Author SHA1 Message Date
nobuti
ff2c75cdf7 More fix. 2016-09-28 12:38:46 +02:00
nobuti
af329465c9 Fix dependency. 2016-09-28 12:29:51 +02:00
5 changed files with 69 additions and 101 deletions

View File

@ -1,5 +1,7 @@
Backbone.Model File Upload
==========================
[![Travis Build](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload.svg?branch=master)](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload)
A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)
@ -41,8 +43,8 @@ email.set('attachment', fileObject);
email.save();
email.on('progress', function(evt) { console.log(evt) });
// Will result: with an event object you can use evt.loaded and evt.total to figure out the percent (i.e. 0.3233)
email.on('progress', console.log);
// Will result: the status in percent i.e. 0.3233
```
### fileAttribute
@ -174,9 +176,6 @@ c Version v0.1
- Switching to "Bracket" notation for flattening nested objects
- Added an "unflatten" internal method to unflatten
#### Version 1.0.2
- Cutting a tag and fixing NPM issues
### Dev/Installation
If you want to work on this plugin, test it, etc., it just needs an install of `node` and `grunt`.
```

View File

@ -13,21 +13,21 @@
// AMD
if (typeof define === 'function' && define.amd) {
define(['underscore', 'backbone'], function(_, Backbone){
factory(root, Backbone, _);
define(['underscore', 'jquery', 'backbone'], function(_, $, Backbone){
factory(root, Backbone, _, $);
});
// NodeJS/CommonJS
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), Backbone = require('backbone');
factory(root, Backbone, _);
var _ = require('underscore'), $ = require('jquery'), Backbone = require('backbone');
factory(root, Backbone, _, $);
// Browser global
} else {
factory(root, root.Backbone, root._);
factory(root, root.Backbone, root._, root.$);
}
}(this, function(root, Backbone, _) {
}(this, function(root, Backbone, _, $) {
'use strict';
// Clone the original Backbone.Model.prototype as superClass
@ -43,8 +43,7 @@
save: function(key, val, options) {
// Variables
var attrs, attributes = this.attributes,
that = this;
var attrs, attributes = this.attributes;
// Signature parsing - taken directly from original Backbone.Model.save
// and it states: 'Handle both "key", value and {key: value} -style arguments.'
@ -87,14 +86,13 @@
// Converting Attributes to Form Data
var formData = new FormData();
_.each( formAttrs, function( value, key ){
if (value instanceof FileList || (key === that.fileAttribute && value instanceof Array)) {
if (value instanceof FileList) {
_.each(value, function(file) {
formData.append( key, file );
});
return;
}
else {
formData.append( key, value );
}
formData.append( key, value );
});
// Set options for AJAX call
@ -102,13 +100,12 @@
options.processData = false;
options.contentType = false;
// Handle "progress" events
if (!options.xhr) {
options.xhr = function(){
var xhr = Backbone.$.ajaxSettings.xhr();
xhr.upload.addEventListener('progress', _.bind(that._progressHandler, that), false);
return xhr
}
// Apply custom XHR for processing status & listen to "progress"
var that = this;
options.xhr = function() {
var xhr = $.ajaxSettings.xhr();
xhr.upload.addEventListener('progress', that._progressHandler.bind(that), false);
return xhr;
}
}

View File

@ -1,12 +1,21 @@
{
"name": "backbone-model-file-upload",
"version": "1.0.2",
"version": "1.0.0",
"description": "A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)",
"main": "backbone-model-file-upload.js",
"directories": {
"test": "test"
},
"dependencies": {},
"dependencies": {
"bower": "^1.3.12",
"formidable": "~1.0.15",
"grunt": "0.4.5",
"grunt-contrib-jasmine": "^0.6.5",
"grunt-run": "0.3.0",
"grunt-run-node": "0.1.3",
"grunt-template-jasmine-requirejs": "^0.2.0",
"lodash": "~2.4.1"
},
"scripts": {
"test": "grunt test"
},
@ -27,14 +36,5 @@
"url": "https://github.com/homeslicesolutions/backbone-model-file-upload/issues"
},
"homepage": "https://github.com/homeslicesolutions/backbone-model-file-upload",
"devDependencies": {
"bower": "^1.3.12",
"formidable": "~1.0.15",
"grunt": "^0.4.5",
"grunt-contrib-jasmine": "^0.6.5",
"grunt-run": "^0.3.0",
"grunt-run-node": "^0.1.0",
"grunt-template-jasmine-requirejs": "^0.2.0",
"lodash": "~2.4.1"
}
"devDependencies": {}
}

View File

@ -18,12 +18,10 @@
var fileModel;
var simulatedFileObj;
var simulatedFileObj2;
beforeEach(function(){
simulatedFileObj = new Blob(['<strong>Hello World</strong>'], {type : 'text/html'});
simulatedFileObj2 = new Blob(['<strong>Hello Again, World</strong>'], {type : 'text/html'});
fileModel = new File({
from: 'sample@email.com',
@ -44,13 +42,13 @@
});
it('should detect the file(blob) save successfully', function(done){
// Arrange
fileModel.set({fileAttachment: simulatedFileObj});
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
@ -72,7 +70,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
@ -94,6 +92,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
@ -110,33 +109,11 @@
});
it ('should be able to save an array of multiple file objects', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
expect(model.get('fileAttachment')[0].size).toBe(28);
expect(model.get('fileAttachment')[0].type).toBe('text/html');
//expect(model.get('fileAttachment')[0].data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==')
expect(model.get('fileAttachment')[1].size).toBe(35);
expect(model.get('fileAttachment')[1].type).toBe('text/html');
//expect(model.get('fileAttachment')[1].data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBBZ2FpbiwgV29ybGQ8L3N0cm9uZz4K=')
done();
});
// Act
fileModel.save('fileAttachment', [simulatedFileObj, simulatedFileObj2], {formData: true});
});
it ('should be able to have "wait" and "validate" option', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
@ -157,7 +134,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('somethingelse@email.com');
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
@ -176,7 +153,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
@ -194,7 +171,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
@ -214,7 +191,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
expect(model.get('fileAttachment').size).toBe(28);
@ -243,7 +220,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
@ -291,7 +268,7 @@
expect(_.isEqual(unflattened, fileModel.toJSON())).toBeTruthy();
console.log(JSON.stringify(fileModel._flatten({
console.log(fileModel._flatten({
'family': 'The Smiths',
'grandpa': {
'name': 'Ole Joe Smith',
@ -310,11 +287,11 @@
}
]
}
})));
}));
});
});
}();
}();

View File

@ -15,17 +15,9 @@ var server = http.createServer(function(req,res) {
console.log('POST Detected with incoming Form-data...');
var form = new formidable.IncomingForm(),
files = {},
fields = {};
var form = new formidable.IncomingForm();
form.on('file', function(field, file) {
files[field] = (files[field] || []).concat([file]);
});
form.on('field', function(field, value) {
fields[field] = value;
});
form.on('end', function(err) {
form.parse(req, function(err, fields, files) {
console.log('POST Finished and publishing object back to browser...');
var headers = {};
@ -41,23 +33,28 @@ var server = http.createServer(function(req,res) {
var output = {};
_.extend(output, unflatten(fields));
var fileOutputs = {};
_.each(files, function(files, filename){
var loopOutputs = [];
_.each(files, function(file) {
var fileOutput = {},
data = fs.readFileSync(file.path);
fileOutput.type = file.type;
fileOutput.size = data.length;
fileOutput.name = file.name;
fileOutput.lastModifiedDate = file.lastModifiedDate;
fileOutput.data = 'data:' + file.type + ';base64,' + data.toString('base64');
loopOutputs.push(fileOutput);
});
loopOutputs = loopOutputs.length > 1 ? loopOutputs : loopOutputs[0];
fileOutputs[filename] = loopOutputs;
});
output = _.merge(output, fileOutputs);
if (!_.isEmpty(files)) {
for (var i in files) {
if (files.hasOwnProperty(i)) {
output[i] = {};
fs.readFile(files[i].path, function (err, data) {
output[i].type = files[i].type;
output[i].size = files[i].size;
output[i].name = files[i].name;
output[i].lastModifiedDate = files[i].lastModifiedDate;
output[i].data = 'data:' + files[i].type + ';base64,' + data.toString('base64');
});
}
}
}
console.info(output);
@ -65,8 +62,6 @@ var server = http.createServer(function(req,res) {
});
form.parse(req)
});
function unflatten(obj, output) {