slices.ComposerView = Backbone.View.extend({ className: 'composer', template: Handlebars.compile( '
    ' + '
    ' + '' + '
    ' ), events: { 'click [data-action="add"]' : 'didClickAdd', 'click [data-action="remove"]' : 'didClickRemove' }, addLabel: 'Add An Item', broadcastChanges: true, views: {}, initialize: function() { _.bindAll(this); this.addLabel = this.options.addLabel || this.addLabel; this.collection = new slices.ComposerItemCollection(this.options.value); this.collection.bind('add' , this.addItem); this.collection.bind('remove' , this.removeItem); this.collection.bind('change' , this.update); this.collection.bind('reset' , this.update); if (this.options.autoAttach) _.defer(this.attach); }, // -- Rendering -- placeholder: function() { return Handlebars.compile('
    ')(this); }, attach: function() { $('#placeholder-' + this.id).replaceWith(this.el); this.render(); }, render: function() { this.broadcastChanges = false; this.$el.html(this.template(this)); this.collection.each(this.addItem); this.makeSortable(); this.update(); this.broadcastChanges = true; return this; }, makeSortable: function() { var list = this.$('.composer-item-list'); list.sortable({ handle: '[data-role="drag-handle"]', scroll: false, beforeStart: _.bind(function(e, ui) { list.freezeHeight(); window.autoscroll.start(); }, this), stop: _.bind(function(e, ui) { list.thawHeight(); window.autoscroll.stop(); }, this), update: this.updateOnSort }); }, updateOnSort: function() { var items = this.$('.composer-item-list').children(); var newOrder = items.map(function() { return $(this).data('model'); }).get(); this.collection.reset(newOrder); }, update: function() { var value = this.collection.toJSON(); this.$el.data('computed-value', value); this.$el[this.collection.isEmpty() ? 'removeClass' : 'addClass']('not-empty'); if (this.broadcastChanges) this.$el.trigger('change'); }, addItem: function(item, collection, options) { var view = new slices.ComposerItemView({ fields: this.options.fields, model: item }); this.$('.composer-item-list').append(view.el); view.render(); this.views[item.cid] = view; this.update(); }, removeItem: function(item) { var view = this.views[item.cid]; view.remove(); delete this.views[item.cid]; this.update(); }, didClickAdd: function(e) { e.preventDefault(); e.stopImmediatePropagation(); this.collection.add({}); }, didClickRemove: function(e) { e.preventDefault(); e.stopImmediatePropagation(); var button = $(e.target), view = button.closest('li'), item = view.data('model'); this.collection.remove(item); } });