Calling tooltip in context of d3 visualization - javascript

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.

Related

Show content from data in tooltip d3

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.

Access local variable inside d3 anonymous function

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)
});

Trigger 2 mouseover events after hovering on a Bar of Bar Chart created using d3.js?

In the following d3.js code:
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("transform", "translate(10,0)")
.attr("class", "bar")
.attr("x", function(d) { return x(d.thread_id); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(+d.traffic); })
.attr("height", function(d) { return height - y(+d.traffic); })
.on('mouseover', tip.show) // First time call to show a tooltip
.on('mouseover', justChecking) // Second time to call a Function
.on('mouseout', tip.hide);
When I execute this code, only the second function output is shown but the tooltip disappears.
I want to call both of them on mouseover, i.e., call the function as well as show the tooltip. Any ideas are appreciated?
Any event handler you attach overwrites previously attached event handlers. You can however call both of your functions in the same handler:
.on('mouseover', function(d, i) {
tip.show(d, i);
justChecking(d, i);
})

Adding OnClick event to a bar chart

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/

adding labels to node in d3.js

I am a newbie in d3.js
I am trying to add labels to my nodes.
But whatever I tried is not working..
My code is here:
http://jsfiddle.net/Ymtg5/1/
Its a mash up between http://bl.ocks.org/christophermanning/4208494
and force directed graphs.
Basically I am reading a json file and creating the said graph.
Now I want to add labels to node exactly like http://bl.ocks.org/mbostock/950642
I tried adding these lines
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });
But its not working.
Any help. suggestions..
Thanks
Most probably the problem is that your JSON classes don't have a "name".
Right, this was not the problem
The relevant part of your code is as follows:
var node = svg.selectAll("path.node")
.data(nodes)
.enter().append("path").attr("class", "node")
.style("fill", function(d) { return fill(d.value); })
.style("stroke", function(d) { return d3.rgb(fill(d.value)).darker(); })
.call(force.drag);
// HERE should go node manipulation to add the text
force
.nodes(nodes)
.links(links)
.on("tick", tick)
.start();
function tick() {
//node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; );
node.attr("d", function(d) { return clip({"type":"F {"type":"Point","coordin...
link.attr("d", function(d) { return clip({"type":"Feature","geometry":{ ...
I have inserted a comment line where your node manipulation should go, if you want to add labels to the nodes. You are doing that inside the tick function (well, I think you are trying to do it there, the code isn't in the fiddle), and that function should be only for manipulation of the attr of the nodes. The place to create the text and append it to the node is outside of the function.

Categories