vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

185 lines
5.1 KiB

/**
* Create a timeline visualization
* @param {HTMLElement} container
* @param {DataSet | Array | DataTable} [data]
* @param {Object} [options] See Timeline.setOptions for the available options.
* @constructor
*/
function Timeline (container, data, options) {
var me = this;
this.options = {
orientation: 'bottom',
zoomMin: 10, // milliseconds
zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
moveable: true,
zoomable: true
};
// controller
this.controller = new Controller();
// main panel
if (!container) {
throw new Error('No container element provided');
}
this.main = new RootPanel(container, {
autoResize: false
});
this.controller.add(this.main);
// range
var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0);
this.range = new Range({
start: now.clone().add('days', -3).valueOf(),
end: now.clone().add('days', 4).valueOf()
});
// TODO: reckon with options moveable and zoomable
this.range.subscribe(this.main, 'move', 'horizontal');
this.range.subscribe(this.main, 'zoom', 'horizontal');
this.range.on('rangechange', function () {
var force = true;
me.controller.requestReflow(force);
});
this.range.on('rangechanged', function () {
var force = true;
me.controller.requestReflow(force);
});
// TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable
// time axis
this.timeaxis = new TimeAxis(this.main, [], {
orientation: this.options.orientation,
range: this.range
});
this.timeaxis.setRange(this.range);
this.controller.add(this.timeaxis);
// items panel
this.itemset = new ItemSet(this.main, [this.timeaxis], {
orientation: this.options.orientation
});
this.itemset.setRange(this.range);
this.controller.add(this.itemset);
// set options (must take place before setting the data)
this.setOptions(options);
// set data
if (data) {
this.setData(data);
}
}
/**
* Set options
* @param {Object} options TODO: describe the available options
*/
Timeline.prototype.setOptions = function (options) {
util.extend(this.options, options);
// update options the timeaxis
this.timeaxis.setOptions(this.options);
// update options for the range
this.range.setOptions(this.options);
// update options the itemset
var itemsTop,
itemsHeight,
mainHeight,
maxHeight,
me = this;
if (this.options.orientation == 'top') {
itemsTop = function () {
return me.timeaxis.height;
}
}
else {
itemsTop = function () {
return me.main.height - me.timeaxis.height - me.itemset.height;
}
}
if (options.height) {
// fixed height
mainHeight = options.height;
itemsHeight = function () {
return me.main.height - me.timeaxis.height;
};
}
else {
// auto height
mainHeight = function () {
return me.timeaxis.height + me.itemset.height;
};
itemsHeight = null;
}
// TODO: maxHeight should be a string in px or % (currently only accepts a number)
if (this.options.maxHeight) {
if (!util.isNumber(this.options.maxHeight)) {
throw new TypeError('Number expected for property maxHeight');
}
maxHeight = function () {
return me.options.maxHeight - me.timeaxis.height;
}
}
this.main.setOptions({
height: mainHeight
});
this.itemset.setOptions({
orientation: this.options.orientation,
top: itemsTop,
height: itemsHeight,
maxHeight: maxHeight
});
this.controller.repaint();
};
/**
* Set data
* @param {DataSet | Array | DataTable} data
*/
Timeline.prototype.setData = function(data) {
var dataset = this.itemset.data;
if (!dataset) {
// first load of data
this.itemset.setData(data);
if (this.options.start == undefined || this.options.end == undefined) {
// apply the data range as range
var dataRange = this.itemset.getDataRange();
// add 5% on both sides
var min = dataRange.min;
var max = dataRange.max;
if (min != null && max != null) {
var interval = (max.valueOf() - min.valueOf());
min = new Date(min.valueOf() - interval * 0.05);
max = new Date(max.valueOf() + interval * 0.05);
}
// override specified start and/or end date
if (this.options.start != undefined) {
min = new Date(this.options.start.valueOf());
}
if (this.options.end != undefined) {
max = new Date(this.options.end.valueOf());
}
// apply range if there is a min or max available
if (min != null || max != null) {
this.range.setRange(min, max);
}
}
}
else {
// updated data
this.itemset.setData(data);
}
};