diff --git a/HISTORY.md b/HISTORY.md index cd5b9f0a..a7fefc77 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -15,8 +15,9 @@ http://visjs.org - Fixed `select` event fired repeatedly when clicking an empty place on the Timeline, deselecting selected items). - Fixed initial visible window in case items exceed `zoomMax`. Thanks @Remper. -- Option `order` is now deprecated. This was needed for performance improvements. - Fixed an offset in newly created items when using groups. +- Fixed height of a group not reckoning with the height of the group label. +- Option `order` is now deprecated. This was needed for performance improvements. - More examples added. - Minor bug fixes. diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 16ae1181..2c4767ab 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -289,6 +289,9 @@ Timeline.prototype.setOptions = function (options) { } } + // force the itemSet to refresh: options like orientation and margins may be changed + this.itemSet.markDirty(); + // validate the callback functions var validateCallback = (function (fn) { if (!(this.options[fn] instanceof Function) || this.options[fn].length != 2) { diff --git a/src/timeline/component/Group.js b/src/timeline/component/Group.js index b8d6df9b..de95c9fa 100644 --- a/src/timeline/component/Group.js +++ b/src/timeline/component/Group.js @@ -126,7 +126,8 @@ Group.prototype.repaint = function repaint(range, margin, restack) { stack.stack(this.visibleItems, margin, restack); this.stackDirty = false; for (var i = 0, ii = this.visibleItems.length; i < ii; i++) { - this.visibleItems[i].repositionY(); + var item = this.visibleItems[i]; + item.repositionY(); } // recalculate the height of the group @@ -144,6 +145,7 @@ Group.prototype.repaint = function repaint(range, margin, restack) { else { height = margin.axis + margin.item; } + height = Math.max(height, this.props.label.height); // calculate actual size and position var foreground = this.dom.foreground; diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index e4651239..c937f414 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -152,7 +152,17 @@ ItemSet.prototype._create = function _create(){ * Function to let items snap to nice dates when * dragging items. */ -ItemSet.prototype.setOptions = Component.prototype.setOptions; +ItemSet.prototype.setOptions = function setOptions(options) { + Component.prototype.setOptions.call(this, options); +}; + +/** + * Mark the ItemSet dirty so it will refresh everything with next repaint + */ +ItemSet.prototype.markDirty = function markDirty() { + this.groupIds = []; + this.stackDirty = true; +}; /** * Hide the component from the DOM @@ -298,26 +308,38 @@ ItemSet.prototype.repaint = function repaint() { // update className frame.className = 'itemset' + (options.className ? (' ' + asString(options.className)) : ''); + // reorder the groups (if needed) + resized = this._orderGroups() || resized; + // check whether zoomed (in that case we need to re-stack everything) + // 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); + if (zoomed) this.stackDirty = true; this.lastVisibleInterval = visibleInterval; this.lastWidth = this.width; // repaint all groups - var restack = zoomed || this.stackDirty, + var restack = this.stackDirty, + firstGroup = this._firstGroup(), + firstMargin = { + item: margin.item, + axis: margin.axis + }, + nonFirstMargin = { + item: margin.item, + axis: margin.item / 2 + }, height = 0, minHeight = margin.axis + margin.item; util.forEach(this.groups, function (group) { - resized = group.repaint(range, margin, restack) || resized; + var groupMargin = (group == firstGroup) ? firstMargin : nonFirstMargin; + resized = group.repaint(range, groupMargin, restack) || resized; height += group.height; }); height = Math.max(height, minHeight); this.stackDirty = false; - // reorder the groups (if needed) - resized = this._orderGroups() || resized; - // reposition frame frame.style.left = asSize(options.left, ''); frame.style.right = asSize(options.right, ''); @@ -347,6 +369,19 @@ ItemSet.prototype.repaint = function repaint() { return resized; }; +/** + * Get the first group, aligned with the axis + * @return {Group | null} firstGroup + * @private + */ +ItemSet.prototype._firstGroup = function _firstGroup() { + var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1); + var firstGroupId = this.groupIds[firstGroupIndex]; + var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED]; + + return firstGroup || null; +}; + /** * Create or delete the group holding all ungrouped items. This group is used when * there are no groups specified. @@ -733,7 +768,8 @@ ItemSet.prototype._orderGroups = function () { // hide all groups, removes them from the DOM var groups = this.groups; groupIds.forEach(function (groupId) { - groups[groupId].hide(); + var group = groups[groupId]; + group.hide(); }); // show the groups again, attach them to the DOM in correct order