d3.js and coffeescript - reading binded data in string interpolation - d3.js

Let's consider data to be binded to some object:
sample = ["x": "1", "y": "1"]
as simple as possible, now i do
d3.select("#someContainer")
.selectAll("rect")
.data(sample)
.enter()
.attr(
"value_taking_y": (d) -> d.y
"value_taking_x": "someValue#{(d) -> d.x}"
)
Problem i'm getting is that "value_taking_y" got right value, it is d.y, but "value_taking_x" is evaluated to something like "someValuefunction(d){return d.x}" which is obviously not intended by me.
On the other hand if i force evaluation of this function in the first place by adding word "do" then i got error similiar to "d is not known value", which seems to be good behavior in this situation.
I'd appreciate some help on this. Thanks in advance

Related

d3.js Set d3-tip background to element colour

I've created a scatter graph using the following code as a basis:
http://bl.ocks.org/peterssonjonas/4a0e7cb8d23231243e0e
However I'd like to change the background of the tooltip either based upon the colour of the selected element, or by adding a data column related to colour (i.e. d.colour).
The code currently generates tooltip text based upon the selected element via the following lines:
var tip = d3.tip()
.attr("class", "d3-tip")
.offset([-10, 0])
.html(function(d) {
return xCat + ": " + d[xCat] + "<br>" + yCat + ": " + d[yCat];
});
I was hoping that by adding something like:
.style("background", function(d) { return d.colour; })
I'd be able to achieve this. However when I do this I find that d is undefined (by adding a console.log before returning).
I'm a super novice when it comes to this kind of thing, so any advice anyone could give me would be super helpful.
Thanks!
Here is a positive criticism: don't use d3-tip or any other plugin to create your tooltips. Create them yourself. That way, you can have better control over them and customise them the way you want.
Back to the question: without even looking at that plugin's documentation, you can select the element (in this case, a <div>) by class:
d3.select(".d3-tip").style("background-color", color(d[colorCat]));
Here is the updated bl.ocks: http://bl.ocks.org/GerardoFurtado/70f2608e455b61514cc96dff6fe41ea6/65c940cb987ae1cbda5dc352cda54a382a945ae8
Regarding the undefined: the tip.style is not receiving the datum when the event is fired, apparently only tip.html does. To be sure about that you have to check their source code.

Ordering chords based on some property of the source data

I have a chord diagram in d3 that looks something like this:
The color of each group is calculated base on a property of the source data (before being transformed to a matrix) and is looked up from the index of each group with something like this:
var groupPath = group.append("path")
.attr("id", function(d, i) { return "group" + i; })
.attr("d", arc)
.style("fill", function(d, i) { return MySourceData[i].inArea ? "blue" : "red"; });
Now what I'd like to do is sort the chords so that all the blues are together and all the reds are together, but there doesn't seem to be a simple way to do that. I know you provide a function to sortGroups (and sortSubGroups for that matter), but it seems the arguments passed to the function are only the values of the chords and I would need to have the indexes to be able to figure out if they should be grouped together or not.
Is there any simple way to sort the groups based on some criteria that is ultimately derived from the index?
It seems the best way to achieve this is to simply order my source data first before I transform it into a matrix. This works fine if the data isn't going to change (which, in my case it wasn't), but if you had data that might change and in changing might end up needing to be resorted, this would be a real pain since you'd need to reorder the matrix.

How to display label for bi-direct link/path/line in D3js force directed layout

I'm trying to draw a network topology using D3sj force directed layout. I did a basic topology with link and node. However, now i want to show the interface name for each link on each node as the following picture. Could you guys guide me how i can do that?
Thank you in advance!
P/S I attached my topology here!1
Ideally you should present the javascript that you have already written, and explained what it does do, and what is missing. Having said that, I recently finished work on a similar project to what you describe, so had the following results handy.
Does this jsfiddle do what you are attempting?
There are two key components. The first is in defining the text elements (here I append them to an SVG element):
var text = svg.selectAll('text')
.data(force.nodes())
.enter().append('text')
.text(function (d) { return d.name });
Here I'm assuming that the nodes[] array contains objects with a .name property that is to be displayed.
The second component is to translate the text elements to their appropriate positions, inside the tick handler:
function tick () {
text.attr('transform', function (d) {
return 'translate(' + d.x + ',' + d.y + ')';
});
// Other code for nodes and links
}
See the jsfiddle for a complete working example, including commented code that should allow you to add images at the nodes if you want to try to reproduce your sample image more closely.

strange issue with scales domain

I'm having a really strange issue with scales, if I put the domain of the (in this case) yscale like this
.domain([0, d3.max(dataset, function (d) { return d.ycoord; })])
It sets up my axis wrong, like it is only show in half.
The strange thing is that, to solve this, I tried for a while and then put a / 1 at the end, like so:
.domain([0, d3.max(dataset, function (d) { return (d.ycoord / 1); })])
And it did show the axis correctly, as in these screenshots
And also here there's the full code on jsfiddle:
jsfiddle link
So my question is: why it behaves like this? I'm really clueless about this and was wondering if anyone was able to solve this!
The problem is that what you're interpreting as numbers (ycoord) are actually strings because they come directly from the CSV. That is, instead of 140 you have "140", which as a string is indeed smaller than "95". So the determined maximum for the scale is incorrect. The D3 functions that actually require numbers (such as the scale function) implicitly convert the strings you give them to numbers, so there's no error message.
To fix this, simply convert your strings to numbers before you do anything else.
dataset.forEach(function(d) { d.ycoord = +d.ycoord; });

Trying to modify Voronoi Map in D3JS

I am trying to modify this D3 example to use with my dataset
http://mbostock.github.io/d3/talk/20111116/airports.html
I think my problem is creating the array of coordinates for calculating the Voronoi polygons, but at this point I'm not sure.
I'm getting a Uncaught TypeError: Cannot read property '0' of undefined error that points to the line where I am calling the array. The code is live, please see here
http://cds.library.brown.edu/projects/mapping-genres/symbol-maps/brown-voronoi-map.html
The map displays just fine, but the data points, the radio button, and the voronoi lines do not appear (I'm not trying to show lines between data points, so that code has been removed).
Any thoughts or suggestions would be most appreciated. Many thanks!
There are a number of small things going on here which can be easily sorted out but some will require a bit of work. The first is that you're using a new version of d3 (v3) and the example you're trying to replicate is an older version. There have been significant changes between the versions on the mapping side of things. So you can either use an old version of d3 (v2 will work I think) or investigate the changes.
The Uncaught TypeError: Cannot read property '0' of undefined error is being generated because d3.geom.voronoi(positions) line is producing NaN. I'm not 100% sure why but you could just filter these out to get a temporary fix. A simple filter would be something like:
g.append("svg:path")
.attr("class", "cell")
.attr("d", function(d, i) {
if (polygons[i][0][0]) {
return "M" + polygons[i].join("L") + "Z";
}
})
with the if true when there is not a false value (NULL, NaN, etc) in the first element of the polygon. Please note that this is temporary fix while you investigate why you're getting NaN and this will not produce the correct voronoi polygons.
The fix for the data points is very simple, you just have to set the radius to something greater than 0 such as 10 (although I imagine that you might want to scale the dots to a property of your data like TotalPublished). For instance see the last line:
circles.selectAll("circle")
.data(locations.rows
.sort(function(a, b) { return b.TotalPublished - a.TotalPublished; }))
.enter().append("svg:circle")
.attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
.attr("r", 10);
The radio button (or checkbox) does not show up as it's not generated by the javascript (although it can be). In the example you refer to its generated in the html in this snippet:
<div style="position:absolute;bottom:0;font-size:18px;">
<input type="checkbox" id="voronoi"> <label for="voronoi">show Voronoi</label>
</div>
Once you've worked through this you'll need to get the voronoi lines working. I think with your code as is the voronoi lines won't show up as the checkbox is not checked. So you could comment these lines out and see what happens. A quick tip with paths is that if you want to just show the lines you need to set the fill style to none and the stroke to whatever colour you want. If you don't set the fill to none you'll just get a black screen.

Resources