How to rename a node in D3 graph - javascript

I need to provide "renaming" functionality to rename nodes using the Icicle example (http://bl.ocks.org/mbostock/4347473).
I am not able to find any solutions similar to what I would like to do, and as browsers usually do not allow for right click, I was wondering if anyone has any suggestions on how to allow for this option and then also how to go about allowing someone to be able to rename a specific node's name.
Thanks.

For the record and per kind request by user2651192, the most workable path for this that we could find is here and, more specifically, the code to change the text is:
...
node.append("text")
.text(function(d){ return d.name; })
.on('click', function(d){
var result = prompt('Change the name of the node',d.name);
if(result) {
d.name = result;
var node1 = canvas.selectAll('.node').data(nodes);
node1.select('text')
.text(function(d){ return d.name; });
}
)};
...

Related

I can't select elements of an SVG I've loaded externally into D3

I'm trying to load an external SVG into D3 and then be able to select and manipulate using D3 functions. I was able to get it loaded on the page with the following code:
d3.xml("external.svg").mimeType("image/svg+xml").get(function(error, xml) {
if (error) throw error;
document.body.appendChild(xml.documentElement);
})
However, when I try to use d3.select, none of the functions work. When I console.log the selected element, it shows an empty array.
Based on the plunkr you provided, in order for your events to work properly, you need to add them after d3 has loaded the svg.
So, instead of this:
d3.xml("DCMetroMap.svg").mimeType("image/svg+xml").get(function(error, xml) {
if (error) throw error;
document.body.appendChild(xml.documentElement);
})
// this runs before the above finishes, so d3 won't find something to select
d3.select("#K05")
.on("mouseover", function(d) {
console.log(d)
console.log('hello')
})
console.log(d3.select("#K05"))
You need to move the select like this:
d3.xml("DCMetroMap.svg").mimeType("image/svg+xml").get(function(error, xml) {
if (error) throw error;
// load the document
document.body.appendChild(xml.documentElement);
//then add the events
d3.select("#K05")
.on("mouseover", function(d) {
console.log(d) // d will be null here
console.log('hello')
alert("Hi!")
})
})
Like this: http://plnkr.co/edit/WbYyBKtzZe6MtKGbjzw9?p=preview
In other words, anything you do, you must put it after document.body.appendChild(xml.documentElement);
Hope this helps! Good luck!

d3 force-directed tree shows NaN when clicking node

When I run this example locally
http://bl.ocks.org/mbostock/1138500
if I click on, or try dragging, a node it does this.
Why?
These 1,200 errors point to this section of the code:
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
Seems like the x and y are not getting the proper data?
I tried putting force.stop() in a few different places based on the comment in this article, but no luck so far.
NaN on Force-Directed Layout Append in D3.js
Thanks.
Queue was not the problem. The solution was to ignore the 404 errors caused by the last two links, or just delete the links.
The problem was that since there were links to three JS files in the HTML I assumed those were needed.
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?1.29.1"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?1.29.1"></script>
The last two had 404 errors, so I looked for them elsewhere online, and copied them from code.google.com, but it still didn't work. Just by luck I just tried deleting the links and it worked.
Apparently those two last links are not needed, that's why the 404 errors didn't break it.
Then I found this page: https://github.com/mbostock/d3/wiki/Upgrading-to-3.0
I hadn't noticed this was a four year old example, so old links didn't come to mind as an issue. I now see that the 1.29.1 was an indication of v1 of D3.
And of course, switching that to the current version also works
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js

How to call ajax by clicking d3.js graph

I want to call an ajax function to send data from my graph (d3.js forced layout graph) to a controller action in rails.
My graph is created from json (from the classic miserables example). I want to allow a user to click on a node and for that to trigger an ajax 'GET' call to an action in rails.
The controller is called users and the action is show
I want to send the name of the node back to the show action
So far I have:
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", function(d) { return d.group * 3; })
.style("fill", function(d) { return color(d.group); })
.call(force.drag)
.on("click", getprofile(d.name));})
.on('dblclick', connectedNodes);
function getprofile(){
$.ajax({
type: "GET",
url: "/users/show" ,
})
};
Obviously this doesn't work. I'm not really sure how to pass the name of the node to ajax.
I don't have access to all your variables, but I ran a stripped down version and this seems to work. I changed your line:
.on("click", getprofile(d.name));})
to
.on("click", function(d) { getprofile(d.name); })
and I don't know where in the ajax call you were planning on plugging the name variable in, but this:
function getprofile(name){
console.log(name);
};
Will console.log your d.name from your node. You can just use that name var to plug in to wherever you need it in your AJAX call. Hope that helps.

D3JS tree example in JSFiddle

I'm trying to implement one of the examples found on the d3.js site in JSFiddle and not having any luck. Here's what I have so far. I'm not really a JS developer (nor have I ever played one on TV), but I'm usually able to get something going with a little persistence and research (often in that order). I'm stumped. What am I doing wrong?
Other than implementing the data block as a variable instead of loading it from a file, I haven't altered the code at all. In the HTML, I took out one line that referred to the dndTree.js, and moved the CSS to the CSS section of JSFiddle.
At line 804, the treeData variable is first referenced:
// Call visit function to establish maxLabelLength
visit(treeData, function (d) {
totalNodes++;
maxLabelLength = Math.max(d.name.length, maxLabelLength);
}, function (d) {
return d.children && d.children.length > 0 ? d.children : null;
});

d3 nesting two network csv files (nodes & edges)

what I'm trying to do is d3.nest() one csv into another.
The node list looks like this:
id,movie,year,genre
85442,Hamlet,1907,Drama
57421,Don Quijote,1908,Drama
13146,Amleto [I],1908,Drama
85443,Hamlet,1908,Drama
160468,Othello,1909,Drama
160468,Othello,1909,Romance
And the edges or links look like this:
sourceid,targetid
234,99455
234,125817
234,201681
476,72885
476,188536
476,246634
1028,14948
1028,60050
So I would like to nest the edges into the node list by the given IDs.
I'm doing some unclever nesting that doesn't work that looks like this right now:
d3.csv("edges.csv", function(edges){
d3.csv("nodes.csv", function(nodes){
var nested_data = d3.nest()
.key(function(d) { return d.sourceid; })
.key(function(d) { return d.id; })
.entries(edges)
.entries(nodes);
console.debug(nested_data);
});
});
I searched for help and found this: D3 change elements based on two different datasets?
But I can't get my head around it. Is it really so difficult? Or might there be another way of doing this? I found this visualization (http://mbostock.github.io/d3/talk/20111116/airports.html) which also deals with two csv files and network structures without using nest().
Thanks,
Kim
Because many people looked at this question, I thought of writing a short follow-up on how this can be solved, to my understanding now.
Lars already gave the right hints. So here just a coded version.
d3.csv("edges.csv", function(edges){
d3.csv("nodes.csv", function(nodes){
var newlist = [];
var i = edges.length;
while(i--){
var edge = edges[i];
newlist.push(
nodes[edge.sourceid].x),
nodes[edge.targetid].y)
);
}
var nested_data = d3.nest()
.key(function(d) { return ... })
.entries(newlist);
});
});
It's not fitting the question perfectly because it assumes that the nodes list is ordered by the ids. The two lists above could be itterated over with something like http://underscorejs.org/#find
Hope this helps.

Categories