diff --git a/HISTORY.md b/HISTORY.md
index 89e618c2..5fad761d 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -17,6 +17,7 @@ http://visjs.org
### DataSet
- Support for queueing of changes, and flushing them at once.
+- Implemented `DataSet.setOptions`. Only applicable for the `queue` options.
## 2014-10-24, version 3.6.2
diff --git a/docs/dataset.html b/docs/dataset.html
index b5830523..d6c2bf81 100644
--- a/docs/dataset.html
+++ b/docs/dataset.html
@@ -185,7 +185,6 @@ var data = new vis.DataSet([data] [, options])
Default value is Infinity
.
-
@@ -326,6 +325,41 @@ var data = new vis.DataSet([data] [, options])
+
update(data [, senderId])
diff --git a/index.js b/index.js
index 211d73ca..a92b6d87 100644
--- a/index.js
+++ b/index.js
@@ -5,6 +5,7 @@ exports.DOMutil = require('./lib/DOMutil');
// data
exports.DataSet = require('./lib/DataSet');
exports.DataView = require('./lib/DataView');
+exports.Queue = require('./lib/Queue');
// Graph3d
exports.Graph3d = require('./lib/graph3d/Graph3d');
diff --git a/lib/DataSet.js b/lib/DataSet.js
index d57b2445..f1f3b67a 100644
--- a/lib/DataSet.js
+++ b/lib/DataSet.js
@@ -84,16 +84,42 @@ function DataSet (data, options) {
this.add(data);
}
- // change the dataset in a queued one
- if (this._options.queue) {
- var queue = {
- replace: ['add', 'update', 'remove']
- };
- if (typeof this._options.queue === 'object') util.extend(queue, this._options.queue);
- Queue.extend(this, queue);
- }
+ this.setOptions(options);
}
+/**
+ * @param {Object} [options] Available options:
+ * {Object} queue Queue changes to the DataSet,
+ * flush them all at once.
+ * Queue options:
+ * - {number} delay Delay in ms, null by default
+ * - {number} max Maximum number of entries in the queue, Infinity by default
+ * @param options
+ */
+DataSet.prototype.setOptions = function(options) {
+ if (options && options.queue !== undefined) {
+ if (options.queue === false) {
+ // delete queue if loaded
+ if (this._queue) {
+ this._queue.destroy();
+ delete this._queue;
+ }
+ }
+ else {
+ // create queue and update its options
+ if (!this._queue) {
+ this._queue = Queue.extend(this, {
+ replace: ['add', 'update', 'remove']
+ });
+ }
+
+ if (typeof options.queue === 'object') {
+ this._queue.setOptions(options.queue);
+ }
+ }
+ }
+};
+
/**
* Subscribe to an event, add an event listener
* @param {String} event Event name. Available events: 'put', 'update',
diff --git a/lib/Queue.js b/lib/Queue.js
index 6c3cb6b9..4e9f56a4 100644
--- a/lib/Queue.js
+++ b/lib/Queue.js
@@ -2,7 +2,7 @@
* A queue
* @param {Object} options
* Available options:
- * - delay: number When a number, the queue will be flushed
+ * - delay: number When provided, the queue will be flushed
* automatically after an inactivity of this delay
* in milliseconds.
* Default value is null.
@@ -13,14 +13,41 @@
*/
function Queue(options) {
// options
- this.delay = options && typeof options.delay === 'number' ? options.delay : null;
- this.max = options && typeof options.max === 'number' ? options.max : Infinity;
+ this.delay = null;
+ this.max = Infinity;
// properties
this._queue = [];
this._timeout = null;
+ this._extended = null;
+
+ this.setOptions(options);
}
+/**
+ * Update the configuration of the queue
+ * @param {Object} options
+ * Available options:
+ * - delay: number When provided, the queue will be flushed
+ * automatically after an inactivity of this delay
+ * in milliseconds.
+ * Default value is null.
+ * - max: number When the queue exceeds the given maximum number
+ * of entries, the queue is flushed automatically.
+ * Default value of max is Infinity.
+ * @param options
+ */
+Queue.prototype.setOptions = function (options) {
+ if (options && typeof options.delay !== 'undefined') {
+ this.delay = options.delay;
+ }
+ if (options && typeof options.max !== 'undefined') {
+ this.max = options.max;
+ }
+
+ this._flushIfNeeded();
+};
+
/**
* Extend an object with queuing functionality.
* The object will be extended with a function flush, and the methods provided
@@ -31,13 +58,14 @@ function Queue(options) {
* - replace: Array.
* A list with method names of the methods
* on the object to be replaced with queued ones.
- * - delay: number When a number, the queue will be flushed
+ * - delay: number When provided, the queue will be flushed
* automatically after an inactivity of this delay
* in milliseconds.
* Default value is null.
* - max: number When the queue exceeds the given maximum number
* of entries, the queue is flushed automatically.
* Default value of max is Infinity.
+ * @return {Queue} Returns the created queue
*/
Queue.extend = function (object, options) {
var queue = new Queue(options);
@@ -49,11 +77,51 @@ Queue.extend = function (object, options) {
queue.flush();
};
+ var methods = [{
+ name: 'flush',
+ original: undefined
+ }];
+
if (options && options.replace) {
for (var i = 0; i < options.replace.length; i++) {
- queue.replace(object, options.replace[i]);
+ var name = options.replace[i];
+ methods.push({
+ name: name,
+ original: object[name]
+ });
+ queue.replace(object, name);
}
}
+
+ queue._extended = {
+ object: object,
+ methods: methods
+ };
+
+ return queue;
+};
+
+/**
+ * Destroy the queue. The queue will first flush all queued actions, and in
+ * case it has extended an object, will restore the original object.
+ */
+Queue.prototype.destroy = function () {
+ this.flush();
+
+ if (this._extended) {
+ var object = this._extended.object;
+ var methods = this._extended.methods;
+ for (var i = 0; i < methods.length; i++) {
+ var method = methods[i];
+ if (method.original) {
+ object[method.name] = method.original;
+ }
+ else {
+ delete object[method.name];
+ }
+ }
+ this._extended = null;
+ }
};
/**
@@ -96,15 +164,23 @@ Queue.prototype.queue = function(entry) {
this._queue.push(entry);
}
+ this._flushIfNeeded();
+};
+
+/**
+ * Check whether the queue needs to be flushed
+ * @private
+ */
+Queue.prototype._flushIfNeeded = function () {
// flush when the maximum is exceeded.
if (this._queue.length > this.max) {
this.flush();
}
// flush after a period of inactivity when a delay is configured
- if (typeof this.delay === 'number') {
+ clearTimeout(this._timeout);
+ if (this.queue.length > 0 && typeof this.delay === 'number') {
var me = this;
- clearTimeout(this._timeout);
this._timeout = setTimeout(function () {
me.flush();
}, this.delay);
diff --git a/test/DataSet.test.js b/test/DataSet.test.js
index fb3fd1de..85f8e455 100644
--- a/test/DataSet.test.js
+++ b/test/DataSet.test.js
@@ -236,4 +236,42 @@ describe('DataSet', function () {
}, 200)
});
+ it('should remove a queue from the dataset', function () {
+ var options = {queue: true};
+ var dataset = new DataSet([
+ {id: 1, content: 'Item 1'},
+ {id: 2, content: 'Item 2'}
+ ], options);
+
+ assert.deepEqual(dataset.get(), [
+ {id: 1, content: 'Item 1'},
+ {id: 2, content: 'Item 2'}
+ ]);
+
+ dataset.add({id: 3, content: 'Item 3'});
+ dataset.update({id: 1, content: 'Item 1 (updated)'});
+ dataset.remove(2);
+
+ assert.deepEqual(dataset.get(), [
+ {id: 1, content: 'Item 1'},
+ {id: 2, content: 'Item 2'}
+ ]);
+
+ dataset.setOptions({queue: false}); // remove queue, should flush changes
+
+ assert.deepEqual(dataset.get(), [
+ {id: 1, content: 'Item 1 (updated)'},
+ {id: 3, content: 'Item 3'}
+ ]);
+
+ dataset.add({id: 4, content: 'Item 4'});
+
+ assert.deepEqual(dataset.get(), [
+ {id: 1, content: 'Item 1 (updated)'},
+ {id: 3, content: 'Item 3'},
+ {id: 4, content: 'Item 4'}
+ ]);
+
+ });
+
});
\ No newline at end of file
diff --git a/test/Queue.test.js b/test/Queue.test.js
index f99351e4..0dfa1779 100644
--- a/test/Queue.test.js
+++ b/test/Queue.test.js
@@ -153,4 +153,8 @@ describe('Queue', function () {
assert.equal(obj.count, 2);
});
+ // TODO: test Queue.setOptions
+
+ // TODO: test Queue.destroy
+
});
|