Compare commits

...

14 Commits

Author SHA1 Message Date
Joe Vu
7b27f21900 Fixing NPM Issues 2016-09-12 16:17:10 -07:00
Joe Vu
3f68ed5dbe 1.0.1 2016-09-12 16:15:25 -07:00
Joe Vu
17749e3e3e Update README.md
Small changes
2016-06-24 17:00:24 -07:00
Joe Vu
0850191d77 Merge pull request #31 from HuFlungDu/master
I agree.  Lets try this out. I will take a closer look when i get a good amount of time. Usually list of things will have that "length" property i guess.
2016-02-09 04:10:44 -08:00
Josiah Baldwin
34dbcf37a6 Added test for array of files. Also added JSON.stringify around the flatten call in the log call at the end of the unflatten test 2016-01-19 11:43:11 -08:00
Josiah Baldwin
86142c6af8 Updated mock file server to allow multiple file echo. Still does not pass, probably because formidable fails to read the files correctly, but the logic is sound. 2016-01-19 11:41:21 -08:00
Josiah Baldwin
3d9da19009 Updated file upload array to be more simple. Fixed problem when using older browsers that do not support function.prototype.bind (or phantomJS in this case, for the tests) 2016-01-19 11:36:07 -08:00
Josiah Baldwin
bbd293f738 Added handling array of files, instead of FileList, because FileList cannot be instantiated by the user 2016-01-15 14:50:30 -08:00
Joe Vu
c602d2816a Update README.md 2015-11-24 02:44:55 -08:00
Joe Vu
ea32f22c2d Just some update in README.md description 2015-11-23 11:53:37 -08:00
Joe Vu
61991eceaa Merge pull request #26 from feychenie/patch-2
Moved dependencies to devDependancies
2015-11-12 22:36:01 -08:00
Joe Vu
22d4b7c1e0 Merge pull request #24 from feychenie/patch-1
Remove explicit dependancy to jQuery
2015-11-12 22:35:43 -08:00
Frederik Eychenié
35f623c834 Moved dependencies to devDependancies
The dependencies listed in the package.json are actually devDependencies, and not required to install the main script.
2015-10-26 11:07:54 +01:00
Frederik Eychenié
fbf99e030a Remove explicit dependancy to jQuery
Sometimes Backbone is used without jQuery (see https://github.com/akre54/Backbone.NativeAjax)
2015-10-12 15:29:46 +02:00
5 changed files with 101 additions and 69 deletions

View File

@ -1,7 +1,5 @@
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.)
@ -43,8 +41,8 @@ email.set('attachment', fileObject);
email.save();
email.on('progress', console.log);
// Will result: the status in percent i.e. 0.3233
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)
```
### fileAttribute
@ -176,6 +174,9 @@ 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', 'jquery', 'backbone'], function(_, $, Backbone){
factory(root, Backbone, _, $);
define(['underscore', 'backbone'], function(_, Backbone){
factory(root, Backbone, _);
});
// NodeJS/CommonJS
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $ = require('jquery'), Backbone = require('backbone');
factory(root, Backbone, _, $);
var _ = require('underscore'), Backbone = require('backbone');
factory(root, Backbone, _);
// Browser global
} else {
factory(root, root.Backbone, root._, root.$);
factory(root, root.Backbone, root._);
}
}(this, function(root, Backbone, _, $) {
}(this, function(root, Backbone, _) {
'use strict';
// Clone the original Backbone.Model.prototype as superClass
@ -43,7 +43,8 @@
save: function(key, val, options) {
// Variables
var attrs, attributes = this.attributes;
var attrs, attributes = this.attributes,
that = this;
// Signature parsing - taken directly from original Backbone.Model.save
// and it states: 'Handle both "key", value and {key: value} -style arguments.'
@ -86,13 +87,14 @@
// Converting Attributes to Form Data
var formData = new FormData();
_.each( formAttrs, function( value, key ){
if (value instanceof FileList) {
if (value instanceof FileList || (key === that.fileAttribute && value instanceof Array)) {
_.each(value, function(file) {
formData.append( key, file );
});
return;
}
formData.append( key, value );
else {
formData.append( key, value );
}
});
// Set options for AJAX call
@ -100,12 +102,13 @@
options.processData = false;
options.contentType = false;
// 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;
// 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
}
}
}

View File

@ -1,21 +1,12 @@
{
"name": "backbone-model-file-upload",
"version": "1.0.0",
"version": "1.0.2",
"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": {
"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"
},
"dependencies": {},
"scripts": {
"test": "grunt test"
},
@ -36,5 +27,14 @@
"url": "https://github.com/homeslicesolutions/backbone-model-file-upload/issues"
},
"homepage": "https://github.com/homeslicesolutions/backbone-model-file-upload",
"devDependencies": {}
"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"
}
}

View File

@ -18,10 +18,12 @@
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',
@ -42,13 +44,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');
@ -70,7 +72,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
@ -92,7 +94,6 @@
// 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)
@ -109,11 +110,33 @@
});
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)
@ -134,7 +157,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==');
@ -153,7 +176,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==');
@ -171,7 +194,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==');
@ -191,7 +214,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);
@ -220,7 +243,7 @@
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
@ -268,7 +291,7 @@
expect(_.isEqual(unflattened, fileModel.toJSON())).toBeTruthy();
console.log(fileModel._flatten({
console.log(JSON.stringify(fileModel._flatten({
'family': 'The Smiths',
'grandpa': {
'name': 'Ole Joe Smith',
@ -287,11 +310,11 @@
}
]
}
}));
})));
});
});
}();
}();

View File

@ -15,9 +15,17 @@ var server = http.createServer(function(req,res) {
console.log('POST Detected with incoming Form-data...');
var form = new formidable.IncomingForm();
var form = new formidable.IncomingForm(),
files = {},
fields = {};
form.parse(req, function(err, fields, files) {
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) {
console.log('POST Finished and publishing object back to browser...');
var headers = {};
@ -33,28 +41,23 @@ var server = http.createServer(function(req,res) {
var output = {};
_.extend(output, unflatten(fields));
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');
});
}
}
}
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);
console.info(output);
@ -62,6 +65,8 @@ var server = http.createServer(function(req,res) {
});
form.parse(req)
});
function unflatten(obj, output) {