xxxxxxxxxx
<meta charset="utf-8">
<link href="https://novus.github.com/nvd3/src/nv.d3.css" rel="stylesheet" type="text/css">
<style>
body {
overflow-y:scroll;
}
text {
font: 12px sans-serif;
}
svg {
display: block;
}
#chart1 svg {
height: 500px;
min-width: 100px;
min-height: 100px;
/*
margin: 50px;
Minimum height and width is a good idea to prevent negative SVG dimensions...
For example width should be =< margin.left + margin.right + 1,
of course 1 pixel for the entire chart would not be very useful, BUT should not have errors
*/
}
</style>
<body>
<div id="chart">
<svg style="height: 500px;"></svg>
</div>
<script src="https://d3js.org/d3.v2.js"></script>
<!-- https://novus.github.com/nvd3 -->
<!-- https://raw.github.com/GerHobbelt/nvd3/master -->
<script src="https://novus.github.com/nvd3/nv.d3.js"></script>
<script>
var bang = false;
var show_gaps_in_1870_1875_period = true; // this lets some undefined Y for some X values slip through to show the lack of data 'mid stream'
try {
d3.json('elev_data.json', function(data) {
var i, e, j, v, r_start, r_end;
if (!data) {
alert("error loading JSON!");
return bang = true;
}
// filter the 'NaN'-causing entries from the data set, i.e. the ones with x but without y value:
if (!show_gaps_in_1870_1875_period) {
// just blow them all away
for (i = 0; e = data.series[i]; i++) {
e.values = e.values.filter(function(d) {
return d[1] !== undefined;
});
}
} else {
// In this case we want to KEEP any UNDEFINED Y entries in the 'middle' of the data series;
// we are only going to strip off any 'undefined' entries leading up or tailing the data.
//
// We do this so 'gaps' in the data will be visualized as such; in this example, there's
// gaps in the range for years 1870-1875 (2 gaps)...
for (i = 0; e = data.series[i]; i++) {
// scan for start of valid data series:
for (j = 0; v = e.values[j]; j++) {
if (v[1] !== undefined)
break;
}
r_start = j;
// reverse scan for end of valid data series:
//
// (since we 'know' that each data series has a head or tail of 'undefined Y' entries,
// we thus know that we won't be scanning the entire series twice this way,
// but rather slightly less than once.)
for (j = e.values.length - 1; v = e.values[j]; j--) {
if (v[1] !== undefined)
break;
}
r_end = j + 1;
// now splice of any head or tail:
if (r_start) {
e.values.splice(0, r_start);
r_end -= r_start;
}
if (r_end < e.values.length) {
e.values = e.values.splice(0, r_end);
}
}
}
// nv.addGraph() not really needed as you only have one graph here, but keeping it like it was; no harm and might be useful for multi-graph F/X later anyway
nv.addGraph(function() {
var chart = nv.models.lineWithFocusChart();
// and following on advice from Bob Monteverde, using chart.x() / chart.y() instead of the deprecated {X:..., Y:...} mapping:
chart.x(function(d) {
return d[0];
});
chart.y(function(d) {
return d[1] || 0;
// '|| 0' is only needed because 'show_gaps_in_1870_1875_period' may be TRUE, in which case some 'undefined' values might make it through to here.
// To prevent those from corrupting the axes, we assign them the harmless Y value 0.
});
// see nvd3::src/lineWithFocus.js --> src/models/lineWithFocusChart.js
chart.xTickFormat(function(d) { return d3.time.format('%b %Y')(new Date(d)); });
chart.yTickFormat(d3.format(',.2f'));
// always make sure 0 is part of the Y axis; when negative numbers must be shown, that's okay too, but 0 should always be there:
// lineWithFocusChart::lines --> src/line.js::yDomain --> src/scatter.js::yDomain --> src/scatter.js::forceY
// --> turns out using forceY is handier than trying to replace the entire yDomain() function there. :-)
chart.forceY([0]); // List of numbers to Force into the Y scale (ie. 0, or a max / min, etc.)
chart.defined(function(d) {
return d[1] || 0;
// This way we detect any 'undefined' Y values in the data set; this is needed because
// 'show_gaps_in_1870_1875_period' may be TRUE, in which case some 'undefined' values
// might make it through to here. Otherwise the NaN filter above ~ line 58 should've taken
// care of everything 'illegal'.
});
d3.select('#chart svg')
.datum(data.series) // picking the data sets out of the JSON
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
});
} catch (e) {
//console.log("exception: ", e);
if (!bang) alert("Error: " + e);
}
//function testData() {
// return [...]
// .map(function(series) {
// series.values = series.values.map(function(d) { return {x: d[0] || 0, y: d[1] || 0 } });
// return series;
// });
//}
</script>
</body>
</html>
Modified http://d3js.org/d3.v2.js to a secure url
Modified http://novus.github.com/nvd3/nv.d3.js to a secure url
https://d3js.org/d3.v2.js
https://novus.github.com/nvd3/nv.d3.js