diff --git a/README.md b/README.md
index 7d35b959..2d397abb 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,10 @@ Install via bower:
bower install vis
+Link via cdnjs:
+
+ http://cdnjs.com
+
Or download the library from the github project:
[https://github.com/almende/vis.git](https://github.com/almende/vis.git).
diff --git a/docs/timeline.html b/docs/timeline.html
index 96a7c333..26fcefd9 100644
--- a/docs/timeline.html
+++ b/docs/timeline.html
@@ -854,6 +854,15 @@ var options = {
Description
+
+
addCustomTime(time[, id])
+
Number | String
+
+ Only applicable when the option showCustomTime is true.
+ Add new vertical bar representing custom time that can be dragged by the user. Parameter time can be a Date, Number, or String. Parameter id can be Number or String. If id is provided, it will be used as ID for the new vertical bar, otherwise the ID will be auto generated.
+ Returns ID of the newly created bar.
+
+
clear([what])
none
@@ -903,9 +912,9 @@ timeline.clear({options: true}); // clear options only
-
getCustomTime()
+
getCustomTime([id])
Date
-
Retrieve the custom time. Only applicable when the option showCustomTime is true.
+
Retrieve the custom time. Only applicable when the option showCustomTime is true. If parameter id is provided, time of the custom time bar under that ID is returned.
+ Remove vertical bars previously added to the timeline via addCustomTime method. Parameter id is the ID of the custom vertical bar returned by addCustomTime method.
+
+
+
setCurrentTime(time)
none
@@ -967,9 +984,9 @@ timeline.clear({options: true}); // clear options only
-
setCustomTime(time)
+
setCustomTime(time [, id])
none
-
Adjust the custom time bar. Only applicable when the option showCustomTime is true. time can be a Date object, numeric timestamp, or ISO date string.
+
Adjust the custom time bar. Only applicable when the option showCustomTime is true. Parameter time can be a Date object, numeric timestamp, or ISO date string. Parameter id represents ID of the custom time bar, provided by addCustomTime method and can be a Number or String.
diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js
index 9ca3c209..2edab7f5 100644
--- a/lib/timeline/Core.js
+++ b/lib/timeline/Core.js
@@ -7,6 +7,7 @@ var Range = require('./Range');
var ItemSet = require('./component/ItemSet');
var Activator = require('../shared/Activator');
var DateUtil = require('./DateUtil');
+var CustomTime = require('./component/CustomTime');
/**
* Create a timeline visualization
@@ -277,25 +278,123 @@ Core.prototype.destroy = function () {
/**
* Set a custom time bar
* @param {Date} time
+ * @param {int} id
*/
-Core.prototype.setCustomTime = function (time) {
+Core.prototype.setCustomTime = function (time, id) {
if (!this.customTime) {
throw new Error('Cannot get custom time: Custom time bar is not enabled');
}
- this.customTime.setCustomTime(time);
+ var barId = id || 0;
+
+ this.components.forEach(function (element, index, components) {
+ if (element instanceof CustomTime && element.options.id === barId) {
+ element.setCustomTime(time);
+ }
+ });
};
/**
* Retrieve the current custom time.
* @return {Date} customTime
+ * @param {int} id
*/
-Core.prototype.getCustomTime = function() {
+Core.prototype.getCustomTime = function(id) {
if (!this.customTime) {
throw new Error('Cannot get custom time: Custom time bar is not enabled');
}
- return this.customTime.getCustomTime();
+ var barId = id || 0,
+ customTime = this.customTime.getCustomTime();
+
+ this.components.forEach(function (element, index, components) {
+ if (element instanceof CustomTime && element.options.id === barId) {
+ customTime = element.getCustomTime();
+ }
+ });
+
+ return customTime;
+};
+
+/**
+ * Add custom vertical bar
+ * @param {Date | String | Number} time A Date, unix timestamp, or
+ * ISO date string. Time point where the new bar should be placed
+ * @param {Number | String} ID of the new bar
+ * @return {Number | String} ID of the new bar
+ */
+Core.prototype.addCustomTime = function (time, id) {
+ if (!this.currentTime) {
+ throw new Error('Option showCurrentTime must be true');
+ }
+
+ if (time === undefined) {
+ throw new Error('Time parameter for the custom bar must be provided');
+ }
+
+ var ts = util.convert(time, 'Date').valueOf(),
+ numIds, customTime, customBarId;
+
+ // All bar IDs are kept in 1 array, mixed types
+ // Bar with ID 0 is the default bar.
+ if (!this.customBarIds || this.customBarIds.constructor !== Array) {
+ this.customBarIds = [0];
+ }
+
+ // If the ID is not provided, generate one, otherwise just use it
+ if (id === undefined) {
+
+ numIds = this.customBarIds.filter(function (element) {
+ return util.isNumber(element);
+ });
+
+ customBarId = numIds.length > 0 ? Math.max.apply(null, numIds) + 1 : 1;
+
+ } else {
+
+ // Check for duplicates
+ this.customBarIds.forEach(function (element) {
+ if (element === id) {
+ throw new Error('Custom time ID already exists');
+ }
+ });
+
+ customBarId = id;
+ }
+
+ this.customBarIds.push(customBarId);
+
+ customTime = new CustomTime(this.body, {
+ showCustomTime : true,
+ time : ts,
+ id : customBarId
+ });
+
+ this.components.push(customTime);
+ this.redraw();
+
+ return customBarId;
+};
+
+/**
+ * Remove previously added custom bar
+ * @param {int} id ID of the custom bar to be removed
+ * @return {boolean} True if the bar exists and is removed, false otherwise
+ */
+Core.prototype.removeCustomTime = function (id) {
+
+ var me = this;
+
+ this.components.forEach(function (bar, index, components) {
+ if (bar instanceof CustomTime && bar.options.id === id) {
+ // Only the lines added by the user will be removed
+ if (bar.options.id !== 0) {
+ me.customBarIds.splice(me.customBarIds.indexOf(id), 1);
+ components.splice(index, 1);
+ bar.destroy();
+ }
+ }
+ });
};
diff --git a/lib/timeline/component/CustomTime.js b/lib/timeline/component/CustomTime.js
index 44c2a4da..eea21450 100644
--- a/lib/timeline/component/CustomTime.js
+++ b/lib/timeline/component/CustomTime.js
@@ -20,11 +20,17 @@ function CustomTime (body, options) {
this.defaultOptions = {
showCustomTime: false,
locales: locales,
- locale: 'en'
+ locale: 'en',
+ id: 0
};
this.options = util.extend({}, this.defaultOptions);
- this.customTime = new Date();
+ if (options && options.time) {
+ this.customTime = options.time;
+ } else {
+ this.customTime = new Date();
+ }
+
this.eventParams = {}; // stores state parameters while dragging the bar
// create the DOM
@@ -43,7 +49,12 @@ CustomTime.prototype = new Component();
CustomTime.prototype.setOptions = function(options) {
if (options) {
// copy all options that we know
- util.selectiveExtend(['showCustomTime', 'locale', 'locales'], this.options, options);
+ util.selectiveExtend(['showCustomTime', 'locale', 'locales', 'id'], this.options, options);
+
+ // Triggered by addCustomTimeBar, redraw to add new bar
+ if (this.options.id) {
+ this.redraw();
+ }
}
};
@@ -169,6 +180,7 @@ CustomTime.prototype._onDrag = function (event) {
// fire a timechange event
this.body.emitter.emit('timechange', {
+ id: this.options.id,
time: new Date(this.customTime.valueOf())
});
@@ -186,6 +198,7 @@ CustomTime.prototype._onDragEnd = function (event) {
// fire a timechanged event
this.body.emitter.emit('timechanged', {
+ id: this.options.id,
time: new Date(this.customTime.valueOf())
});