diff --git a/lib/timeline/Range.js b/lib/timeline/Range.js index 3ee0c44d9e..a2e74c672d 100644 --- a/lib/timeline/Range.js +++ b/lib/timeline/Range.js @@ -284,6 +284,12 @@ Range.prototype._applyRange = function(start, end) { var changed = (this.start != newStart || this.end != newEnd); + // if the new range does NOT overlap with the old range, emit checkRangedItems to avoid not showing ranged items (ranged meaning has end time, not neccesarily of type Range) + if (!((newStart >= this.start && newStart <= this.start) || (newEnd >= this.start && newEnd <= this.end)) && + !((this.start >= newStart && this.start <= newEnd) || (this.end >= newStart && this.end <= newEnd) )) { + this.body.emitter.emit('checkRangedItems'); + } + this.start = newStart; this.end = newEnd; return changed; diff --git a/lib/timeline/component/Group.js b/lib/timeline/component/Group.js index d9ddbff2f3..1e1e47579d 100644 --- a/lib/timeline/component/Group.js +++ b/lib/timeline/component/Group.js @@ -30,6 +30,11 @@ function Group (groupId, data, itemSet) { byStart: [], byEnd: [] }; + this.checkRangedItems = false; // needed to refresh the ranged items if the window is programatically changed with NO overlap. + var me = this; + this.itemSet.body.emitter.on("checkRangedItems", function () { + me.checkRangedItems = true; + }) this._create(); @@ -413,9 +418,9 @@ Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, ra // this function is used to do the binary search. var searchFunction = function (value) { - if (value < lowerBound) {return -1;} - else if (value >= lowerBound && value <= upperBound) {return 0;} - else {return 1;} + if (value < lowerBound) {return -1;} + else if (value <= upperBound) {return 0;} + else {return 1;} } // first check if the items that were in view previously are still in view. @@ -423,32 +428,35 @@ Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, ra // also cleans up invisible items. if (oldVisibleItems.length > 0) { for (i = 0; i < oldVisibleItems.length; i++) { - item = oldVisibleItems[i]; - if (item.isVisible(range)) { - visibleItems.push(item); - visibleItemsLookup[item.id] = true; - } - else { - if (item.displayed) item.hide(); - } + this._checkIfVisibleWithReference(oldVisibleItems[i], visibleItems, visibleItemsLookup, range); } } // we do a binary search for the items that have only start values. var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, 'data','start'); - // we do a binary search for the items that have defined end times. - var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data','end'); - // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the start values. this._traceVisible(initialPosByStart, orderedItems.byStart, visibleItems, visibleItemsLookup, function (item) { return (item.data.start < lowerBound || item.data.start > upperBound); }); - // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the end values. - this._traceVisible(initialPosByEnd, orderedItems.byEnd, visibleItems, visibleItemsLookup, function (item) { - return (item.data.end < lowerBound || item.data.end > upperBound); - }); + // if the window has changed programmatically without overlapping the old window, the ranged items with start < lowerBound and end > upperbound are not shown. + // We therefore have to brute force check all items in the byEnd list + if (this.checkRangedItems == true) { + this.checkRangedItems = false; + for (i = 0; i < orderedItems.byEnd.length; i++) { + this._checkIfVisibleWithReference(orderedItems.byEnd[i], visibleItems, visibleItemsLookup, range); + } + } + else { + // we do a binary search for the items that have defined end times. + var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data','end'); + + // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the end values. + this._traceVisible(initialPosByEnd, orderedItems.byEnd, visibleItems, visibleItemsLookup, function (item) { + return (item.data.end < lowerBound || item.data.end > upperBound); + }); + } // finally, we reposition all the visible items. @@ -533,5 +541,29 @@ Group.prototype._checkIfVisible = function(item, visibleItems, range) { }; +/** + * this function is very similar to the _checkIfInvisible() but it does not + * return booleans, hides the item if it should not be seen and always adds to + * the visibleItems. + * this one is for brute forcing and hiding. + * + * @param {Item} item + * @param {Array} visibleItems + * @param {{start:number, end:number}} range + * @private + */ +Group.prototype._checkIfVisibleWithReference = function(item, visibleItems, visibleItemsLookup, range) { + if (item.isVisible(range)) { + if (visibleItemsLookup[item.id] === undefined) { + visibleItemsLookup[item.id] = true; + visibleItems.push(item); + } + } + else { + if (item.displayed) item.hide(); + } +}; + + module.exports = Group;