/** * A generic list view class. * * Expects the following properties to be overriden: * render when the collection is empty. * - createItemView (function): Create and return an item view for a * model in the collection. * - newModelOptions (object): Options to pass to models which are * added to the collection. * - itemCategoryDisplayName (string): Display name for the category * of items this list contains. For example, 'Group Configuration'. * Note that it must be translated. * - emptyMessage (string): Text to render when the list is empty. * - restrictEditing (bool) : Boolean flag for hiding edit and remove options, defaults to false. */ define([ 'js/views/baseview' ], function(BaseView) { 'use strict'; var ListView = BaseView.extend({ events: { 'click .action-add': 'onAddItem', 'click .new-button': 'onAddItem' }, listContainerCss: '.list-items', initialize: function() { this.restrictEditing = this.options.restrictEditing || false; this.listenTo(this.collection, 'add', this.addNewItemView); this.listenTo(this.collection, 'remove', this.onRemoveItem); this.template = this.loadTemplate('list'); // Don't render the add button when editing a form this.listenTo(this.collection, 'change:editing', this.toggleAddButton); this.listenTo(this.collection, 'add', this.toggleAddButton); this.listenTo(this.collection, 'remove', this.toggleAddButton); }, render: function(model) { var template = this.template({ itemCategoryDisplayName: this.itemCategoryDisplayName, newItemMessage: this.newItemMessage, emptyMessage: this.emptyMessage, length: this.collection.length, isEditing: model && model.get('editing'), canCreateNewItem: this.canCreateItem(this.collection), restrictEditing: this.restrictEditing }); edx.HtmlUtils.setHtml(this.$el, edx.HtmlUtils.HTML(template)); this.collection.each(function(model) { this.$(this.listContainerCss).append( this.createItemView({model: model, restrictEditing: this.restrictEditing}).render().el ); }, this); return this; }, hideOrShowAddButton: function(shouldShow) { var addButtonCss = '.action-add'; if (this.collection.length) { if (shouldShow) { this.$(addButtonCss).removeClass('is-hidden'); } else { this.$(addButtonCss).addClass('is-hidden'); } } }, toggleAddButton: function(model) { if (model.get('editing') && this.collection.contains(model)) { this.hideOrShowAddButton(false); } else { this.hideOrShowAddButton(true); } }, addNewItemView: function(model) { var view = this.createItemView({model: model}); // If items already exist, just append one new. // Otherwise re-render the empty list HTML. if (this.collection.length > 1) { this.$(this.listContainerCss).append(view.render().el); } else { this.render(); } view.$el.focus(); }, canCreateItem: function(collection) { var canCreateNewItem = true; if (collection.length > 0) { var maxAllowed = collection.maxAllowed; if (!_.isUndefined(maxAllowed) && collection.length >= maxAllowed) { canCreateNewItem = false; } } return canCreateNewItem; }, onAddItem: function(event) { if (event && event.preventDefault) { event.preventDefault(); } this.collection.add({editing: true}, this.newModelOptions); }, onRemoveItem: function() { if (this.collection.length === 0) { this.render(); } } }); return ListView; });