diff --git a/lib/timeline/component/Group.js b/lib/timeline/component/Group.js index 6a26b27b..306d0f4c 100644 --- a/lib/timeline/component/Group.js +++ b/lib/timeline/component/Group.js @@ -206,7 +206,19 @@ Group.prototype.getLabelWidth = function() { return this.props.label.width; }; -Group.prototype._didMarkerHeightChange = function() { + +/** + * Repaint this group + * @param {{start: number, end: number}} range + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * @param {boolean} [forceRestack=false] Force restacking of all items + * @return {boolean} Returns true if the group is resized + */ +Group.prototype.redraw = function(range, margin, forceRestack) { + var resized = false; + + // force recalculation of the height of the items when the marker height changed + // (due to the Timeline being attached to the DOM or changed from display:none to visible) var markerHeight = this.dom.marker.clientHeight; if (markerHeight != this.lastMarkerHeight) { this.lastMarkerHeight = markerHeight; @@ -214,22 +226,27 @@ Group.prototype._didMarkerHeightChange = function() { item.dirty = true; if (item.displayed) item.redraw(); }); - return true; - } -} -Group.prototype._calculateGroupSizeAndPosition = function() { + forceRestack = true; + } + + // recalculate the height of the subgroups + this._calculateSubGroupHeights(margin); + + // calculate actual size and position var foreground = this.dom.foreground; this.top = foreground.offsetTop; this.right = foreground.offsetLeft; this.width = foreground.offsetWidth; -} -Group.prototype._redrawItems = function(forceRestack, lastIsVisible, margin, range) { - var restack = forceRestack || this.stackDirty || this.isVisible && !lastIsVisible; + var lastIsVisible = this.isVisible; + this.isVisible = this._isGroupVisible(range, margin); + + var restack = forceRestack || this.stackDirty || (this.isVisible && !lastIsVisible); - // if restacking, reposition visible items vertically - if (restack) { + this._updateSubgroupsSizes(); + // if restacking, reposition visible items vertically + if(restack) { if (typeof this.itemSet.options.order === 'function') { // a custom order function // brute force restack of all items @@ -238,7 +255,7 @@ Group.prototype._redrawItems = function(forceRestack, lastIsVisible, margin, ran var me = this; var limitSize = false; util.forEach(this.items, function (item) { - if (!item.displayed) { + if (!item.dom) { // If this item has never been displayed then the dom property will not be defined, this means we need to measure the size item.redraw(); me.visibleItems.push(item); } @@ -251,41 +268,41 @@ Group.prototype._redrawItems = function(forceRestack, lastIsVisible, margin, ran }); stack.stack(customOrderedItems, margin, true /* restack=true */); this.visibleItems = this._updateItemsInRange(this.orderedItems, this.visibleItems, range); - } else { + + } + else { // no custom order function, lazy stacking this.visibleItems = this._updateItemsInRange(this.orderedItems, this.visibleItems, range); - if (this.itemSet.options.stack) { - // TODO: ugly way to access options... - stack.stack(this.visibleItems, margin, true /* restack=true */); - } else { - // no stacking + if (this.itemSet.options.stack) { // TODO: ugly way to access options... + stack.stack(this.visibleItems, margin, true /* restack=true */); + } + else { // no stacking stack.nostack(this.visibleItems, margin, this.subgroups, this.itemSet.options.stackSubgroups); } } - + this.stackDirty = false; } -} + // recalculate the height of the group + var height = this._calculateHeight(margin); -Group.prototype._didResize = function(resized, height) { + // calculate actual size and position + foreground = this.dom.foreground; + this.top = foreground.offsetTop; + this.right = foreground.offsetLeft; + this.width = foreground.offsetWidth; resized = util.updateProperty(this, 'height', height) || resized; // recalculate size of label - var labelWidth = this.dom.inner.clientWidth; - var labelHeight = this.dom.inner.clientHeight; - resized = util.updateProperty(this.props.label, 'width', labelWidth) || resized; - resized = util.updateProperty(this.props.label, 'height', labelHeight) || resized; - return resized; -} + resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; + resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; -Group.prototype._applyGroupHeight = function(height) { - this.dom.background.style.height = height + 'px'; - this.dom.foreground.style.height = height + 'px'; + // apply new height + this.dom.background.style.height = height + 'px'; + this.dom.foreground.style.height = height + 'px'; this.dom.label.style.height = height + 'px'; -} -// update vertical position of items after they are re-stacked and the height of the group is calculated -Group.prototype._updateItemsVerticalPosition = function(resized, margin) { + // update vertical position of items after they are re-stacked and the height of the group is calculated for (var i = 0, ii = this.visibleItems.length; i < ii; i++) { var item = this.visibleItems[i]; item.repositionY(margin); @@ -295,84 +312,10 @@ Group.prototype._updateItemsVerticalPosition = function(resized, margin) { } if (!this.isVisible && this.height) { - return false; + return resized = false; } return resized; -} - -/** - * Repaint this group - * @param {{start: number, end: number}} range - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * @param {boolean} [forceRestack=false] Force restacking of all items - * @param {boolean} [returnQueue=false] return the queue or if the group resized - * @return {boolean} Returns true if the group is resized or the redraw queue if returnQueue=true - */ -Group.prototype.redraw = function(range, margin, forceRestack, returnQueue) { - var resized = false; - var lastIsVisible = this.isVisible; - var height; - - var queue = [ - // force recalculation of the height of the items when the marker height changed - // (due to the Timeline being attached to the DOM or changed from display:none to visible) - (function () { - forceRestack = this._didMarkerHeightChange.bind(this); - }).bind(this), - - // recalculate the height of the subgroups - this._updateSubGroupHeights.bind(this, margin), - - // calculate actual size and position - this._calculateGroupSizeAndPosition.bind(this), - - // check if group is visible - (function() { - this.isVisible = this._isGroupVisible.bind(this)(range, margin); - }).bind(this), - - // redraw Items if needed - (function() { - this._redrawItems.bind(this)(forceRestack, lastIsVisible, margin, range) - }).bind(this), - - // update subgroups - this._updateSubgroupsSizes.bind(this), - - // recalculate the height of the group - (function() { - height = this._calculateHeight.bind(this)(margin); - }).bind(this), - - // calculate actual size and position again - this._calculateGroupSizeAndPosition.bind(this), - - // check if resized - (function() { - resized = this._didResize.bind(this)(resized, height) - }).bind(this), - - // apply group height - (function() { - this._applyGroupHeight.bind(this)(height) - }).bind(this), - - // update vertical position of items after they are re-stacked and the height of the group is calculated - (function() { - return resized = this._updateItemsVerticalPosition.bind(this)(resized, margin) - }).bind(this) - ] - - if (returnQueue) { - return queue; - } else { - var result; - queue.forEach(function (fn) { - result = fn(); - }); - return result; - } }; /** @@ -381,7 +324,7 @@ Group.prototype.redraw = function(range, margin, forceRestack, returnQueue) { * @param {{item: vis.Item}} margin * @private */ -Group.prototype._updateSubGroupHeights = function (margin) { +Group.prototype._calculateSubGroupHeights = function (margin) { if (Object.keys(this.subgroups).length > 0) { var me = this; diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index 5bd9bb41..51f9a02a 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -681,37 +681,13 @@ ItemSet.prototype.redraw = function() { // redraw the background group this.groups[BACKGROUND].redraw(range, nonFirstMargin, forceRestack); - var redrawQueue = {}; - var redrawQueueLength = 0; - - // collect redraw functions - util.forEach(this.groups, function (group, key) { - if (key === BACKGROUND) return; - var groupMargin = group == firstGroup ? firstMargin : nonFirstMargin; - var returnQueue = true; - redrawQueue[key] = group.redraw(range, groupMargin, forceRestack, returnQueue); - redrawQueueLength = redrawQueue[key].length; + // redraw all regular groups + util.forEach(this.groups, function (group) { + var groupMargin = (group == firstGroup) ? firstMargin : nonFirstMargin; + var groupResized = group.redraw(range, groupMargin, forceRestack); + resized = groupResized || resized; + height += group.height; }); - - if (redrawQueueLength) { - var redrawResults = {}; - - for (var i = 0; i < redrawQueueLength; i++) { - util.forEach(redrawQueue, function (fns, key) { - redrawResults[key] = fns[i](); - }); - } - - // redraw all regular groups - util.forEach(this.groups, function (group, key) { - if (key === BACKGROUND) return; - var groupResized = redrawResults[key]; - resized = groupResized || resized; - height += group.height; - }); - height = Math.max(height, minHeight); - } - height = Math.max(height, minHeight); // update frame height