How to add hypertext link to Cluster Force Layout circle - d3.js

I have a cluster force layout which works fine, and I can add text to the circles. However, when I try to add a hypertext link, nothing is displayed.
What is the problem with my code?
The code for the text is
node.append("a")
.text(function(d){
return d.name;
})
.attr("href", function(d){
return '/profile/'+d.name;
})
.attr("dx", -10)
.text(function(d){
return d.name;
})
.style("stroke", "white");

In SVGs you are not allowed to put textual content into the <a> itself. For an overview of what is actually allowed in an <a> element have a look at the Content model section of the spec.
You need to wrap another text element around your link labels:
node.append("a")
.attr("xlink:href", function(d){
return '/profile/'+d.name;
})
.append("text") // <-- Wrap <text> element around link label
.text(function(d){
return d.name;
})
.attr("dx", -10)
.style("stroke", "white");

Related

Does SVG foreignObject work only with static HTML?

As described on http://bl.ocks.org/mbostock/1424037, I have seen the foreignObject feature working only with statically inputted text. What happens if I try something like this:
svg.append("foreignObject")
.attr("width", 400)
.attr("height", 200)
.append("xhtml:body")
.style("font", "16px 'Helvetica Neue'")
.html(function(d) {
return d.name;
})
Does the foreignObject feature work with data returned by functions?
Well, that does work. However one thing that needs to be taken care of is to replace .html with .text.
node.append("foreignObject")
.attr("class", "innerNode")
.text(function (d) {
return d.name; })

Selecting all elements in one group of a categorical variable

I have a scatterplot based on this example. I would like highlight all the dots of one color when mousing over any single dot. Aka, if I hover over a green dot, all the green dots switch to full opacity.
I made a fiddle here: https://jsfiddle.net/nancynancy/mc3tz3dj/55/
As I understand it, my code currently only selects one dot, so I presume I need to create a group for each category of the species variable-- but I'm not sure what that looks like. In R the species variable would be a factor with different levels; what's the analog in D3?
// Part of the plot function
chart.selectAll(".dot")
.data(params.data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", function(d){ return responseScale(d.petalWidth);})
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species);});
// Create a group here, say ".species" that will replace ".dot"?
this.selectAll(".dot")
.on("mouseover", function(d){
d3.select(this)
.transition()
.style("opacity", 1)
})
.on("mouseout", function(d){
d3.select(this)
.transition()
.style("opacity", 0.1)
});
I would probably 'selectAll' the dots and then filter the selection to include only those which have a species property matching that of the mouseover-ed dot like this
chart.selectAll(".dot")
.on("mouseover", function(d){
d3.selectAll('.dot')
.filter(function(dot){
return (dot.species == d.species)
})
.transition()
.style("opacity", 1)
})
.on("mouseout", function(d){
d3.selectAll('.dot')
.filter(function(dot){
return (dot.species == d.species)
})
.transition()
.style("opacity", 0.1)
});
Note, also, I tend to avoid using this where possible as it's value can change depending upon the call site of the containing function -- this can make refactoring awkward
JS Fiddle

GET request when clicking on D3.js node text

I would like to make the text in the D3.js nodes submit a GET request upon click.
The jsfiddle for the code can be found here: https://jsfiddle.net/ft5107wo/2/
I would like the GET request to be on the id key in node's JSON.
I have attempted this solution, but it did not work.
The relevant code for creating the rectangles and appending node text is from lines 191 to 218, and is as follows:
// Create the node rectangles.
nodes.append("rect")
.attr("class", "node")
.attr("height", 40)
.attr("width", 40)
.attr("id", function (d) {
return d.id;
})
.attr("display", function (d) {
if (d.hidden) {
return "none"
} else {
return ""
};
})
.attr("x", kx)
.attr("y", ky);
// Create the node text label.
nodes.append("text")
.text(function (d) {
return d.name;
}).attr("transform", "translate(0," + 5 + ")")
.style("text-anchor", "middle")
.attr("x", tx)
.attr("y", ty)
.attr("dy", 0)
.call(wrap, 40);
How can this be achieved?
It turns out one needs to use this hack to have it work correctly and avoid problems with namespaces.

d3.js Add labels in Chord diagram

I am new to this kind of chord visualization. I am working on a sample http://bl.ocks.org/mbostock/4062006:
I would like to add "black", "blonde","brown","red" as labels in the respective chord. How is this possible.
I tried something like this but is not working:
var textLabel = d3.scale.ordinal().range(['Black','Blonde','Brown','Red']);
svg.append("g").selectAll("path")
.data(chord.groups)
.enter()
.append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
svg.append("g").append("svg:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.text(function(d,i) { return textLabel(i+1); })
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
You have forgotten to use the enter selection and also do not link the svg:textPath to an actual path in the SGV. To do this the path you want the text to follow needs to have been given an id attribute and you need to reference this in the textPath with an href attribute.
So you want to add the id attribute to the path you want the text to follow
.attr("id", function(d, i){return "group-" + i;})
You then want to do something like this to add textPath elements
svg.append("g").selectAll("text")
.data(chord.groups)
.enter()
.append("sgv:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.attr("xlink:href", function(d, i){return "#group-" + i;})
.text(function(d,i) {return textLabel(i+1);});
Finally with the colour black you will probably want to invert the text so you don't end up with black on black text.
.filter(function(d, i){return i === 0 ? true : false;})
.attr("style", "fill:white;");

Trying to append a click function to the node text in d3

I'm trying to generate a modal with information pulled from my json file when the text of a node is clicked on. I'm having trouble, so I'm just trying to generate an alert box at the moment. I think that I need to declare a variable for the node text, but I'm having trouble. Here is what I have right now:
node.append("svg:text")
.attr("text-anchor", "middle")
.attr("dy", "3.5em")
.text(function(d) { return d.name; })
var textNodes = node.append("svg:text").text()
.on("click", function(d, i) { alert("Hello world"); });
Or this, I don't see why this wouldn't work either.
node.append("svg:text")
.attr("text-anchor", "middle")
.attr("dy", "3.5em")
.text(function(d) { return d.name; })
.on("click", function(d) { alert("Hello world"); });
You are explicitly setting pointer-events: none for the text nodes (maybe a copy and paste error). Removing this line in the styles allows the click event to fire.
I managed to do do recogize a click on the label using something like this:
const text = this.g.selectAll('text')
.data(nodes)
.enter().append('text')
.attr('class', 'label')
.style('fill-opacity', function(d) { return d.parent === root ? 1 : 0; })
.style('display', function(d) { return d.parent === root ? 'inline' : 'none'; })
.style('pointer-events', 'auto')
.on("click", function(d) {
d3.event.stopPropagation();
console.log(d.data.name);
})
.text(function(d) { return d.data.name});
to expand on the topic, the following function
d3.event.stopPropagation();
will make the node not expand or collapse if you clicked on the text but the node will continue to expand and collapse if you clicked on the node circle next to the name. Pretty neat.

Resources