Browse Source

cleaned up subgroups, removed magic numbers, added example, works for top and bottom orientations.

v3_develop
Alex de Mulder 10 years ago
parent
commit
c35261eb9e
5 changed files with 2767 additions and 2594 deletions
  1. +2615
    -2565
      dist/vis.js
  2. +73
    -0
      examples/timeline/30_subgroups.html
  3. +8
    -2
      lib/timeline/Stack.js
  4. +22
    -22
      lib/timeline/component/Group.js
  5. +49
    -5
      lib/timeline/component/item/BackgroundItem.js

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


+ 73
- 0
examples/timeline/30_subgroups.html View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | Background areas</title>
<style>
body, html {
font-family: arial, sans-serif;
font-size: 11pt;
}
.vis.timeline .item.background.negative {
background-color: rgba(255, 0, 0, 0.2);
}
.vis.timeline .item.background.positive {
background-color: rgba(105, 255, 98, 0.20);
}
.vis.timeline .item.background.marker {
border-left: 2px solid green;
}
</style>
<script src="../../dist/vis.js"></script>
<link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>This example demonstrates the item type "background", see "Period A" and "Period B". The background areas can be styled with css.</p>
<div id="visualization"></div>
<script>
// create a dataset with items
// we specify the type of the fields `start` and `end` here to be strings
// containing an ISO date. The fields will be outputted as ISO dates
// automatically getting data from the DataSet via items.get().
var items = new vis.DataSet({
type: { start: 'ISODate', end: 'ISODate' }
});
var groups = new vis.DataSet([{
id: 'bar', content:'bar'
},{
id: 'foo', content:'foo'
}]);
// add items to the DataSet
items.add([
{id: 'A', content:'1',start: '2014-01-20', end: '2014-01-22', type: 'background', group:'foo'},
{id: 'B', content:'1',start: '2014-01-22', end: '2014-01-23', type: 'background', group:'foo', className: 'negative'},
{id: 0, content: 'item 4', start: '2014-01-20', end: '2014-01-22',group:'foo'},
{id: 'ab', content:'1',start: '2014-01-25', end: '2014-01-27', type: 'background', group:'bar', subgroup:0},
{id: 'bb', content:'1',start: '2014-01-26', end: '2014-01-27', type: 'background', className: 'positive',group:'bar', subgroup:0},
{id: 1, content: 'subgroup0', start: '2014-01-25 12:00:00', end: '2014-01-26 12:00:00',group:'bar', subgroup:0},
{id: 'aab', content:'1',start: '2014-01-27', end: '2014-01-29', type: 'background', group:'bar', subgroup:1},
{id: 'bab', content:'1',start: '2014-01-27', end: '2014-01-28', type: 'background', className: 'negative',group:'bar', subgroup:1},
{id: 'bdab', content:'1',start: '2014-01-29', end: '2014-01-30', type: 'background', className: 'negative',group:'bar'},
{id: 2, content: 'subgroup1', start: '2014-01-27', end: '2014-01-29',group:'bar', subgroup:1},
]);
var container = document.getElementById('visualization');
var options = {
start: '2014-01-10',
end: '2014-02-10',
editable: true,
stack: false,
// orientation:'top'
};
var timeline = new vis.Timeline(container, items, groups, options);
</script>
</body>
</html>

+ 8
- 2
lib/timeline/Stack.js View File

@ -74,6 +74,7 @@ exports.stack = function(items, margin, force) {
}
};
/**
* Adjust vertical positions of the items without stacking them
* @param {Item[]} items
@ -81,12 +82,17 @@ exports.stack = function(items, margin, force) {
* @param {{item: {horizontal: number, vertical: number}, axis: number}} margin
* Margins between items and between items and the axis.
*/
exports.nostack = function(items, margin) {
exports.nostack = function(items, margin, subgroups) {
var i, iMax;
// reset top position of all items
for (i = 0, iMax = items.length; i < iMax; i++) {
items[i].top = margin.axis;
if (items[i].data.subgroup !== undefined) {
items[i].top = margin.axis + (subgroups[items[i].data.subgroup].height + margin.item.vertical) * items[i].data.subgroup;
}
else {
items[i].top = margin.axis;
}
}
};

+ 22
- 22
lib/timeline/component/Group.js View File

@ -11,7 +11,8 @@ var DateUtil = require('../DateUtil');
*/
function Group (groupId, data, itemSet) {
this.groupId = groupId;
this.subgroups = {};
this.visibleSubgroups = 0;
this.itemSet = itemSet;
this.dom = {};
@ -64,7 +65,7 @@ Group.prototype._create = function() {
// to the DOM, or the style of a parent of the Timeline is changed from
// display:none is changed to visible.
this.dom.marker = document.createElement('div');
this.dom.marker.style.visibility = 'hidden';
this.dom.marker.style.visibility = 'hidden'; // TODO: ask jos why this is not none?
this.dom.marker.innerHTML = '?';
this.dom.background.appendChild(this.dom.marker);
};
@ -163,18 +164,28 @@ Group.prototype.redraw = function(range, margin, restack) {
stack.stack(this.visibleItems, margin, restack);
}
else { // no stacking
stack.nostack(this.visibleItems, margin);
stack.nostack(this.visibleItems, margin, this.subgroups);
}
// recalculate the height of the group
var height;
var visibleItems = this.visibleItems;
var visibleSubgroups = [];
this.visibleSubgroups = 0;
var me = this;
if (visibleItems.length) {
var min = visibleItems[0].top;
var max = visibleItems[0].top + visibleItems[0].height;
util.forEach(visibleItems, function (item) {
min = Math.min(min, item.top);
max = Math.max(max, (item.top + item.height));
if (item.data.subgroup !== undefined) {
me.subgroups[item.data.subgroup].height = Math.max(me.subgroups[item.data.subgroup].height,item.height);
if (visibleSubgroups.indexOf(item.data.subgroup) == -1){
visibleSubgroups.push(item.data.subgroup);
me.visibleSubgroups += 1;
}
}
});
if (min > margin.axis) {
// there is an empty gap between the lowest item and the axis
@ -210,7 +221,7 @@ Group.prototype.redraw = function(range, margin, restack) {
// 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();
item.repositionY(margin);
}
return resized;
@ -270,6 +281,13 @@ Group.prototype.add = function(item) {
this.items[item.id] = item;
item.setParent(this);
// add to
if (item.data.subgroup !== undefined) {
if (this.subgroups[item.data.subgroup] === undefined) {
this.subgroups[item.data.subgroup] = {height:0};
}
}
if (this.visibleItems.indexOf(item) == -1) {
var range = this.itemSet.body.range; // TODO: not nice accessing the range like this
this._checkIfVisible(item, this.visibleItems, range);
@ -396,7 +414,6 @@ Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range
* @private
*/
Group.prototype._checkIfInvisible = function(item, visibleItems, range) {
//if (DateUtil.isHidden(item.data.start,this.itemSet.body.hiddenDates).hidden == false) {
if (item.isVisible(range)) {
if (!item.displayed) item.show();
item.repositionX();
@ -409,16 +426,6 @@ Group.prototype._checkIfInvisible = function(item, visibleItems, range) {
if (item.displayed) item.hide();
return true;
}
//}
//else {
// if (item.isVisible(range)) {
// return false;
// }
// else {
// if (item.displayed) item.hide();
// return true;
// }
//}
};
/**
@ -433,7 +440,6 @@ Group.prototype._checkIfInvisible = function(item, visibleItems, range) {
* @private
*/
Group.prototype._checkIfVisible = function(item, visibleItems, range) {
//if (DateUtil.isHidden(item.data.start,this.itemSet.body.hiddenDates).hidden == false) {
if (item.isVisible(range)) {
if (!item.displayed) item.show();
// reposition item horizontally
@ -443,12 +449,6 @@ Group.prototype._checkIfVisible = function(item, visibleItems, range) {
else {
if (item.displayed) item.hide();
}
//}
//else {
// if (!item.isVisible(range)) {
// if (item.displayed) item.hide();
// }
//}
};
module.exports = Group;

+ 49
- 5
lib/timeline/component/item/BackgroundItem.js View File

@ -137,15 +137,59 @@ BackgroundItem.prototype.repositionX = RangeItem.prototype.repositionX;
* Reposition the item vertically
* @Override
*/
BackgroundItem.prototype.repositionY = function() {
BackgroundItem.prototype.repositionY = function(margin) {
var onTop = this.options.orientation === 'top';
this.dom.content.style.top = onTop ? '' : '0';
this.dom.content.style.bottom = onTop ? '0' : '';
var height;
var height = Math.max(this.parent.height,
this.parent.itemSet.body.domProps.centerContainer.height);
this.dom.box.style.top = onTop ? '0' : '';
this.dom.box.style.bottom = onTop ? '' : '0';
// special positioning for subgroups
if (this.data.subgroup !== undefined) {
var subgroup = this.data.subgroup;
height = this.parent.subgroups[subgroup].height + margin.item.vertical;
// if the orientation is top, we need to take the difference in height into account.
if (onTop == true) {
// the first subgroup will have to account for the distance from the top to the first item.
height += subgroup == 0 ? margin.axis - 0.5*margin.item.vertical : 0;
var newTop = this.parent.top + (subgroup) * height;
// the others will have to be offset downwards with this same distance.
newTop += subgroup != 0 ? margin.axis - 0.5 * margin.item.vertical : 0;
this.dom.box.style.top = newTop + 'px';
this.dom.box.style.bottom = '';
}
// and when the orientation is bottom:
else {
var amountvisibleSubgroups = this.parent.visibleSubgroups - 1;
this.dom.box.style.top = (amountvisibleSubgroups - subgroup) * height + this.parent.top + 'px';
this.dom.box.style.bottom = '';
}
}
// and in the case of no subgroups:
else {
// we want backgrounds with groups to only show in groups.
if (this.data.group !== undefined) {
height = this.parent.height;
// alignment for items when orientation is top
if (onTop == true) {
this.dom.box.style.top = this.parent.top + 'px';
this.dom.box.style.bottom = '';
}
// and when the orientation is bottom
else {
this.dom.box.style.top = this.parent.top + 'px';
this.dom.box.style.bottom = '';
}
}
else {
// if the item is not in a group:
height = Math.max(this.parent.height, this.parent.itemSet.body.domProps.centerContainer.height);
this.dom.box.style.top = onTop ? '0' : '';
this.dom.box.style.bottom = onTop ? '' : '0';
}
}
this.dom.box.style.height = height + 'px';
};

Loading…
Cancel
Save