Browse Source

ItemSet starts to work again

css_transitions
jos 10 years ago
parent
commit
3dfd05ee6c
10 changed files with 175 additions and 176 deletions
  1. +89
    -26
      src/timeline/Timeline.js
  2. +2
    -0
      src/timeline/component/CustomTime.js
  3. +12
    -29
      src/timeline/component/Group.js
  4. +45
    -108
      src/timeline/component/ItemSet.js
  5. +13
    -2
      src/timeline/component/css/itemset.css
  6. +8
    -6
      src/timeline/component/css/labelset.css
  7. +1
    -0
      src/timeline/component/css/panel.css
  8. +3
    -3
      src/timeline/component/item/ItemBox.js
  9. +1
    -1
      src/timeline/component/item/ItemPoint.js
  10. +1
    -1
      src/timeline/component/item/ItemRange.js

+ 89
- 26
src/timeline/Timeline.js View File

@ -86,15 +86,7 @@ function Timeline (container, items, options) {
if (!container) throw new Error('No container provided'); if (!container) throw new Error('No container provided');
container.appendChild(this.dom.root); container.appendChild(this.dom.root);
// TODO: remove temporary contents
//this.dom.background.innerHTML = '<span style="color: red;">background</span>';
this.dom.center.innerHTML = '<span style="color: red;">center</span>';
this.dom.center.innerHTML = 'center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center<br>center';
this.dom.left.innerHTML = '<span style="color: red;">left</span>';
this.dom.right.innerHTML = '<span style="color: red;">right</span>';
//this.dom.top.innerHTML = '<span style="color: red;">top</span>';
//this.dom.bottom.innerHTML = '<span style="color: red;">bottom</span>';
// all components listed here will be repainted automatically
this.components = []; this.components = [];
// range // range
@ -117,6 +109,11 @@ function Timeline (container, items, options) {
this.customTime = new CustomTime(this, this.options); this.customTime = new CustomTime(this, this.options);
this.components.push(this.customTime); this.components.push(this.customTime);
// item set
this.itemSet = new ItemSet(this, this.options);
this.components.push(this.itemSet);
this.emitter.on('change', this.repaint.bind(this));
/* TODO /* TODO
// root panel // root panel
var rootOptions = util.extend(Object.create(this.options), { var rootOptions = util.extend(Object.create(this.options), {
@ -375,8 +372,6 @@ Timeline.prototype._create = function () {
this.dom.leftContainer.appendChild(this.dom.left); this.dom.leftContainer.appendChild(this.dom.left);
this.dom.rightContainer.appendChild(this.dom.right); this.dom.rightContainer.appendChild(this.dom.right);
// TODO: move watch from RootPanel to here
// create a central event bus // create a central event bus
this.emitter = this; this.emitter = this;
@ -437,11 +432,11 @@ Timeline.prototype.setOptions = function (options) {
remove: isBoolean ? options.editable : (options.editable.remove || false) remove: isBoolean ? options.editable : (options.editable.remove || false)
}; };
} }
/* TODO
// force update of range (apply new min/max etc.) // force update of range (apply new min/max etc.)
// both start and end are optional // both start and end are optional
this.range.setRange(options.start, options.end); this.range.setRange(options.start, options.end);
*/
if ('editable' in options || 'selectable' in options) { if ('editable' in options || 'selectable' in options) {
if (this.options.selectable) { if (this.options.selectable) {
// force update of selection // force update of selection
@ -452,10 +447,10 @@ Timeline.prototype.setOptions = function (options) {
this.setSelection([]); this.setSelection([]);
} }
} }
/* TODO
// force the itemSet to refresh: options like orientation and margins may be changed // force the itemSet to refresh: options like orientation and margins may be changed
this.itemSet.markDirty(); this.itemSet.markDirty();
*/
// validate the callback functions // validate the callback functions
var validateCallback = (function (fn) { var validateCallback = (function (fn) {
if (!(this.options[fn] instanceof Function) || this.options[fn].length != 2) { if (!(this.options[fn] instanceof Function) || this.options[fn].length != 2) {
@ -491,6 +486,10 @@ Timeline.prototype.setOptions = function (options) {
} }
} }
*/ */
// enable/disable autoResize
this._initAutoResize();
// TODO: remove deprecation error one day (deprecated since version 0.8.0) // TODO: remove deprecation error one day (deprecated since version 0.8.0)
if (options && options.order) { if (options && options.order) {
throw new Error('Option order is deprecated. There is no replacement for this feature.'); throw new Error('Option order is deprecated. There is no replacement for this feature.');
@ -567,7 +566,7 @@ Timeline.prototype.setItems = function(items) {
* Set groups * Set groups
* @param {vis.DataSet | Array | google.visualization.DataTable} groups * @param {vis.DataSet | Array | google.visualization.DataTable} groups
*/ */
Timeline.prototype.setGroups = function setGroups(groups) {
Timeline.prototype.setGroups = function(groups) {
// convert to type DataSet when needed // convert to type DataSet when needed
var newDataSet; var newDataSet;
if (!groups) { if (!groups) {
@ -595,7 +594,7 @@ Timeline.prototype.setGroups = function setGroups(groups) {
* @param {Object} [what] Optionally specify what to clear. By default: * @param {Object} [what] Optionally specify what to clear. By default:
* {items: true, groups: true, options: true} * {items: true, groups: true, options: true}
*/ */
Timeline.prototype.clear = function clear(what) {
Timeline.prototype.clear = function(what) {
// clear items // clear items
if (!what || what.items) { if (!what || what.items) {
this.setItems(null); this.setItems(null);
@ -615,7 +614,7 @@ Timeline.prototype.clear = function clear(what) {
/** /**
* Set Timeline window such that it fits all items * Set Timeline window such that it fits all items
*/ */
Timeline.prototype.fit = function fit() {
Timeline.prototype.fit = function() {
// apply the data range as range // apply the data range as range
var dataRange = this.getItemRange(); var dataRange = this.getItemRange();
@ -646,7 +645,7 @@ Timeline.prototype.fit = function fit() {
* When no minimum is found, min==null * When no minimum is found, min==null
* When no maximum is found, max==null * When no maximum is found, max==null
*/ */
Timeline.prototype.getItemRange = function getItemRange() {
Timeline.prototype.getItemRange = function() {
// calculate min from start filed // calculate min from start filed
var itemsData = this.itemsData, var itemsData = this.itemsData,
min = null, min = null,
@ -686,7 +685,7 @@ Timeline.prototype.getItemRange = function getItemRange() {
* selected. If ids is an empty array, all items will be * selected. If ids is an empty array, all items will be
* unselected. * unselected.
*/ */
Timeline.prototype.setSelection = function setSelection (ids) {
Timeline.prototype.setSelection = function(ids) {
this.itemSet && this.itemSet.setSelection(ids); this.itemSet && this.itemSet.setSelection(ids);
}; };
@ -694,7 +693,7 @@ Timeline.prototype.setSelection = function setSelection (ids) {
* Get the selected items by their id * Get the selected items by their id
* @return {Array} ids The ids of the selected items * @return {Array} ids The ids of the selected items
*/ */
Timeline.prototype.getSelection = function getSelection() {
Timeline.prototype.getSelection = function() {
return this.itemSet && this.itemSet.getSelection() || []; return this.itemSet && this.itemSet.getSelection() || [];
}; };
@ -711,7 +710,7 @@ Timeline.prototype.getSelection = function getSelection() {
* @param {Date | Number | String | Object} [start] Start date of visible window * @param {Date | Number | String | Object} [start] Start date of visible window
* @param {Date | Number | String} [end] End date of visible window * @param {Date | Number | String} [end] End date of visible window
*/ */
Timeline.prototype.setWindow = function setWindow(start, end) {
Timeline.prototype.setWindow = function(start, end) {
if (arguments.length == 1) { if (arguments.length == 1) {
var range = arguments[0]; var range = arguments[0];
this.range.setRange(range.start, range.end); this.range.setRange(range.start, range.end);
@ -725,7 +724,7 @@ Timeline.prototype.setWindow = function setWindow(start, end) {
* Get the visible window * Get the visible window
* @return {{start: Date, end: Date}} Visible range * @return {{start: Date, end: Date}} Visible range
*/ */
Timeline.prototype.getWindow = function setWindow() {
Timeline.prototype.getWindow = function() {
var range = this.range.getRange(); var range = this.range.getRange();
return { return {
start: new Date(range.start), start: new Date(range.start),
@ -737,7 +736,7 @@ Timeline.prototype.getWindow = function setWindow() {
* Force a repaint of the Timeline. Can be useful to manually repaint when * Force a repaint of the Timeline. Can be useful to manually repaint when
* option autoResize=false * option autoResize=false
*/ */
Timeline.prototype.repaint = function repaint() {
Timeline.prototype.repaint = function() {
var resized = false, var resized = false,
options = this.options, options = this.options,
props = this.props, props = this.props,
@ -880,6 +879,7 @@ Timeline.prototype._onSelectItem = function (event) {
* @param event * @param event
* @private * @private
*/ */
// TODO: move this function to ItemSet
Timeline.prototype._onAddItem = function (event) { Timeline.prototype._onAddItem = function (event) {
if (!this.options.selectable) return; if (!this.options.selectable) return;
if (!this.options.editable.add) return; if (!this.options.editable.add) return;
@ -970,7 +970,8 @@ Timeline.prototype._onMultiSelectItem = function (event) {
* @return {Date} time The datetime the corresponds with given position x * @return {Date} time The datetime the corresponds with given position x
* @private * @private
*/ */
Timeline.prototype._toTime = function _toTime(x) {
// TODO: move this function to Range
Timeline.prototype._toTime = function(x) {
var conversion = this.range.conversion(this.props.center.width); var conversion = this.range.conversion(this.props.center.width);
return new Date(x / conversion.scale + conversion.offset); return new Date(x / conversion.scale + conversion.offset);
}; };
@ -982,7 +983,69 @@ Timeline.prototype._toTime = function _toTime(x) {
* with the given date. * with the given date.
* @private * @private
*/ */
Timeline.prototype._toScreen = function _toScreen(time) {
// TODO: move this function to Range
Timeline.prototype._toScreen = function(time) {
var conversion = this.range.conversion(this.props.center.width); var conversion = this.range.conversion(this.props.center.width);
return (time.valueOf() - conversion.offset) * conversion.scale; return (time.valueOf() - conversion.offset) * conversion.scale;
}; };
/**
* Initialize watching when option autoResize is true
* @private
*/
Timeline.prototype._initAutoResize = function () {
if (this.options.autoResize == true) {
this._startAutoResize();
}
else {
this._stopAutoResize();
}
};
/**
* Watch for changes in the size of the container. On resize, the Panel will
* automatically redraw itself.
* @private
*/
Timeline.prototype._startAutoResize = function () {
var me = this;
this._stopAutoResize();
function checkSize() {
if (me.options.autoResize != true) {
// stop watching when the option autoResize is changed to false
me._stopAutoResize();
return;
}
if (me.dom.root) {
// check whether the frame is resized
if ((me.dom.root.clientWidth != me.props.lastWidth) ||
(me.dom.root.clientHeight != me.props.lastHeight)) {
me.props.lastWidth = me.dom.root.clientWidth;
me.props.lastHeight = me.dom.root.clientHeight;
me.emitter.emit('change');
}
}
}
// TODO: automatically cleanup the event listener when the frame is deleted
util.addEventListener(window, 'resize', checkSize);
this.watchTimer = setInterval(checkSize, 1000);
};
/**
* Stop watching for a resize of the frame.
* @private
*/
Timeline.prototype._stopAutoResize = function () {
if (this.watchTimer) {
clearInterval(this.watchTimer);
this.watchTimer = undefined;
}
// TODO: remove event listener on window.resize
};

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

@ -54,6 +54,8 @@ CustomTime.prototype._create = function _create () {
* @return {boolean} Returns true if the component is resized * @return {boolean} Returns true if the component is resized
*/ */
CustomTime.prototype.repaint = function () { CustomTime.prototype.repaint = function () {
// FIXME: CustomTime should be on the foreground
if (this.options.showCustomTime) { if (this.options.showCustomTime) {
if (this.bar.parentNode != this.timeline.dom.backgroundVertical) { if (this.bar.parentNode != this.timeline.dom.backgroundVertical) {
// attach to the dom // attach to the dom

+ 12
- 29
src/timeline/component/Group.js View File

@ -78,6 +78,13 @@ Group.prototype.setData = function setData(data) {
this.dom.inner.innerHTML = this.groupId; this.dom.inner.innerHTML = this.groupId;
} }
if (!this.dom.inner.firstChild) {
util.addClassName(this.dom.inner, 'hidden');
}
else {
util.removeClassName(this.dom.inner, 'hidden');
}
// update className // update className
var className = data && data.className; var className = data && data.className;
if (className) { if (className) {
@ -85,30 +92,6 @@ Group.prototype.setData = function setData(data) {
} }
}; };
/**
* Get the foreground container element
* @return {HTMLElement} foreground
*/
Group.prototype.getForeground = function getForeground() {
return this.dom.foreground;
};
/**
* Get the background container element
* @return {HTMLElement} background
*/
Group.prototype.getBackground = function getBackground() {
return this.dom.background;
};
/**
* Get the axis container element
* @return {HTMLElement} axis
*/
Group.prototype.getAxis = function getAxis() {
return this.dom.axis;
};
/** /**
* Get the width of the group label * Get the width of the group label
* @return {number} width * @return {number} width
@ -196,19 +179,19 @@ Group.prototype.repaint = function repaint(range, margin, restack) {
*/ */
Group.prototype.show = function show() { Group.prototype.show = function show() {
if (!this.dom.label.parentNode) { if (!this.dom.label.parentNode) {
this.itemSet.getLabelSet().appendChild(this.dom.label);
this.itemSet.dom.labelSet.appendChild(this.dom.label);
} }
if (!this.dom.foreground.parentNode) { if (!this.dom.foreground.parentNode) {
this.itemSet.getForeground().appendChild(this.dom.foreground);
this.itemSet.dom.foreground.appendChild(this.dom.foreground);
} }
if (!this.dom.background.parentNode) { if (!this.dom.background.parentNode) {
this.itemSet.getBackground().appendChild(this.dom.background);
this.itemSet.dom.background.appendChild(this.dom.background);
} }
if (!this.dom.axis.parentNode) { if (!this.dom.axis.parentNode) {
this.itemSet.getAxis().appendChild(this.dom.axis);
this.itemSet.dom.axis.appendChild(this.dom.axis);
} }
}; };
@ -246,7 +229,7 @@ Group.prototype.add = function add(item) {
item.setParent(this); item.setParent(this);
if (item instanceof ItemRange && this.visibleItems.indexOf(item) == -1) { if (item instanceof ItemRange && this.visibleItems.indexOf(item) == -1) {
var range = this.itemSet.range; // TODO: not nice accessing the range like this
var range = this.itemSet.timeline.range; // TODO: not nice accessing the range like this
this._checkIfVisible(item, this.visibleItems, range); this._checkIfVisible(item, this.visibleItems, range);
} }
}; };

+ 45
- 108
src/timeline/component/ItemSet.js View File

@ -4,31 +4,24 @@ var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
* An ItemSet holds a set of items and ranges which can be displayed in a * An ItemSet holds a set of items and ranges which can be displayed in a
* range. The width is determined by the parent of the ItemSet, and the height * range. The width is determined by the parent of the ItemSet, and the height
* is determined by the size of the items. * is determined by the size of the items.
* @param {Panel} backgroundPanel Panel which can be used to display the
* vertical lines of box items.
* @param {Panel} axisPanel Panel on the axis where the dots of box-items
* can be displayed.
* @param {Panel} sidePanel Left side panel holding labels
* @param {{dom: Object}} timeline
* @param {Object} [options] See ItemSet.setOptions for the available options. * @param {Object} [options] See ItemSet.setOptions for the available options.
* @constructor ItemSet * @constructor ItemSet
* @extends Panel * @extends Panel
*/ */
function ItemSet(backgroundPanel, axisPanel, sidePanel, options) {
this.id = util.randomUUID();
function ItemSet(timeline, options) {
this.timeline = timeline;
// one options object is shared by this itemset and all its items // one options object is shared by this itemset and all its items
this.options = options || {}; this.options = options || {};
this.backgroundPanel = backgroundPanel;
this.axisPanel = axisPanel;
this.sidePanel = sidePanel;
this.itemOptions = Object.create(this.options); this.itemOptions = Object.create(this.options);
this.dom = {}; this.dom = {};
this.props = {};
this.hammer = null; this.hammer = null;
var me = this; var me = this;
this.itemsData = null; // DataSet this.itemsData = null; // DataSet
this.groupsData = null; // DataSet this.groupsData = null; // DataSet
this.range = null; // Range or Object {start: number, end: number}
// listeners for the DataSet of the items // listeners for the DataSet of the items
this.itemListeners = { this.itemListeners = {
@ -69,7 +62,7 @@ function ItemSet(backgroundPanel, axisPanel, sidePanel, options) {
this._create(); this._create();
} }
ItemSet.prototype = new Panel();
ItemSet.prototype = new Component();
// available item types will be registered here // available item types will be registered here
ItemSet.types = { ItemSet.types = {
@ -84,13 +77,14 @@ ItemSet.types = {
*/ */
ItemSet.prototype._create = function _create(){ ItemSet.prototype._create = function _create(){
var frame = document.createElement('div'); var frame = document.createElement('div');
frame.className = 'itemset';
frame['timeline-itemset'] = this; frame['timeline-itemset'] = this;
this.frame = frame;
this.dom.frame = frame;
// create background panel // create background panel
var background = document.createElement('div'); var background = document.createElement('div');
background.className = 'background'; background.className = 'background';
this.backgroundPanel.frame.appendChild(background);
frame.appendChild(background);
this.dom.background = background; this.dom.background = background;
// create foreground panel // create foreground panel
@ -103,13 +97,11 @@ ItemSet.prototype._create = function _create(){
var axis = document.createElement('div'); var axis = document.createElement('div');
axis.className = 'axis'; axis.className = 'axis';
this.dom.axis = axis; this.dom.axis = axis;
this.axisPanel.frame.appendChild(axis);
// create labelset // create labelset
var labelSet = document.createElement('div'); var labelSet = document.createElement('div');
labelSet.className = 'labelset'; labelSet.className = 'labelset';
this.dom.labelSet = labelSet; this.dom.labelSet = labelSet;
this.sidePanel.frame.appendChild(labelSet);
// create ungrouped Group // create ungrouped Group
this._updateUngrouped(); this._updateUngrouped();
@ -122,13 +114,14 @@ ItemSet.prototype._create = function _create(){
this.hammer.on('dragstart', this._onDragStart.bind(this)); this.hammer.on('dragstart', this._onDragStart.bind(this));
this.hammer.on('drag', this._onDrag.bind(this)); this.hammer.on('drag', this._onDrag.bind(this));
this.hammer.on('dragend', this._onDragEnd.bind(this)); this.hammer.on('dragend', this._onDragEnd.bind(this));
// attach to the DOM
this.show();
}; };
/** /**
* Set options for the ItemSet. Existing options will be extended/overwritten. * Set options for the ItemSet. Existing options will be extended/overwritten.
* @param {Object} [options] The following options are available: * @param {Object} [options] The following options are available:
* {String | function} [className]
* class name for the itemset
* {String} [type] * {String} [type]
* Default type for the items. Choose from 'box' * Default type for the items. Choose from 'box'
* (default), 'point', or 'range'. The default * (default), 'point', or 'range'. The default
@ -152,9 +145,7 @@ ItemSet.prototype._create = function _create(){
* Function to let items snap to nice dates when * Function to let items snap to nice dates when
* dragging items. * dragging items.
*/ */
ItemSet.prototype.setOptions = function setOptions(options) {
Component.prototype.setOptions.call(this, options);
};
ItemSet.prototype.setOptions = Component.prototype.setOptions;
/** /**
* Mark the ItemSet dirty so it will refresh everything with next repaint * Mark the ItemSet dirty so it will refresh everything with next repaint
@ -168,16 +159,16 @@ ItemSet.prototype.markDirty = function markDirty() {
* Hide the component from the DOM * Hide the component from the DOM
*/ */
ItemSet.prototype.hide = function hide() { ItemSet.prototype.hide = function hide() {
// remove the frame containing the items
if (this.dom.frame.parentNode) {
this.dom.frame.parentNode.removeChild(this.dom.frame);
}
// remove the axis with dots // remove the axis with dots
if (this.dom.axis.parentNode) { if (this.dom.axis.parentNode) {
this.dom.axis.parentNode.removeChild(this.dom.axis); this.dom.axis.parentNode.removeChild(this.dom.axis);
} }
// remove the background with vertical lines
if (this.dom.background.parentNode) {
this.dom.background.parentNode.removeChild(this.dom.background);
}
// remove the labelset containing all group labels // remove the labelset containing all group labels
if (this.dom.labelSet.parentNode) { if (this.dom.labelSet.parentNode) {
this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); this.dom.labelSet.parentNode.removeChild(this.dom.labelSet);
@ -189,34 +180,22 @@ ItemSet.prototype.hide = function hide() {
* @return {Boolean} changed * @return {Boolean} changed
*/ */
ItemSet.prototype.show = function show() { ItemSet.prototype.show = function show() {
// show axis with dots
if (!this.dom.axis.parentNode) {
this.axisPanel.frame.appendChild(this.dom.axis);
// show frame containing the items
if (!this.dom.frame.parentNode) {
this.timeline.dom.center.appendChild(this.dom.frame);
} }
// show background with vertical lines
if (!this.dom.background.parentNode) {
this.backgroundPanel.frame.appendChild(this.dom.background);
// show axis with dots
if (!this.dom.axis.parentNode) {
this.timeline.dom.bottom.appendChild(this.dom.axis);
} }
// show labelset containing labels // show labelset containing labels
if (!this.dom.labelSet.parentNode) { if (!this.dom.labelSet.parentNode) {
this.sidePanel.frame.appendChild(this.dom.labelSet);
this.timeline.dom.left.appendChild(this.dom.labelSet);
} }
}; };
/**
* Set range (start and end).
* @param {Range | Object} range A Range or an object containing start and end.
*/
ItemSet.prototype.setRange = function setRange(range) {
if (!(range instanceof Range) && (!range || !range.start || !range.end)) {
throw new TypeError('Range must be an instance of Range, ' +
'or an object containing start and end.');
}
this.range = range;
};
/** /**
* Set selected items by their id. Replaces the current selection * Set selected items by their id. Replaces the current selection
* Unknown id's are silently ignored. * Unknown id's are silently ignored.
@ -275,27 +254,18 @@ ItemSet.prototype._deselect = function _deselect(id) {
} }
}; };
/**
* Return the item sets frame
* @returns {HTMLElement} frame
*/
ItemSet.prototype.getFrame = function getFrame() {
return this.frame;
};
/** /**
* Repaint the component * Repaint the component
* @return {boolean} Returns true if the component is resized * @return {boolean} Returns true if the component is resized
*/ */
ItemSet.prototype.repaint = function repaint() { ItemSet.prototype.repaint = function repaint() {
var margin = this.options.margin, var margin = this.options.margin,
range = this.range,
range = this.timeline.range,
asSize = util.option.asSize, asSize = util.option.asSize,
asString = util.option.asString,
options = this.options, options = this.options,
orientation = this.getOption('orientation'), orientation = this.getOption('orientation'),
resized = false, resized = false,
frame = this.frame;
frame = this.dom.frame;
// TODO: document this feature to specify one margin for both item and axis distance // TODO: document this feature to specify one margin for both item and axis distance
if (typeof margin === 'number') { if (typeof margin === 'number') {
@ -305,19 +275,16 @@ ItemSet.prototype.repaint = function repaint() {
}; };
} }
// update className
frame.className = 'itemset' + (options.className ? (' ' + asString(options.className)) : '');
// reorder the groups (if needed) // reorder the groups (if needed)
resized = this._orderGroups() || resized; resized = this._orderGroups() || resized;
// check whether zoomed (in that case we need to re-stack everything) // check whether zoomed (in that case we need to re-stack everything)
// TODO: would be nicer to get this as a trigger from Range // TODO: would be nicer to get this as a trigger from Range
var visibleInterval = this.range.end - this.range.start;
var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.width != this.lastWidth);
var visibleInterval = range.end - range.start;
var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.props.width != this.props.lastWidth);
if (zoomed) this.stackDirty = true; if (zoomed) this.stackDirty = true;
this.lastVisibleInterval = visibleInterval; this.lastVisibleInterval = visibleInterval;
this.lastWidth = this.width;
this.props.lastWidth = this.props.width;
// repaint all groups // repaint all groups
var restack = this.stackDirty, var restack = this.stackDirty,
@ -350,10 +317,10 @@ ItemSet.prototype.repaint = function repaint() {
//frame.style.height = asSize('height' in options ? options.height : height); // TODO: reckon with height //frame.style.height = asSize('height' in options ? options.height : height); // TODO: reckon with height
// calculate actual size and position // calculate actual size and position
this.top = frame.offsetTop;
this.left = frame.offsetLeft;
this.width = frame.offsetWidth;
this.height = height;
this.props.top = frame.offsetTop;
this.props.left = frame.offsetLeft;
this.props.width = frame.offsetWidth;
this.props.height = height;
// reposition axis // reposition axis
this.dom.axis.style.left = asSize(options.left, '0'); this.dom.axis.style.left = asSize(options.left, '0');
@ -416,30 +383,6 @@ ItemSet.prototype._updateUngrouped = function _updateUngrouped() {
} }
}; };
/**
* Get the foreground container element
* @return {HTMLElement} foreground
*/
ItemSet.prototype.getForeground = function getForeground() {
return this.dom.foreground;
};
/**
* Get the background container element
* @return {HTMLElement} background
*/
ItemSet.prototype.getBackground = function getBackground() {
return this.dom.background;
};
/**
* Get the axis container element
* @return {HTMLElement} axis
*/
ItemSet.prototype.getAxis = function getAxis() {
return this.dom.axis;
};
/** /**
* Get the element for the labelset * Get the element for the labelset
* @return {HTMLElement} labelSet * @return {HTMLElement} labelSet
@ -471,7 +414,7 @@ ItemSet.prototype.setItems = function setItems(items) {
if (oldItemsData) { if (oldItemsData) {
// unsubscribe from old dataset // unsubscribe from old dataset
util.forEach(this.itemListeners, function (callback, event) { util.forEach(this.itemListeners, function (callback, event) {
oldItemsData.unsubscribe(event, callback);
oldItemsData.off(event, callback);
}); });
// remove all drawn items // remove all drawn items
@ -552,7 +495,7 @@ ItemSet.prototype.setGroups = function setGroups(groups) {
// update the order of all items in each group // update the order of all items in each group
this._order(); this._order();
this.emit('change');
this.timeline.emitter.emit('change');
}; };
/** /**
@ -630,7 +573,7 @@ ItemSet.prototype._onUpdate = function _onUpdate(ids) {
this._order(); this._order();
this.stackDirty = true; // force re-stacking of all items next repaint this.stackDirty = true; // force re-stacking of all items next repaint
this.emit('change');
this.timeline.emitter.emit('change');
}; };
/** /**
@ -660,7 +603,7 @@ ItemSet.prototype._onRemove = function _onRemove(ids) {
// update order // update order
this._order(); this._order();
this.stackDirty = true; // force re-stacking of all items next repaint this.stackDirty = true; // force re-stacking of all items next repaint
this.emit('change');
this.timeline.emitter.emit('change');
} }
}; };
@ -730,7 +673,7 @@ ItemSet.prototype._onAddGroups = function _onAddGroups(ids) {
} }
}); });
this.emit('change');
this.timeline.emitter.emit('change');
}; };
/** /**
@ -751,7 +694,7 @@ ItemSet.prototype._onRemoveGroups = function _onRemoveGroups(ids) {
this.markDirty(); this.markDirty();
this.emit('change');
this.timeline.emitter.emit('change');
}; };
/** /**
@ -872,6 +815,7 @@ ItemSet.prototype._constructByEndArray = function _constructByEndArray(array) {
* Get the width of the group labels * Get the width of the group labels
* @return {Number} width * @return {Number} width
*/ */
// TODO: is this function getLabelsWidth redundant?
ItemSet.prototype.getLabelsWidth = function getLabelsWidth() { ItemSet.prototype.getLabelsWidth = function getLabelsWidth() {
var width = 0; var width = 0;
@ -882,14 +826,6 @@ ItemSet.prototype.getLabelsWidth = function getLabelsWidth() {
return width; return width;
}; };
/**
* Get the height of the itemsets background
* @return {Number} height
*/
ItemSet.prototype.getBackgroundHeight = function getBackgroundHeight() {
return this.height;
};
/** /**
* Start dragging the selected events * Start dragging the selected events
* @param {Event} event * @param {Event} event
@ -966,9 +902,10 @@ ItemSet.prototype._onDragStart = function (event) {
*/ */
ItemSet.prototype._onDrag = function (event) { ItemSet.prototype._onDrag = function (event) {
if (this.touchParams.itemProps) { if (this.touchParams.itemProps) {
var snap = this.options.snap || null,
var range = this.timeline.range,
snap = this.options.snap || null,
deltaX = event.gesture.deltaX, deltaX = event.gesture.deltaX,
scale = (this.width / (this.range.end - this.range.start)),
scale = (this.props.width / (range.end - range.start)),
offset = deltaX / scale; offset = deltaX / scale;
// move // move
@ -1001,7 +938,7 @@ ItemSet.prototype._onDrag = function (event) {
// TODO: implement onMoving handler // TODO: implement onMoving handler
this.stackDirty = true; // force re-stacking of all items next repaint this.stackDirty = true; // force re-stacking of all items next repaint
this.emit('change');
this.timeline.emitter.emit('change');
event.stopPropagation(); event.stopPropagation();
} }
@ -1051,7 +988,7 @@ ItemSet.prototype._onDragEnd = function (event) {
if ('end' in props) props.item.data.end = props.end; if ('end' in props) props.item.data.end = props.end;
me.stackDirty = true; // force re-stacking of all items next repaint me.stackDirty = true; // force re-stacking of all items next repaint
me.emit('change');
me.timeline.emitter.emit('change');
} }
}); });
} }

+ 13
- 2
src/timeline/component/css/itemset.css View File

@ -12,21 +12,31 @@
/**/ /**/
} }
.vis.timeline .background {
.vis.timeline .background,
.vis.timeline .foreground {
position: absolute;
width: 100%;
height: 100%;
} }
.vis.timeline .foreground { .vis.timeline .foreground {
overflow: hidden;
} }
.vis.timeline .axis { .vis.timeline .axis {
overflow: visible;
} }
.vis.timeline .group { .vis.timeline .group {
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 1px solid #bfbfbf;
}
.vis.timeline .group:last-child {
border-bottom: none;
} }
/*
.vis.timeline.top .group { .vis.timeline.top .group {
border-top: 1px solid #bfbfbf; border-top: 1px solid #bfbfbf;
border-bottom: none; border-bottom: none;
@ -36,3 +46,4 @@
border-top: none; border-top: none;
border-bottom: 1px solid #bfbfbf; border-bottom: 1px solid #bfbfbf;
} }
*/

+ 8
- 6
src/timeline/component/css/labelset.css View File

@ -18,17 +18,19 @@
box-sizing: border-box; box-sizing: border-box;
} }
.vis.timeline.top .labelset .vlabel {
border-top: 1px solid #bfbfbf;
border-bottom: none;
.vis.timeline .labelset .vlabel {
border-bottom: 1px solid #bfbfbf;
} }
.vis.timeline.bottom .labelset .vlabel {
border-top: none;
border-bottom: 1px solid #bfbfbf;
.vis.timeline .labelset .vlabel:last-child {
border-bottom: none;
} }
.vis.timeline .labelset .vlabel .inner { .vis.timeline .labelset .vlabel .inner {
display: inline-block; display: inline-block;
padding: 5px; padding: 5px;
} }
.vis.timeline .labelset .vlabel .inner.hidden {
padding: 0;
}

+ 1
- 0
src/timeline/component/css/panel.css View File

@ -32,6 +32,7 @@
.vis.timeline .vispanel.right { .vis.timeline .vispanel.right {
border-top-style: solid; border-top-style: solid;
border-bottom-style: solid; border-bottom-style: solid;
overflow: hidden;
} }
.vis.timeline .vispanel.center, .vis.timeline .vispanel.center,

+ 3
- 3
src/timeline/component/item/ItemBox.js View File

@ -78,17 +78,17 @@ ItemBox.prototype.repaint = function repaint() {
throw new Error('Cannot repaint item: no parent attached'); throw new Error('Cannot repaint item: no parent attached');
} }
if (!dom.box.parentNode) { if (!dom.box.parentNode) {
var foreground = this.parent.getForeground();
var foreground = this.parent.dom.foreground;
if (!foreground) throw new Error('Cannot repaint time axis: parent has no foreground container element'); if (!foreground) throw new Error('Cannot repaint time axis: parent has no foreground container element');
foreground.appendChild(dom.box); foreground.appendChild(dom.box);
} }
if (!dom.line.parentNode) { if (!dom.line.parentNode) {
var background = this.parent.getBackground();
var background = this.parent.dom.background;
if (!background) throw new Error('Cannot repaint time axis: parent has no background container element'); if (!background) throw new Error('Cannot repaint time axis: parent has no background container element');
background.appendChild(dom.line); background.appendChild(dom.line);
} }
if (!dom.dot.parentNode) { if (!dom.dot.parentNode) {
var axis = this.parent.getAxis();
var axis = this.parent.dom.axis;
if (!background) throw new Error('Cannot repaint time axis: parent has no axis container element'); if (!background) throw new Error('Cannot repaint time axis: parent has no axis container element');
axis.appendChild(dom.dot); axis.appendChild(dom.dot);
} }

+ 1
- 1
src/timeline/component/item/ItemPoint.js View File

@ -76,7 +76,7 @@ ItemPoint.prototype.repaint = function repaint() {
throw new Error('Cannot repaint item: no parent attached'); throw new Error('Cannot repaint item: no parent attached');
} }
if (!dom.point.parentNode) { if (!dom.point.parentNode) {
var foreground = this.parent.getForeground();
var foreground = this.parent.dom.foreground;
if (!foreground) { if (!foreground) {
throw new Error('Cannot repaint time axis: parent has no foreground container element'); throw new Error('Cannot repaint time axis: parent has no foreground container element');
} }

+ 1
- 1
src/timeline/component/item/ItemRange.js View File

@ -69,7 +69,7 @@ ItemRange.prototype.repaint = function repaint() {
throw new Error('Cannot repaint item: no parent attached'); throw new Error('Cannot repaint item: no parent attached');
} }
if (!dom.box.parentNode) { if (!dom.box.parentNode) {
var foreground = this.parent.getForeground();
var foreground = this.parent.dom.foreground;
if (!foreground) { if (!foreground) {
throw new Error('Cannot repaint time axis: parent has no foreground container element'); throw new Error('Cannot repaint time axis: parent has no foreground container element');
} }

Loading…
Cancel
Save