Browse Source

fixed disappearing items

v3_develop
Alex de Mulder 10 years ago
parent
commit
3b9142fdf0
4 changed files with 1162 additions and 1098 deletions
  1. +1047
    -1015
      dist/vis.js
  2. +105
    -74
      lib/timeline/component/Group.js
  3. +1
    -1
      lib/timeline/component/LineGraph.js
  4. +9
    -8
      lib/util.js

+ 1047
- 1015
dist/vis.js
File diff suppressed because it is too large
View File


+ 105
- 74
lib/timeline/component/Group.js View File

@ -26,7 +26,7 @@ function Group (groupId, data, itemSet) {
this.items = {}; // items filtered by groupId of this group this.items = {}; // items filtered by groupId of this group
this.visibleItems = []; // items currently visible in window this.visibleItems = []; // items currently visible in window
this.orderedItems = { // items sorted by start and by end
this.orderedItems = {
byStart: [], byStart: [],
byEnd: [] byEnd: []
}; };
@ -361,6 +361,7 @@ Group.prototype.remove = function(item) {
// TODO: also remove from ordered items? // TODO: also remove from ordered items?
}; };
/** /**
* Remove an item from the corresponding DataSet * Remove an item from the corresponding DataSet
* @param {Item} item * @param {Item} item
@ -369,35 +370,31 @@ Group.prototype.removeFromDataSet = function(item) {
this.itemSet.removeItem(item.id); this.itemSet.removeItem(item.id);
}; };
/** /**
* Reorder the items * Reorder the items
*/ */
Group.prototype.order = function() { Group.prototype.order = function() {
var array = util.toArray(this.items); var array = util.toArray(this.items);
this.orderedItems.byStart = array;
this.orderedItems.byEnd = this._constructByEndArray(array);
stack.orderByStart(this.orderedItems.byStart);
stack.orderByEnd(this.orderedItems.byEnd);
};
/**
* Create an array containing all items being a range (having an end date)
* @param {Item[]} array
* @returns {RangeItem[]}
* @private
*/
Group.prototype._constructByEndArray = function(array) {
var startArray = [];
var endArray = []; var endArray = [];
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
if (array[i] instanceof RangeItem) {
if (array[i].data.end !== undefined) {
endArray.push(array[i]); endArray.push(array[i]);
} }
startArray.push(array[i]);
} }
return endArray;
this.orderedItems = {
byStart: startArray,
byEnd: endArray
};
stack.orderByStart(this.orderedItems.byStart);
stack.orderByEnd(this.orderedItems.byEnd);
}; };
/** /**
* Update the visible items * Update the visible items
* @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date * @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date
@ -406,79 +403,111 @@ Group.prototype._constructByEndArray = function(array) {
* @return {Item[]} visibleItems The new visible items. * @return {Item[]} visibleItems The new visible items.
* @private * @private
*/ */
Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range) {
var initialPosByStart,
newVisibleItems = [],
i;
Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, range) {
var visibleItems = [];
var visibleItemsLookup = {};
var interval = (range.end - range.start) / 4;
var lowerBound = range.start - interval;
var upperBound = range.end + interval;
var item, i;
// 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;}
}
// first check if the items that were in view previously are still in view. // first check if the items that were in view previously are still in view.
// this handles the case for the RangeItem that is both before and after the current one.
if (visibleItems.length > 0) {
for (i = 0; i < visibleItems.length; i++) {
this._checkIfVisible(visibleItems[i], newVisibleItems, range);
// IMPORTANT: this handles the case for the items with startdate before the window and enddate after the window!
// 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();
}
} }
} }
// If there were no visible items previously, use binarySearch to find a visible PointItem or RangeItem (based on startTime)
if (newVisibleItems.length == 0) {
initialPosByStart = util.binarySearch(orderedItems.byStart, range, 'data','start');
}
else {
initialPosByStart = orderedItems.byStart.indexOf(newVisibleItems[0]);
}
// we do a binary search for the items that have only start values.
var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, 'data','start');
// use visible search to find a visible RangeItem (only based on endTime)
var initialPosByEnd = util.binarySearch(orderedItems.byEnd, range, 'data','end');
// we do a binary search for the items that have defined end times.
var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data','end');
// if we found a initial ID to use, trace it up and down until we meet an invisible item.
if (initialPosByStart != -1) {
for (i = initialPosByStart; i >= 0; i--) {
if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;}
}
for (i = initialPosByStart + 1; i < orderedItems.byStart.length; i++) {
if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;}
}
}
// 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);
});
// if we found a initial ID to use, trace it up and down until we meet an invisible item.
if (initialPosByEnd != -1) {
for (i = initialPosByEnd; i >= 0; i--) {
if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;}
}
for (i = initialPosByEnd + 1; i < orderedItems.byEnd.length; i++) {
if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;}
}
// 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.
for (i = 0; i < visibleItems.length; i++) {
item = visibleItems[i];
if (!item.displayed) item.show();
// reposition item horizontally
item.repositionX();
} }
return newVisibleItems;
};
// debug
//console.log("new line")
//if (this.groupId == null) {
// for (i = 0; i < orderedItems.byStart.length; i++) {
// item = orderedItems.byStart[i].data;
// console.log('start',i,initialPosByStart, item.start.valueOf(), item.content, item.start >= lowerBound && item.start <= upperBound,i == initialPosByStart ? "<------------------- HEREEEE" : "")
// }
// for (i = 0; i < orderedItems.byEnd.length; i++) {
// item = orderedItems.byEnd[i].data;
// console.log('rangeEnd',i,initialPosByEnd, item.end.valueOf(), item.content, item.end >= range.start && item.end <= range.end,i == initialPosByEnd ? "<------------------- HEREEEE" : "")
// }
//}
return visibleItems;
};
Group.prototype._traceVisible = function (initialPos, items, visibleItems, visibleItemsLookup, breakCondition) {
var item;
var i;
/**
* this function checks if an item is invisible. If it is NOT we make it visible
* and add it to the global visible items. If it is, return true.
*
* @param {Item} item
* @param {Item[]} visibleItems
* @param {{start:number, end:number}} range
* @returns {boolean}
* @private
*/
Group.prototype._checkIfInvisible = function(item, visibleItems, range) {
if (item.isVisible(range)) {
if (!item.displayed) item.show();
item.repositionX();
if (visibleItems.indexOf(item) == -1) {
visibleItems.push(item);
if (initialPos != -1) {
for (i = initialPos; i >= 0; i--) {
item = items[i];
if (breakCondition(item)) {
break;
}
else {
if (visibleItemsLookup[item.id] === undefined) {
visibleItemsLookup[item.id] = true;
visibleItems.push(item);
}
} }
return false;
} }
else {
if (item.displayed) item.hide();
return true;
for (i = initialPos + 1; i < items.length; i++) {
item = items[i];
if (breakCondition(item)) {
break;
}
else {
if (visibleItemsLookup[item.id] === undefined) {
visibleItemsLookup[item.id] = true;
visibleItems.push(item);
}
}
} }
};
}
}
/** /**
* this function is very similar to the _checkIfInvisible() but it does not * this function is very similar to the _checkIfInvisible() but it does not
@ -503,4 +532,6 @@ Group.prototype._checkIfVisible = function(item, visibleItems, range) {
} }
}; };
module.exports = Group; module.exports = Group;

+ 1
- 1
lib/timeline/component/LineGraph.js View File

@ -691,7 +691,7 @@ LineGraph.prototype._getRelevantData = function (groupIds, groupsData, minDate,
var dataContainer = groupsData[groupIds[i]]; var dataContainer = groupsData[groupIds[i]];
// optimization for sorted data // optimization for sorted data
if (group.options.sort == true) { if (group.options.sort == true) {
var guess = Math.max(0, util.binarySearchGeneric(group.itemsData, minDate, 'x', 'before'));
var guess = Math.max(0, util.binarySearchValue(group.itemsData, minDate, 'x', 'before'));
for (j = guess; j < group.itemsData.length; j++) { for (j = guess; j < group.itemsData.length; j++) {
item = group.itemsData[j]; item = group.itemsData[j];
if (item !== undefined) { if (item !== undefined) {

+ 9
- 8
lib/util.js View File

@ -1141,14 +1141,14 @@ exports.mergeOptions = function (mergeTarget, options, option) {
* This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses * This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses
* this function will then iterate in both directions over this sorted list to find all visible items. * this function will then iterate in both directions over this sorted list to find all visible items.
* *
* @param {Item[]} orderedItems Items ordered by start
* @param {{start: number, end: number}} range
* @param {Item[]} orderedItems | Items ordered by start
* @param {function} searchFunction | -1 is lower, 0 is found, 1 is higher
* @param {String} field * @param {String} field
* @param {String} field2 * @param {String} field2
* @returns {number} * @returns {number}
* @private * @private
*/ */
exports.binarySearch = function(orderedItems, range, field, field2) {
exports.binarySearchCustom = function(orderedItems, searchFunction, field, field2) {
var maxIterations = 10000; var maxIterations = 10000;
var iteration = 0; var iteration = 0;
var low = 0; var low = 0;
@ -1158,12 +1158,13 @@ exports.binarySearch = function(orderedItems, range, field, field2) {
var middle = Math.floor((low + high) / 2); var middle = Math.floor((low + high) / 2);
var item = orderedItems[middle]; var item = orderedItems[middle];
if (item.isVisible(range)) { // jihaa, found a visible item!
var value = (field2 === undefined) ? item[field] : item[field][field2];
var searchResult = searchFunction(value);
if (searchResult == 0) { // jihaa, found a visible item!
return middle; return middle;
} }
var value = (field2 === undefined) ? item[field] : item[field][field2];
if (value < range.start) { // it is too small --> increase low
else if (searchResult == -1) { // it is too small --> increase low
low = middle + 1; low = middle + 1;
} }
else { // it is too big --> decrease high else { // it is too big --> decrease high
@ -1188,7 +1189,7 @@ exports.binarySearch = function(orderedItems, range, field, field2) {
* @returns {number} * @returns {number}
* @private * @private
*/ */
exports.binarySearchGeneric = function(orderedItems, target, field, sidePreference) {
exports.binarySearchValue = function(orderedItems, target, field, sidePreference) {
var maxIterations = 10000; var maxIterations = 10000;
var iteration = 0; var iteration = 0;
var low = 0; var low = 0;

Loading…
Cancel
Save