Commit 4937ef0f
Changed files (6)
app
assets
javascripts
backbone
controllers
api
vendor
assets
javascripts
app/assets/javascripts/backbone/models/photo.js.coffee
@@ -1,5 +1,6 @@
class Cake.Models.Photo extends Backbone.Model
paramRoot: 'photo'
+ fileAttribute: 'image'
defaults:
thumb_url: null
@@ -8,7 +9,6 @@ class Cake.Models.Photo extends Backbone.Model
class Cake.Collections.PhotosCollection extends Backbone.Collection
model: Cake.Models.Photo
- url: '/api/v1/cakes/1/photos'
initialize: (options) ->
@url="/api/v1/cakes/#{options.cake_id}/photos"
app/assets/javascripts/backbone/templates/photos/new.jst.ejs
@@ -3,9 +3,9 @@
<form id="new-photo" name="photo" class="form-horizontal">
<fieldset>
<div class="control-group">
- <label class="control-label" for="photo_image">Photo</label>
+ <label class="control-label" for="photo_attachment">Photo</label>
<div class="controls">
- <input class="input-xxlarge" id="photo_image" name="image" type="file">
+ <input class="input-xxlarge" id="photo_attachment" name="attachment" type="file">
</div>
</div>
<div class="form-actions">
app/assets/javascripts/backbone/views/photos/new_view.js.coffee
@@ -20,14 +20,24 @@ class Cake.Views.Photos.NewView extends Backbone.View
@model.unset("errors")
- @collection.create(@model.toJSON(),
- success: (photo) =>
- @model = photo
- window.location.hash = "/#{@model.id}"
-
- error: (photo, jqXHR) =>
- @model.set({errors: $.parseJSON(jqXHR.responseText)})
- )
+ fileObject = @$(':input[type="file"]')[0].files[0]
+ photo = new Cake.Models.Photo(cake_id: 100)
+ photo.url = => @collection.url
+ photo.set('image', fileObject)
+ photo.on('progress', console.log)
+ photo.save()
+
+ #@model.set('image', fileObject)
+ #@model.save()
+ #@model.on('progress', console.log)
+ #@collection.create(@model.toJSON(),
+ #success: (photo) =>
+ #@model = photo
+ #window.location.hash = "/#{@model.id}"
+
+ #error: (photo, jqXHR) =>
+ #@model.set({errors: $.parseJSON(jqXHR.responseText)})
+ #)
render: ->
$(@el).html(@template(@model.toJSON() ))
app/assets/javascripts/application.js
@@ -28,4 +28,5 @@
//= require backbone_rails_sync
//= require backbone_datalink
//= require backbone/cake
+//= require backbone-model-file-upload
//= require_tree .
app/controllers/api/v1/photos_controller.rb
@@ -5,7 +5,7 @@ module Api
def create
cake_id = params[:cake_id]
- UploadPhoto.new.run(cake_id, photo_params)
+ UploadPhoto.new.run(cake_id, params)
@photo = Creation.find(cake_id).photos.last
respond_with(@photo)
end
vendor/assets/javascripts/backbone-model-file-upload.js
@@ -0,0 +1,117 @@
+// Backbone.Model File Upload v0.1
+// by Joe Vu - joe.vu@homeslicesolutions.com
+// For all details and documentation:
+// https://github.com/homeslicesolutions/backbone-model-file-upload
+
+!function(_, Backbone){
+
+ // Clone the original Backbone.Model.prototype
+ var backboneModelClone = _.clone( Backbone.Model.prototype );
+
+ // Extending out
+ _.extend(Backbone.Model.prototype, {
+
+ // ! Default file attribute - can be overwritten
+ fileAttribute: 'file',
+
+ // @ Save - overwritten
+ save: function(key, val, options) {
+
+ // Variables
+ 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.'
+ if (key == null || typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ // Validate & wait options - taken directly from original Backbone.Model.save
+ options = _.extend({validate: true}, options);
+ if (attrs && !options.wait) {
+ if (!this.set(attrs, options)) return false;
+ } else {
+ if (!this._validate(attrs, options)) return false;
+ }
+ if (attrs && options.wait) {
+ this.attributes = _.extend({}, attributes, attrs);
+ }
+
+ // Check for "formData" flag and check for if file exist.
+ if ( options.formData === true
+ || options.formData !== false
+ && this.attributes[ this.fileAttribute ]
+ && this.attributes[ this.fileAttribute ] instanceof File ) {
+
+ // Flatten Attributes reapplying File Object
+ var formAttrs = _.clone( this.attributes ),
+ fileAttr = this.attributes[ this.fileAttribute ];
+ formAttrs = this._flatten( formAttrs );
+ formAttrs[ this.fileAttribute ] = fileAttr;
+
+ // Converting Attributes to Form Data
+ var formData = new FormData();
+ _.each( formAttrs, function( value, key ){
+ formData.append( key, value );
+ });
+
+ // Set options for AJAX call
+ options = options || {};
+ options.data = formData;
+ 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', function(){
+
+ that._progressHandler.apply(that, arguments);
+ }, false);
+ return xhr;
+ }
+ }
+
+ // Resume back to original state
+ if (attrs && options.wait) this.attributes = attributes;
+
+ // Continue to call the existing "save" method
+ return backboneModelClone.save.call(this, attrs, options);
+
+ },
+
+ // _ FlattenObject gist by "penguinboy". Thank You!
+ // https://gist.github.com/penguinboy/762197
+ _flatten: function( obj ) {
+ var output = {};
+ for (var i in obj) {
+ if (!obj.hasOwnProperty(i)) continue;
+ if (typeof obj[i] == 'object') {
+ var flatObject = this._flatten(obj[i]);
+ for (var x in flatObject) {
+ if (!flatObject.hasOwnProperty(x)) continue;
+ output[i + '.' + x] = flatObject[x];
+ }
+ } else {
+ output[i] = obj[i];
+ }
+ }
+ return output;
+
+ },
+
+ // _ Get the Progress of the uploading file
+ _progressHandler: function( event ) {
+ if (event.lengthComputable) {
+ var percentComplete = event.loaded / event.total;
+ this.trigger( 'progress', percentComplete );
+ }
+ }
+
+ });
+
+}(_, Backbone);