I am making an interactive D3.js visualization with popup/tooltips to the data points so that on a mouseover event, a popup will appear next to the selected point with some information
Currently I have achieved this with the code below - the tooltip appears on mouseover. When the user moves the mouse to another point, the original tooltip disappears and the correct tooltip appears next to the new data point.
However, the mouseout event is not functioning as it should - the tooltip is not disappearing once the mouse leaves the datapoint. If the user does not move the mouse over a new data point, for example, the old tooltip remains there.
Relevant bits of code:
svg.selectAll("path")
//other stuff here
.on("mouseover", function(d) {
div.transition()
.duration(200) //mouseover transition does not seem to work, but that's minor
.style("opacity", .8);
div .html(d.datetime.substring(0,10) )
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 24) + "px")
.attr("display", display);
})
.on("mouseout", function(d) {
div.attr("display", none);
})
//bit of code where I append the tooltip to the right element
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", .8);
});
What am I doing wrong?
Thanks!
none is a string. So you have to enclose it in quotes. Also note that display is a css style attribute. So it should be applied as shown below.
div.style("display","none");
Other alternative options for implementing the same are the following.
Option 2:
div.attr("hidden",true);//to hide
div.attr("hidden",null);//to show
Option 3:
div.style("opacity",0);//to hide
div.style("opacity",1);//to show
Here is a working code snippet.
var button = d3.select("body")
.append("button")
.text("Mouse Over Me");
button.on("mouseover",function(){
div.style("display","block");
});
button.on("mouseout",function(){
div.style("display","none");
});
var div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("display", "none")
.text("Hello This is a sample");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
display is not an HTML attribute, this is CSS. You need to change your code to something like this if you want to hide the element:
div.css({ "display": "none" });
Or just use the jQuery shortcut: div.hide();.
I would like to use hide() or show(). change from
div.attr("display", display);
to
div.hide();
here is the comments from .hide() or display: none? jQuery
"The matched elements will be hidden immediately, with no animation. This is roughly equivalent to calling .css('display', 'none'), except that the value of the display property is saved in jQuery's data cache so that display can later be restored to its initial value. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline."
This looks like you are following the tutorial here, right down to the extra space before the .html in the mouseover event. (Which is fine...the only reason I recognized that little syntax is because I spent all day staring at it!)
http://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html
You post the relevant code above, but are you also selecting the div that you want to operate on using the select method? This may be why your transition isn't working the way you want it to.
eg:
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
otherwise or in addition the proper way to get the tooltip to go away is as Gilsha answered above with this line on mouseout:
div.style("display","none");
Related
I have a bar chart that I want to be able to hover over the bars and display some data on the top of the chart as text.
I don't want to use tooltips and when I change my text to a normal string like "boom" it will display that on mouse entry. However, it wont display the data.
I have the mouseenter and the function it calls in the code below. Basically I need a way for the mousenter to tell the function what the data it. For some reason it wont do that.
Ive tried useing .text(d3.select(this).text(d.data)) in the function.
I have also tried getting rid of the function and having it all as one code. Also did not work
.on("mouseenter", flash("mode0Danceability"))
function flash(name) {
return function() {
svg.append("text").attr({id: "fish"})
.attr("class", "boom")
.attr("x", 45)
.attr("y", -33)
.text(svg.html(d.mode0Danceability))
.style("font", "20px sans-serif")
.style("fill", "steelblue");
};
}
Best method IS to create a tooltip, just give it no borders and append it as a text to a particular location not as a div.
I've created a line-chart in D3 (with angular) and trying to implement tooltips. The problem is, when I append the tooltip DIV to directive element, it doesn't work, while it works fine if I append the div to body (which I don't want):
// not working
// d3.select(element[0]).append() doesn't work either
var div = g.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// works fine
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
Here is the JSFiddle. (line 69)
You can't use HTML elements (such as div) inside a SVG, unless you use a foreign object (not supported by all browsers). You can create your tooltip using a rect element.
All:
I am pretty new to CSS. One Data visualization user case I try to implement(I use D3.js) is :
Say there are several DIVs overlap each other, the one clicked will show on the top layer,I wonder how can I set its z-index when all DIVs z-index are "auto"?(for certain reason like data binding, I can not adjust its location in the DOM tree)?
The main difficulties that I have is:
How to determine the starting minimum z-index for those DIVs( because there are some other elements, even I can give a higher z-index to the one clicked and lower for all other DIVs, but the number still can possibly be smaller than other elements) So, if I can get that z-index, I do not need to know what it is, but as long as I can increase it to make sure the clicked one has higher number than that, then it is done.
Or is there other ways to do this?
var container = d3.select("body")
.append("div")
.classed("random", true)
.style("position", "fixed")
.style({
"top":"50px",
"width":"200px",
"height":"200px",
"background-color":"rgba(100,100,100, 0.5)"
})
var color = d3.scale.category20();
container.selectAll("span")
.data([1,2,3,4])
.enter()
.append("span")
.style({
"position":"absolute",
"width":"50px",
"height":"50px"
})
.style("margin", function(d,i){
return i*10+10+"px";
})
.style("background-color", function(d, i){
return color(i);
})
.text(function(d, i){
return d;
})
container.selectAll("span")
.on("click", function(d, i){
var block = d3.select(this);
// this is the part I can not figure out ================
block.moveToFront();
});
you don't use a SVG and can apply z-index style to clicked element
example here: https://jsfiddle.net/serGlazkov/z3gykfc1/
UPD:
change your example to SVG format and make top position by click https://jsfiddle.net/serGlazkov/z3gykfc1/3/
I have read several articles and tutorials but couldn't find a sufficient answer on how to select the parent div of the svg using d3.select. I basically just want to append a tooltip to the div which contains my chart like this.
//this selection probably doesn't make sense...
var tooltip = d3.select("#pie-svg").select(this.parentNode).append("div")
.attr("class", "piechart-tooltip")
.style("opacity", 0);
Along the lines of this question:
var tooltip;
d3.select("#pie-svg").each(function() {
tooltip = d3.select(this.parentNode).append("div")
.attr("class", "piechart-tooltip")
.style("opacity", 0);
});
The problem with the code you've posted in the question is that this won't be defined (or set to the right element) in this context. When used with .each(), it will.
I'm relatively new to D3, svg, and javascript in general, so please bear with me :]
I have been experimenting with D3 for creating plots and graphs. I have created a small plot using D3 and have been attempting to make it compatible with IE8. Here is a link to the more-or-less working build of my graph.
http://jsfiddle.net/kingernest/YDQR4/1/
After some research, I quickly realized that the only way running D3 on IE8 would be at all feasible is by using other APIs in conjunction with D3. Luckily, I found that someone had already put in some work into a project called "r2d3" which, from my understanding, uses raphael to paint the canvas on the IE8 window instead of using SVG (which apparenly was not supported in IE8).
I have been able to get items drawn on the screen, which is half the battle. However, I'm having many issues, particularly with my tooltip. My tooltip is written as a DIV container that floats and changes position/opacity on hover of the data circles. This seems to work fine in other browsers, but with r2d3, I have not been able to get it working. I suspect this is because of the fact that I am creating the div tooltip outside of the (in the #main div). However, I have tried placing tooltips inside of the SVG container with no avail. I then did more reseach and discovered I would have to wrap a div container inside a tag, but after some experimentation with this, I still wasn't able to get the tooltip to work correctly in IE. I attempted to wrap the in a SVG group (), and altered the positioning of this object instead, but this did not seem to work either, and simply through numerous exceptions when trying to append the foreignObject tag to a group.
At this point I'm sort of stuck, and was wondering if anyone had any suggestions as to how I may be able to successfully implement the tooltips. I've also noticed that using d3.select(this) inside my functions, when attempting to select a particular data point (in this case, a circle) seems to present a number of issues when attempting to access or modify that item's attributes, but I think this is a whole other issue entirely.
Any help is greatly appreciated!
Example of how I'm currently creating the tooltips:
//Create tooltip element
var tooltip = d3.select("#main")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);
function mousemove()
{ //Move tooltip to mouse location
return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
}
//Mouseover function for circles, displays shortened tooltip and causes other circles to become opaque
function mouseover()
{
var myCircle = d3.select(this);
d3.select(this).attr("class", "dataCircleSelected"); //Color circle green
tooltip.html( //Populate tooltip text
"Username: " + d3.select(this).attr("username") + "<br/>" +
"Session ID: " + d3.select(this).attr("sessionid") + "<br/>" +
"Impact CPU: " + d3.select(this).attr("impact")
)
.transition()
.duration(250)
.style("opacity", .7);
//After 1000ms, make other circle opaque
svg.selectAll("circle")
.filter(function(d, i){ //return every other circle
return !d.compare(myCircle[0][0].__data__);
})
.transition().delay(1000)
.style("opacity", .2);
}
Have you tried using foreignObjects AND explicitly using the xhtml namespace for html tags in the foreignObject (write xhtml:div instead of div) as explained here: HTML element inside SVG not displayed ?
This would give something like that for the tooltip definition
var tooltip = d3.select("#main").append("foreignObject")
.append("xhtml:div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);