list.js 3.81 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/**
 * 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.
13
 * - emptyMessage (string): Text to render when the list is empty.
14 15 16 17 18 19 20 21 22 23 24
 */
define([
    'js/views/baseview'
], function(BaseView) {
    'use strict';
    var ListView = BaseView.extend({
        events: {
            'click .action-add': 'onAddItem',
            'click .new-button': 'onAddItem'
        },

25 26
        listContainerCss: '.list-items',

27 28 29 30 31 32 33 34 35 36 37 38 39 40
        initialize: function() {
            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) {
            this.$el.html(this.template({
                itemCategoryDisplayName: this.itemCategoryDisplayName,
asadiqbal committed
41
                newItemMessage: this.newItemMessage,
42
                emptyMessage: this.emptyMessage,
43
                length: this.collection.length,
44 45
                isEditing: model && model.get('editing'),
                canCreateNewItem: this.canCreateItem(this.collection)
46 47 48
            }));

            this.collection.each(function(model) {
49
                this.$(this.listContainerCss).append(this.createItemView({model: model}).render().el);
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
            }, 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) {
80
                this.$(this.listContainerCss).append(view.render().el);
81 82 83 84 85 86 87
            } else {
                this.render();
            }

            view.$el.focus();
        },

88 89 90 91 92 93 94 95 96 97 98
        canCreateItem: function(collection) {
            var canCreateNewItem = true;
            if (collection.length > 0) {
                var maxAllowed = collection.maxAllowed;
                if (!_.isUndefined(maxAllowed) && collection.length >= maxAllowed) {
                    canCreateNewItem = false;
                }
            }
            return canCreateNewItem;
        },

99 100 101 102 103 104 105 106 107 108 109 110 111 112
        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;
});