// Responsible for an invidiual thumbnail. This view is intended to remain // fairly dumb - let AssetLibraryView handle events. slices.AssetThumbView = Backbone.View.extend({ tagName: 'li', className: 'asset-library-item', happyTime: 1000, template: Handlebars.compile( '{{name}}' + '{{displayName}}' + '
' + '
{{name}}
' + '
{{size}}
' + '
Added {{createdAt}}
' + '
Edit
' + '
' ), events: { 'mousedown' : 'press', 'mouseup' : 'release', 'mousedown [data-action="edit"]' : 'pressEdit', 'click [data-action="edit"]' : 'releaseEdit' }, initialize: function() { _.bindAll(this); this.$el.append('
'); this.model.bind('change', this.whenModelChanges); this.model.bind('destroying', this.whenModelIsDestroying); }, render: function() { this.$el.find('.asset-details').html(this.template(this)); return this; }, src: function() { return this.model.get('asset_url') || '<%= asset_path 'slices/icon_generic_file.png' %>'; }, name: function() { return this.model.get('name'); }, url: function() { return this.model.url(); }, displayName: function() { if (!this.model.isImage()) return this.name(); }, createdAt: function() { return moment(this.model.get('created_at')).calendar(); }, size: function() { return humanFileSize(this.model.get('file_file_size')); }, select: function() { $(this.el).addClass('selected'); }, deselect: function() { $(this.el).removeClass('selected'); }, selected: function() { return $(this.el).hasClass('selected'); }, remove: function() { this.unbind(); $(this.el).remove(); }, press: function(event) { if (!this.options.selectable) return; if (event.which !== 1) return; event.preventDefault(); event.stopImmediatePropagation(); this.trigger('thumb:press', event, this); }, release: function(event) { if (!this.options.selectable) return; if (event.which !== 1) return; this.trigger('thumb:release', event, this); }, pressEdit: function(e) { e.stopImmediatePropagation(); }, releaseEdit: function(e) { e.preventDefault(); e.stopImmediatePropagation(); this.trigger('thumb:blur'); var el = $(this.el); el.addClass('editing'); var editor = slices.AssetEditorView.openModal({ model: this.model }); editor.bind('close', function() { _.delay(function() { el.removeClass('editing') }, 350); }); }, whenModelChanges: function() { this.render(); }, whenModelIsDestroying: function() { $(this.el).addClass('destroying'); }, // Update the upload progress information, wrapped around the file. updateFile: function(attrs) { if (!this.fileView) this.makeFileView(); $(this.el). removeClass(this.fileView.possibleStatusList). addClass('status-' + this.fileView.model.status()); }, // Update the upload progress information so we see happy face, then // wait for the thumbnail to load or happyTime, whichever is longer. updateFileAndComplete: function(file) { this.updateFile(file); this.gracefullyRemoveFileView(); }, // Make fileview, this gets done on the fly. makeFileView: function() { this.fileView = new slices.FileView({ model: this.model.get('file') }); this.$el.append(this.fileView.el); $(this.fileView.el).css({ position: 'absolute', top: 0 }); }, // Remove fileview removeFileView: function() { if (this.fileView) { this.fileView.remove(); delete this.fileView; } }, // Wait for thumnail to load and happyTime to pass, then complete the // transition to showing our lovely new thumbnail. gracefullyRemoveFileView: function() { $.when( this.thumbnailHasLoaded(), this.happyTimeHasPassed() ).then(this.resolveGracefully); }, // Complete transition by fading out fileView, rendering, then // fading our thumbnail in. resolveGracefully: function() { this.$('.asset-details').css({ opacity: 0 }); $(this.fileView.el).animate({ opacity: 0 }, 'fast', _.bind(function() { this.removeFileView(); this.$('.asset-details').animate({ opacity: 1 }); }, this)); }, // Returns a deferred promise wrapping thumbnail pre-load. thumbnailHasLoaded: function() { var dfd = new $.Deferred(); this.$('img').load(dfd.resolve); return dfd.promise(); }, // Returns a deferred promise wrapping happyTime. happyTimeHasPassed: function() { var dfd = new $.Deferred(); _.delay(dfd.resolve, this.happyTime); return dfd.promise(); } });