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.
Related
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!
I want to create dynamically charts with de JavaScript Library "D3.js" in JSF. I mean with dynamically that a java methods takes data from the DB and writes a corresponding JSON. This method I have already programmed and it works. Then the JavaScript should access to the JSON and create the chart.
My question is: How to pass the JSON sting/file to the JavaScript. I think the best way is to write it in the HTTP response. But how to do that in JSF? Or do you have other suggestions?
Just let JSF print out the JSON string as if it's a JS variable.
<script>var data = #{bean.json};</script>
Step by step:
Create a backing bean method for updating a String attribute (jsonData) with the numerical array string JSON representation. You will have to:
Call to an EJB bean or JAX-RS service that returns the data.
Read the data in a List.
Convert the List collection to a JSON object and then stringify it, for example using the javax.json package from the standard.
Update the jsonData model attribute.
In the JSF page you have to include an outputLabel component binded to the jsonData attribute. You can hide it with CSS.
In the JSF page write Javascript code to put the component value in a Javascript variable. You can achieve it with a jQuery selector or in plain Javascript with getElementById function.
Finally you use the Javascript variable in the D3 library.
Note: The use of D3 libraty has been copied from here.
The code in the JSF page would be similar to this:
<h:form id="myForm">
<h:outputLabel id="myLink" value="#{yourBackingBean.jsonData}"
style="display:none;" styleClass="myLink"/>
<div class="someclass">
<h2>Create A Bar Chart With D3 JavaScript</h2>
<div id="bar-chart">
</div>
</div>
<script>
var chartdata = eval(document.getElementById("myForm:myLink").innerHTML);
// you can use jQuery too: $(".myLink").html()
// the size of the overall svg element
var height = 200,
width = 720,
// the width of each bar and the offset between each bar
barWidth = 40,
barOffset = 20;
d3.select('#bar-chart').append('svg')
.attr('width', width)
.attr('height', height)
.style('background', '#dff0d8')
.selectAll('rect').data(chartdata)
.enter().append('rect')
.style({'fill': '#3c763d', 'stroke': '#d6e9c6', 'stroke-width': '5'})
.attr('width', barWidth)
.attr('height', function (data) {
return data;
})
.attr('x', function (data, i) {
return i * (barWidth + barOffset);
})
.attr('y', function (data) {
return height - data;
});
</script>
</h:form>
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
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;
});
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; });
}
)};
...