UNPKG

backbone-fractal

Version:

Lightweight composite views for Backbone

96 lines (81 loc) 2.58 kB
import { map, invert } from 'underscore'; import { eachRight } from './underscore-compat'; import { View, Model } from 'backbone'; export default class CollectionView<SubView extends View = View> extends View { items: SubView[]; container: string; _container: JQuery<Element>; subview: { new (options?: any): SubView }; initCollectionEvents(): this { return this.listenTo(this.collection, { add: this.insertItem, remove: this.removeItem, sort: this.sortItems, update: this.placeItems, reset: this.resetItems, }); } render(): this { this.beforeRender(); this.detachItems(); this.renderContainer(); this._container = (this.container ? this.$(this.container).first() : this.$el); this.placeItems(); this.afterRender(); return this; } beforeRender() { return this; } renderContainer() { return this; } afterRender() { return this; } remove(): this { this.clearItems(); super.remove(); return this; } makeItem(model?) { return new this.subview({model}); } initItems(): this { this.items = this.collection.map(this.makeItem.bind(this)); return this; } clearItems(): this { eachRight(this.items, item => item.remove()); return this; } insertItem(model, collection?, options?: any): this { let item = this.makeItem(model); let index = options && options.index; if (index != undefined) { this.items.splice(index, 0, item); } else { this.items.push(item); } return this; } removeItem(model, collection, options: any): this { let index = options.index; this.items[index].remove(); this.items.splice(index, 1); return this; } sortItems(): this { let order = invert(map(this.collection.models, 'cid')); this.items.sort((l, r) => +order[l.model.cid] - +order[r.model.cid]); return this; } detachItems(): this { eachRight(this.items, item => item.$el.detach()); return this; } placeItems(): this { // No need to detach the items first. // Each item is unique, so jQuery moves rather than copies it. let container = this._container; container.append(map(this.items, 'el')); return this; } resetItems(): this { return this.clearItems().initItems().placeItems(); } }