Tooltip on mouseover d3 - javascript

Within a Callbackfunction I have this:
/...
feature.on("mouseover",function(d) {
d3.select(this)
.transition()
.ease("cubic")
.duration(10)
.attr('r', function (d){
return (d.x);
})
.tooltip.style("visibility", "visible");
});
My tooltip is defined like so:
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
However, the tooltip won't pop up. Any ideas why?
How would I append the tooltip to the mouseoverevent? And: How would I change the text in there (assuming I want text from my data which I can access with function(d) {....)
Code extracted from here

First give an ID or class to your tooltip for selection like this:
var tooltip = d3.select("body")
.append("div")
.attr("id", "mytooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
Next Instead of doing this:
feature.on("mouseover",function(d) {
d3.select(this)
.transition()
.ease("cubic")
.duration(10)
.attr('r', function (d){
return (d.x);
})
.tooltip.style("visibility", "visible");//this is wrong
});
Do this to show tooltip on mouse over:
feature.on("mouseover",function(d) {
d3.select(this)
.transition()
.ease("cubic")
.duration(10)
.attr('r', function (d){
return (d.x);
});
//show tooltip on hover
d3.select("#mytooltip")
.style("visibility", "visible")//set style to it
.text("new tooltip")//set text to it
});
Furthermore, add this for the tooltip to show up next to the mouse (as shown here)! Otherwise the tooltip probably gets displayed somewhere on your site where you cannot see it!
feature.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY-10)+"px")
.style("left",(d3.event.pageX+10)+"px");
});

Related

Add tooltip to D3 Icicle visual (Observable)

I am working with this icicle visual on D3 Observable. I need to add a tooltip, so that it works faster and looks better than native browser version.
I tried this:
var tooltip = d3.select("body")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px");
var mouseover = function(d) {
tooltip
.style("opacity", 1)
};
var mousemove = function(d) {
tooltip
.html("hello")
.style("left", (d3.mouse(this)[0]+90) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
};
var mouseleave = function(d) {
tooltip
.transition()
.duration(200)
.style("opacity", 0)
};
And adding the events onto the rect:
.on("mouseover", mouseover)
.on("mousemove", mousemove )
.on("mouseleave", mouseleave)
Nothing shows up at all when you hover over the rects of the visual. Can elements be appended to the body in D3 observable?

D3 tooltip or mouseover on bar chart

var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate("+barWidth*i+",0)";
})
.on("mouseover", function() {
d3.select(this)
.attr("fill", "red");
})
.on("mouseout", function(d, i) {
d3.select(this)
.attr("fill", "blue");
});
I am trying to do a mouseover to show data. I am starting by trying to change the colour on a mouseover as per code above.
http://codepen.io/JohnnyBizzel/pen/xqbjVQ
I updated your codepen
A couple of things wrong here:
You are trying to apply the transition to the g and not the rect
Instead of attr you want to use style
Here is the solution:
.on("mouseover", function() {
d3.select(this).select('rect').style('fill', 'red');
})
.on("mouseout", function(d, i) {
d3.select(this).select('rect').style('fill', 'blue');
});
You need to select the shape that is into your element and his style function to change the color.

D3.js / Javascript Node-Lines pop-up window and color change

I am working on D3.js and I have a map with lines and nodes. When I come on them with mouse I want them to change color and get thicker and I want a small pop-up window which shows their IDs.
On HTML for the pop-up there is a function onmouseover.
First question: Is there any function in javascript like onmouseover?
Second question: Is there any way me to change the color and make the lines or nodes thicker when the mouse are on that specific node or line. (I can use JQuery if there is a way in JQuery)
For the tooltip I have this fiddle : http://jsfiddle.net/reko91/7NReF/36/
Firstly, create the container for the toolip :
var tooltip = d3.select("body")
.append("div")
.attr('class','tooltipdiv')
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
Then on mouseover set the text to what you want, mousemove, move the tooltip, and mouseout, hide the tooltip :
circles.on("mouseover", function(d){return tooltip.style("visibility", "visible").text(d);})
.on("mousemove", function(){return tooltip.style("top",
(d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
As for the nodes, you can either style it directly or add a class and do it all in one. So you only need to change the CSS. So with the above being said, I have implemented both in this fiddle : http://jsfiddle.net/reko91/7NReF/37/
Source code :
var w = 500;
var h = 50;
var dataset = [ 5, 10, 15, 20, 25 ];
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
.attr("cy", h/2)
.attr("r", function(d) {
return d;
});
var tooltip = d3.select("body")
.append("div")
.attr('class','tooltipdiv')
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
circles.on("mouseover", function(d){
d3.select(this).classed('hovernode', true)
return tooltip.style("visibility", "visible").text(d);})
.on("mousemove", function(){return tooltip.style("top",
(d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){
d3.select(this).classed('hovernode', false)
return tooltip.style("visibility", "hidden");});
.tooltipdiv{
background:white;
}
.hovernode{
fill:red;
stroke:blue;
stroke-width:5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
</body>
I have added the ability to change the border of the nodes
var node = svg.selectAll(".node")
.data(Data.nodes)
.on("mouseover", function(){
d3.select(this).style("stroke","thick"); // sample CSS operation.
})
this is the element a node in your case which you want to work on.
I would suggest against using jquery. I somehow feel d3 is faster than jquery and can implement similar functionality with greater control.
Okay I wrote a piece of code as an answer to change the color and it works:
.on("mouseover", function(){
d3.select(this)
.attr("fill", "orange");
})
.on("mouseout", function(d){
d3.select(this)
.attr("fill", "rgb(0, 0, " +(d*10) + ")");
});
first .on function makes it orange(you can change the color however you want, second .on makes the original color when you're not on the element anymore.
For pop-up window:
.append("title")
.text(function(d){return d;});

Styling d3´s tooltip

I implement a tooltip over circles placed through d3 on a leafletmap like this:
var tooltip = d3.select("body")
.append("div")
.attr("id", "mytooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
feature.on("mouseover",function(d) {
d3.select(this)
.transition()
.ease("elastic")
.duration(500)
.attr('r', function (d){
return (d.properties.xy * 5)
.style("stroke", "black")
d3.select("#mytooltip")
.style("visibility", "visible")
.text(d.properties.xy1 + " " + d.properties.xy2)
});
feature.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY-10)+"px")
.style("left",(d3.event.pageX+10)+"px");
});
feature.on("mouseout",function(d) {
d3.select(this)
.transition()
.ease("elastic")
.duration(500)
.attr('r', function (d){
return (d.properties.xy);
})
.style("stroke", "none")
d3.select("#mytooltip")
.style("visibility", "hidden")
});
Where my feature is this:
var feature = g.selectAll("circle")
.data(myData.features)
.enter()
//...
I wonder how I can style the tooltip that shows up? Is there a way to give it a background, write something in bold, italic, different colors etc?
This is what I like to do. First, I set the CSS style for the tooltip, using a div with a class named "tooltip":
div.tooltip {
position: absolute;
etc...
}
Then I set a tooltip var (here, svgId is the ID of the element where you append your SVG, not much different of selecting "body" as you did):
var tooltip = d3.select("#svgId").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
The div has 0 opacity. Then it's just a matter of showing the tooltip on mouseover or mousemove:
selection.on("mousemove", function(d) {
tooltip.html("<strong> Look, I'm bold !</strong> and now I'm not bold<br>
and this is another line!and this is my data: " + d.whatever)
.style('top', d3.event.pageY - 12 + 'px')
.style('left', d3.event.pageX + 25 + 'px')
.style("opacity", 1);
});
You can use HTML tags to style your text inside the tooltip, making it bold, italic etc. And, finally, we make the tooltip disappear on mouseout (as you did):
selection.on("mouseout", function(d) {
tooltip.style("opacity", 0);
});
Since the div with 0 opacity still takes space in the page, a better approach is changing its display property from none to block during the mouseover, and back to none in the mouse out.
You can style the tooltip with CSS. You could do that in a separate .css file, in a <style> tag, or with d3 the same way you give the tooltip visibility. Something like .style("background", "rgba(179, 107, 0, 0.5)")

doesn't update d3.js elements in .each function

My code works and it shows me the elements for my data, but d3 doesn't update the text of my SVG Element after changing my data and running the same code again. I have to refresh the whole site for it to change.
var blackbox= d3.select("#content")
.selectAll(".silencer")
.data([0]);
blackbox.enter()
.append("div")
.attr("class", "silencer")
.attr("id", "silencer");
blackbox.exit().remove();
var box = blackbox.selectAll(".ursa")
.data(fraung);
box.enter()
.append("div")
.attr("class", "ursa")
.each(function(d) {
d3.select(this)
.append("svg")
.attr("class", "invoker")
.each(function(d) {
d3.select(this).append("svg:image")
.attr("xlink:href", "images/qwer.png")
.attr("x", "0")
.attr("y", "0")
.attr("width", "100")
.attr("height", "100")
.append("title")
.text(function(d) {return (d.name)});
});
d3.select(this).append("div")
.attr("class", "chen")
.each(function(d) {
d3.select(this).append("table")
.attr("class", "tab")
.each(function(d) {
d3.select(this).append("tbody")
.each(function(d) {
d3.select(this).append("tr")
.text(function(d) {return("Name: ")})
.attr("class", "key")
.each(function(d) {
d3.select(this).append("td")
.text(function(d) {return (d.name)});
});
});
});
});
});
box.exit().remove();
It sounds like your SVG element isn't being cleared before you load the second data set and so the second data set is being drawn behind the first. If the only thing that is changing is the text, it would look like nothing is happening at all. A browser refresh would clear any dynamically drawn content. Before you invoke "blackbox", you can do something like this to clear everything in the "#content" element, which I'm assuming is your SVG container.
if(!d3.select("#content").empty()) d3.select("#content").remove();
This will remove the SVG container entirely. So you'll have to create it again before you can load in new data. Alternatively if you just want to remove the child elements from the SVG container, you could do this:
if(!d3.select("#content").selectAll("*").empty()) d3.select("#content").selectAll("*").remove();

Categories

Resources