Browse Source

updated background item for better subgroup alignment. Fixed dragging items with hiddenDates

v3_develop
Alex de Mulder 10 years ago
parent
commit
f6a1a252ed
9 changed files with 4593 additions and 4476 deletions
  1. +4470
    -4413
      dist/vis.js
  2. +4
    -1
      examples/timeline/29_hiding_times.html
  3. +1
    -1
      examples/timeline/30_subgroups.html
  4. +47
    -14
      lib/timeline/DateUtil.js
  5. +0
    -1
      lib/timeline/Range.js
  6. +10
    -2
      lib/timeline/Stack.js
  7. +17
    -7
      lib/timeline/component/Group.js
  8. +21
    -21
      lib/timeline/component/ItemSet.js
  9. +23
    -16
      lib/timeline/component/item/BackgroundItem.js

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


+ 4
- 1
examples/timeline/29_hiding_times.html View File

@ -44,11 +44,14 @@
}, },
start: '2014-04-17', start: '2014-04-17',
end: '2014-05-01', end: '2014-05-01',
height: '200px'
height: '200px',
editable: true,
showCustomTime: true
}; };
// Create a Timeline // Create a Timeline
var timeline = new vis.Timeline(container, items, options); var timeline = new vis.Timeline(container, items, options);
timeline.setCustomTime("2014-04-18 13:00:00");
</script> </script>
</body> </body>
</html> </html>

+ 1
- 1
examples/timeline/30_subgroups.html View File

@ -50,7 +50,7 @@
{id: 'ab', content:'1',start: '2014-01-25', end: '2014-01-27', type: 'background', group:'bar', subgroup:0}, {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: '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: 1, content: '0', 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: '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: '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: 'bdab', content:'1',start: '2014-01-29', end: '2014-01-30', type: 'background', className: 'negative',group:'bar'},

+ 47
- 14
lib/timeline/DateUtil.js View File

@ -280,9 +280,8 @@ exports.toScreen = function(Core, time, width) {
time = hidden.startDate; time = hidden.startDate;
} }
var res = exports.correctTimeForDuration(Core.body.hiddenDates, Core.range, time);
var duration = res.duration;
time = res.time;
var duration = exports.getHiddenDuration(Core.body.hiddenDates, Core.range);
time = exports.getHiddenTimeBefore(Core.body.hiddenDates, Core.range, time);
var conversion = Core.range.conversion(width, duration); var conversion = Core.range.conversion(width, duration);
return (time.valueOf() - conversion.offset) * conversion.scale; return (time.valueOf() - conversion.offset) * conversion.scale;
@ -298,10 +297,13 @@ exports.toScreen = function(Core, time, width) {
* @returns {Date} * @returns {Date}
*/ */
exports.toTime = function(body, range, x, width) { exports.toTime = function(body, range, x, width) {
var duration = exports.getHiddenDuration(body.hiddenDates, range);
var conversion = range.conversion(width, duration);
var hiddenDuration = exports.getHiddenDuration(body.hiddenDates, range);
var totalDuration = range.end - range.start - hiddenDuration;
var partialDuration = totalDuration * x / width;
var accumulatedHiddenDuration = exports.getAccumulatedHiddenDuration(body.hiddenDates,range, partialDuration);
return new Date(x / conversion.scale + conversion.offset);
var newTime = new Date(accumulatedHiddenDuration + partialDuration + range.start);
return newTime;
}; };
@ -328,32 +330,63 @@ exports.getHiddenDuration = function(hiddenTimes, range) {
/** /**
* Support function * Support function
* @param hiddenTimes
* @param hiddenDates
* @param range * @param range
* @param time * @param time
* @returns {{duration: number, time: *, offset: number}} * @returns {{duration: number, time: *, offset: number}}
*/ */
exports.correctTimeForDuration = function(hiddenTimes, range, time) {
var duration = 0;
exports.getHiddenTimeBefore = function(hiddenDates, range, time) {
var timeOffset = 0; var timeOffset = 0;
time = moment(time).toDate().valueOf(); time = moment(time).toDate().valueOf();
for (var i = 0; i < hiddenTimes.length; i++) {
var startDate = hiddenTimes[i].start;
var endDate = hiddenTimes[i].end;
for (var i = 0; i < hiddenDates.length; i++) {
var startDate = hiddenDates[i].start;
var endDate = hiddenDates[i].end;
// if time after the cutout, and the // if time after the cutout, and the
if (startDate >= range.start && endDate < range.end) { if (startDate >= range.start && endDate < range.end) {
duration += (endDate - startDate);
if (time >= endDate) { if (time >= endDate) {
timeOffset += (endDate - startDate); timeOffset += (endDate - startDate);
} }
} }
} }
time -= timeOffset; time -= timeOffset;
return {duration: duration, time:time, offset: timeOffset};
return time;
};
/**
* Support function
* @param hiddenDates
* @param range
* @param time
* @returns {{duration: number, time: *, offset: number}}
*/
exports.getAccumulatedHiddenDuration = function(hiddenDates, range, requiredDuration) {
var hiddenDuration = 0;
var duration = 0;
var previousPoint = range.start;
//exports.printDates(hiddenDates)
for (var i = 0; i < hiddenDates.length; i++) {
var startDate = hiddenDates[i].start;
var endDate = hiddenDates[i].end;
// if time after the cutout, and the
if (startDate >= range.start && endDate < range.end) {
duration += startDate - previousPoint;
previousPoint = endDate;
if (duration >= requiredDuration) {
break;
}
else {
hiddenDuration += endDate - startDate;
}
}
}
return hiddenDuration;
}; };
/** /**
* used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true * used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true
* @param hiddenTimes * @param hiddenTimes

+ 0
- 1
lib/timeline/Range.js View File

@ -385,7 +385,6 @@ Range.prototype._onDrag = function (event) {
var duration = DateUtil.getHiddenDuration(this.body.hiddenDates, this); var duration = DateUtil.getHiddenDuration(this.body.hiddenDates, this);
interval -= duration; interval -= duration;
var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height; var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height;
var diffRange = -delta / width * interval; var diffRange = -delta / width * interval;
var newStart = this.props.touch.start + diffRange; var newStart = this.props.touch.start + diffRange;

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

@ -83,12 +83,20 @@ exports.stack = function(items, margin, force) {
* Margins between items and between items and the axis. * Margins between items and between items and the axis.
*/ */
exports.nostack = function(items, margin, subgroups) { exports.nostack = function(items, margin, subgroups) {
var i, iMax;
var i, iMax, newTop;
// reset top position of all items // reset top position of all items
for (i = 0, iMax = items.length; i < iMax; i++) { for (i = 0, iMax = items.length; i < iMax; i++) {
if (items[i].data.subgroup !== undefined) { if (items[i].data.subgroup !== undefined) {
items[i].top = margin.axis + (subgroups[items[i].data.subgroup].height + margin.item.vertical) * items[i].data.subgroup;
newTop = margin.axis;
for (var subgroupIdx in subgroups) {
if (subgroups.hasOwnProperty(subgroupIdx)) {
if (subgroups[subgroupIdx].visible == true && subgroupIdx < items[i].data.subgroup) {
newTop += subgroups[subgroupIdx].height + margin.item.vertical;
}
}
}
items[i].top = newTop;
} }
else { else {
items[i].top = margin.axis; items[i].top = margin.axis;

+ 17
- 7
lib/timeline/component/Group.js View File

@ -170,8 +170,9 @@ Group.prototype.redraw = function(range, margin, restack) {
// recalculate the height of the group // recalculate the height of the group
var height; var height;
var visibleItems = this.visibleItems; var visibleItems = this.visibleItems;
var visibleSubgroups = [];
this.visibleSubgroups = 0;
//var visibleSubgroups = [];
//this.visibleSubgroups = 0;
this.resetSubgroups();
var me = this; var me = this;
if (visibleItems.length) { if (visibleItems.length) {
var min = visibleItems[0].top; var min = visibleItems[0].top;
@ -181,10 +182,11 @@ Group.prototype.redraw = function(range, margin, restack) {
max = Math.max(max, (item.top + item.height)); max = Math.max(max, (item.top + item.height));
if (item.data.subgroup !== undefined) { if (item.data.subgroup !== undefined) {
me.subgroups[item.data.subgroup].height = Math.max(me.subgroups[item.data.subgroup].height,item.height); 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;
}
me.subgroups[item.data.subgroup].visible = true;
//if (visibleSubgroups.indexOf(item.data.subgroup) == -1){
// visibleSubgroups.push(item.data.subgroup);
// me.visibleSubgroups += 1;
//}
} }
}); });
if (min > margin.axis) { if (min > margin.axis) {
@ -284,7 +286,7 @@ Group.prototype.add = function(item) {
// add to // add to
if (item.data.subgroup !== undefined) { if (item.data.subgroup !== undefined) {
if (this.subgroups[item.data.subgroup] === undefined) { if (this.subgroups[item.data.subgroup] === undefined) {
this.subgroups[item.data.subgroup] = {height:0};
this.subgroups[item.data.subgroup] = {height:0, visible: false};
} }
} }
@ -294,6 +296,14 @@ Group.prototype.add = function(item) {
} }
}; };
Group.prototype.resetSubgroups = function() {
for (var subgroup in this.subgroups) {
if (this.subgroups.hasOwnProperty(subgroup)) {
this.subgroups[subgroup].visible = false;
}
}
}
/** /**
* Remove an item from the group * Remove an item from the group
* @param {Item} item * @param {Item} item

+ 21
- 21
lib/timeline/component/ItemSet.js View File

@ -8,6 +8,7 @@ var BoxItem = require('./item/BoxItem');
var PointItem = require('./item/PointItem'); var PointItem = require('./item/PointItem');
var RangeItem = require('./item/RangeItem'); var RangeItem = require('./item/RangeItem');
var BackgroundItem = require('./item/BackgroundItem'); var BackgroundItem = require('./item/BackgroundItem');
var DateUtil = require('../DateUtil');
var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
@ -1036,18 +1037,17 @@ ItemSet.prototype._onDragStart = function (event) {
return; return;
} }
var item = this.touchParams.item || null,
me = this,
props;
var item = this.touchParams.item || null;
var me = this;
var props = {};
props.initialX = event.gesture.center.clientX;
if (item && item.selected) { if (item && item.selected) {
var dragLeftItem = event.target.dragLeftItem; var dragLeftItem = event.target.dragLeftItem;
var dragRightItem = event.target.dragRightItem; var dragRightItem = event.target.dragRightItem;
if (dragLeftItem) { if (dragLeftItem) {
props = {
item: dragLeftItem
};
props.item = dragLeftItem;
if (me.options.editable.updateTime) { if (me.options.editable.updateTime) {
props.start = item.data.start.valueOf(); props.start = item.data.start.valueOf();
@ -1059,9 +1059,7 @@ ItemSet.prototype._onDragStart = function (event) {
this.touchParams.itemProps = [props]; this.touchParams.itemProps = [props];
} }
else if (dragRightItem) { else if (dragRightItem) {
props = {
item: dragRightItem
};
props.item = dragRightItem;
if (me.options.editable.updateTime) { if (me.options.editable.updateTime) {
props.end = item.data.end.valueOf(); props.end = item.data.end.valueOf();
@ -1075,9 +1073,7 @@ ItemSet.prototype._onDragStart = function (event) {
else { else {
this.touchParams.itemProps = this.getSelection().map(function (id) { this.touchParams.itemProps = this.getSelection().map(function (id) {
var item = me.items[id]; var item = me.items[id];
var props = {
item: item
};
props.item = item;
if (me.options.editable.updateTime) { if (me.options.editable.updateTime) {
if ('start' in item.data) props.start = item.data.start.valueOf(); if ('start' in item.data) props.start = item.data.start.valueOf();
@ -1103,23 +1099,27 @@ ItemSet.prototype._onDragStart = function (event) {
ItemSet.prototype._onDrag = function (event) { ItemSet.prototype._onDrag = function (event) {
if (this.touchParams.itemProps) { if (this.touchParams.itemProps) {
var me = this; var me = this;
var range = this.body.range;
var snap = this.body.util.snap || null; var snap = this.body.util.snap || null;
var deltaX = event.gesture.deltaX;
var scale = (this.props.width / (range.end - range.start));
var offset = deltaX / scale;
// move // move
this.touchParams.itemProps.forEach(function (props) { this.touchParams.itemProps.forEach(function (props) {
var newProps = {}; var newProps = {};
if ('start' in props) {
var start = new Date(props.start + offset);
if ('start' in props && !('end' in props)) { // only start in props
var start = me.body.util.toTime(event.gesture.center.clientX)
newProps.start = snap ? snap(start) : start; newProps.start = snap ? snap(start) : start;
} }
if ('end' in props) {
else if ('start' in props) { // start and end in props
var current = me.body.util.toTime(event.gesture.center.clientX);
var initial = me.body.util.toTime(props.initialX);
var offset = current - initial;
var start = new Date(props.start + offset);
var end = new Date(props.end + offset); var end = new Date(props.end + offset);
newProps.start = snap ? snap(start) : start;
newProps.end = snap ? snap(end) : end;
}
else if ('end' in props) { // only end in props
var end = me.body.util.toTime(event.gesture.center.clientX);
newProps.end = snap ? snap(end) : end; newProps.end = snap ? snap(end) : end;
} }

+ 23
- 16
lib/timeline/component/item/BackgroundItem.js View File

@ -146,14 +146,20 @@ BackgroundItem.prototype.repositionY = function(margin) {
// special positioning for subgroups // special positioning for subgroups
if (this.data.subgroup !== undefined) { if (this.data.subgroup !== undefined) {
var subgroup = this.data.subgroup; var subgroup = this.data.subgroup;
height = this.parent.subgroups[subgroup].height + margin.item.vertical;
var subgroups = this.parent.subgroups;
// if the orientation is top, we need to take the difference in height into account. // if the orientation is top, we need to take the difference in height into account.
if (onTop == true) { if (onTop == true) {
// the first subgroup will have to account for the distance from the top to the first item. // the first subgroup will have to account for the distance from the top to the first item.
height = this.parent.subgroups[subgroup].height + margin.item.vertical;
height += subgroup == 0 ? margin.axis - 0.5*margin.item.vertical : 0; height += subgroup == 0 ? margin.axis - 0.5*margin.item.vertical : 0;
var newTop = this.parent.top + (subgroup) * height;
var newTop = this.parent.top;
for (var subgroupIdx in subgroups) {
if (subgroups.hasOwnProperty(subgroupIdx)) {
if (subgroups[subgroupIdx].visible == true && subgroupIdx < subgroup) {
newTop += subgroups[subgroupIdx].height + margin.item.vertical;
}
}
}
// the others will have to be offset downwards with this same distance. // the others will have to be offset downwards with this same distance.
newTop += subgroup != 0 ? margin.axis - 0.5 * margin.item.vertical : 0; newTop += subgroup != 0 ? margin.axis - 0.5 * margin.item.vertical : 0;
@ -162,8 +168,16 @@ BackgroundItem.prototype.repositionY = function(margin) {
} }
// and when the orientation is bottom: // and when the orientation is bottom:
else { else {
var amountvisibleSubgroups = this.parent.visibleSubgroups - 1;
this.dom.box.style.top = (amountvisibleSubgroups - subgroup) * height + this.parent.top + 'px';
var newTop = this.parent.top;
for (var subgroupIdx in subgroups) {
if (subgroups.hasOwnProperty(subgroupIdx)) {
if (subgroups[subgroupIdx].visible == true && subgroupIdx > subgroup) {
newTop += subgroups[subgroupIdx].height + margin.item.vertical;
}
}
}
height = this.parent.subgroups[subgroup].height + margin.item.vertical;
this.dom.box.style.top = newTop + 'px';
this.dom.box.style.bottom = ''; this.dom.box.style.bottom = '';
} }
} }
@ -172,16 +186,9 @@ BackgroundItem.prototype.repositionY = function(margin) {
// we want backgrounds with groups to only show in groups. // we want backgrounds with groups to only show in groups.
if (this.data.group !== undefined) { if (this.data.group !== undefined) {
height = this.parent.height; 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 = '';
}
// same alignment for items when orientation is top or bottom
this.dom.box.style.top = this.parent.top + 'px';
this.dom.box.style.bottom = '';
} }
else { else {
// if the item is not in a group: // if the item is not in a group:

Loading…
Cancel
Save