Merge branch 'development' of https://github.com/novus/nvd3 into development

master
frank shao 11 years ago
commit 058503a0be

@ -12,7 +12,7 @@ body {
<br> <br> <br> <br> <br>
<div class="gallery" id="chart"></div>
<div class="gallery with-transitions" id="chart"></div>
<script src="../lib/d3.v3.js"></script>
<script src="../nv.d3.js"></script>

@ -13,12 +13,9 @@ text {
font: 12px sans-serif;
}
svg {
display: block;
}
#chart1 svg {
height: 500px;
.chart svg {
height: 450px;
min-width: 100px;
min-height: 100px;
/*
@ -37,8 +34,13 @@ svg {
<a href="../test/stackedAreaChartTest.html">Stacked Area</a>
<a href="cumulativeLineChart.html">Cumulative Line</a>
</div>
<div id="chart1">
<svg style="height: 500px;"></svg>
<div id="chart1" class='chart with-transitions'>
<strong>Chart with new tooltips and guide line (with-transitions)</strong>
<svg></svg>
</div>
<div id="chart2" class='chart with-transitions'>
<strong>Chart with old tooltips (with-transitions)</strong>
<svg></svg>
</div>
<script src="../lib/d3.v3.js"></script>
@ -55,10 +57,9 @@ svg {
// Wrapping in nv.addGraph allows for '0 timeout render', stores rendered charts in nv.graphs, and may do more in the future... it's NOT required
var chart;
nv.addGraph(function() {
chart = nv.models.cumulativeLineChart()
nv.addGraph(function() {
var chart = nv.models.cumulativeLineChart()
.useInteractiveGuideline(true)
.x(function(d) { return d[0] })
.y(function(d) { return d[1]/100 })
@ -75,15 +76,42 @@ nv.addGraph(function() {
.tickFormat(d3.format(',.1%'));
d3.select('#chart1 svg')
// .datum(cumulativeTestData())
.datum(cumulativeTestData())
//.transition().duration(500)
.call(chart);
//TODO: Figure out a good way to do this automatically
nv.utils.windowResize(chart.update);
//nv.utils.windowResize(function() { d3.select('#chart1 svg').call(chart) });
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });
return chart;
});
nv.addGraph(function() {
var chart = nv.models.cumulativeLineChart()
.useInteractiveGuideline(false)
.rightAlignYAxis(true)
.margin({right:90})
.x(function(d) { return d[0] })
.y(function(d) { return d[1]/100 })
.color(d3.scale.category10().range())
.average(function(d) { return d.mean/100; })
.clipVoronoi(false);
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%m/%d/%y')(new Date(d))
});
chart.yAxis
.tickFormat(d3.format(',.1%'));
d3.select('#chart2 svg')
.datum(cumulativeTestData())
.call(chart);
//TODO: Figure out a good way to do this automatically
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });

@ -12,7 +12,7 @@ text {
}
</style>
<body>
<body class='with-transitions'>
<svg id="test1"></svg>

@ -23,7 +23,7 @@ svg {
<a href="#" id="zoomIn">Zoom In</a> <a href="#" id="zoomOut">Zoom Out</a>
</div>
<div id="chart1">
<div id="chart1" class='with-transitions'>
<svg></svg>
</div>

@ -28,7 +28,7 @@ text {
</style>
<body>
<div id="chart1">
<div id="chart1" class='with-transitions'>
<svg> </svg>
</div>

@ -41,7 +41,7 @@ div {
<body>
<div id="offsetDiv">
<div id="test1" class="chartWrap">
<div id="test1" class="with-transitions chartWrap">
<svg></svg>
</div>
</div>

@ -138,7 +138,7 @@ nv.interactiveGuideline = function() {
//Private variables
var previousXCoordinate = null
isMSIE = navigator.userAgent.indexOf("MSIE") !== -1
isMSIE = navigator.userAgent.indexOf("MSIE") !== -1 //Check user-agent for Microsoft Internet Explorer.
;
@ -176,16 +176,14 @@ nv.interactiveGuideline = function() {
if (isMSIE) {
/*
D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer.
D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.
d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving
over a rect in IE. THe coordinates are off by 25% of the element's offsetLeft position.
For instance, if the <rect> is 100px left of the screen, the left most mouse point returned
will be -25 on IE. This hack solves the problem.
over a rect in IE 10.
However, d3.event.offsetX/Y also returns the mouse coordinates
relative to the triggering <rect>. So we use offsetX/Y on IE.
*/
var offsetLeft = offsetParent.getBoundingClientRect().left;
var offsetTop = offsetParent.getBoundingClientRect().top;
mouseX = mouseX + 0.25 * offsetLeft;
mouseY = mouseY + 0.25 * offsetTop;
mouseX = d3.event.offsetX;
mouseY = d3.event.offsetY;
}
var pointXValue = xScale.invert(mouseX);
@ -201,6 +199,25 @@ nv.interactiveGuideline = function() {
var mouseX = d3mouse[0];
var mouseY = d3mouse[1];
if (isMSIE) {
/*
On IE 9+, the pointer-events property does not work for DIV's (it does on Chrome, FireFox).
So the result is, when you mouse over this interactive layer, and then mouse over a tooltip,
the mouseout event is called, causing the tooltip to disappear. This causes very buggy behavior.
To bypass this, only on IE, we check d3.event.relatedTarget. If this is equal to anything in the tooltip,
we do NOT fire elementMouseout.
*/
var rTarget = d3.event.relatedTarget;
if (rTarget) {
while(rTarget && rTarget.id !== tooltip.id()) {
rTarget = rTarget.parentNode;
}
if (rTarget && tooltip.id() === rTarget.id) {
return;
}
}
}
dispatch.elementMouseout({
mouseX: mouseX,
mouseY: mouseY
@ -343,6 +360,8 @@ window.nv.tooltip.* also has various helper methods.
, 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.
//Generates a unique id when you create a new tooltip() object
, id = "nvtooltip-" + Math.floor(Math.random() * 100000)
;
//Format function for the tooltip values column
@ -385,6 +404,9 @@ window.nv.tooltip.* also has various helper methods.
function convertViewBoxRatio() {
if (chartContainer) {
var svg = d3.select(chartContainer);
if (svg.node().tagName !== "svg") {
svg = svg.select("svg");
}
var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
if (viewBox) {
viewBox = viewBox.split(' ');
@ -408,13 +430,14 @@ window.nv.tooltip.* also has various helper methods.
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"))
.attr("class", "nvtooltip with-3d-shadow " + (classes? classes: "xy-tooltip"))
.attr("id",id)
;
}
container.node().innerHTML = newContent;
container.style("top",0).style("left",0);
container.style("top",0).style("left",0).style("opacity",0);
return container.node();
}
@ -538,6 +561,11 @@ window.nv.tooltip.* also has various helper methods.
return nvtooltip;
};
//id() is a read-only function. You can't use it to set the id.
nvtooltip.id = function() {
return id;
};
return nvtooltip;
};
@ -548,7 +576,7 @@ window.nv.tooltip.* also has various helper methods.
//Create new tooltip div if it doesn't exist on DOM.
var container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
container.className = 'nvtooltip with-3d-shadow ' + (classes ? classes : 'xy-tooltip');
var body = parentContainer;
if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
@ -665,6 +693,12 @@ window.nv.tooltip.* also has various helper methods.
if (tLeft + width > windowWidth) left = left - width/2 + 5;
if (scrollTop > tTop) top = scrollTop;
break;
case 'none':
left = pos[0];
top = pos[1] - dist;
var tLeft = tooltipLeft(container);
var tTop = tooltipTop(container);
break;
}
@ -672,7 +706,6 @@ window.nv.tooltip.* also has various helper methods.
container.style.top = top+'px';
container.style.opacity = 1;
container.style.position = 'absolute';
container.style.pointerEvents = 'none';
return container;
};
@ -2099,9 +2132,6 @@ nv.models.cumulativeLineChart = function() {
dispatch.stateChange(state);
}
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@ -2171,26 +2201,21 @@ nv.models.cumulativeLineChart = function() {
//------------------------------------------------------------
// Setup containers and skeleton of chart
var foregroundPointerEvents = (useInteractiveGuideline) ? "none" : "all";
var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
var g = wrap.select('g');
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
gEnter.append('g').attr('class', 'nv-avgLinesWrap');
gEnter.append('g').attr('class', 'nv-interactive');
gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-y nv-axis').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-background').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -2254,6 +2279,13 @@ nv.models.cumulativeLineChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
gEnter.select('.nv-background')
.append('rect');
@ -2293,6 +2325,14 @@ nv.models.cumulativeLineChart = function() {
var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
.data(avgLineData, function(d) { return d.key; });
var getAvgLineY = function(d) {
//If average lines go off the svg element, clamp them to the svg bounds.
var yVal = y(average(d));
if (yVal < 0) return 0;
if (yVal > availableHeight) return availableHeight;
return yVal;
};
avgLines.enter()
.append('line')
.style('stroke-width',2)
@ -2302,14 +2342,20 @@ nv.models.cumulativeLineChart = function() {
})
.attr('x1',0)
.attr('x2',availableWidth)
.attr('y1', function(d) { return y(average(d)); })
.attr('y2', function(d) { return y(average(d)); });
.attr('y1', getAvgLineY)
.attr('y2', getAvgLineY);
avgLines
.style('stroke-opacity',function(d){
//If average lines go offscreen, make them transparent
var yVal = y(average(d));
if (yVal < 0 || yVal > availableHeight) return 0;
return 1;
})
.attr('x1',0)
.attr('x2',availableWidth)
.attr('y1', function(d) { return y(average(d)); })
.attr('y2', function(d) { return y(average(d)); });
.attr('y1', getAvgLineY)
.attr('y2', getAvgLineY);
avgLines.exit().remove();
@ -2322,6 +2368,7 @@ nv.models.cumulativeLineChart = function() {
.attr('x', -2)
.attr('fill', 'red')
.attr('fill-opacity', .5)
.style("pointer-events","all")
.call(indexDrag)
indexLine
@ -4643,9 +4690,15 @@ nv.models.indentedTree = function() {
var seriesWidths = [];
series.each(function(d,i) {
var legendText = d3.select(this).select('text');
var svgComputedTextLength = legendText.node().getComputedTextLength()
|| nv.utils.calcApproxTextWidth(legendText);
seriesWidths.push(svgComputedTextLength + 28); // 28 is ~ the width of the circle plus some padding
var nodeTextLength;
try {
nodeTextLength = legendText.node().getComputedTextLength();
}
catch(e) {
nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
}
seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding
});
//nv.log('Series Widths: ', JSON.stringify(seriesWidths));
@ -5211,12 +5264,6 @@ nv.models.lineChart = function() {
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -5249,6 +5296,15 @@ nv.models.lineChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
lines
.width(availableWidth)
.height(availableHeight)
@ -10942,7 +10998,9 @@ nv.models.scatter = function() {
points.each(function(d,i) {
d3.select(this)
.classed('nv-point', true)
.classed('nv-point-' + i, true);
.classed('nv-point-' + i, true)
.classed('hover',false)
;
});
points.transition()
.attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
@ -10971,7 +11029,9 @@ nv.models.scatter = function() {
points.each(function(d,i) {
d3.select(this)
.classed('nv-point', true)
.classed('nv-point-' + i, true);
.classed('nv-point-' + i, true)
.classed('hover',false)
;
});
points.transition()
.attr('transform', function(d,i) {
@ -11333,7 +11393,7 @@ nv.models.scatterChart = function() {
- margin.top - margin.bottom;
chart.update = function() { container.transition().call(chart); };
// chart.container = this;
chart.container = this;
//set state.disabled
state.disabled = data.map(function(d) { return !!d.disabled });
@ -13481,13 +13541,6 @@ nv.models.stackedAreaChart = function() {
gEnter.append('g').attr('class', 'nv-controlsWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -13555,6 +13608,13 @@ nv.models.stackedAreaChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
stacked
.width(availableWidth)
.height(availableHeight)

14
nv.d3.min.js vendored

File diff suppressed because one or more lines are too long

@ -19,7 +19,7 @@ nv.interactiveGuideline = function() {
//Private variables
var previousXCoordinate = null
isMSIE = navigator.userAgent.indexOf("MSIE") !== -1
isMSIE = navigator.userAgent.indexOf("MSIE") !== -1 //Check user-agent for Microsoft Internet Explorer.
;
@ -57,16 +57,14 @@ nv.interactiveGuideline = function() {
if (isMSIE) {
/*
D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer.
D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.
d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving
over a rect in IE. THe coordinates are off by 25% of the element's offsetLeft position.
For instance, if the <rect> is 100px left of the screen, the left most mouse point returned
will be -25 on IE. This hack solves the problem.
over a rect in IE 10.
However, d3.event.offsetX/Y also returns the mouse coordinates
relative to the triggering <rect>. So we use offsetX/Y on IE.
*/
var offsetLeft = offsetParent.getBoundingClientRect().left;
var offsetTop = offsetParent.getBoundingClientRect().top;
mouseX = mouseX + 0.25 * offsetLeft;
mouseY = mouseY + 0.25 * offsetTop;
mouseX = d3.event.offsetX;
mouseY = d3.event.offsetY;
}
var pointXValue = xScale.invert(mouseX);
@ -82,6 +80,25 @@ nv.interactiveGuideline = function() {
var mouseX = d3mouse[0];
var mouseY = d3mouse[1];
if (isMSIE) {
/*
On IE 9+, the pointer-events property does not work for DIV's (it does on Chrome, FireFox).
So the result is, when you mouse over this interactive layer, and then mouse over a tooltip,
the mouseout event is called, causing the tooltip to disappear. This causes very buggy behavior.
To bypass this, only on IE, we check d3.event.relatedTarget. If this is equal to anything in the tooltip,
we do NOT fire elementMouseout.
*/
var rTarget = d3.event.relatedTarget;
if (rTarget) {
while(rTarget && rTarget.id !== tooltip.id()) {
rTarget = rTarget.parentNode;
}
if (rTarget && tooltip.id() === rTarget.id) {
return;
}
}
}
dispatch.elementMouseout({
mouseX: mouseX,
mouseY: mouseY

@ -152,9 +152,6 @@ nv.models.cumulativeLineChart = function() {
dispatch.stateChange(state);
}
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@ -224,26 +221,21 @@ nv.models.cumulativeLineChart = function() {
//------------------------------------------------------------
// Setup containers and skeleton of chart
var foregroundPointerEvents = (useInteractiveGuideline) ? "none" : "all";
var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
var g = wrap.select('g');
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
gEnter.append('g').attr('class', 'nv-avgLinesWrap');
gEnter.append('g').attr('class', 'nv-interactive');
gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-y nv-axis').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-background').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events",foregroundPointerEvents);
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -307,6 +299,13 @@ nv.models.cumulativeLineChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
gEnter.select('.nv-background')
.append('rect');
@ -346,6 +345,14 @@ nv.models.cumulativeLineChart = function() {
var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
.data(avgLineData, function(d) { return d.key; });
var getAvgLineY = function(d) {
//If average lines go off the svg element, clamp them to the svg bounds.
var yVal = y(average(d));
if (yVal < 0) return 0;
if (yVal > availableHeight) return availableHeight;
return yVal;
};
avgLines.enter()
.append('line')
.style('stroke-width',2)
@ -355,14 +362,20 @@ nv.models.cumulativeLineChart = function() {
})
.attr('x1',0)
.attr('x2',availableWidth)
.attr('y1', function(d) { return y(average(d)); })
.attr('y2', function(d) { return y(average(d)); });
.attr('y1', getAvgLineY)
.attr('y2', getAvgLineY);
avgLines
.style('stroke-opacity',function(d){
//If average lines go offscreen, make them transparent
var yVal = y(average(d));
if (yVal < 0 || yVal > availableHeight) return 0;
return 1;
})
.attr('x1',0)
.attr('x2',availableWidth)
.attr('y1', function(d) { return y(average(d)); })
.attr('y2', function(d) { return y(average(d)); });
.attr('y1', getAvgLineY)
.attr('y2', getAvgLineY);
avgLines.exit().remove();
@ -375,6 +388,7 @@ nv.models.cumulativeLineChart = function() {
.attr('x', -2)
.attr('fill', 'red')
.attr('fill-opacity', .5)
.style("pointer-events","all")
.call(indexDrag)
indexLine

@ -18,6 +18,7 @@ nv.models.indentedTree = function() {
, iconOpen = 'images/grey-plus.png' //TODO: consider removing this and replacing with a '+' or '-' unless user defines images
, iconClose = 'images/grey-minus.png'
, dispatch = d3.dispatch('elementClick', 'elementDblclick', 'elementMouseover', 'elementMouseout')
, getUrl = function(d) { return d.url }
;
//============================================================
@ -122,10 +123,21 @@ nv.models.indentedTree = function() {
}
nodeName.append('span')
.attr('class', d3.functor(column.classes) )
.text(function(d) { return column.format ? column.format(d) :
nodeName.each(function(d) {
if (!index && getUrl(d))
d3.select(this)
.append('a')
.attr('href',getUrl)
.append('span')
else
d3.select(this)
.append('span')
d3.select(this).select('span')
.attr('class', d3.functor(column.classes) )
.text(function(d) { return column.format ? column.format(d) :
(d[column.key] || '-') });
});
if (column.showCount) {
nodeName.append('span')
@ -140,8 +152,8 @@ nv.models.indentedTree = function() {
});
}
if (column.click)
nodeName.select('span').on('click', column.click);
// if (column.click)
// nodeName.select('span').on('click', column.click);
});
@ -310,6 +322,12 @@ nv.models.indentedTree = function() {
return chart;
}
chart.getUrl = function(_){
if (!arguments.length) return getUrl;
getUrl = _;
return chart;
}
//============================================================

@ -73,9 +73,15 @@ nv.models.legend = function() {
var seriesWidths = [];
series.each(function(d,i) {
var legendText = d3.select(this).select('text');
var svgComputedTextLength = legendText.node().getComputedTextLength()
|| nv.utils.calcApproxTextWidth(legendText);
seriesWidths.push(svgComputedTextLength + 28); // 28 is ~ the width of the circle plus some padding
var nodeTextLength;
try {
nodeTextLength = legendText.node().getComputedTextLength();
}
catch(e) {
nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
}
seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding
});
//nv.log('Series Widths: ', JSON.stringify(seriesWidths));

@ -137,12 +137,6 @@ nv.models.lineChart = function() {
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -175,6 +169,15 @@ nv.models.lineChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
lines
.width(availableWidth)
.height(availableHeight)

@ -369,7 +369,9 @@ nv.models.scatter = function() {
points.each(function(d,i) {
d3.select(this)
.classed('nv-point', true)
.classed('nv-point-' + i, true);
.classed('nv-point-' + i, true)
.classed('hover',false)
;
});
points.transition()
.attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
@ -398,7 +400,9 @@ nv.models.scatter = function() {
points.each(function(d,i) {
d3.select(this)
.classed('nv-point', true)
.classed('nv-point-' + i, true);
.classed('nv-point-' + i, true)
.classed('hover',false)
;
});
points.transition()
.attr('transform', function(d,i) {

@ -107,7 +107,7 @@ nv.models.scatterChart = function() {
- margin.top - margin.bottom;
chart.update = function() { container.transition().call(chart); };
// chart.container = this;
chart.container = this;
//set state.disabled
state.disabled = data.map(function(d) { return !!d.disabled });

@ -140,13 +140,6 @@ nv.models.stackedAreaChart = function() {
gEnter.append('g').attr('class', 'nv-controlsWrap');
gEnter.append('g').attr('class', 'nv-interactive');
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
//------------------------------------------------------------
// Legend
@ -214,6 +207,13 @@ nv.models.stackedAreaChart = function() {
//------------------------------------------------------------
// Main Chart Component(s)
//------------------------------------------------------------
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer.width(availableWidth).height(availableHeight).xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
stacked
.width(availableWidth)
.height(availableHeight)

@ -10,6 +10,18 @@
overflow: hidden;
}
/********************
Box shadow and border radius styling
*/
.with-3d-shadow {
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
/********************
* TOOLTIP CSS
@ -25,33 +37,29 @@
font-family: Arial;
font-size: 13px;
text-align: left;
/*transition: opacity 500ms linear;
-moz-transition: opacity 500ms linear;
-webkit-transition: opacity 500ms linear;
transition-delay: 500ms;
-moz-transition-delay: 500ms;
-webkit-transition-delay: 500ms;
*/
/* -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
pointer-events: none;
white-space: nowrap;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; */
user-select: none;
}
/*Give tooltips that old fade in transition by
putting a "with-transitions" class on the container div.
*/
.nvtooltip.with-transitions, .with-transitions .nvtooltip {
transition: opacity 250ms linear;
-moz-transition: opacity 250ms linear;
-webkit-transition: opacity 250ms linear;
transition-delay: 250ms;
-moz-transition-delay: 250ms;
-webkit-transition-delay: 250ms;
}
.nvtooltip.x-nvtooltip,
@ -391,18 +399,18 @@ svg .title {
}
.nvd3 .nv-groups .nv-point {
/* transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
.with-transitions .nvd3 .nv-groups .nv-point {
transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: stroke-width 0ms linear, stroke-opacity 0ms linear;*/
-webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
}
.nvd3.nv-scatter .nv-groups .nv-point.hover,
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 20px;
fill-opacity: .5 !important;
stroke-opacity: .5 !important;
stroke-width: 7px;
fill-opacity: .95 !important;
stroke-opacity: .95 !important;
}
@ -499,11 +507,12 @@ svg .title {
fill-opacity: 0;
}
/*
.nvd3.nv-stackedarea .nv-groups .nv-point.hover {
stroke-width: 20px;
stroke-opacity: .75;
fill-opacity: 1;
}
}*/

@ -46,6 +46,8 @@ window.nv.tooltip.* also has various helper methods.
, 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.
//Generates a unique id when you create a new tooltip() object
, id = "nvtooltip-" + Math.floor(Math.random() * 100000)
;
//Format function for the tooltip values column
@ -88,6 +90,9 @@ window.nv.tooltip.* also has various helper methods.
function convertViewBoxRatio() {
if (chartContainer) {
var svg = d3.select(chartContainer);
if (svg.node().tagName !== "svg") {
svg = svg.select("svg");
}
var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
if (viewBox) {
viewBox = viewBox.split(' ');
@ -111,13 +116,14 @@ window.nv.tooltip.* also has various helper methods.
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"))
.attr("class", "nvtooltip with-3d-shadow " + (classes? classes: "xy-tooltip"))
.attr("id",id)
;
}
container.node().innerHTML = newContent;
container.style("top",0).style("left",0);
container.style("top",0).style("left",0).style("opacity",0);
return container.node();
}
@ -241,6 +247,11 @@ window.nv.tooltip.* also has various helper methods.
return nvtooltip;
};
//id() is a read-only function. You can't use it to set the id.
nvtooltip.id = function() {
return id;
};
return nvtooltip;
};
@ -251,7 +262,7 @@ window.nv.tooltip.* also has various helper methods.
//Create new tooltip div if it doesn't exist on DOM.
var container = document.createElement('div');
container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');
container.className = 'nvtooltip with-3d-shadow ' + (classes ? classes : 'xy-tooltip');
var body = parentContainer;
if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
@ -368,6 +379,12 @@ window.nv.tooltip.* also has various helper methods.
if (tLeft + width > windowWidth) left = left - width/2 + 5;
if (scrollTop > tTop) top = scrollTop;
break;
case 'none':
left = pos[0];
top = pos[1] - dist;
var tLeft = tooltipLeft(container);
var tTop = tooltipTop(container);
break;
}
@ -375,7 +392,6 @@ window.nv.tooltip.* also has various helper methods.
container.style.top = top+'px';
container.style.opacity = 1;
container.style.position = 'absolute';
container.style.pointerEvents = 'none';
return container;
};

@ -0,0 +1,194 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link href="../src/nv.d3.css" rel="stylesheet" type="text/css">
<link href="teststyle.css" rel="stylesheet" type='text/css'>
<body>
<div style='position:relative;' class='with-transitions'>
<h3>Scatter chart 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="ScatterChartTest.html">Scatter</a>
<a href="interactiveBisectTest.html">nv.interactiveBisect unit tests</a>
</div>
<div id="test1" class="chart third">
Normal - four series', all random (40 points)
<svg></svg>
</div>
<div id="test2" class="chart third">
Normal - one series', all random (5 points), zero left margin
<svg></svg>
</div>
<div id="test3" class="chart third">
Zero right margin, 200 points
<svg></svg>
</div>
<div id="test4" class="chart third">
Bigger margins
<svg></svg>
</div>
<div id="test5" class="chart third">
Zero data points
<svg></svg>
</div>
<div id="test6" class="chart third">
One point.
<svg></svg>
</div>
<div id="test7" class="chart third">
Two points
<svg></svg>
</div>
<div id="test8" class="chart third">
Three series', one point each
<svg></svg>
</div>
<div id="test9" class="chart third">
Three series', first one has zero points
<svg></svg>
</div>
<div id="test10" class="chart third">
Lots of series
<svg></svg>
</div>
<div id="test11" class="chart third">
Scatter plus line: y=2x + 0
<svg></svg>
</div>
<div id="test12" class="chart third">
Scatter plus line: y=2x + 10;
<svg></svg>
</div>
<div id="test13" class="chart third">
Scatter plus line: y=-0.5x + 1.0;
<svg></svg>
</div>
</div>
<script src="../lib/d3.v3.js"></script>
<!--<script src="../lib/fisheye.js"></script>-->
<script src="../nv.d3.js"></script>
<script src="../src/tooltip.js"></script>
<script src="../src/utils.js"></script>
<script src="../src/models/legend.js"></script>
<script src="../src/models/axis.js"></script>
<script src="../src/models/distribution.js"></script>
<script src="../src/models/scatter.js"></script>
<script src="../src/models/scatterChart.js"></script>
<script src="../src/models/scatterPlusLineChart.js"></script>
<script>
defaultChartTest("test1", randomData(4,40));
defaultChartTest("test2", randomData(1,5), {left:0});
defaultChartTest("test3", randomData(2,200), {right: 0});
defaultChartTest("test4", randomData(2, 8), {top:40, right: 90, bottom: 150, left: 150});
defaultChartTest("test5", randomData(0,0));
defaultChartTest("test6", randomData(1,1));
defaultChartTest("test7", randomData(1,2));
defaultChartTest("test8", randomData(3,1));
defaultChartTest("test9", [
{key: "Group 0", values: []},
{key: "Group 1", values: [{x:1, y:1}]}
]);
defaultChartTest("test10", randomData(30,2));
scatterPlusLineTest("test11", randomDataSloped(2,0));
scatterPlusLineTest("test12", randomDataSloped(2,10));
scatterPlusLineTest("test13", randomDataSloped(-0.5,1));
function defaultChartTest(container, data, margin) {
nv.addGraph(function() {
var chart;
chart = nv.models.scatterChart()
.showDistX(true).showDistY(true);
chart.xAxis.tickFormat(d3.format('.02f'));
chart.yAxis.tickFormat(d3.format('.02f'));
if (margin) {
chart.margin(margin);
}
chart.tooltipContent(function(key) {
return "<h3>" + key + "</h3>";
});
d3.select('#' + container + ' svg').datum(data).transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function scatterPlusLineTest(container, data) {
nv.addGraph(function() {
var chart;
chart = nv.models.scatterPlusLineChart()
.showDistX(true).showDistY(true);
chart.xAxis.tickFormat(d3.format('.02f'));
chart.yAxis.tickFormat(d3.format('.02f'));
chart.tooltipContent(function(key) {
return "<h3>" + key + "</h3>";
});
d3.select('#' + container + ' svg').datum(data).transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function randomData(groups, points) { //# groups,# points per group
var data = [],
shapes = ['circle', 'cross', 'triangle-up', 'triangle-down', 'diamond', 'square'],
random = d3.random.normal();
for (i = 0; i < groups; i++) {
data.push({
key: 'Group ' + i,
values: []
});
for (j = 0; j < points; j++) {
data[i].values.push({
x: random(),
y: random(),
size: Math.random(),
shape: shapes[j % 6]
});
}
}
return data;
}
function randomDataSloped(slope,intercept) { //# groups,# points per group
var data = [],
shapes = ['circle', 'cross', 'triangle-up', 'triangle-down', 'diamond', 'square'],
random = d3.random.normal();
var groups = 2, points = 10;
for (i = 0; i < groups; i++) {
data.push({
key: 'Group ' + i,
values: [],
slope: slope,
intercept: intercept
});
for (j = 0; j < points; j++) {
data[i].values.push({
x: random(),
y: random(),
size: Math.random(),
shape: shapes[j % 6]
});
}
}
return data;
}
</script>

@ -12,14 +12,15 @@
<a href="lineChartTest.html">Line Chart</a>
<a href="stackedAreaChartTest.html">Stacked Area</a>
<a href="../examples/cumulativeLineChart.html">Cumulative Line</a>
<a href="ScatterChartTest.html">Scatter</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.
<div class='chart half with-transitions' id='chart2'>
Chart with old tooltip style (with-transitions).
<svg></svg>
</div>
<div class='chart half' id='chart3'>

@ -12,7 +12,7 @@
<a href="../examples/cumulativeLineChart.html">Cumulative Line</a>
</div>
<div class='chart full' id='chart1'>Full chart example with new tooltip and guideline<svg></svg></div>
<div class='chart half' id='chart2'>Chart with old tooltips<svg></svg></div>
<div class='chart half with-transitions' id='chart2'>Chart with old tooltips (with-transitions)<svg></svg></div>
<div class='chart half' id='chart3'>Chart with single point<svg></svg></div>
<div class='chart half' id='chart4'>Chart with two points<svg></svg></div>
<div class='chart half' id='chart5'>Chart with 'holes'<svg></svg></div>

Loading…
Cancel
Save