I am working with d3 and javascript and I am new to them. I am trying to pass a variable inside anonymous function for click but I cant get it to work.Here is an example:
var someVariable=xyz;
var mapModel=someObj;
svg.append("g")
.style("display","table")
.style("margin","0 auto")
.data(topojson.feature(mapModel, mapModel.objects[objdisplay]).features)
.enter()
.append("path")
.attr("id", function(d) { return d.id; })
.attr("d", this.path)
.on("click",function(d){
alert(someVariable + d.id)
});
I need to access somevariable inside anonymous function for click but can't seem to get it working.This question might have been asked before but can someone help me in going in the right direction.Thanks
You can't access 'someVariable' inside your click function this way .
Try this...
var someVariable=xyz;
svg.append("g")
.style("display","table")
.style("margin","0 auto")
.enter()
.append("path")
.data([{'someVariable':someVariable}])
.on("click",function(d){
alert(d.someVariable + d.id)
});
Related
I am following this example to add a tooltip to my circles, displayed on a map.
var tooltip = d3.select("body")
.append("div")
.attr("id", "mytooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
Then Ive got this mouseover
// callbackfunction preparing the data
// then
var feature = g.selectAll("circle")
.data(data.features)
.enter()
.append("circle")
//...
feature.on("mouseover",function(d) {
d3.select(this)
.transition()
.ease("elastic")
.duration(500)
.attr('r', function (d){
return (d.features.xy);
})
d3.select("#mytooltip")
.style("visibility", "visible")
.text(function(d) {
console.log(d.features.xy)
return (d.features.xy)
})
That does not display the value of xy.
Output of console.log is:
TypeError: undefined is not an object (evaluating 'd.xy')
The Problem is obviously that with the d3.select("#mytooltip") statement I enter the var tooltip to which my data.features... is not bound to. How do I bind the circles to the mouseover (which are created in var feature = g.selectAll("circle"), after calling d3.select?
The .data function is expecting an array, to be distributed among several elements ("data" is plural). If you want to give a single "piece of data" to a single element (namely, your tooltip), you need the .datum function:
tooltip.datum(myData)
Alternatively, you can do:
tooltip.data([myData])
In your original code, since you don't have the tooltip variable (nor, for that matter, myData), you can insert it in the mouseover event:
(...)
d3.select("#mytooltip")
.datum(d)
.style("visibility", "visible")
(...)
Another option: you can draw the tooltip directly, without binding any data to it:
d3.select("#mytooltip")
.style("visibility", "visible")
.text(d.features.xy);
Here d still refers to the data of the object you are mouseover-ing, so this should work just as well.
I am trying to get a subselection of a given D3.js selection.
This part of the code creates the paths:
pieces.paths = pieces.groups
.append("path")
.attr("fill", function (d) { return d.data.color; });
Then, I set de "d" attribute:
pieces.paths
.attr("d", arc);
Working perfect. But pieces.paths has 3 elements, and I want to set the class of the first two elements to "highest". How may I do that?
selection.filter() is one option:
pieces.paths
.filter(function(d, i) {return i<2;})
.attr("class", "highest");
So I have a visualization and I'm trying to use d3.tip() - https://github.com/Caged/d3-tip/blob/master/docs/initializing-tooltips.md#d3tip
This is my code-
this.svg = d3.select(".timechart").append("svg")
.attr("width", this.width + this.margin.left + this.margin.right)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.append("g")
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
svg.selectAll('.point')
.data(newData)
.enter()
.append("svg:circle")
.attr("cx", function(d,i){
var date = d["date"].match(/(\d+)/g);
date = new Date(date[2], date[0], date[1]);
return xScale(date);
})
.attr("cy", function(d,i){
var quantitySold = yScale(d["quantity-sold"]);
return quantitySold;
})
.attr("fill", "red")
.attr("r", 4)
.on("mouseover", function(d){
tooltip.show();
})
.on("mouseout", function(d){
tooltip.hide();
});
var tooltip = d3.tip()
.attr("class", "tooltip")
.offset([0,5])
.html(function(d){
console.log(d);
return "<strong> 20 </strong>";
});
svg.call(tooltip);
The console.log(d) gives me undefined, when it should give me the datum.
Why?
I also realize - I'm not sure what code I should post here to help - just let me know what would be useful.
The tooltip library that you're using (d3.tip) creates a single html tooltip for the entire visualization. The data for a particular element is passed to the tooltip using the tooltip's .show(d,i) method.
This example from the plug-in's creator shows how it is supposed to work. In particular, note that the show and hide methods are given directly as parameters to the .on(event, function) method of the rectangle selection:
svg.selectAll(".bar")
/* ... */
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
When the event occurs, d3 will therefore call these methods and pass the data object to them as a parameter.
In contrast, in your code:
.on("mouseover", function(d){
tooltip.show();
})
.on("mouseout", function(d){
tooltip.hide();
});
d3 will pass the data to your anonymous function, but you do not pass it on to the show/hide functions. So the data is undefined when the tooltip's show function tries to set the html content of the tooltip.
If you find that all confusing still, you might appreciate this write-up about passing functions as parameters.
Finally, although it isn't your main problem right now, you should be defining the tooltip before assigning its functions to an event handler. If you tried to do .on('mouseover', tooltip.show) before defining tooltip, you would get an error. You only avoided it by wrapping that function call in another function.
This is all the code that I have, there is something wrong with the "on click" part that I couldn't figure out.
It errors and says "drill not defined"
Isn't it the way we can call a method on click event of one of those bar charts that I am drawing in the D3 section?
$( document ).ready(function() {
gon.data.pop(); // get rid of query_time element.
var dataset = gon.data;
function drill(d, i) {
console.log(d.total_count); //data object
var url = "http://localhost:4567/drill/" + d.brand_name + "/" + d.generic_name;
window.location.href = url;
}
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.attr("onclick", "drill()")
.style("height", function(d) {
return d.brand_name + "px";
});
});
To add event listeners to selections you should use selection's on method.
You can write
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.on("click", drill)
.style("height", function(d) {
return d.brand_name + "px";
});
Move your declaration of the drill function to outside of your document-ready handler.
Better still, use the on method that d3 provides, rather than the onclick attribute.
you can also use jQuery .click() if you want, here's an example
$("#test").click(function(){
sayHello();
});
jsfiddle here:
http://jsfiddle.net/SGRmX/1/
I made a scatter plot, and want to add a link to each dot.
chart.selectAll("scatter-dots")
.data(data)
.enter().append("circle")
.attr("cx", function (d) { return x(d.position[0]); } )
.attr("cy", function (d) { return y(d.position[1]); } )
.attr("r", 4)
.style("fill", "#666")
.style("opacity", 0.5)
.on("click", function(){
var url = "http://somelink.com/link.php?id=";
url += d.link_id;
//$(location).attr('href', url);
//window.location = url;
});
It works if I just put the pure String link such as
window.location = "http://stackoverflow.com"
However, if I add queries to the end of the URL from a variable, the page does not redirected.
Neither jquery nor javascript worked (as commented.)
I also tried an external js file, still fail.
This is in a PHP file, if this helps.
If it works with a static string then something is wrong with d.link_id. Try seeing what's inside either by doing alert(d.link_id) or if you use a firebug or similars do console.log(d.link_id).
Alternatively, you should use real anchors for linking your nodes instead of setting click events. This would go something like...
chart.selectAll("scatter-dots")
.data(data)
.enter()
.append("a")
.attr("xlink:href", function(d) {return "http://somelink.com/link.php?id=" + d.link_id})
.append("circle")
.attr("cx", function (d) { return x(d.position[0]); } )
.attr("cy", function (d) { return y(d.position[1]); } )
.attr("r", 4)
.style("fill", "#666")
.style("opacity", 0.5)
(I can't seem to recall if this is the exact way of doing it, you might need to save the anchors in a variable and then append the circles to them.)