Big fixes with arguments and save

The current state was completely messed up with saving and all the
different scenarios.  This update brings back my main intent of the
code and also does a separate merge of the attributes for the use of
the FileObj.  It also adds Blob support, and I finally written some
tests.
This commit is contained in:
homeslicesolutions 2014-08-30 12:08:56 -07:00
parent 5236fd812b
commit 3a31989778
4 changed files with 218 additions and 72 deletions

View File

@ -1,4 +1,4 @@
// Backbone.Model File Upload v0.3 // Backbone.Model File Upload v0.4
// by Joe Vu - joe.vu@homeslicesolutions.com // by Joe Vu - joe.vu@homeslicesolutions.com
// For all details and documentation: // For all details and documentation:
// https://github.com/homeslicesolutions/backbone-model-file-upload // https://github.com/homeslicesolutions/backbone-model-file-upload
@ -31,16 +31,11 @@
// Variables // Variables
var attrs, attributes = this.attributes; var attrs, attributes = this.attributes;
// Signature parsing - similar to original Backbone.Model.save // Signature parsing - taken directly from original Backbone.Model.save
// Handle (key, value, options), ({key: value}, options), and (options) -style arguments. // and it states: 'Handle both "key", value and {key: value} -style arguments.'
if (typeof key === 'object') { if (key == null || typeof key === 'object') {
if (typeof val === void 0) {
attrs = attributes;
options = key;
} else {
attrs = key; attrs = key;
options = val; options = val;
}
} else { } else {
(attrs = {})[key] = val; (attrs = {})[key] = val;
} }
@ -52,19 +47,24 @@
} else { } else {
if (!this._validate(attrs, options)) return false; if (!this._validate(attrs, options)) return false;
} }
// Merge data temporarily for formdata
var mergedAttrs = _.extend({}, attributes, attrs);
if (attrs && options.wait) { if (attrs && options.wait) {
this.attributes = _.extend({}, attributes, attrs); this.attributes = mergedAttrs;
} }
// Check for "formData" flag and check for if file exist. // Check for "formData" flag and check for if file exist.
if ( options.formData === true if ( options.formData === true
|| options.formData !== false || options.formData !== false
&& attrs[ this.fileAttribute ] && mergedAttrs[ this.fileAttribute ]
&& attrs[ this.fileAttribute ] instanceof File ) { && mergedAttrs[ this.fileAttribute ] instanceof File
|| mergedAttrs[ this.fileAttribute ] instanceof Blob ) {
// Flatten Attributes reapplying File Object // Flatten Attributes reapplying File Object
var formAttrs = _.clone( attrs ), var formAttrs = _.clone( mergedAttrs ),
fileAttr = attrs[ this.fileAttribute ]; fileAttr = mergedAttrs[ this.fileAttribute ];
formAttrs = this._flatten( formAttrs ); formAttrs = this._flatten( formAttrs );
formAttrs[ this.fileAttribute ] = fileAttr; formAttrs[ this.fileAttribute ] = fileAttr;
@ -75,7 +75,6 @@
}); });
// Set options for AJAX call // Set options for AJAX call
options = options || {};
options.data = formData; options.data = formData;
options.processData = false; options.processData = false;
options.contentType = false; options.contentType = false;
@ -85,7 +84,6 @@
options.xhr = function() { options.xhr = function() {
var xhr = $.ajaxSettings.xhr(); var xhr = $.ajaxSettings.xhr();
xhr.upload.addEventListener('progress', function(){ xhr.upload.addEventListener('progress', function(){
that._progressHandler.apply(that, arguments); that._progressHandler.apply(that, arguments);
}, false); }, false);
return xhr; return xhr;

View File

@ -1,12 +1,21 @@
!function(){ !function(){
'use strict' 'use strict'
describe('Testing Backbone Model Plugin', function(){
var File = Backbone.Model.extend({ var File = Backbone.Model.extend({
url: 'upload-test.php', url: 'upload-test.php',
fileAttribute: 'fileAttachment' fileAttribute: 'fileAttachment'
}); });
var file = new File({ var fileModel;
var simulatedFileObj;
beforeEach(function(){
simulatedFileObj = new Blob(['<strong>Hello World</strong>'], {type : 'text/html'});
fileModel = new File({
from: 'sample@email.com', from: 'sample@email.com',
subject: 'Hello, friend!', subject: 'Hello, friend!',
body: 'Dear friend, Just saying hello! Love, Yours truly.', body: 'Dear friend, Just saying hello! Love, Yours truly.',
@ -15,15 +24,138 @@
} }
}); });
$('#fileupload').on('change', function(e){ });
var fileObj = $(this)[0].files[0];
console.log(fileObj) it('should detect the file(blob) save successfully', function(done){
file.set('fileAttachment', fileObj);
file.save(); // Arrange
fileModel.set({fileAttachment: simulatedFileObj});
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
}) })
//file.save(); // Act
fileModel.save(null);
});
it ('should be able to be saved in as an argument of "save" as object', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
});
// Act
fileModel.save({fileAttachment: simulatedFileObj});
});
it ('should be able to be saved in as an argument of "save" as key/value argument', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('sample@email.com');
expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
});
// Act
fileModel.save('fileAttachment', simulatedFileObj);
});
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');
expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
});
// Act
fileModel.save({fileAttachment: simulatedFileObj},{wait: true, validate: false});
});
it('should still have the option to save normally by setting it and save(null)', function(done){
// 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==');
done();
});
// Act
fileModel.set({from: 'somethingelse@email.com'});
fileModel.save(null);
});
it('should still have the option to save normally by save("from","yes")', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
});
// Act
fileModel.save('from','yes');
});
it('should still have the option to save normally by save({from: "yes"})', function(done){
// Listen
fileModel.on('sync', function(model){
// Assert
expect(model.get('from')).toBe('yes');
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
done();
});
// Act
fileModel.save({from: "yes"});
});
});
}(); }();

View File

@ -11,22 +11,13 @@
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script type="text/javascript" src="../backbone-model-file-upload.js"></script> <script type="text/javascript" src="../backbone-model-file-upload.js"></script>
<!--
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine-html.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/boot.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/boot.js"></script>
-->
</head> </head>
<body> <body>
<script>
</script>
<input type="file" id="fileupload" />
<script type="text/javascript" src="backbone-model-file-upload.spec.js"></script> <script type="text/javascript" src="backbone-model-file-upload.spec.js"></script>
</body> </body>
</html> </html>

View File

@ -1,23 +1,48 @@
<?php <?php
// Parse as Form Data
$passthrough = $_REQUEST;
// Parse as JSON API Request
foreach (getallheaders() as $name => $value) {
if (strpos(strtolower($name), 'content-type') > -1
&& strpos(strtolower($value), 'json') > -1) {
$json = file_get_contents('php://input');
$obj = json_decode($json);
foreach ($obj as $key => $value) {
$passthrough[$key] = $value;
}
break;
}
}
$model = array(
'from' => $passthrough['from'],
'subject' => $passthrough['subject'],
'body' => $passthrough['body'],
'nestedObject' => array(
'nest' => $passthrough["nestedObject_nest"]
)
);
$fileName = $_FILES['fileAttachment']['name']; $fileName = $_FILES['fileAttachment']['name'];
$fileType = $_FILES['fileAttachment']['type']; $fileType = $_FILES['fileAttachment']['type'];
$fileContent = file_get_contents($_FILES['fileAttachment']['tmp_name']);
$dataUrl = 'data:' . $fileType . ';base64,' . base64_encode($fileContent);
if ($_FILES['fileAttachment']['tmp_name'] != "") {
$fileContent = file_get_contents($_FILES['fileAttachment']['tmp_name']);
$dataUrl = 'data:' . $fileType . ';base64,' . base64_encode($fileContent);
$json = json_encode(array( $model['fileAttachment'] = array(
'fileAttachment' => array(
'name' => $fileName, 'name' => $fileName,
'type' => $fileType, 'type' => $fileType,
'data' => $dataUrl 'data' => $dataUrl
), );
'from' => $_REQUEST['from'],
'subject' => $_REQUEST['subject'],
'body' => $_REQUEST['body'],
'nestedObject' => array(
'nest' => $_REQUEST["nestedObject.nest"]
)
));
echo $json; }
echo json_encode($model);
?> ?>