Browse Source

Hide vertically hidden ranged items in groups that are not visible (#2062)

* Hide vertically hidden ranged items in groups that are not visible
* Fix misspelling
* Fix examples that do not contain groups
* Add example for vertical hidden ranged items
* Fix indent format in RangeItem
* Fix example
* Fix other examples after addition of vertical hiding range items in groups
* Add case of zero margin axis
codeClimate
yotamberk 8 years ago
committed by Alexander Wunschik
parent
commit
0ba6e16498
3 changed files with 164 additions and 13 deletions
  1. +122
    -0
      examples/timeline/groups/verticalItemsHide.html
  2. +34
    -11
      lib/timeline/component/Group.js
  3. +8
    -2
      lib/timeline/component/item/RangeItem.js

+ 122
- 0
examples/timeline/groups/verticalItemsHide.html View File

@ -0,0 +1,122 @@
<html>
<head>
<title>Timeline | A lot of grouped data</title>
<script src="../../../docs/js/jquery.min.js"></script>
<script src="../../../dist/vis.js"></script>
<link href="../../../dist/vis.css" rel="stylesheet" type="text/css" />
<style type="text/css">
body {
color: #4D4D4D;
font: 10pt arial;
}
</style>
<script src="../../googleAnalytics.js"></script>
</head>
<body onresize="/*timeline.checkResize();*/">
<h1>Timeline vertical visibility</h1>
<button onclick="showVisibleItems()">Show current visible items</button>
<div>
<h2>visible items:</h2>
<h3 id="visibleItemsContainer"></h3>
</div>
<div id="mytimeline"></div>
<br>
<script>
function showVisibleItems() {
var a = timeline.getVisibleItems();
console.log(a);
document.getElementById("visibleItemsContainer").innerHTML = ""
document.getElementById("visibleItemsContainer").innerHTML += a;
};
// get selected item count from url parameter
var count = 1000;
// create groups
var groups = new vis.DataSet([
{id: 1, content: 'Truck&nbsp;1'},
{id: 2, content: 'Truck&nbsp;2'},
{id: 3, content: 'Truck&nbsp;3'},
{id: 4, content: 'Truck&nbsp;4'},
{id: 5, content: 'Truck&nbsp;5'},
{id: 6, content: 'Truck&nbsp;6'},
{id: 7, content: 'Truck&nbsp;7'},
{id: 8, content: 'Truck&nbsp;8'},
{id: 9, content: 'Truck&nbsp;9'},
{id: 10, content: 'Truck&nbsp;10'},
{id: 11, content: 'Truck&nbsp;11'},
{id: 12, content: 'Truck&nbsp;12'},
{id: 13, content: 'Truck&nbsp;13'},
{id: 14, content: 'Truck&nbsp;14'},
{id: 15, content: 'Truck&nbsp;15'},
{id: 16, content: 'Truck&nbsp;16'},
{id: 17, content: 'Truck&nbsp;17'},
{id: 18, content: 'Truck&nbsp;18'},
{id: 19, content: 'Truck&nbsp;19'},
{id: 20, content: 'Truck&nbsp;20'},
{id: 21, content: 'Truck&nbsp;21'},
{id: 22, content: 'Truck&nbsp;22'},
{id: 23, content: 'Truck&nbsp;23'},
{id: 24, content: 'Truck&nbsp;24'},
{id: 25, content: 'Truck&nbsp;25'},
]);
// create items
var items = new vis.DataSet();
var order = 1;
var truck = 1;
for (var j = 0; j < 25; j++) {
var date = new Date();
for (var i = 0; i < count/25; i++) {
date.setHours(date.getHours() + 4 * (Math.random() < 0.2));
var start = new Date(date);
date.setHours(date.getHours() + 2 + Math.floor(Math.random()*4));
var end = new Date(date);
items.add({
id: order,
group: truck,
start: start,
end: end,
content: 'Order ' + order
});
order++;
}
truck++;
}
// specify options
var options = {
stack: true,
maxHeight: 400,
start: new Date(),
end: new Date(1000*60*60*24 + (new Date()).valueOf()),
editable: true,
margin: {
item: 10, // minimal margin between items
axis: 5 // minimal margin between items and the axis
},
orientation: 'top'
};
// create a Timeline
var container = document.getElementById('mytimeline');
timeline = new vis.Timeline(container, null, options);
timeline.setGroups(groups);
timeline.setItems(items);
</script>
</body>
</html>

+ 34
- 11
lib/timeline/component/Group.js View File

@ -14,6 +14,7 @@ function Group (groupId, data, itemSet) {
this.subgroupIndex = 0; this.subgroupIndex = 0;
this.subgroupOrderer = data && data.subgroupOrder; this.subgroupOrderer = data && data.subgroupOrder;
this.itemSet = itemSet; this.itemSet = itemSet;
this.isVisible = null;
this.dom = {}; this.dom = {};
this.props = { this.props = {
@ -180,6 +181,8 @@ Group.prototype.redraw = function(range, margin, restack) {
// recalculate the height of the subgroups // recalculate the height of the subgroups
this._calculateSubGroupHeights(); this._calculateSubGroupHeights();
this.isVisible = this._isGroupVisible(range, margin);
// reposition visible items vertically // reposition visible items vertically
if (typeof this.itemSet.options.order === 'function') { if (typeof this.itemSet.options.order === 'function') {
// a custom order function // a custom order function
@ -219,6 +222,10 @@ Group.prototype.redraw = function(range, margin, restack) {
} }
} }
if (!this.isVisible && this.height) {
return resized = false;
}
// recalculate the height of the group // recalculate the height of the group
var height = this._calculateHeight(margin); var height = this._calculateHeight(margin);
@ -265,6 +272,17 @@ Group.prototype._calculateSubGroupHeights = function () {
} }
}; };
/**
* check if group is visible
* @private
*/
Group.prototype._isGroupVisible = function (range, margin) {
var isVisible =
(this.top <= range.body.domProps.centerContainer.height - range.body.domProps.scrollTop + margin.axis)
&& (this.top + this.height + margin.axis >= - range.body.domProps.scrollTop);
return isVisible;
}
/** /**
* recalculate the height of the group * recalculate the height of the group
* @param {{item: {horizontal: number, vertical: number}, axis: number}} margin * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin
@ -475,10 +493,18 @@ Group.prototype.order = function() {
Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, range) { Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, range) {
var visibleItems = []; var visibleItems = [];
var visibleItemsLookup = {}; // we keep this to quickly look up if an item already exists in the list without using indexOf on visibleItems var visibleItemsLookup = {}; // we keep this to quickly look up if an item already exists in the list without using indexOf on visibleItems
if (!this.isVisible) {
for (var i = 0; i < oldVisibleItems.length; i++) {
var item = oldVisibleItems[i];
if (item.displayed) item.hide();
}
return visibleItems;
}
var interval = (range.end - range.start) / 4; var interval = (range.end - range.start) / 4;
var lowerBound = range.start - interval; var lowerBound = range.start - interval;
var upperBound = range.end + interval; var upperBound = range.end + interval;
var item, i;
// this function is used to do the binary search. // this function is used to do the binary search.
var searchFunction = function (value) { var searchFunction = function (value) {
@ -491,7 +517,7 @@ Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, ra
// IMPORTANT: this handles the case for the items with startdate before the window and enddate after the window! // IMPORTANT: this handles the case for the items with startdate before the window and enddate after the window!
// also cleans up invisible items. // also cleans up invisible items.
if (oldVisibleItems.length > 0) { if (oldVisibleItems.length > 0) {
for (i = 0; i < oldVisibleItems.length; i++) {
for (var i = 0; i < oldVisibleItems.length; i++) {
this._checkIfVisibleWithReference(oldVisibleItems[i], visibleItems, visibleItemsLookup, range); this._checkIfVisibleWithReference(oldVisibleItems[i], visibleItems, visibleItemsLookup, range);
} }
} }
@ -524,8 +550,8 @@ Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, ra
// finally, we reposition all the visible items. // finally, we reposition all the visible items.
for (i = 0; i < visibleItems.length; i++) {
item = visibleItems[i];
for (var i = 0; i < visibleItems.length; i++) {
var item = visibleItems[i];
if (!item.displayed) item.show(); if (!item.displayed) item.show();
// reposition item horizontally // reposition item horizontally
item.repositionX(); item.repositionX();
@ -548,12 +574,9 @@ Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, ra
}; };
Group.prototype._traceVisible = function (initialPos, items, visibleItems, visibleItemsLookup, breakCondition) { Group.prototype._traceVisible = function (initialPos, items, visibleItems, visibleItemsLookup, breakCondition) {
var item;
var i;
if (initialPos != -1) { if (initialPos != -1) {
for (i = initialPos; i >= 0; i--) {
item = items[i];
for (var i = initialPos; i >= 0; i--) {
var item = items[i];
if (breakCondition(item)) { if (breakCondition(item)) {
break; break;
} }
@ -565,8 +588,8 @@ Group.prototype._traceVisible = function (initialPos, items, visibleItems, visib
} }
} }
for (i = initialPos + 1; i < items.length; i++) {
item = items[i];
for (var i = initialPos + 1; i < items.length; i++) {
var item = items[i];
if (breakCondition(item)) { if (breakCondition(item)) {
break; break;
} }

+ 8
- 2
lib/timeline/component/item/RangeItem.js View File

@ -43,8 +43,14 @@ RangeItem.prototype.baseClassName = 'vis-item vis-range';
*/ */
RangeItem.prototype.isVisible = function(range) { RangeItem.prototype.isVisible = function(range) {
// determine visibility // determine visibility
return (this.data.start < range.end) && (this.data.end > range.start);
};
var isVisible =
// determine horizontal visibillity
(this.data.start < range.end) &&
(this.data.end > range.start) &&
// determine vertical visibillity
(this.parent.top < range.body.domProps.centerContainer.height - range.body.domProps.scrollTop) &&
(this.parent.top + this.parent.height > - range.body.domProps.scrollTop)
return isVisible;};
/** /**
* Repaint the item * Repaint the item

Loading…
Cancel
Save