Browse Source

Merge remote-tracking branch 'origin/develop' into develop

Conflicts:
	dist/vis.js
flowchartTest
Alex de Mulder 9 years ago
parent
commit
23c6db6503
11 changed files with 207 additions and 72 deletions
  1. +8
    -4
      HISTORY.md
  2. +1
    -1
      dist/vis.map
  3. +18
    -18
      dist/vis.min.js
  4. +6
    -0
      docs/timeline/index.html
  5. +15
    -10
      lib/timeline/Core.js
  6. +1
    -1
      lib/timeline/Graph2d.js
  7. +101
    -31
      lib/timeline/Timeline.js
  8. +16
    -0
      lib/timeline/component/item/BoxItem.js
  9. +16
    -0
      lib/timeline/component/item/Item.js
  10. +21
    -3
      lib/timeline/component/item/PointItem.js
  11. +4
    -4
      test/timeline.html

+ 8
- 4
HISTORY.md View File

@ -1,7 +1,11 @@
# vis.js history # vis.js history
http://visjs.org http://visjs.org
## UNREALEASED, version 4.1.1
## not-yet-released, version 4.1.1-SNAPSHOT
### Timeline
- Improved function `fit()` to take into account the actual width of items.
### Graph2D ### Graph2D
@ -22,14 +26,14 @@ http://visjs.org
- Fixed #859, images now resize again when they are loaded. - Fixed #859, images now resize again when they are loaded.
- Fixed dynamic edges not correctly handling non-existent nodes. - Fixed dynamic edges not correctly handling non-existent nodes.
- Accepted pull from @killerDJO for fixing selected and hover colors for edges. - Accepted pull from @killerDJO for fixing selected and hover colors for edges.
- Fixed bug with rightmouse button, scroll center and popup positions using the wrong coordinates.
- Fixed bug with right mouse button, scroll center and popup positions using the wrong coordinates.
- Fixed click to use. - Fixed click to use.
- Fixed getConnectedEdges method. - Fixed getConnectedEdges method.
- Fixed clustering bug. - Fixed clustering bug.
- Added getNodesInCluster method. - Added getNodesInCluster method.
- Renamed editNodeMode to editNode, editNodeMode now give a deprication log message.
- Renamed editNodeMode to editNode, editNodeMode now give a deprecation log message.
- Added multiselect to the docs. - Added multiselect to the docs.
- Removed depricated dynamic entree, allow any smooth curve style for hierarchical layout.
- Removed deprecated dynamic entree, allow any smooth curve style for hierarchical layout.
- Fixed bug with the moveTo and getViewPosition methods. - Fixed bug with the moveTo and getViewPosition methods.
- Fixed #861, brokenImage only working for one node if nodes have the same image. - Fixed #861, brokenImage only working for one node if nodes have the same image.
- Fixed hoverNode and blurNode events and added them to the docs. - Fixed hoverNode and blurNode events and added them to the docs.

+ 1
- 1
dist/vis.map
File diff suppressed because it is too large
View File


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


+ 6
- 0
docs/timeline/index.html View File

@ -1001,6 +1001,12 @@ function (option, path) {
<li><code>what</code> (String or null): name of the clicked thing: <code>item</code>, <code>background</code>, <code>axis</code>, <code>group-label</code>, <code>custom-time</code>, or <code>current-time</code>.</li> <li><code>what</code> (String or null): name of the clicked thing: <code>item</code>, <code>background</code>, <code>axis</code>, <code>group-label</code>, <code>custom-time</code>, or <code>current-time</code>.</li>
<li><code>event</code> (Object): the original click event.</li> <li><code>event</code> (Object): the original click event.</li>
</ul> </ul>
Example usage:
<pre class="prettyprint lang-js">
document.getElementById('myTimeline').onclick = function (event) {
var props = timeline.getEventProperties(event)
console.log(props);
}</pre>
</td> </td>
</tr> </tr>

+ 15
- 10
lib/timeline/Core.js View File

@ -457,27 +457,32 @@ Core.prototype.getVisibleItems = function() {
* function is 'easeInOutQuad'. * function is 'easeInOutQuad'.
*/ */
Core.prototype.fit = function(options) { Core.prototype.fit = function(options) {
var range = this._getDataRange();
var range = this.getDataRange();
// skip range set if there is no start and end date // skip range set if there is no start and end date
if (range.start === null && range.end === null) { if (range.start === null && range.end === null) {
return; return;
} }
// apply a margin of 1% left and right of the data
var interval = range.max - range.min;
var min = new Date(range.min.valueOf() - interval * 0.01);
var max = new Date(range.max.valueOf() + interval * 0.01);
var animation = (options && options.animation !== undefined) ? options.animation : true; var animation = (options && options.animation !== undefined) ? options.animation : true;
this.range.setRange(range.start, range.end, animation);
this.range.setRange(min, max, animation);
}; };
/** /**
* Calculate the data range of the items and applies a 5% window around it.
* @returns {{start: Date | null, end: Date | null}}
* Calculate the data range of the items start and end dates
* @returns {{min: Date | null, max: Date | null}}
* @protected * @protected
*/ */
Core.prototype._getDataRange = function() {
Core.prototype.getDataRange = function() {
// apply the data range as range // apply the data range as range
var dataRange = this.getItemRange(); var dataRange = this.getItemRange();
// add 5% space on both sides
// add 1% space on both sides
var start = dataRange.min; var start = dataRange.min;
var end = dataRange.max; var end = dataRange.max;
if (start != null && end != null) { if (start != null && end != null) {
@ -486,13 +491,13 @@ Core.prototype._getDataRange = function() {
// prevent an empty interval // prevent an empty interval
interval = 24 * 60 * 60 * 1000; // 1 day interval = 24 * 60 * 60 * 1000; // 1 day
} }
start = new Date(start.valueOf() - interval * 0.05);
end = new Date(end.valueOf() + interval * 0.05);
start = new Date(start.valueOf() - interval * 0.01);
end = new Date(end.valueOf() + interval * 0.01);
} }
return { return {
start: start,
end: end
start: null,
end: null
} }
}; };

+ 1
- 1
lib/timeline/Graph2d.js View File

@ -242,7 +242,7 @@ Graph2d.prototype.isGroupVisible = function(groupId) {
* When no minimum is found, min==null * When no minimum is found, min==null
* When no maximum is found, max==null * When no maximum is found, max==null
*/ */
Graph2d.prototype.getItemRange = function() {
Graph2d.prototype.getDataRange = function() {
var min = null; var min = null;
var max = null; var max = null;

+ 101
- 31
lib/timeline/Timeline.js View File

@ -209,11 +209,11 @@ Timeline.prototype.setItems = function(items) {
if (initialLoad) { if (initialLoad) {
if (this.options.start != undefined || this.options.end != undefined) { if (this.options.start != undefined || this.options.end != undefined) {
if (this.options.start == undefined || this.options.end == undefined) { if (this.options.start == undefined || this.options.end == undefined) {
var dataRange = this._getDataRange();
var range = this.getItemRange();
} }
var start = this.options.start != undefined ? this.options.start : dataRange.start;
var end = this.options.end != undefined ? this.options.end : dataRange.end;
var start = this.options.start != undefined ? this.options.start : range.min;
var end = this.options.end != undefined ? this.options.end : range.max;
this.setWindow(start, end, {animation: false}); this.setWindow(start, end, {animation: false});
} }
@ -344,44 +344,114 @@ Timeline.prototype.focus = function(id, options) {
}; };
/** /**
* Get the data range of the item set.
* @returns {{min: Date, max: Date}} range A range with a start and end Date.
* When no minimum is found, min==null
* When no maximum is found, max==null
* Set Timeline window such that it fits all items
* @param {Object} [options] Available options:
* `animation: boolean | {duration: number, easingFunction: string}`
* If true (default), the range is animated
* smoothly to the new window. An object can be
* provided to specify duration and easing function.
* Default duration is 500 ms, and default easing
* function is 'easeInOutQuad'.
*/ */
Timeline.prototype.getItemRange = function() {
// calculate min from start filed
var dataset = this.itemsData && this.itemsData.getDataSet();
Timeline.prototype.fit = function (options) {
var animation = (options && options.animation !== undefined) ? options.animation : true;
var range = this.getItemRange();
this.range.setRange(range.min, range.max, animation);
};
/**
* Determine the range of the items, taking into account their actual width
* and a margin of 10 pixels on both sides.
* @return {{min: Date | null, max: Date | null}}
*/
Timeline.prototype.getItemRange = function () {
// get a rough approximation for the range based on the items start and end dates
var range = this.getDataRange();
var min = range.min;
var max = range.max;
var minItem = null;
var maxItem = null;
if (min != null && max != null) {
var interval = (max - min); // ms
if (interval <= 0) {
interval = 10;
}
var factor = interval / this.props.center.width;
function getStart(item) {
return util.convert(item.data.start, 'Date').valueOf()
}
function getEnd(item) {
var end = item.data.end != undefined ? item.data.end : item.data.start;
return util.convert(end, 'Date').valueOf();
}
// calculate the date of the left side and right side of the items given
util.forEach(this.itemSet.items, function (item) {
item.show();
var start = getStart(item);
var end = getEnd(item);
var left = new Date(start - (item.getWidthLeft() + 10) * factor);
var right = new Date(end + (item.getWidthRight() + 10) * factor);
if (left < min) {
min = left;
minItem = item;
}
if (right > max) {
max = right;
maxItem = item;
}
}.bind(this));
if (minItem && maxItem) {
var lhs = minItem.getWidthLeft() + 10;
var rhs = maxItem.getWidthRight() + 10;
var delta = this.props.center.width - lhs - rhs; // px
if (delta > 0) {
min = getStart(minItem) - lhs * interval / delta; // ms
max = getEnd(maxItem) + rhs * interval / delta; // ms
}
}
}
return {
min: min != null ? new Date(min) : null,
max: max != null ? new Date(max) : null
}
};
/**
* Calculate the data range of the items start and end dates
* @returns {{min: Date | null, max: Date | null}}
*/
Timeline.prototype.getDataRange = function() {
var min = null; var min = null;
var max = null; var max = null;
var dataset = this.itemsData && this.itemsData.getDataSet();
if (dataset) { if (dataset) {
// calculate the minimum value of the field 'start'
var minItem = dataset.min('start');
min = minItem ? util.convert(minItem.start, 'Date').valueOf() : null;
// Note: we convert first to Date and then to number because else
// a conversion from ISODate to Number will fail
// calculate maximum value of fields 'start' and 'end'
var maxStartItem = dataset.max('start');
if (maxStartItem) {
max = util.convert(maxStartItem.start, 'Date').valueOf();
}
var maxEndItem = dataset.max('end');
if (maxEndItem) {
if (max == null) {
max = util.convert(maxEndItem.end, 'Date').valueOf();
dataset.forEach(function (item) {
var start = util.convert(item.start, 'Date').valueOf();
var end = util.convert(item.end != undefined ? item.end : item.start, 'Date').valueOf();
if (min === null || start < min) {
min = start;
} }
else {
max = Math.max(max, util.convert(maxEndItem.end, 'Date').valueOf());
if (max === null || end > max) {
max = start;
} }
}
});
} }
return { return {
min: (min != null) ? new Date(min) : null,
max: (max != null) ? new Date(max) : null
};
min: min != null ? new Date(min) : null,
max: max != null ? new Date(max) : null
}
}; };
/** /**

+ 16
- 0
lib/timeline/component/item/BoxItem.js View File

@ -215,4 +215,20 @@ BoxItem.prototype.repositionY = function() {
dot.style.top = (-this.props.dot.height / 2) + 'px'; dot.style.top = (-this.props.dot.height / 2) + 'px';
}; };
/**
* Return the width of the item left from its start date
* @return {number}
*/
BoxItem.prototype.getWidthLeft = function () {
return this.width / 2;
};
/**
* Return the width of the item right from its start date
* @return {number}
*/
BoxItem.prototype.getWidthRight = function () {
return this.width / 2;
};
module.exports = BoxItem; module.exports = BoxItem;

+ 16
- 0
lib/timeline/component/item/Item.js View File

@ -273,4 +273,20 @@ Item.prototype._contentToString = function (content) {
return content; return content;
}; };
/**
* Return the width of the item left from its start date
* @return {number}
*/
Item.prototype.getWidthLeft = function () {
return 0;
};
/**
* Return the width of the item right from the max of its start and end date
* @return {number}
*/
Item.prototype.getWidthRight = function () {
return 0;
};
module.exports = Item; module.exports = Item;

+ 21
- 3
lib/timeline/component/item/PointItem.js View File

@ -105,9 +105,7 @@ PointItem.prototype.redraw = function() {
dom.point.className = 'vis-item vis-point' + className; dom.point.className = 'vis-item vis-point' + className;
dom.dot.className = 'vis-item vis-dot' + className; dom.dot.className = 'vis-item vis-dot' + className;
// recalculate size
this.width = dom.point.offsetWidth;
this.height = dom.point.offsetHeight;
// recalculate size of dot and contents
this.props.dot.width = dom.dot.offsetWidth; this.props.dot.width = dom.dot.offsetWidth;
this.props.dot.height = dom.dot.offsetHeight; this.props.dot.height = dom.dot.offsetHeight;
this.props.content.height = dom.content.offsetHeight; this.props.content.height = dom.content.offsetHeight;
@ -119,6 +117,10 @@ PointItem.prototype.redraw = function() {
dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px';
dom.dot.style.left = (this.props.dot.width / 2) + 'px'; dom.dot.style.left = (this.props.dot.width / 2) + 'px';
// recalculate size
this.width = dom.point.offsetWidth;
this.height = dom.point.offsetHeight;
this.dirty = false; this.dirty = false;
} }
@ -177,4 +179,20 @@ PointItem.prototype.repositionY = function() {
} }
}; };
/**
* Return the width of the item left from its start date
* @return {number}
*/
PointItem.prototype.getWidthLeft = function () {
return this.props.dot.width;
};
/**
* Return the width of the item right from its start date
* @return {number}
*/
PointItem.prototype.getWidthRight = function () {
return this.width - this.props.dot.width;
};
module.exports = PointItem; module.exports = PointItem;

+ 4
- 4
test/timeline.html View File

@ -137,7 +137,7 @@
title: 'hello title!' title: 'hello title!'
}, },
{_id: 5, content: 'item 5', start: now.clone().add(9, 'days').toDate(), type:'point', title: 'hello title!', className: 'special'}, {_id: 5, content: 'item 5', start: now.clone().add(9, 'days').toDate(), type:'point', title: 'hello title!', className: 'special'},
{_id: 6, content: 'item 6', start: now.clone().add(11, 'days').toDate()}
{_id: 6, content: 'item 6 very long test bla bla bla', start: now.clone().add(11, 'days').toDate()}
]); ]);
var container = document.getElementById('visualization'); var container = document.getElementById('visualization');
@ -147,8 +147,8 @@
editable: true, editable: true,
//orientation: 'top', //orientation: 'top',
orientation: 'both', orientation: 'both',
start: now.clone().add(-7, 'days'),
end: now.clone().add(7, 'days'),
// start: now.clone().add(-7, 'days'),
// end: now.clone().add(7, 'days'),
//maxHeight: 200, //maxHeight: 200,
//height: 200, //height: 200,
showCurrentTime: true, showCurrentTime: true,
@ -170,7 +170,7 @@
//min: moment('2013-01-01'), //min: moment('2013-01-01'),
//max: moment('2013-12-31'), //max: moment('2013-12-31'),
//zoomMin: 1000 * 60 * 60 * 24, // 1 day //zoomMin: 1000 * 60 * 60 * 24, // 1 day
zoomMax: 1000 * 60 * 60 * 24 * 30 * 6 // 6 months
// zoomMax: 1000 * 60 * 60 * 24 * 30 * 6 // 6 months
}; };
console.timeEnd('create dataset'); console.timeEnd('create dataset');

Loading…
Cancel
Save