appending onto multiple elements in d3js - javascript

i wanted to know is there way to distinguish between which element of the parent array we are appending onto and append selectively?
eg:
cell = parent.selectAll("g")
.data(nodes)
.enter()
.append("svg:g")
.filter(function(d,j){ var a = parent.selectAll("text");
for(i=0;i<3;i++)
if(a[i][0].innerHTML == d.parent.name)
return true;
return false;
})
.attr("class", "cell")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("click", function(d) { return zoom(node == d.parent ? root : d.parent); });
parent is cell of the previous iteration which consists of 3 cells
i want to writ a filter logic such that i can choose which object of nodes array goes to which cell
i can't hard code it as it will be dynamic>
thanks for you help.

Related

Storing a D3 selection and then calling enter() fails to render

I'm trying to implement the general update pattern in D3, to allow me to update existing elements before entering new ones.
This code works and generates the elements I want:
var nodes = nodeGroup.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y +")";
})
Now I want to change the code to store the update selection and modify some attributes before retrieving the enter selection.
But when I make this simple change, nothing gets appended any more:
var nodes = nodeGroup.selectAll(".node")
.data(root.descendants())
nodes.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y +")";
})
Why don't these two pieces of code behave identically?

Add labels to nodes in Hobbelt's "Group/Bundle Nodes" D3 force layout example?

I adapted Ger Hobbelt's excellent example of group/bundle nodes
https://gist.github.com/GerHobbelt/3071239
as a JSFiddle here:
https://jsfiddle.net/NovasTaylor/tco2fkad/
The display demonstrates both collapsible nodes and regions (hulls).
The one tweak that eludes me is how to add labels to expanded nodes. I have successfully added labels to nodes in my other force network diagrams using code similar to:
nodes.append("text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) {
// d.name is a label for the node, present in the JSON source
return d.name;
});
Is anyone familiar enough with Ger's example to guide me in the right direction?
On enter, instead of appending circle append a g with a circle and a text. Then re-factor a bit to fix the movement of the g instead of the circle. Finally, append write out the .text() only if the node has a name (meaning it's a leaf):
node = nodeg.selectAll("g.node").data(net.nodes, nodeid);
node.exit().remove();
var onEnter = node.enter();
var g = onEnter
.append("g")
.attr("class", function(d) { return "node" + (d.size?"":" leaf"); })
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
g.append("circle")
// if (d.size) -- d.size > 0 when d is a group node.
.attr("r", function(d) { return d.size ? d.size + dr : dr+1; })
.style("fill", function(d) { return fill(d.group); })
.on("click", function(d) {
expand[d.group] = !expand[d.group];
init();
});
g.append("text")
.attr("fill","black")
.text(function(d,i){
if (d['name']){
return d['name'];
}
});
And refactored tick to use g instead of circle:
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
Updated fiddle.

d3 node- tooltip update on mouseover

var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click)
.on("mouseover",function (d){
if(d.name=="Purchased"){
jQuery.getJSON("RequestHandler?usercommand=jsoncompany&subcommand=propCount&useraction=d3Tree_frm&mgmtId="+d.id+"&type="+d.name, function(json){
var count=JSON.stringify(json.prop_purchased_count);
result="Purchased Property :"+count;
});
}
var g = d3.select(this);
var info = g.append("text")
.classed('info', true)
.attr('x', 30)
.attr('y', 30)
.text(result);
})
.on("mouseout", function() {
d3.select(this).select('text.info').remove();
});
i am using above code to display basic tooltip on mouse over of a node. The problem is that when i move from one node to another tooltip value is not updated quickely it show me previous value .if i move my cursor little bit and move again to that node then only it shows me correct value of that node.
How to resolve that issue?

Trouble with custom d3.js based visualization

I'm learning d3.js and need to create a visualization mirroring that of the example image I've included in the below fiddle.
http://jsfiddle.net/mike_ellan/37PYJ/
I know how to create and bind text elements and was planning on doing so for the labeling inside the circles but I'm having a hard time getting my head around how I should be doing it with this particular data structure. I don't have the option to request a flatter json structure so I have to get it mapped out properly as is. Here is the data I'm starting with:
var consumption = [
{
"fruits": [
{
"year":"2011",
"apples":"213",
"oranges":"176",
"pears":"987"
},
{
"year":"2012",
"apples":"199",
"oranges":"234",
"pears":"672"
}
]
}
];
As for the years, my plan was to generate a 2 row/column table and then add a column for each year based on whats coming back in the json. Can you give me some tips or guidance on how I might achieve this?
Mike this is a quick way to make the graph.
Create the Columns and append header
// Group Columns
var columns = groupColumn.selectAll("g")
.data(consumption[0].fruits)
.enter()
.append("g")
.attr("class", function(d,i) { return "column - " + i });
// Append year
columns.append("text")
.attr("transform", function(d,i) { return "translate(" + i*(width/2) + "," + height/2 + ")"; })
.text(function(d) {return d.year });
Create rows and append fields
// Append row
var groupRow = columns.append("g")
.attr("class", "fruits")
.attr("transform", function(d,i) { return "translate(" + i*(width/2) + "," + height/2 + ")"; })
// Append fields of row
var rows = groupRow.selectAll("circle")
.data(function(d) {return d3.entries(d).filter(function(d) { return d.key !== "year"; })})
.enter()
.append("circle")
.attr("cx",function(d,i){ return (60 * i) + 30 } )
.attr("cy",50)
.attr("r",25)
.attr("fill", function(d){
if(d.key === "apples"){ return "red" }
else if (d.key === "oranges"){ return "orange" }
else if (d.key === "pears"){ return "green" }
})
Append Text to Fields
var text = groupRow.selectAll("text")
.data(function(d) {return d3.entries(d).filter(function(d) { return d.key !== "year"; })})
.enter()
.append("text")
.attr("dx", function(d,i){ return (60 * i) + 20 })
.attr("dy", 55)
.attr("fill", "white")
.text(function(d) {return d.value});
View code http://jsfiddle.net/jmeza/37PYJ/3/
The example is not complete, I give you the first steps...

D3, having trouble adding new group element and line

I'm in the process of visualizing a linked list. Just doing it for fun and to learn d3.js. I am able to create group elements for the circles (which represent a node). But I can't figure out why a new group element is not being added after that. I want this new group to contain the line/arrow (the .next reference representation). I debugged through CDT the code is being executed but nothing is being added to the DOM.
var g = svg.selectAll("g")
.data(dataArr)
.enter().append("g")
.attr("transform", function() {
if (addMethod === "headAdd") {
return "translate(" + 50 + " ," + y + ")";
} else {
return "translate(" + x + " ," + y + ")";
}
})
.attr("class", "nodes")
.attr("id", function(d) { return d.getData(); });
// Create a circle representing the node.
g.append("circle")
.attr("r", 40)
.style("fill", "#7DC24B")
.style("stroke", "#122A0A")
.style("stroke-width", 5)
.style("opacity", 0)
.style("stroke-opacity", 0.8)
.transition().duration(1000).style("opacity", 1);
// Add data to the node.
g.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("fill", "#ffffff")
.text(function(d) { return d.getData(); });
// Create the "next" arrow.
// l is the line group that will enclose the line
// and the text.
// This doesn't seem to be working from here below.
var l = svg.selectAll("g")
.data(["1"])
.enter().append("g")
.attr("class", "lines")
.attr("transform", "translate(" + (x + 40) + ", " + y + ")");
l.append("line")
.attr("x1", x + 40)
.attr("y1", y)
.attr("x2", x + 100)
.attr("y2", y)
.style("stroke", "#8EBD99")
.style("stroke-width", 30);
The ...
var l = svg.selectAll("g")
.data(["1"])
... selects the existing group elements (i.e. the one you've just created) and performs a data join with those. The enter() selection will be empty since the elements you selected were already present in the DOM. Therefore the parts after .enter() will not be executed and the l selection will be empty.
You have to make the selector more specific, like:
var l = svg.selectAll(".lines")
.data(["1"])
The Thinking with Joins article does a good job in explaining the data join concepts. See also the General Update Patterns (I,II,III) for more details about the different kind of selections you'll encounter during data joins.

Categories

Resources