Created more robust tooltip solution. Tooltips render inside the SVG's parent DIV.

They can be positioned, even if there are relative positioned elements above it.
master
Robin Hu 11 years ago
parent 8dea03da44
commit 3a75b583ca

@ -336,7 +336,7 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) {
, snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
, fixedTop = null //If not null, this fixes the top position of the tooltip.
, classes = null //Attaches additional CSS classes to the tooltip DIV that is created.
, chartContainer = null //SVG Container that holds the chart.
, chartContainer = null //Parent DIV, of the SVG Container that holds the chart.
, position = {left: null, top: null} //Relative position of the tooltip inside chartContainer.
, enabled = true //True -> tooltips are rendered. False -> don't render tooltips.
;
@ -393,26 +393,24 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) {
//Creates new tooltip container, or uses existing one on DOM.
function getTooltipContainer(newContent) {
var container = document.getElementsByClassName("nvtooltip");
if (container.length === 0) {
var body;
if (chartContainer)
body = d3.select(chartContainer);
else
body = d3.select("body");
var container = body.select(".nvtooltip");
if (container.node() === null) {
//Create new tooltip div if it doesn't exist on DOM.
container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
var body;
if (chartContainer)
body = chartContainer;
else
body = document.getElementsByTagName('body')[0];
body.appendChild(container);
}
else {
//Element already exists on DOM, so reuse it.
container = container[0];
container = body.append("div")
.attr("class", "nvtooltip " + (classes? classes: "xy-tooltip"))
;
}
container.innerHTML = newContent;
return container;
container.node().innerHTML = newContent;
container.style("top",0).style("left",0);
return container.node();
}
@ -426,23 +424,27 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) {
var left = position.left;
var top = (fixedTop != null) ? fixedTop : position.top;
var container = getTooltipContainer(contentGenerator(data));
if (chartContainer) {
var svgComp = chartContainer.getElementsByTagName("svg")[0];
var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect();
left += boundRect.left + window.pageXOffset;
top += boundRect.top + window.pageYOffset;
var svgOffset = {left:0,top:0};
if (svgComp) {
var svgBound = svgComp.getBoundingClientRect();
var chartBound = chartContainer.getBoundingClientRect();
svgOffset.top = Math.abs(svgBound.top - chartBound.top);
svgOffset.left = Math.abs(svgBound.left - chartBound.left);
}
left += chartContainer.offsetLeft + svgOffset.left;
top += chartContainer.offsetTop + svgOffset.top;
}
if (snapDistance && snapDistance > 0) {
top = Math.floor(top/snapDistance) * snapDistance;
}
var container = getTooltipContainer(contentGenerator(data));
nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container, true);
nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container, false);
return nvtooltip;
};

12
nv.d3.min.js vendored

File diff suppressed because one or more lines are too long

@ -39,7 +39,7 @@
, snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
, fixedTop = null //If not null, this fixes the top position of the tooltip.
, classes = null //Attaches additional CSS classes to the tooltip DIV that is created.
, chartContainer = null //SVG Container that holds the chart.
, chartContainer = null //Parent DIV, of the SVG Container that holds the chart.
, position = {left: null, top: null} //Relative position of the tooltip inside chartContainer.
, enabled = true //True -> tooltips are rendered. False -> don't render tooltips.
;
@ -96,24 +96,24 @@
//Creates new tooltip container, or uses existing one on DOM.
function getTooltipContainer(newContent) {
var container = d3.select(".nvtooltip");
if (container.node() === null) {
var body;
if (chartContainer)
body = d3.select(chartContainer);
else
body = d3.select("body");
var body;
if (chartContainer)
body = d3.select(chartContainer);
else
body = d3.select("body");
var container = body.select(".nvtooltip");
if (container.node() === null) {
//Create new tooltip div if it doesn't exist on DOM.
container = body.append("div").attr("class", "nvtooltip " + (classes? classes: "xy-tooltip"));
}
else {
//Element already exists on DOM, so reuse it.
container = container.node();
container = body.append("div")
.attr("class", "nvtooltip " + (classes? classes: "xy-tooltip"))
;
}
container.innerHTML = newContent;
return container;
container.node().innerHTML = newContent;
container.style("top",0).style("left",0);
return container.node();
}
@ -127,23 +127,27 @@
var left = position.left;
var top = (fixedTop != null) ? fixedTop : position.top;
var container = getTooltipContainer(contentGenerator(data));
if (chartContainer) {
var svgComp = chartContainer.getElementsByTagName("svg")[0];
var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect();
left += boundRect.left + window.pageXOffset;
top += boundRect.top + window.pageYOffset;
var svgOffset = {left:0,top:0};
if (svgComp) {
var svgBound = svgComp.getBoundingClientRect();
var chartBound = chartContainer.getBoundingClientRect();
svgOffset.top = Math.abs(svgBound.top - chartBound.top);
svgOffset.left = Math.abs(svgBound.left - chartBound.left);
}
left += chartContainer.offsetLeft + svgOffset.left;
top += chartContainer.offsetTop + svgOffset.top;
}
if (snapDistance && snapDistance > 0) {
top = Math.floor(top/snapDistance) * snapDistance;
}
var container = getTooltipContainer(contentGenerator(data));
nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container, true);
nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container, false);
return nvtooltip;
};

@ -6,68 +6,70 @@
<body>
<h3>Line chart test cases - feel free to add more tests</h3>
<div class='navigation'>
Tests:
<a href="lineChartTest.html">Line Chart</a>
<a href="stackedAreaChartTest.html">Stacked Area</a>
<a href="../examples/cumulativeLineChart.html">Cumulative Line</a>
<a href="interactiveBisectTest.html">nv.interactiveBisect unit tests</a>
</div>
<div class='chart full' id='chart1'>
Example of chart with many series', and new interactive guideline plus tooltip.
<svg></svg>
</div>
<div class='chart half' id='chart2'>
Chart with old tooltip style.
<svg></svg>
</div>
<div class='chart half' id='chart3'>
Chart with three data points.
<svg></svg>
</div>
<div class='chart third' id='chart4'>
Chart where two series have different number of points.
<svg></svg>
</div>
<div class='chart third' id='chart5'>
Chart with one point.
<svg></svg>
</div>
<div class='chart third' id='chart6'>
Chart with 1000 points.
<svg></svg>
</div>
<div class='chart third' id='chart7'>
Chart with no data.
<svg></svg>
</div>
<div class='chart third' id='chart8'>
All points random. No order.
<svg></svg>
</div>
<div class='chart third' id='chart9'>
Points do not increase linearly.
<svg></svg>
</div>
<div class='chart third' id='chart10'>
Chart with 15 series'
<svg></svg>
</div>
<div class='chart third' id='chart11'>
Data points go backwards
<svg></svg>
</div>
<div class='chart third' id='chart12'>
Duplicate X coordinate points.
<svg></svg>
</div>
<div class='chart third' id='chart13'>
What if there are null, Infinity and NaN values in points?
<svg></svg>
</div>
<div style='position:relative;'>
<div class='navigation'>
Tests:
<a href="lineChartTest.html">Line Chart</a>
<a href="stackedAreaChartTest.html">Stacked Area</a>
<a href="../examples/cumulativeLineChart.html">Cumulative Line</a>
<a href="interactiveBisectTest.html">nv.interactiveBisect unit tests</a>
</div>
<div class='chart full' id='chart1'>
Example of chart with many series', and new interactive guideline plus tooltip.
<svg></svg>
</div>
<div class='chart half' id='chart2'>
Chart with old tooltip style.
<svg></svg>
</div>
<div class='chart half' id='chart3'>
Chart with three data points.
<svg></svg>
</div>
<div class='chart third' id='chart4'>
Chart where two series have different number of points.
<svg></svg>
</div>
<div class='chart third' id='chart5'>
Chart with one point.
<svg></svg>
</div>
<div class='chart third' id='chart6'>
Chart with 1000 points.
<svg></svg>
</div>
<div class='chart third' id='chart7'>
Chart with no data.
<svg></svg>
</div>
<div class='chart third' id='chart8'>
All points random. No order.
<svg></svg>
</div>
<div class='chart third' id='chart9'>
Points do not increase linearly.
<svg></svg>
</div>
<div class='chart third' id='chart10'>
Chart with 15 series'
<svg></svg>
</div>
<div class='chart third' id='chart11'>
Data points go backwards
<svg></svg>
</div>
<div class='chart third' id='chart12'>
Duplicate X coordinate points.
<svg></svg>
</div>
<div class='chart third' id='chart13'>
What if there are null, Infinity and NaN values in points?
<svg></svg>
</div>
</div>
<script src="../lib/d3.v3.js"></script>
<script src="../nv.d3.js"></script>

@ -28,4 +28,8 @@ text {
.navigation a{
margin-right: 1em;
}
}
.navigation {
margin-bottom: 1em;
}

Loading…
Cancel
Save