Reputation: 1687
I am trying to write a reusable linechart here, but I am getting the following error on load:
Uncaught TypeError: Cannot read property 'length' of undefined
JSfiddle here: http://jsfiddle.net/2qs95/
I first wrote it "directly" and un-reusable, and that works, but when I tried to convert it to a function it broke for some reason. I am sure it is some scope problem. Just can't seem to figure it out.
Working JSfiddle here: http://jsfiddle.net/ht9rG/
function LineChart (data, chart) {
this.data = data;
this.margin = chart.margin || { top: 0, bottom: 0, left: 0, right: 0 };
this.height = chart.height || 100;
this.width = chart.width || 400;
this.target = chart.target || 'body';
this.yLabelClass = chart.classes.yLabelClass || 'y-label';
this.yTicksClass = chart.classes.yTicksClass || 'y-ticks';
this.specialTextClass = chart.classes.specialTextClass || 'special-text';
}
LineChart.prototype = {
draw: function () {
this.g.selectAll("." + this.yLabelClass)
.data(this.y.ticks(2))
.enter().append("svg:text")
.attr("class", this.yLabelClass)
.text(String)
.attr("x", d3.select(this.target).attr('width') - 50)
.attr("y", function(d) { return -1 * this.y(d) })
.attr("text-anchor", "left")
.attr("dy", 5);
this.g.selectAll("." + this.yTicksClass)
.data(y.ticks(2))
.enter().append("svg:line")
.attr("class", this.yTicksClass)
.attr("y1", function(d) { return -1 * this.y(d); })
.attr("x1", this.x(-0.3))
.attr("y2", function(d) { return -1 * this.y(d); })
.attr("x2", d3.select('svg').attr('width') - 70);
this.g.append('text')
.attr({
class: this.specialTextClass,
y: -50,
x: 0
})
.text(this.data[this.data.length - 1] + 'ms');
this.g.append("svg:path").attr("d", line(this.data));
},
y: d3.scale.linear()
.domain([0, d3.max(this.data)])
.range([this.margin.bottom, this.height - this.margin.bottom]),
x: d3.scale.linear()
.domain([0, this.data.length])
.range([this.margin.left, this.width - this.margin.left]),
svg: d3.select(this.target)
.append("svg:svg")
.attr("width", this.width)
.attr("height", this.height),
g: svg.append("svg:g")
.attr("transform", "translate(0, " + h + ")"),
line: d3.svg.line()
.interpolate('linear')
.x(function (d, i) { return x(i); })
.y(function (d) { return -1 * y(d); })
}
var data = [432, 123, 432,123,765,234,234,656,800,123,431,543,652, 100, 200];
var options = {
width: 800,
height: 100,
margin: {
top: 10,
bottom: 10,
left: 10,
right: 10
},
target: 'body'
};
var x = new LineChart(data, options);
x.draw();
Upvotes: 0
Views: 3553
Reputation: 109232
You were missing a few things here and there, mostly
this.
,this
inside a D3 callback, at which point it referred to the SVG element and not the chart object,I won't list everything here, but a working example is here and you can compare to your version.
Upvotes: 3