From c4d357dd85a4d097c4fb622141d4a6ec5ba2ea07 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 5 Feb 2015 14:04:49 +0100 Subject: [PATCH] Fixed #339: Added a method `refresh()` to the `DataView`, to update filter results --- HISTORY.md | 1 + docs/dataview.html | 16 +++++++++++++ lib/DataView.js | 42 ++++++++++++++++++++++++++++++++++ test/DataView.test.js | 53 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 74cf8c49..cfb0404a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -13,6 +13,7 @@ http://visjs.org - Added property `length` holding the total number of items to the `DataSet` and `DataView`. +- Added a method `refresh()` to the `DataView`, to update filter results. ### Timeline diff --git a/docs/dataview.html b/docs/dataview.html index 159ad720..316da77a 100644 --- a/docs/dataview.html +++ b/docs/dataview.html @@ -219,6 +219,22 @@ var data = new vis.DataView(dataset, options) + + refresh() + none + + Refresh the filter results of a DataView. Useful when the filter function contains dynamic properties, like: + +
var data = new vis.DataSet(...);
+var view = new vis.DataView(data, {
+  filter: function (item) {
+    return item.value > threshold;
+  }
+});
+ In this example, threshold is an external parameter. When the value of threshold changes, the DataView must be notified that the filter results may have changed by calling DataView.refresh(). + + + setDataSet(data) diff --git a/lib/DataView.js b/lib/DataView.js index c5fbdfb8..cc4e04bd 100644 --- a/lib/DataView.js +++ b/lib/DataView.js @@ -79,6 +79,48 @@ DataView.prototype.setData = function (data) { } }; +/** + * Refresh the DataView. Useful when the DataView has a filter function + * containing a variable parameter. + */ +DataView.prototype.refresh = function () { + var id; + var ids = this._data.getIds({filter: this._options && this._options.filter}); + var newIds = {}; + var added = []; + var removed = []; + + // check for additions + for (var i = 0; i < ids.length; i++) { + id = ids[i]; + newIds[id] = true; + if (!this._ids[id]) { + added.push(id); + this._ids[id] = true; + this.length++; + } + } + + // check for removals + for (id in this._ids) { + if (this._ids.hasOwnProperty(id)) { + if (!newIds[id]) { + removed.push(id); + delete this._ids[id]; + this.length--; + } + } + } + + // trigger events + if (added.length) { + this._trigger('add', {items: added}); + } + if (removed.length) { + this._trigger('remove', {items: removed}); + } +}; + /** * Get data from the data view * diff --git a/test/DataView.test.js b/test/DataView.test.js index 43110ba2..bb8ff1f9 100644 --- a/test/DataView.test.js +++ b/test/DataView.test.js @@ -94,4 +94,57 @@ describe('DataView', function () { assert.equal(group2.length, 0); }); + + it('should refresh a DataView with filter', function () { + var data = new DataSet([ + {id:1, value:2}, + {id:2, value:4}, + {id:3, value:7} + ]); + + var threshold = 5; + + // create a view. The view has a filter with a dynamic property `threshold` + var view = new DataView(data, { + filter: function (item) { + return item.value < threshold; + } + }); + + var added, updated, removed; + view.on('add', function (event, props) {added = added.concat(props.items)}); + view.on('update', function (event, props) {updated = updated.concat(props.items)}); + view.on('remove', function (event, props) {removed = removed.concat(props.items)}); + + assert.deepEqual(view.get(), [ + {id:1, value:2}, + {id:2, value:4} + ]); + + // change the threshold to 3 + added = []; + updated = []; + removed = []; + threshold = 3; + view.refresh(); + assert.deepEqual(view.get(), [{id:1, value:2}]); + assert.deepEqual(added, []); + assert.deepEqual(updated, []); + assert.deepEqual(removed, [2]); + + // change threshold to 8 + added = []; + updated = []; + removed = []; + threshold = 8; + view.refresh(); + assert.deepEqual(view.get(), [ + {id:1, value:2}, + {id:2, value:4}, + {id:3, value:7} + ]); + assert.deepEqual(added, [2, 3]); + assert.deepEqual(updated, []); + assert.deepEqual(removed, []); + }) });