aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/store/view.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/js/store/view.js')
-rw-r--r--web/src/js/store/view.js87
1 files changed, 87 insertions, 0 deletions
diff --git a/web/src/js/store/view.js b/web/src/js/store/view.js
new file mode 100644
index 00000000..261429b2
--- /dev/null
+++ b/web/src/js/store/view.js
@@ -0,0 +1,87 @@
+function SortByStoreOrder(elem) {
+ return this.store.index(elem.id);
+}
+
+var default_sort = SortByStoreOrder;
+var default_filt = function(elem){
+ return true;
+};
+
+function StoreView(store, filt, sortfun) {
+ EventEmitter.call(this);
+ filt = filt || default_filt;
+ sortfun = sortfun || default_sort;
+
+ this.store = store;
+ this.store._views.push(this);
+ this.recalculate(this.store._list, filt, sortfun);
+}
+
+_.extend(StoreView.prototype, EventEmitter.prototype, {
+ close: function () {
+ this.store._views = _.without(this.store._views, this);
+ },
+ recalculate: function (elems, filt, sortfun) {
+ if (filt) {
+ this.filt = filt;
+ }
+ if (sortfun) {
+ this.sortfun = sortfun.bind(this);
+ }
+
+ this.list = elems.filter(this.filt);
+ this.list.sort(function (a, b) {
+ return this.sortfun(a) - this.sortfun(b);
+ }.bind(this));
+ this.emit("recalculate");
+ },
+ index: function (elem) {
+ return _.sortedIndex(this.list, elem, this.sortfun);
+ },
+ add: function (elem) {
+ if (this.filt(elem)) {
+ var idx = this.index(elem);
+ if (idx === this.list.length) { //happens often, .push is way faster.
+ this.list.push(elem);
+ } else {
+ this.list.splice(idx, 0, elem);
+ }
+ this.emit("add", elem, idx);
+ }
+ },
+ update: function (elem) {
+ var idx;
+ var i = this.list.length;
+ // Search from the back, we usually update the latest entries.
+ while (i--) {
+ if (this.list[i].id === elem.id) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx === -1) { //not contained in list
+ this.add(elem);
+ } else if (!this.filt(elem)) {
+ this.remove(elem.id);
+ } else {
+ if (this.sortfun(this.list[idx]) !== this.sortfun(elem)) { //sortpos has changed
+ this.remove(this.list[idx]);
+ this.add(elem);
+ } else {
+ this.list[idx] = elem;
+ this.emit("update", elem, idx);
+ }
+ }
+ },
+ remove: function (elem_id) {
+ var idx = this.list.length;
+ while (idx--) {
+ if (this.list[idx].id === elem_id) {
+ this.list.splice(idx, 1);
+ this.emit("remove", elem_id, idx);
+ break;
+ }
+ }
+ }
+}); \ No newline at end of file