backbone-fractal
Version:
Lightweight composite views for Backbone
96 lines (81 loc) • 2.58 kB
text/typescript
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();
}
}