diff --git a/src/DataSet.js b/src/DataSet.js index 40c16504..de6f5c09 100644 --- a/src/DataSet.js +++ b/src/DataSet.js @@ -47,6 +47,7 @@ function DataSet (data, options) { this.options = options || {}; this.data = {}; // map with data indexed by id + this.length = 0; // number of items in the dataset this.fieldId = this.options.fieldId || 'id'; // name of the field containing id this.convert = {}; // field types by field name this.showInternalIds = this.options.showInternalIds || false; // show internal ids with the get function @@ -685,6 +686,7 @@ DataSet.prototype._remove = function (id) { if (this.data[id]) { delete this.data[id]; delete this.internalIds[id]; + this.length--; return id; } } @@ -693,6 +695,7 @@ DataSet.prototype._remove = function (id) { if (itemId && this.data[itemId]) { delete this.data[itemId]; delete this.internalIds[itemId]; + this.length--; return itemId; } } @@ -709,6 +712,7 @@ DataSet.prototype.clear = function (senderId) { this.data = {}; this.internalIds = {}; + this.length--; this._trigger('remove', {items: ids}, senderId); @@ -828,6 +832,7 @@ DataSet.prototype._addItem = function (item) { } } this.data[id] = d; + this.length++; return id; }; diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index ca24de0b..8edadcac 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -497,6 +497,7 @@ Timeline.prototype.getWindow = function() { */ Timeline.prototype.redraw = function() { var resized = false, + updateProperty = util.updateProperty, options = this.options, props = this.props, dom = this.dom; @@ -519,12 +520,15 @@ Timeline.prototype.redraw = function() { // calculate the heights. If any of the side panels is empty, we set the height to // minus the border width, such that the border will be invisible - props.center.height = dom.center.offsetHeight; + //props.center.height = dom.center.offsetHeight; + resized = updateProperty(props.center, 'height', this.itemSet.props.height || 0) || resized; // TODO: this is a really ugly hack props.left.height = dom.left.offsetHeight; props.right.height = dom.right.offsetHeight; props.top.height = dom.top.clientHeight || -props.border.top; props.bottom.height = dom.bottom.clientHeight || -props.border.bottom; + console.log('props.center.height', props.center.height); + // TODO: compensate borders when any of the panels is empty. // apply auto height @@ -532,7 +536,7 @@ Timeline.prototype.redraw = function() { var contentHeight = Math.max(props.left.height, props.center.height, props.right.height); var autoHeight = props.top.height + contentHeight + props.bottom.height + borderRootHeight + props.border.top + props.border.bottom; - dom.root.style.height = util.option.asSize(options.height, autoHeight + 'px'); + resized = updateProperty(dom.root.style, 'height', util.option.asSize(options.height, autoHeight + 'px')) || resized; // calculate heights of the content panels props.root.height = dom.root.offsetHeight; @@ -679,8 +683,10 @@ Timeline.prototype._startAutoResize = function () { this._stopAutoResize(); function checkSize() { - if (me.options.autoResize != true) { - // stop watching when the option autoResize is changed to false + if (me.options.autoResize != true || !me.dom.root.parentNode) { + //if (me.options.autoResize != true) { + // stop watching when the option autoResize is changed to false, + // or when the Timeline is no longer attached to the DOM. me._stopAutoResize(); return; } @@ -697,7 +703,6 @@ Timeline.prototype._startAutoResize = function () { } } - // TODO: automatically cleanup the event listener when the frame is deleted util.addEventListener(window, 'resize', checkSize); this.watchTimer = setInterval(checkSize, 1000); diff --git a/src/timeline/component/Group.js b/src/timeline/component/Group.js index 343ba185..b67d12e9 100644 --- a/src/timeline/component/Group.js +++ b/src/timeline/component/Group.js @@ -78,6 +78,7 @@ Group.prototype.setData = function(data) { this.dom.inner.innerHTML = this.groupId; } + // Mark hidden when empty if (!this.dom.inner.firstChild) { util.addClassName(this.dom.inner, 'hidden'); } @@ -89,18 +90,11 @@ Group.prototype.setData = function(data) { var className = data && data.className; if (className) { util.addClassName(this.dom.label, className); + // TODO: addClassName to contents as well } + // TODO: be able to remove className }; -/** - * Get the width of the group label - * @return {number} width - */ -Group.prototype.getLabelWidth = function() { - return this.props.label.width; -}; - - /** * Repaint this group * @param {{start: number, end: number}} range @@ -154,7 +148,7 @@ Group.prototype.redraw = function(range, margin, restack) { // calculate actual size and position var foreground = this.dom.foreground; - this.top = foreground.offsetTop; + this.top = this.itemSet.getGroupTop(this.groupId); // top is determined by the ItemSet, from the heights of previous groups this.left = foreground.offsetLeft; this.width = foreground.offsetWidth; resized = util.updateProperty(this, 'height', height) || resized; diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index 95c5ed86..be01dac8 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -385,7 +385,8 @@ ItemSet.prototype._deselect = function(id) { * @return {boolean} Returns true if the component is resized */ ItemSet.prototype.redraw = function() { - var margin = this.options.margin, + var me = this, + margin = this.options.margin, range = this.body.range, asSize = util.option.asSize, options = this.options, @@ -421,7 +422,8 @@ ItemSet.prototype.redraw = function() { }, height = 0, minHeight = margin.axis + margin.item; - util.forEach(this.groups, function (group) { + this.groupIds.forEach(function (groupId) { + var group = me.groups[groupId]; var groupMargin = (group == firstGroup) ? firstMargin : nonFirstMargin; var groupResized = group.redraw(range, groupMargin, restack); resized = groupResized || resized; @@ -451,6 +453,24 @@ ItemSet.prototype.redraw = function() { return resized; }; +/** + * Calculate the top for a group + * @param {Number} groupId + */ +ItemSet.prototype.getGroupTop = function(groupId) { + var top = 0, + count = this.groupIds.length, + orientation = this.options.orientation; + for (var index = 0; index < count; index++) { + var id = this.groupIds[index]; + if (id == groupId) break; + + top += this.groups[id].height; + } + + return top; +}; + /** * Get the first group, aligned with the axis * @return {Group | null} firstGroup diff --git a/src/timeline/component/css/animation.css b/src/timeline/component/css/animation.css index 0b03f57f..3ea58b18 100644 --- a/src/timeline/component/css/animation.css +++ b/src/timeline/component/css/animation.css @@ -1,26 +1,23 @@ -.vis.timeline.root { - /* - -webkit-transition: height .4s ease-in-out; - transition: height .4s ease-in-out; - */ -} - -.vis.timeline .vispanel { - /* +/* + Note: .vis.timeline.root may not have transitions, else its height cannot be + determined (depends on autoHeight, css height, css minHeight, and css maxHeight) +*/ +/*.vis.timeline.root,*/ +.vis.timeline .axis, +.vis.timeline .vispanel.center, +.vis.timeline .vispanel.left, +.vis.timeline .vispanel.right, +.vis.timeline .vispanel.bottom { -webkit-transition: height .4s ease-in-out, top .4s ease-in-out; transition: height .4s ease-in-out, top .4s ease-in-out; - */ } -.vis.timeline .axis { - /* - -webkit-transition: top .4s ease-in-out; - transition: top .4s ease-in-out; - */ +.vis.timeline .vispanel .itemset .group, +.vis.timeline .vispanel .labelset .vlabel { + -webkit-transition: height .4s ease-in-out; + transition: height .4s ease-in-out; } -/* TODO: get animation working nicely - .vis.timeline .item { -webkit-transition: top .4s ease-in-out; transition: top .4s ease-in-out; @@ -30,4 +27,3 @@ -webkit-transition: height .4s ease-in-out, top .4s ease-in-out; transition: height .4s ease-in-out, top .4s ease-in-out; } -/**/ \ No newline at end of file diff --git a/test/timeline_groups.html b/test/timeline_groups.html index de2f5b16..4e0c11b1 100644 --- a/test/timeline_groups.html +++ b/test/timeline_groups.html @@ -79,6 +79,7 @@ updateTime: true, updateGroup: true }, + autoResize: false, //stack: false, //height: 200, groupOrder: 'content'