Developed stronger backward compatibility with the old tooltip format. Old

tooltips work by default, but if you enable 'useInteractiveGuideline', the
new stuff will show.
master
Robin Hu 11 years ago
parent 0b3ef24e0b
commit 27d80457b9

@ -3,13 +3,15 @@ This places a rectangle on top of the chart. When you mouse move over it, it sen
containing the X-coordinate. It can also render a vertical line where the mouse is located.
*/
nv.interactiveLineLayer = function() {
nv.interactiveGuideline = function() {
var tooltip = nv.models.tooltip();
//Public settings
var width = null
, height = null
, xScale = d3.scale.linear()
, yScale = d3.scale.linear()
, dispatch = d3.dispatch('elementMousemove', 'elementMouseout')
, showGuideLine = true
;
//Private variables
@ -40,15 +42,16 @@ nv.interactiveLineLayer = function() {
var mouseX = d3.mouse(this)[0];
var mouseY = d3.mouse(this)[1];
var pointIndex = Math.floor(xScale.invert(mouseX + padding));
var pointLocation = xScale(pointIndex);
var pointXLocation = xScale(pointIndex);
dispatch.elementMousemove({
mouseX: mouseX,
mouseY: mouseY,
pointIndex: pointIndex,
pointLocation: pointLocation
pointXLocation: pointXLocation,
pointYLocation: mouseY //TODO: Return the proper Y coordinate, not just mouseY.
});
showGuideLine(pointLocation);
renderGuideLine(pointXLocation);
})
@ -64,19 +67,20 @@ nv.interactiveLineLayer = function() {
pointIndex: pointIndex
});
showGuideLine(null);
renderGuideLine(null);
})
;
function showGuideLine(x) {
function renderGuideLine(x) {
if (!showGuideLine) return;
var line = wrap.select(".nv-interactiveGuideLine")
.selectAll("line")
.data((x != null) ? [x] : [], String);
line.enter()
.append("line")
.attr("stroke", "#ccc")
.attr("class", "nv-guideline")
.attr("x1", function(d) { return d;})
.attr("x2", function(d) { return d;})
.attr("y1", availableHeight)
@ -89,6 +93,7 @@ nv.interactiveLineLayer = function() {
}
layer.dispatch = dispatch;
layer.tooltip = tooltip;
layer.width = function(_) {
if (!arguments.length) return width;
@ -108,6 +113,12 @@ nv.interactiveLineLayer = function() {
return layer;
};
layer.showGuideLine = function(_) {
if (!arguments.length) return showGuideLine;
showGuideLine = _;
return layer;
};
return layer;
};

@ -9,8 +9,7 @@ nv.models.lineChart = function() {
, xAxis = nv.models.axis()
, yAxis = nv.models.axis()
, legend = nv.models.legend()
, interactiveLayer = nv.interactiveLineLayer()
, tooltip = nv.models.tooltip()
, interactiveLayer = nv.interactiveGuideline()
;
//set margin.right to 23 to fit dates on the x-axis within the chart
@ -22,10 +21,11 @@ nv.models.lineChart = function() {
, showXAxis = true
, showYAxis = true
, rightAlignYAxis = false
, useInteractiveGuideline = false
, tooltips = true
, tooltip = function(d) {
return '<h3>' + d.key + '</h3>' +
'<p>' + d.series[0].value + ' at ' + d.value + '</p>'
, tooltip = function(key, x, y, e, graph) {
return '<h3>' + key + '</h3>' +
'<p>' + y + ' at ' + x + '</p>'
}
, x
, y
@ -51,29 +51,14 @@ nv.models.lineChart = function() {
//------------------------------------------------------------
var showTooltip = function(e, offsetElement) {
var x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex));
var tip = nv.models.tooltip()
.position(e.position)
.chartContainer(offsetElement)
.gravity('w')
.distance(50)
.snapDistance(25)
.enabled(tooltips)
.valueFormatter(function(d,i) {
return yAxis.tickFormat()(d);
})
.data(
{
key: "",
value: x,
// seriesSelectedKey: e.series.key,
series: e.allSeriesData
}
)
.render()
;
if (useInteractiveGuideline) return;
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
top = e.pos[1] + ( offsetElement.offsetTop || 0),
x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),
content = tooltip(e.series.key, x, y, e, chart);
nv.tooltip.show([left, top], content, null, null, offsetElement);
};
//============================================================
@ -155,10 +140,10 @@ nv.models.lineChart = function() {
//------------------------------------------------------------
//Set up interactive layer
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -194,7 +179,7 @@ nv.models.lineChart = function() {
lines
.width(availableWidth)
.height(availableHeight)
.interactive(false)
.interactive(!useInteractiveGuideline)
.color(data.map(function(d,i) {
return d.color || color(d, i);
}).filter(function(d,i) { return !data[i].disabled }));
@ -271,7 +256,7 @@ nv.models.lineChart = function() {
interactiveLayer.dispatch.on('elementMousemove', function(e) {
lines.dispatch.clearHighlights();
var xValue, allData = [];
var singlePoint, allData = [];
data
.filter(function(series, i) {
series.seriesIndex = i;
@ -281,19 +266,32 @@ nv.models.lineChart = function() {
lines.dispatch.highlightPoint(i, e.pointIndex, true);
var point = series.values[e.pointIndex];
if (typeof point === 'undefined') return;
if (typeof singlePoint === 'undefined') singlePoint = point;
allData.push({
key: series.key,
value: lines.y()(series.values[e.pointIndex], e.pointIndex),
value: lines.y()(point, e.pointIndex),
color: color(series,series.seriesIndex)
});
});
showTooltip({
position: {left: e.pointLocation + margin.left, top: e.mouseY + margin.top},
pointIndex: e.pointIndex,
allSeriesData: allData
var xValue = xAxis.tickFormat()(lines.x()(singlePoint,e.pointIndex));
interactiveLayer.tooltip
.position({left: e.pointXLocation + margin.left, top: e.mouseY + margin.top})
.chartContainer(that.parentNode)
.enabled(tooltips)
.valueFormatter(function(d,i) {
return yAxis.tickFormat()(d);
})
.data(
{
key: "",
value: xValue,
// seriesSelectedKey: e.series.key,
series: allData
}
)();
}, that.parentNode);
});
interactiveLayer.dispatch.on("elementMouseout",function(e) {
@ -333,11 +331,11 @@ nv.models.lineChart = function() {
lines.dispatch.on('elementMouseover.tooltip', function(e) {
e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
// dispatch.tooltipShow(e);
dispatch.tooltipShow(e);
});
lines.dispatch.on('elementMouseout.tooltip', function(e) {
// dispatch.tooltipHide(e);
dispatch.tooltipHide(e);
});
dispatch.on('tooltipHide', function() {
@ -413,12 +411,23 @@ nv.models.lineChart = function() {
return chart;
};
chart.useInteractiveGuideline = function(_) {
if(!arguments.length) return useInteractiveGuideline;
useInteractiveGuideline = _;
return chart;
};
chart.tooltips = function(_) {
if (!arguments.length) return tooltips;
tooltips = _;
return chart;
};
chart.tooltipContent = function(_) {
if (!arguments.length) return tooltip;
tooltip = _;
return chart;
};
chart.state = function(_) {
if (!arguments.length) return state;

@ -248,22 +248,12 @@ nv.models.scatter = function() {
var series = data[d.series],
point = series.values[d.point];
var allSeriesData = [];
data.forEach(function(item) {
allSeriesData.push({
key: item.key,
value: getY(item.values[d.point], d.point),
color: color(item)
});
});
mDispatch({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point,
allSeriesData: allSeriesData
pointIndex: d.point
});
};
@ -446,8 +436,7 @@ nv.models.scatter = function() {
dispatch.on('highlightPoint', function(seriesIndex, pointIndex, isHoverOver) {
d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
.classed("hover",isHoverOver);
.classed("hover",isHoverOver);
});
dispatch.on('elementMouseover.point', function(d) {
if (interactive) dispatch.highlightPoint(d.seriesIndex,d.pointIndex,true);

@ -725,3 +725,10 @@ svg .title {
.nvd3 .axis text {
text-shadow: 0 1px 0 #fff;
}
/****
Interactive Layer
*/
.nvd3 line.nv-guideline {
stroke: #ccc;
}

@ -11,8 +11,6 @@
/* Model which can be instantiated to handle tooltip rendering.
*/
window.nv.models.tooltip = function() {
var nvtooltip = {};
var content = null //HTML contents of the tooltip. If null, the content is generated via the data variable.
, data = null /* Tooltip data. If data is given in the proper format, a consistent tooltip is generated.
Format of data:
@ -36,9 +34,9 @@
}
*/
, gravity = 's' //Can be 'n','s','e','w'. Determines how tooltip is positioned.
, distance = 20 //Distance to offset tooltip from the mouse location.
, snapDistance = 30
, gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned.
, distance = 50 //Distance to offset tooltip from the mouse location.
, 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 //Parent container that holds the chart.
@ -90,9 +88,27 @@
}
}
//Creates new tooltip container, or uses existing one on DOM.
function getTooltipContainer(newContent) {
var container = document.getElementsByClassName("nvtooltip");
if (container.length === 0) {
//Create new tooltip div if it doesn't exist on DOM.
container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
var body = document.getElementsByTagName('body')[0]; //All new tooltips are placed directly on <body>
body.appendChild(container);
}
else {
//Element already exists on DOM, so reuse it.
container = container[0];
}
container.innerHTML = newContent;
return container;
}
//Draw the tooltip onto the DOM.
nvtooltip.render = function() {
function nvtooltip() {
if (!enabled) return;
if (!dataSeriesExists(data)) return;
@ -107,16 +123,14 @@
}
if (snapDistance && snapDistance > 0) {
// left = Math.floor(left/snapDistance) * snapDistance;
top = Math.floor(top/snapDistance) * snapDistance;
}
nv.tooltip.show([left, top],
contentGenerator(data),
gravity,
distance,
document.getElementsByTagName('body')[0],
classes);
var container = getTooltipContainer(contentGenerator(data));
nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container);
return nvtooltip;
};
nvtooltip.content = function(_) {
@ -200,33 +214,27 @@
return nvtooltip;
};
nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) {
var container = document.getElementsByClassName("nvtooltip");
if (container.length === 0) {
//Create new tooltip div if it doesn't exist on DOM.
container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
var body = parentContainer;
if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
//If the parent element is an SVG element, place tooltip in the <body> element.
body = document.getElementsByTagName('body')[0];
}
container.style.left = 0;
container.style.top = 0;
container.style.opacity = 0;
body.appendChild(container);
}
else {
container = container[0];
//Original tooltip.show function. Kept for backward compatibility.
nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) {
//Create new tooltip div if it doesn't exist on DOM.
var container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
var body = parentContainer;
if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
//If the parent element is an SVG element, place tooltip in the <body> element.
body = document.getElementsByTagName('body')[0];
}
container.style.left = 0;
container.style.top = 0;
container.style.opacity = 0;
container.innerHTML = content;
body.appendChild(container);
nv.tooltip.calcTooltipPosition(pos, gravity, dist, container);
};
//Global utility function to render a tooltip on the DOM.

@ -62,7 +62,7 @@ defaultChartConfig("chart1", sinAndCos(), true);
//-------------- CHART 2
nv.addGraph(function() {
var chart;
chart = nv.models.lineChart();
chart = nv.models.lineChart().useInteractiveGuideline(false);
chart
.x(function(d,i) { return i });
@ -97,7 +97,7 @@ defaultChartConfig("chart6", normalDist());
function defaultChartConfig(containerid, data, useDates) {
nv.addGraph(function() {
var chart;
chart = nv.models.lineChart();
chart = nv.models.lineChart().useInteractiveGuideline(true);
chart
.x(function(d,i) { return i });

Loading…
Cancel
Save