Merge pull request #13 from homeslicesolutions/Refactoring-the-class
Major refactor
This commit is contained in:
commit
243d8bb619
49
Gruntfile.js
49
Gruntfile.js
@ -4,7 +4,7 @@ module.exports = function(grunt) {
|
||||
|
||||
run_node: {
|
||||
start: {
|
||||
files: { src: [ 'tests/mock-file-server.js'] }
|
||||
files: { src: [ 'test/mock-file-server.js'] }
|
||||
}
|
||||
},
|
||||
|
||||
@ -35,41 +35,50 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
jasmine: {
|
||||
amd: {
|
||||
src: 'backbone-model-file-upload.js',
|
||||
host: 'http://localhost:8888/',
|
||||
options: {
|
||||
specs: ['tests/*spec.js'],
|
||||
specs: ['test/*spec.js'],
|
||||
helpers: 'bower_components/Blob/Blob.js',
|
||||
//keepRunner: true,
|
||||
template: require('grunt-template-jasmine-requirejs'),
|
||||
templateOptions: {
|
||||
requireConfig: {
|
||||
paths: {
|
||||
"jquery": "bower_components/jquery/dist/jquery.min",
|
||||
"underscore": "bower_components/underscore/underscore-min",
|
||||
"backbone": "bower_components/backbone/backbone"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
browserGlobal: {
|
||||
src: 'backbone-model-file-upload.js',
|
||||
host: 'http://localhost:8888/',
|
||||
options: {
|
||||
specs: ['test/*spec.js'],
|
||||
//keepRunner: true,
|
||||
vendor: [
|
||||
"bower_components/Blob/Blob.js",
|
||||
"bower_components/jquery/dist/jquery.min.js",
|
||||
"bower_components/underscore/underscore-min.js",
|
||||
"bower_components/backbone/backbone.js",
|
||||
"backbone-model-file-upload.js"
|
||||
"bower_components/backbone/backbone.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
parallel: {
|
||||
runTest: {
|
||||
tasks: [{
|
||||
grunt: true,
|
||||
args: ['run:mockServer']
|
||||
}, {
|
||||
grunt: true,
|
||||
args: ['jasmine']
|
||||
}, {
|
||||
cmd: 'node:kill'
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||
grunt.loadNpmTasks('grunt-run');
|
||||
grunt.loadNpmTasks('grunt-parallel');
|
||||
grunt.loadNpmTasks('grunt-run-node');
|
||||
|
||||
grunt.registerTask('test', ['run:installBower','run_node','jasmine','stop_node']);
|
||||
grunt.registerTask('test', ['build','run_node','jasmine','stop_node']);
|
||||
grunt.registerTask('build', ['run:installBower']);
|
||||
grunt.registerTask('resetNodeWin', ['run:killAllNodeWindows']);
|
||||
grunt.registerTask('resetNodeMac', ['run:killAllNodeMac']);
|
||||
|
||||
|
17
README.md
17
README.md
@ -1,8 +1,9 @@
|
||||
Backbone.Model File Upload
|
||||
==========================
|
||||
![alt tag](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload.svg?branch=master)
|
||||
A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)
|
||||
|
||||
![alt tag](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload.svg?branch=master)
|
||||
|
||||
|
||||
This plugin upgrades the current `save` method to be able to upload files using the HTML5's File API and FormData class.
|
||||
|
||||
@ -162,18 +163,20 @@ c Version v0.1
|
||||
|
||||
#### Version 0.5.2
|
||||
- Add jQuery to the UMD dependency model
|
||||
-
|
||||
|
||||
#### Version 0.5.3
|
||||
- Added CommonJS support
|
||||
|
||||
### Dev/Installation
|
||||
If you want to work on this plugin, test it, etc., it just needs an install of `node` and `grunt`.
|
||||
```
|
||||
npm i -d
|
||||
```
|
||||
To build
|
||||
```
|
||||
grunt build
|
||||
```
|
||||
To test
|
||||
```
|
||||
npm test
|
||||
npm test OR grunt test
|
||||
```
|
||||
|
||||
### Future plans
|
||||
As I'm looking at this plugin and all the plugins, I'm not really extending out the Backbone class like how it should. Also people have been asking me to write a mixin version instead. Also there should be a CommonJS version as well. If any of you guys want to help please do. That would be great!
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Backbone.Model File Upload v0.5.2
|
||||
// Backbone.Model File Upload v0.5.3
|
||||
// by Joe Vu - joe.vu@homeslicesolutions.com
|
||||
// For all details and documentation:
|
||||
// https://github.com/homeslicesolutions/backbone-model-file-upload
|
||||
@ -7,21 +7,32 @@
|
||||
// bildja - Dima Bildin - github.com/bildja
|
||||
// Minjung - Alejandro - github.com/Minjung
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['underscore', 'jquery', 'backbone'], factory);
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(_, $, Backbone);
|
||||
}
|
||||
}(this, function(_, $, Backbone){
|
||||
(function(root, factory) {
|
||||
|
||||
// Clone the original Backbone.Model.prototype
|
||||
var backboneModelClone = _.clone( Backbone.Model.prototype );
|
||||
// AMD
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['underscore', 'jquery', 'backbone'], function(_, $, Backbone){
|
||||
factory(root, Backbone, _, $);
|
||||
});
|
||||
|
||||
// NodeJS/CommonJS
|
||||
} else if (typeof exports !== 'undefined') {
|
||||
var _ = require('underscore'), $ = require('jquery'), Backbone = require('backbone');
|
||||
factory(root, _, $, Backbone);
|
||||
|
||||
// Browser global
|
||||
} else {
|
||||
factory(root, root.Backbone, root._, root.$);
|
||||
}
|
||||
|
||||
}(this, function(root, Backbone, _, $) {
|
||||
'use strict';
|
||||
|
||||
// Clone the original Backbone.Model.prototype as superClass
|
||||
var _superClass = _.clone( Backbone.Model.prototype );
|
||||
|
||||
// Extending out
|
||||
_.extend(Backbone.Model.prototype, {
|
||||
var BackboneModelFileUpload = Backbone.Model.extend({
|
||||
|
||||
// ! Default file attribute - can be overwritten
|
||||
fileAttribute: 'file',
|
||||
@ -100,7 +111,7 @@
|
||||
if (attrs && options.wait) this.attributes = attributes;
|
||||
|
||||
// Continue to call the existing "save" method
|
||||
return backboneModelClone.save.call(this, attrs, options);
|
||||
return _superClass.save.call(this, attrs, options);
|
||||
|
||||
},
|
||||
|
||||
@ -131,7 +142,9 @@
|
||||
this.trigger( 'progress', percentComplete );
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Export out to override Backbone Model
|
||||
Backbone.Model = BackboneModelFileUpload;
|
||||
|
||||
}));
|
||||
|
@ -3,6 +3,7 @@
|
||||
"dependencies": {
|
||||
"jquery": "~2.1.1",
|
||||
"backbone": "~1.1.2",
|
||||
"Blob": "*"
|
||||
"Blob": "*",
|
||||
"requirejs": "~2.1.15"
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
"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"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -14,6 +14,8 @@
|
||||
fileAttribute: 'fileAttachment'
|
||||
});
|
||||
|
||||
|
||||
|
||||
var fileModel;
|
||||
var simulatedFileObj;
|
||||
|
||||
@ -136,7 +138,7 @@
|
||||
|
||||
// Act
|
||||
fileModel.set({from: 'somethingelse@email.com'});
|
||||
fileModel.save(null);
|
||||
fileModel.save();
|
||||
|
||||
});
|
||||
|
91
test/mock-file-server.js
Normal file
91
test/mock-file-server.js
Normal file
@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
var http = require('http'),
|
||||
formidable = require('formidable'),
|
||||
fs = require('fs'),
|
||||
_ = require('lodash');
|
||||
|
||||
|
||||
var options = {
|
||||
host: 'localhost',
|
||||
port: 8989
|
||||
};
|
||||
|
||||
var server = http.createServer(function(req,res) {
|
||||
|
||||
console.log('POST Detected with incoming Form-data...');
|
||||
|
||||
var form = new formidable.IncomingForm();
|
||||
|
||||
form.parse(req, function(err, fields, files) {
|
||||
console.log('POST Finished and publishing object back to browser...');
|
||||
|
||||
var headers = {};
|
||||
headers['Content-Type'] = 'application/json';
|
||||
headers["Access-Control-Allow-Origin"] = req.headers.origin;
|
||||
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
|
||||
headers["Access-Control-Allow-Credentials"] = true;
|
||||
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
|
||||
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Access-Control-Allow-Origin, Content-Type, Accept";
|
||||
|
||||
res.writeHead(200, headers);
|
||||
|
||||
var output = {};
|
||||
|
||||
_.extend(output, unflatten(fields));
|
||||
|
||||
if (_.isEmpty(files)) return res.end(JSON.stringify(output));
|
||||
|
||||
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');
|
||||
|
||||
res.end(JSON.stringify(output));
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var unflatten = function(path, obj, value) {
|
||||
var key, child, output;
|
||||
if (Object.prototype.toString.call(path) == '[object Object]') {
|
||||
output = {};
|
||||
for (key in path) {
|
||||
if (path.hasOwnProperty(key)) {
|
||||
unflatten(key.split('.'), output, path[key]);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
key = path.shift();
|
||||
|
||||
if (!path.length) {
|
||||
obj[key] = value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
if ((child = obj[key]) == void 0) {
|
||||
child = obj[key] = {};
|
||||
}
|
||||
|
||||
unflatten(path, child, value);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
server.listen(options.port, options.host);
|
||||
console.log("listening on " + options.host + ':' + options.port);
|
@ -1,122 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var http = require('http'),
|
||||
formidable = require('formidable'),
|
||||
fs = require('fs'),
|
||||
_ = require('lodash');
|
||||
|
||||
|
||||
var options = {
|
||||
host: 'localhost',
|
||||
port: 8989
|
||||
};
|
||||
|
||||
|
||||
var unflatten = function(path, obj, value) {
|
||||
var key, child, output;
|
||||
if (Object.prototype.toString.call(path) == '[object Object]') {
|
||||
output = {};
|
||||
for (key in path) {
|
||||
if (path.hasOwnProperty(key)) {
|
||||
unflatten(key.split('.'), output, path[key]);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
key = path.shift();
|
||||
|
||||
if (!path.length) {
|
||||
obj[key] = value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
if ((child = obj[key]) == void 0) {
|
||||
child = obj[key] = {};
|
||||
}
|
||||
|
||||
unflatten(path, child, value);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
var server = http.createServer(function(req,res) {
|
||||
|
||||
// Capture POST call
|
||||
//if (req.method == 'POST' && req.headers['content-type'].match('application/json')) {
|
||||
//
|
||||
// console.log('POST Detected with incoming JSON...');
|
||||
//
|
||||
// var body = '';
|
||||
// req.on('data', function (data) {
|
||||
// body += data;
|
||||
// console.log('POST Data: ' + data);
|
||||
// });
|
||||
//
|
||||
// req.on('end', function () {
|
||||
// console.log('POST Finished and publishing object back to browser...');
|
||||
// res.writeHead(200, {'Content-Type': 'application/json'});
|
||||
// res.end(body);
|
||||
// });
|
||||
//
|
||||
//
|
||||
//
|
||||
//} else if ((req.method == 'POST' || req.method == 'OPTIONS') && req.headers['content-type'].match('multipart/form-data') > 0) {
|
||||
|
||||
console.log('POST Detected with incoming Form-data...');
|
||||
|
||||
var form = new formidable.IncomingForm();
|
||||
|
||||
form.parse(req, function(err, fields, files) {
|
||||
console.log('POST Finished and publishing object back to browser...');
|
||||
|
||||
var headers = {};
|
||||
headers['Content-Type'] = 'application/json';
|
||||
headers["Access-Control-Allow-Origin"] = req.headers.origin;
|
||||
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
|
||||
headers["Access-Control-Allow-Credentials"] = true;
|
||||
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
|
||||
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Access-Control-Allow-Origin, Content-Type, Accept";
|
||||
|
||||
res.writeHead(200, headers);
|
||||
|
||||
var output = {};
|
||||
|
||||
_.extend(output, unflatten(fields));
|
||||
|
||||
if (_.isEmpty(files)) return res.end(JSON.stringify(output));
|
||||
|
||||
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');
|
||||
|
||||
res.end(JSON.stringify(output));
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
//} else {
|
||||
// console.log('GET Detected...');
|
||||
// console.log('GET Returning OK');
|
||||
// res.writeHead(200, {'Content-Type': 'text/html'})
|
||||
// res.end('OK');
|
||||
//}
|
||||
|
||||
});
|
||||
|
||||
server.listen(options.port, options.host);
|
||||
console.log("listening on " + options.host + ':' + options.port);
|
Loading…
Reference in New Issue
Block a user