Created
October 27, 2011 15:33
-
-
Save FestivalBobcats/1319903 to your computer and use it in GitHub Desktop.
Multi image uploader in Backbone.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
// | |
//-------------------------------------- Model : Image | |
// | |
Image = Backbone.Model.extend({ | |
defaults: { | |
'delete' : false | |
} | |
}); | |
// | |
//-------------------------------------- Collection : ProductImages | |
// | |
ProductImages = Backbone.Collection.extend({ | |
model: Image, | |
url: '#{ admin_product_images_path(product.id) }', | |
allMarked: function(){ | |
return this.filter(function(image){ return image.get('delete'); }); | |
} | |
}); | |
// | |
//-------------------------------------- View : Image | |
// | |
ImageView = Backbone.View.extend({ | |
tagName: 'li', | |
events: { | |
'click a.img_delete' : 'markForDestroy' | |
}, | |
initialize: function(){ | |
this.template = ich.product_image; | |
this.model.bind('change:delete', this.render, this); | |
}, | |
render: function(){ | |
var self = this, | |
attr = this.model.toJSON(), | |
elem = $(self.el), | |
marked = this.model.get('delete'); | |
if (marked) { | |
attr.cssState = 'marked'; | |
attr.btnTitle = 'undo'; | |
} else { | |
attr.cssState = null; | |
attr.btnTitle = 'delete'; | |
} | |
elem.html( | |
self.template(attr) | |
); | |
// display red-tinted overlay if marked | |
if (marked) { | |
var img = this.$('a.img_thumb'), | |
offset = img.offset(); | |
this.$('.img_overlay').css({ | |
display: 'block', | |
width: img.css('width'), | |
height: img.css('height'), | |
top: offset.top + 'px', | |
left: offset.left + 'px' | |
}); | |
} | |
return elem; | |
}, | |
markForDestroy: function(){ | |
var model = this.model; | |
model.set({ delete: !model.get('delete') }); | |
return false; | |
} | |
}); | |
// | |
//-------------------------------------- View : UploaderSidebar | |
// | |
UploaderSidebar = Backbone.View.extend({ | |
className: 'span-4', | |
events: { | |
'click a.delete_imgs' : 'destroySelected' | |
}, | |
initialize: function(){ | |
this.template = ich.multi_img_upload; | |
this.collection.bind('change:delete', this.render, this); | |
this.collection.bind('reset', this.render, this); | |
}, | |
render: function(){ | |
var self = this, | |
elem = $(this.el), | |
collection = self.collection, | |
control = self.model; | |
elem.html( | |
self.template() | |
); | |
// File uploader | |
self.$('#img_drop').html5Uploader({ | |
name: 'images[]', | |
postUrl: '#{ admin_product_images_path(product.id) }', | |
// When the files are read by the browser | |
onClientLoad: function(){ | |
control.startLoad(); | |
}, | |
// This is a funky callback, thanks to XmlHttpRequest. | |
onServerReadyStateChange: function(request){ | |
if (request.readyState == 4) { | |
control.stopLoad(); | |
if (request.status == 200) { | |
collection.reset( | |
JSON.parse(request.responseText) | |
) | |
} else { | |
throw new Error('File upload request error'); | |
} | |
} | |
} | |
}); | |
// Delete button | |
var markedCount = collection.allMarked().length; | |
if (markedCount) { | |
var btn = self.$('a.delete_imgs'); | |
btn.html('Delete selected (' + markedCount + ')'); | |
btn.css({ display: 'block' }); | |
} | |
return elem; | |
}, | |
destroySelected: function(){ | |
var collection = this.collection, | |
control = this.model; | |
control.startLoad(); | |
$.ajax({ | |
type: 'POST', | |
url: '#{ destroy_admin_product_images_path(product.id) }', | |
data: { | |
images: collection.allMarked().pluck('id') | |
}, | |
success: function(resp){ | |
collection.reset(resp); | |
control.stopLoad(); | |
} | |
}); | |
return false; | |
} | |
}); | |
// | |
//-------------------------------------- View : ProductImages | |
// | |
ProductImagesView = Backbone.View.extend({ | |
className: 'span-16', | |
initialize: function(){ | |
this.collection.bind('reset', this.render, this); | |
}, | |
render: function(){ | |
var self = this, | |
elem = $(self.el); | |
// Clear the element and insert the new product <ul> | |
elem.html('').append( | |
$('<ul class="product_images">') | |
); | |
// Append image_views to product_images <ul> | |
self.collection.each(function(image){ | |
self.$('ul.product_images').append( | |
new ImageView({ model: image }).render() | |
); | |
}); | |
return elem; | |
} | |
}); | |
// | |
//-------------------------------------- View : ImageUploader (main view) | |
// | |
UploaderControl = Backbone.Model.extend({ | |
defaults: { | |
loadState: false | |
}, | |
startLoad: function(){ return this.set({ loadState: true }); }, | |
stopLoad: function(){ return this.set({ loadState: false }); } | |
}); | |
// | |
//-------------------------------------- View : ImageUploader (main view) | |
// | |
ImageUploader = Backbone.View.extend({ | |
initialize: function(selector){ | |
var control = this.model = new UploaderControl(), | |
images = new ProductImages(#{ @images.to_json }), | |
imagesView = new ProductImagesView({ collection: images }), | |
sidebar = new UploaderSidebar({ collection: images, model: control }), | |
elem = $(selector); | |
// Insert views | |
elem | |
.append(sidebar.render()) | |
.append(imagesView.render()); | |
// Bind loader | |
loader = $('<div class="mask_loader">'); | |
elem.append(loader); | |
control.bind('change:loadState', function(){ | |
if (control.get('loadState')) | |
loader.css({ | |
display: 'block', | |
height: elem.height() + 'px' | |
}) | |
else | |
loader.hide() | |
}); | |
} | |
}); | |
// Document ready | |
$(function(){ | |
new ImageUploader('#multi_img_upload'); | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please tell me what is url on line 18
'#{ admin_product_images_path(product.id) }'
Is this some code generated from server side ?