Browse Source

Custom time bar as a component

css_transitions
Fedor Tirsel 11 years ago
parent
commit
251d4e552f
4 changed files with 285 additions and 1 deletions
  1. +3
    -1
      Jakefile.js
  2. +21
    -0
      src/timeline/Timeline.js
  3. +255
    -0
      src/timeline/component/CustomTime.js
  4. +6
    -0
      src/timeline/component/css/customtime.css

+ 3
- 1
Jakefile.js View File

@ -35,7 +35,8 @@ task('build', {async: true}, function () {
'./src/timeline/component/css/itemset.css',
'./src/timeline/component/css/item.css',
'./src/timeline/component/css/timeaxis.css',
'./src/timeline/component/css/currenttime.css'
'./src/timeline/component/css/currenttime.css',
'./src/timeline/component/css/customtime.css'
],
header: '/* vis.js stylesheet */',
separator: '\n'
@ -64,6 +65,7 @@ task('build', {async: true}, function () {
'./src/timeline/component/RootPanel.js',
'./src/timeline/component/TimeAxis.js',
'./src/timeline/component/CurrentTime.js',
'./src/timeline/component/CustomTime.js',
'./src/timeline/component/ItemSet.js',
'./src/timeline/component/item/*.js',
'./src/timeline/component/Group.js',

+ 21
- 0
src/timeline/Timeline.js View File

@ -18,6 +18,7 @@ function Timeline (container, items, options) {
showMinorLabels: true,
showMajorLabels: true,
showCurrentTime: false,
showCustomTime: false,
autoResize: false
}, options);
@ -114,6 +115,10 @@ function Timeline (container, items, options) {
this.currenttime = new CurrentTime(this.timeaxis, [], rootOptions);
this.controller.add(this.currenttime);
// custom time bar
this.customtime = new CustomTime(this.timeaxis, [], rootOptions);
this.controller.add(this.customtime);
// create itemset or groupset
this.setGroups(null);
@ -141,6 +146,22 @@ Timeline.prototype.setOptions = function (options) {
this.controller.repaint();
};
/**
* Set a custom time bar
* @param {Date} time
*/
Timeline.prototype.setCustomTime = function (time) {
this.customtime._setCustomTime(time);
};
/**
* Retrieve the current custom time.
* @return {Date} customTime
*/
Timeline.prototype.getCustomTime = function() {
return new Date(this.customtime.customTime.valueOf());
};
/**
* Set items
* @param {vis.DataSet | Array | DataTable | null} items

+ 255
- 0
src/timeline/component/CustomTime.js View File

@ -0,0 +1,255 @@
/**
* A custom time bar
* @param {Component} parent
* @param {Component[]} [depends] Components on which this components depends
* (except for the parent)
* @param {Object} [options] Available parameters:
* {Boolean} [showCustomTime]
* @constructor CustomTime
* @extends Component
*/
function CustomTime (parent, depends, options) {
this.id = util.randomUUID();
this.parent = parent;
this.depends = depends;
this.options = options || {};
this.defaultOptions = {
showCustomTime: false
};
this.listeners = [];
this.customTime = new Date();
}
CustomTime.prototype = new Component();
CustomTime.prototype.setOptions = Component.prototype.setOptions;
/**
* Get the container element of the bar, which can be used by a child to
* add its own widgets.
* @returns {HTMLElement} container
*/
CustomTime.prototype.getContainer = function () {
return this.frame;
};
/**
* Repaint the component
* @return {Boolean} changed
*/
CustomTime.prototype.repaint = function () {
var bar = this.frame,
parent = this.parent,
parentContainer = parent.parent.getContainer();
if (!parent) {
throw new Error('Cannot repaint bar: no parent attached');
}
if (!parentContainer) {
throw new Error('Cannot repaint bar: parent has no container element');
}
if (!this.getOption('showCustomTime')) {
if (bar) {
parentContainer.removeChild(bar);
delete this.frame;
}
return;
}
if (!bar) {
bar = document.createElement('div');
bar.className = 'customtime';
bar.style.position = 'absolute';
bar.style.top = '0px';
bar.style.height = '100%';
parentContainer.appendChild(bar);
var drag = document.createElement('div');
drag.style.position = 'relative';
drag.style.top = '0px';
drag.style.left = '-10px';
drag.style.height = '100%';
drag.style.width = '20px';
bar.appendChild(drag);
this.frame = bar;
this.subscribe(this, 'movetime');
}
if (!parent.conversion) {
parent._updateConversion();
}
var x = parent.toScreen(this.customTime);
bar.style.left = x + 'px';
bar.title = 'Time: ' + this.customTime;
return false;
};
/**
* Set custom time.
* @param {Date} time
*/
CustomTime.prototype._setCustomTime = function(time) {
this.customTime = new Date(time.valueOf());
this.repaint();
};
/**
* Retrieve the current custom time.
* @return {Date} customTime
*/
CustomTime.prototype._getCustomTime = function() {
return new Date(this.customTime.valueOf());
};
/**
* Add listeners for mouse and touch events to the component
* @param {Component} component
*/
CustomTime.prototype.subscribe = function (component, event) {
var me = this;
var listener = {
component: component,
event: event,
callback: function (event) {
me._onMouseDown(event, listener);
},
params: {}
};
component.on('mousedown', listener.callback);
me.listeners.push(listener);
};
/**
* Event handler
* @param {String} event name of the event, for example 'click', 'mousemove'
* @param {function} callback callback handler, invoked with the raw HTML Event
* as parameter.
*/
CustomTime.prototype.on = function (event, callback) {
var bar = this.frame;
if (!bar) {
throw new Error('Cannot add event listener: no parent attached');
}
events.addListener(this, event, callback);
util.addEventListener(bar, event, callback);
};
/**
* Start moving horizontally
* @param {Event} event
* @param {Object} listener Listener containing the component and params
* @private
*/
CustomTime.prototype._onMouseDown = function(event, listener) {
event = event || window.event;
var params = listener.params;
// only react on left mouse button down
var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1);
if (!leftButtonDown) {
return;
}
// get mouse position
params.mouseX = util.getPageX(event);
params.moved = false;
params.customTime = this.customTime;
// add event listeners to handle moving the custom time bar
var me = this;
if (!params.onMouseMove) {
params.onMouseMove = function (event) {
me._onMouseMove(event, listener);
};
util.addEventListener(document, 'mousemove', params.onMouseMove);
}
if (!params.onMouseUp) {
params.onMouseUp = function (event) {
me._onMouseUp(event, listener);
};
util.addEventListener(document, 'mouseup', params.onMouseUp);
}
util.stopPropagation(event);
util.preventDefault(event);
};
/**
* Perform moving operating.
* This function activated from within the funcion CustomTime._onMouseDown().
* @param {Event} event
* @param {Object} listener
* @private
*/
CustomTime.prototype._onMouseMove = function (event, listener) {
event = event || window.event;
var params = listener.params;
var parent = this.parent;
// calculate change in mouse position
var mouseX = util.getPageX(event);
if (params.mouseX === undefined) {
params.mouseX = mouseX;
}
var diff = mouseX - params.mouseX;
// if mouse movement is big enough, register it as a "moved" event
if (Math.abs(diff) >= 1) {
params.moved = true;
}
var x = parent.toScreen(params.customTime);
var xnew = x + diff;
var time = parent.toTime(xnew);
this._setCustomTime(time);
// fire a timechange event
events.trigger(this, 'timechange', {customTime: this.customTime});
util.preventDefault(event);
};
/**
* Stop moving operating.
* This function activated from within the function CustomTime._onMouseDown().
* @param {event} event
* @param {Object} listener
* @private
*/
CustomTime.prototype._onMouseUp = function (event, listener) {
event = event || window.event;
var params = listener.params;
// remove event listeners here, important for Safari
if (params.onMouseMove) {
util.removeEventListener(document, 'mousemove', params.onMouseMove);
params.onMouseMove = null;
}
if (params.onMouseUp) {
util.removeEventListener(document, 'mouseup', params.onMouseUp);
params.onMouseUp = null;
}
if (params.moved) {
// fire a timechanged event
events.trigger(this, 'timechanged', {customTime: this.customTime});
}
};

+ 6
- 0
src/timeline/component/css/customtime.css View File

@ -0,0 +1,6 @@
.vis.timeline .customtime {
background-color: #6E94FF;
width: 2px;
cursor: move;
z-index: 9;
}

Loading…
Cancel
Save