Can't add anything to my d3 bar graph - javascript

Here is a simplified, for-the-public's-eyes version of my bar graph. I can't seem to add anything to it. I was following this tutorial trying to add the vertical lines from the x-axis and the text inside each bar to my graph, neither of which are showing up. Basically nothing really shows up that I try to add, but I was able to add the x-axis line which you can see in graph.js # line 65. You can see where I tried adding lines to the graph in my code at line 56 in graph.js. The x values are arbitrary as I was just trying to get them to show up. What am I doing wrong?

The problem is that your selector, "line", is not specific enough. There are already 'line' elements in the document; they form the axis ticks.
Because of that, your code is doing the following. It selects the existing line elements and binds the data your provided to those elements. Since those elements already existed, the enter() selection will be empty. This means that your append("line") command will never be executed:
var lines = svg.selectAll("line")
.data(data)
.enter().append("line")
You can provide more specificity by adding a class. For example the following should work:
var lines = svg.selectAll("line.rules")
.data(data)
.enter().append("line")
.attr("class", "rules");
More about the enter, update, and exit selections can be found in Mike's article Thinking with Joins.

Related

Double clicking on c3js line chart

I'm trying to create a double-click event on a c3js line chart. I've created double-click events with other kinds of charts with the following code:
chart.internal.main.selectAll('.' + c3.chart.internal.fn.CLASS.eventRect).on('dblclick', function (d) {
var $$ = chart.internal;
$$.main.selectAll('.' + c3.chart.internal.fn.CLASS.bar).each(function (d) {
if ($$.isWithinShape(this, d)) {
...
}
});
But when I try this on a line chart (changing c3.chart.internal.fn.CLASS.bar to c3.chart.internal.fn.CLASS.line) it catches all the lines in the chart, and gives no information on where on the X-axis I'm clicking. I looked through all the other values under CLASS but can't find anything that might correspond to the dots that separate the line segments.
I figured it out. I need to use c3.chart.internal.fn.CLASS.circle. That will tell me which datapoint is being clicked on.
I haven't tried this with circles turned off. It might not work then.

Redrawing grid lines on a line chart (remove and redraw) in d3.js

I inherited a project that was using d3.js and one of the charts was a line chart; I had to make a lot of changes to it, one being adding grid lines, I did this like so:
grid_wrap = plot.append('g').classed('grid-wrapper', true);
//......
chart = function() {
//.....
valueScale.domain([0, settings.value_scale_max]).range([plot_height, 0]);
grid_wrap.append("g")
.attr("class", "grid")
.attr("width", grid_width)
.call(make_y_axis(valueScale)
.tickSize(-grid_width)
.tickFormat("")
);
//.....
}
Note the chart function above gets called on a redraw.
function make_y_axis(valueScale) {
return d3.axisLeft()
.scale(valueScale)
.ticks(5);
}
Now, this draws the grid lines fine, however whenever the window is resized it uses a resize event trigger to redraw the graphs, however whilst everything else redraws correctly my grid lines instead get duplicated over and over ending up with several .grid elements.
I checked out how the other code is handling it and I understand it this way:
There are also these threshold elements on the graph and they are built this way:
thresholds = plot.append('g').classed('thresholds', true);
chart = function() {
//.....
valueScale.domain([0, settings.value_scale_max]).range([plot_height, 0]);
thresholds = plot.select('.thresholds').selectAll('.threshold').data(chart.Thresholds);
Uses data to populate the threshold elements.
new_thresholds = thresholds.enter().append('g').attr('class', 'threshold');
Now, as I understand it, thresholds won't contain any elements on the first draw, but on redraws will contain the already existing elements.
new_thresholds will then work on this data and add needed new .threshold elements to match the amount needed in the dataset since we are using the enter function here.
new_thresholds.append('rect').classed('threshold-rect', true).attr('x', 0).attr('y', 0).attr('width', plot_width);
Adding elements to our newly created elements.
thresholds.exit().remove();
Then as I understand it this removes any extra elements that are too many compared to the dataset we provided?
//.....
}
So I guess what I am asking is how can I achieve the same thing with the grid lines since it's not working on a dataset?
I was overthinking it, all I had to do was add this:
grid_wrap.selectAll('.grid').remove();
above the below code...
grid_wrap.append("g")
.attr("class", "grid")
.attr("width", grid_width)
.call(make_y_axis(valueScale)
.tickSize(-grid_width)
.tickFormat("")
);
This makes sure any gridlines are removed before and hence when they get created it only ends up with the one being there.

update a line dynamically using d3 makes the line move back and forth

I have real time data which I need to show in a line chart. So I am updating the path using (doing this for every second)
svg.select(".strream").data([streamData]).interrupt().transition()
.duration(1000)
.ease("linear").attr("d", StepAfterLine)
This makes my graph moving smoother, but I want to delete the old data from the array. So I was comparing the times and deleting the old data, surprisingly it makes my chart moving back and forth. Can any one please help me why the lines are moving differently if I remove old data from an array?
I got answer to my question. In the above code I was animating line. Instead apply animation to transform.
svg.select(".strream").data([strreamDataArray])
.attr("transform", "translate(0,10)")
.attr("d", realStepAfterLine)
.interrupt().transition().ease("linear")
.duration(1000)
.attr("transform", "translate(xscale(0))");

Alter first vertical grid line in nvd3

I want to remove (or make effectively hidden) the first vertical line in the grid for an nvd3 chart. I thought it was a problem with my chart, but after testing it, I realized it seems to be a more general problem.
I tested it by running the line:
d3.selectAll('.tick, .nv-axislabel, .nv-axis text').attr('fill','#999999')
in the console, at the simplest line chart I could find: http://nvd3.org/examples/line.html and it still didn't work! It changes all the lines except the very first vertical line. I'm baffled, I've tried every combination of classes with stroke, fill, opacity, etc - I can either affect the entire svg (with opacity), or nothing. Anyone have any ideas?
EDIT:
I should have specified this originally, I apologize - I do not want to remove the Y axis entirely. I still need the label and the tick marks - I just want to remove that one vertical line (or at least lighten it - it is much darker than the rest of my chart).
Going by your comments:
You don't want to see the " the first vertical line in the grid for an nvd3 chart"
Which is the y axis:
Two ways to achieve that:
Option1
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(false) //hide the y-axis
.showXAxis(true); //Show the x-axis
Option2:
Since in your example you are going for a CSS option
d3.selectAll('.nv-y').attr('display','none')
I will prefer Option1
EDIT post your clarification, you wish to make the y axis line light you can use:
d3.selectAll('.nv-y path').attr('opacity','0.1')
or if you want to hide it completely
d3.selectAll('.nv-y path').attr('display','none')
One solution is to specify an array of tick values that you want to use for each axis. Use axis.tickValues([values]) to explicitly declare which XAxis ticks you want for your graph. So you could pop .tickValues([1, 2, 3, 5, 8, 13, 21]); into either the chart.xAxis or the chart.yAxis, and ticks would only appear from the corresponding values in the array. In your case, you would want to put it in the chart.xAxis variable. However if you want to have a dynamic chart, explicitly declaring the tick values would pose a problem once the data is updated in the graph. If on the other hand you are using static data, this is a pretty easy fix. I've tested this solution in their live code editor and it seems to do the trick.
Refer to https://github.com/mbostock/d3/wiki/SVG-Axes#ticks to see some other directives that could be of use.

d3 tooltip removes my axis (and doesn't work)

I am trying to add tooltips to my D3 graph here:
http://jsfiddle.net/ericps/b5v4R/1/
but adding these mouseevents mess up how everything is rendered and I don't know why. It is a line graph with axis
dots.enter()
.append("circle")
.attr("class", "dot")
.attr("cx", open_line.x())
.attr("cy", open_line.y())
.attr("r",3.5)
.on("mouseover", myMouseOverFunction)
.on("mouseout", myMouseOutFunction);
commenting out both .on methods at line 144 makes everything render how I expect it to
any insight into this?
The tooltips are based on this fiddle
http://jsfiddle.net/ericps/E4vrX/
You're missing myMouseOverFunction.
Simply defining the function will render your graph correctly (with the axes), allowing you to properly define your MouseOver functionality.
var myMouseOverFunction = function() {}
You can see an updated response to your jsfiddle: http://jsfiddle.net/sahhhm/hQgbc/
This could be implemented differently, but just a quick change was to remove the .FILL definition in your CSS and instead populating that value when creating the dot itself.
Few problems:
mouse:
The d3.mouse(container) function gives mouse location relative to the container (a node). You specified d3.mouse(this), but this is referring to the circle node, while you want to refer to the svg container: d3.select("svg").node().
infobox:
The infobox div was not defined anywhere, so nothing to be shown.
See updated Fiddle: http://jsfiddle.net/b5v4R/4/

Categories