UNPKG

visjs-network

Version:

A dynamic, browser-based network visualization library.

200 lines (178 loc) 5.53 kB
/** * A 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. * @constructor Queue */ function Queue(options) { // options 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. */ 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 * in options.replace will be replaced with queued ones. * @param {Object} object * @param {Object} options * Available options: * - replace: Array.<string> * A list with method names of the methods * on the object to be replaced with queued ones. * - 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) if (object.flush !== undefined) { throw new Error('Target object already has a property flush') } object.flush = function() { queue.flush() } var methods = [ { name: 'flush', original: undefined } ] if (options && options.replace) { for (var i = 0; i < options.replace.length; 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 } } /** * Replace a method on an object with a queued version * @param {Object} object Object having the method * @param {string} method The method name */ Queue.prototype.replace = function(object, method) { var me = this var original = object[method] if (!original) { throw new Error('Method ' + method + ' undefined') } object[method] = function() { // create an Array with the arguments var args = [] for (var i = 0; i < arguments.length; i++) { args[i] = arguments[i] } // add this call to the queue me.queue({ args: args, fn: original, context: this }) } } /** * Queue a call * @param {function | {fn: function, args: Array} | {fn: function, args: Array, context: Object}} entry */ Queue.prototype.queue = function(entry) { if (typeof entry === 'function') { this._queue.push({ fn: entry }) } else { 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 clearTimeout(this._timeout) if (this.queue.length > 0 && typeof this.delay === 'number') { var me = this this._timeout = setTimeout(function() { me.flush() }, this.delay) } } /** * Flush all queued calls */ Queue.prototype.flush = function() { while (this._queue.length > 0) { var entry = this._queue.shift() entry.fn.apply(entry.context || entry.fn, entry.args || []) } } module.exports = Queue