Skip to content
This repository has been archived by the owner on Jul 29, 2019. It is now read-only.

[Timeline] Added followMouse & overflowMethod to tooltip options #2544

Merged
merged 1 commit into from
Jan 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,30 @@ <h2 id="Configuration_Options">Configuration Options</h2>
</td>
</tr>

<tr class='toggle collapsible' onclick="toggleTable('optionTable','tooltip', this);">
<td><span parent="tooltip" class="right-caret"></span> tooltip</td>
<td>Object</td>
<td><code>Object</code></td>
<td>Specify how the tooltip is positioned.</td>
</tr>
<tr parent="tooltip" class="hidden">
<td class="indent">tooltip.followMouse</td>
<td>boolean</td>
<td><code>false</code></td>
<td>If true, tooltips will follow the mouse as they move around in the item.</td>
</tr>

<tr parent="tooltip" class="hidden">
<td class="indent">tooltip.overflowMethod</td>
<td>String</td>
<td><code>'flip'</code></td>
<td>
Set how the tooltip should act if it is about to overflow out of the timeline.<br />
Choose from <code>'cap'</code> and <code>'flip'</code>. <br />
If it is set to <code>'cap'</code>, the tooltip will just cap its position to inside to timeline. <br />
While if it is set to <code>'flip'</code>, the position of the tooltip will flip around the cursor so that a corner is at the cursor, and the rest of it is visible. <br />
</tr>

<tr class='toggle collapsible' onclick="toggleTable('optionTable','tooltipOnItemUpdateTime', this);">
<td><span parent="tooltipOnItemUpdateTime" class="right-caret"></span> tooltipOnItemUpdateTime</td>
<td>Object/Boolean</td>
Expand Down
35 changes: 35 additions & 0 deletions examples/timeline/items/tooltip.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ <h1>Tooltips</h1>

<div id="tooltips"></div>

<p>
The example below has the tooltip follow the mouse.
</p>

<div id="tooltips-follow"></div>

<p>
The example below has the tooltip overflow set to 'cap'. Compare this to the one above,
to see how they differ. For the best results, move the cursor to the top right,
where the tool-tip is going to overflow out of the timeline.
</p>

<div id="tooltips-cap"></div>

<script type="text/javascript">
// Create a DataSet (allows two way data-binding)
var items = new vis.DataSet([
Expand All @@ -43,6 +57,27 @@ <h1>Tooltips</h1>
var timelineTooltips = new vis.Timeline(document.getElementById('tooltips'),
items, options
);

// Follow options
var follow_options = {
tooltip: {
followMouse: true
}
};

var timelineFollow = new vis.Timeline(document.getElementById('tooltips-follow'),
items, follow_options);

// Cap options
var cap_options = {
tooltip: {
followMouse: true,
overflowMethod: 'cap'
}
}

var timelineCap = new vis.Timeline(document.getElementById('tooltips-cap'),
items, cap_options);
</script>

</body>
Expand Down
63 changes: 43 additions & 20 deletions lib/shared/Popup.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
/**
* Popup is a class to create a popup window with some text
* @param {Element} container The container object.
* @param {Number} [x]
* @param {Number} [y]
* @param {String} [text]
* @param {Object} [style] An object containing borderColor,
* backgroundColor, etc.
* @param {Element} container The container object.
* @param {string} overflowMethod How the popup should act to overflowing ('flip' or 'cap')
*/
class Popup {
constructor(container) {
constructor(container, overflowMethod) {
this.container = container;
this.overflowMethod = overflowMethod || 'cap';

this.x = 0;
this.y = 0;
Expand Down Expand Up @@ -60,20 +57,46 @@ class Popup {
var maxHeight = this.frame.parentNode.clientHeight;
var maxWidth = this.frame.parentNode.clientWidth;

var top = (this.y - height);
if (top + height + this.padding > maxHeight) {
top = maxHeight - height - this.padding;
}
if (top < this.padding) {
top = this.padding;
}
var left = 0, top = 0;

var left = this.x;
if (left + width + this.padding > maxWidth) {
left = maxWidth - width - this.padding;
}
if (left < this.padding) {
left = this.padding;
if (this.overflowMethod == 'flip') {
var isLeft = false, isTop = true; // Where around the position it's located

if (this.y - height < this.padding) {
isTop = false;
}

if (this.x + width > maxWidth - this.padding) {
isLeft = true;
}

if (isLeft) {
left = this.x - width;
} else {
left = this.x;
}

if (isTop) {
top = this.y - height;
} else {
top = this.y;
}
} else {
top = (this.y - height);
if (top + height + this.padding > maxHeight) {
top = maxHeight - height - this.padding;
}
if (top < this.padding) {
top = this.padding;
}

left = this.x;
if (left + width + this.padding > maxWidth) {
left = maxWidth - width - this.padding;
}
if (left < this.padding) {
left = this.padding;
}
}

this.frame.style.left = left + "px";
Expand Down
31 changes: 27 additions & 4 deletions lib/timeline/component/ItemSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ function ItemSet(body, options) {
axis: 20
},

tooltip: {
followMouse: false,
overflowMethod: 'flip'
},

tooltipOnItemUpdateTime: false
};

Expand Down Expand Up @@ -250,6 +255,7 @@ ItemSet.prototype._create = function(){

this.body.dom.centerContainer.addEventListener('mouseover', this._onMouseOver.bind(this));
this.body.dom.centerContainer.addEventListener('mouseout', this._onMouseOut.bind(this));
this.body.dom.centerContainer.addEventListener('mousemove', this._onMouseMove.bind(this));

// attach to the DOM
this.show();
Expand Down Expand Up @@ -325,7 +331,7 @@ ItemSet.prototype.setOptions = function(options) {
var fields = [
'type', 'rtl', 'align', 'order', 'stack', 'stackSubgroups', 'selectable', 'multiselect', 'itemsAlwaysDraggable',
'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'visibleFrameTemplate',
'hide', 'snap', 'groupOrderSwap', 'tooltipOnItemUpdateTime'
'hide', 'snap', 'groupOrderSwap', 'tooltip', 'tooltipOnItemUpdateTime'
];
util.selectiveExtend(fields, this.options, options);

Expand Down Expand Up @@ -1884,13 +1890,13 @@ ItemSet.prototype._onMouseOver = function (event) {

if (item.getTitle()) {
if (item.popup == null) {
item.setPopup(new Popup(this.body.dom.root));
item.setPopup(new Popup(this.body.dom.root, this.options.tooltip.overflowMethod || 'flip'));
}

var container = this.body.dom.centerContainer;
item.popup.setPosition(
event.clientX - util.getAbsoluteLeft(container),
event.clientY - util.getAbsoluteTop(container)
event.clientX - util.getAbsoluteLeft(container) + container.offsetLeft,
event.clientY - util.getAbsoluteTop(container) + container.offsetTop
);
item.popup.show();
}
Expand Down Expand Up @@ -1920,6 +1926,23 @@ ItemSet.prototype._onMouseOut = function (event) {
event: util.elementsCensor(event)
});
};
ItemSet.prototype._onMouseMove = function (event) {
var item = this.itemFromTarget(event);
if (!item) return;

if (this.options.tooltip.followMouse) {
if (item.popup) {
if (!item.popup.hidden) {
var container = this.body.dom.centerContainer;
item.popup.setPosition(
event.clientX - util.getAbsoluteLeft(container) + container.offsetLeft,
event.clientY - util.getAbsoluteTop(container) + container.offsetTop
);
item.popup.show(); // Redraw
}
}
}
};


/**
Expand Down
9 changes: 9 additions & 0 deletions lib/timeline/optionsTimeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ let allOptions = {
template: {'function': 'function'},
groupTemplate: {'function': 'function'},
visibleFrameTemplate: {string, 'function': 'function'},
tooltip: {
followMouse: { 'boolean': bool },
overflowMethod: { 'string': ['cap', 'flip'] },
__type__: {object}
},
tooltipOnItemUpdateTime: {
template: {'function': 'function'},
__type__: { 'boolean': bool, object}
Expand Down Expand Up @@ -230,6 +235,10 @@ let configureOptions = {
// scale: ['millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'],
// step: [1, 1, 10, 1]
//},
tooltip: {
followMouse: false,
overflowMethod: 'flip'
},
tooltipOnItemUpdateTime: false,
type: ['box', 'point', 'range', 'background'],
width: '100%',
Expand Down