Removing text on mouseout event - d3.js

Small problem on one viz.
I have a bar chart, and I want it to display some text in the line on 'mouseenter'. That works fine, but I want to remove this text on 'mouseout', and I can't seem to get the hang of it.
Thank you very much for your help!
Attached: the concerned section of the d3.js script
d3.selectAll("div.line")
.append("div")
.attr("class","bar")
.style("width", function(d){return d.occurrence /10 + "px"})
.on("mouseenter", function(d) {
d3.select(this)
.append("text")
.text(function(d){return d.occurrence + " occurences"});
})
.on("mouseout", function(d) {
d3.select(this)
.select(".text").remove();
});

In your code, you're trying to select .text on mouseout. You're selecting nodes with which have the class: "text" rather than text nodes. Remove the dot.
I'd probably also change the mouseout "select" to "selectall" just in case you miss a mouseout event and accidentally add two text nodes.
Edit:
http://jsfiddle.net/QbGRE/
d3.select("div.line").selectAll("div.bar")
.data(data, function(d) { return d.id; })
.enter()
.append("div").attr("class","bar")
.style("width", function(d){return d.occurrence /10 + "px";})
.on("mouseover", function(d) {
d3.select(this)
.append("text").style("pointer-events", "none")
.text(function(d){return d.occurrence + " occurences";});
})
.on("mouseout", function(d) {
d3.select(this)
.select("text").remove();
});
Cleaned up your code.
"mouseover/mouseout" instead of "mouseenter/mouseout"
.select("text") instead of ".text".
style("pointer-events", "none) on the text to stop it causing extra mouse events when it's added.
Added fake data.

The easiest way to do this is to assign a unique ID to the new text element and select by that:
.on("mouseenter", function(d) {
d3.select(this)
.append("text")
.attr("id", "myText")
.text(function(d){return d.occurrence + " occurences"});
})
.on("mouseout", function(d) {
d3.select("#myText").remove();
});

Related

D3.js : Duplicate 100% working interactive legend for a bubble map

I have created a interactive legend, that works 100% perfectly fine. I just didnt manage to duplicate it for another column of my dataframe.
It starts with bubbles I'm plotting with the code below. Then I draw the actual legend.
1. creating bubbles
selection
.selectAll('circle')
.data(cities)
//.attr('r', 14)
.attr('r', function(d) {
return Math.max(Math.pow(d.population, 0.57) / 40, 7);})
.attr('cx', function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).x;
})
.attr('cy', function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).y;
})
.attr("class", function(d) { return "bubbles " + d[attribute] }) //Important feature for legend
//.attr("class", function(d) { return "bubbles " + d.category })
.attr('stroke', 'white')
.attr('stroke-width', function(d) {
return 1.2 / projection.scale;})
.style("fill", function(d) {
return color(d[attribute])})
.attr("stroke", "#FFFF")
.attr("stroke-width", 1)
.attr("fill-opacity", .9)
.on("mouseover", showTooltip)
.on("mousemove", moveTooltip)
.on("mouseleave", hideTooltip)
2. Drawing actual legend
svg_chorop.selectAll("mydots")
.data(allgroups)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", function(d, i) {
return 60 + i * (size + 10)
}) // 60 is where the first dot appears. 10 is the distance between dots
.attr("width", size)
.attr("height", size)
.style("fill", function(d) {
return mycolor(d)
})
.style("stroke", "#DCDCDC")
.on("mouseover", highlight)
.on("mouseleave", noHighlight)
My goal : make the exact same legend with another hovering option.
Problem : I can't find a way to ADD another class attribute (in my case d.category, for economic sector) in the first bunch of code.
Fiddle link, so it's easier for you to see the code : jsfiddle
I have simply tried to add another .attr("class",..). It doesn't work. And I can find a similar fix for this problem online.
.attr("class", function(d) { return "bubbles " + d[attribute] }) //Important feature for legend
//.attr("class", function(d) { return "bubbles " + d.category })
Here you can see the two legends, left one functionnal, right, the
one to be implemented
Here you can see the dataframe and the category column

Conflict in transitions

I'm coming to you today with another D3.js problem.
I have a simple bar chart.
When the mouse hovers a bar, a string is displayed on it.
This morning, I added a new transition that changes the background colour of the bar.
Now, the problem is the following:
If the .transition changing the background-color is placed under the one that displays the string, only the background colour changes, the string does not appear.
And if the .transition displaying the string is placed under the one that changes the background colour, only the string appears, without a change in the colour.
Here's a JSFiddle: http://jsfiddle.net/QbGRE/1/
d3.selectAll("div.bar")
.on("mouseover", function(d) {
d3.select(this)
.transition().duration(300)
.style("background-color", "#EE3B3B");
})
.on("mouseout", function(d) {
d3.select(this)
.transition().duration(300)
.style("background-color", "DarkRed");
});
d3.selectAll("div.line")
.append("div")
.attr("class","bar")
.style("width", function(d){return d.occurrence /10 + "px";})
.on("mouseover", function(d) {
d3.select(this)
.append("text").style("pointer-events", "none")
.text(function(d){return d.occurrence + " occurences";});
})
.on("mouseout", function(d) {
d3.select(this)
.select("text").remove();
});
Thank you all for your help, d3-savvy persons
The reason for this is that you're attaching mouse event handlers twice and the later ones overwrite the earlier ones. So first you're attaching the one that adds the text and then later you're attaching the one that changes the color which replaces the first.
The easiest way to fix this is to do everything you want to do on mouse events in one place:
.on("mouseover", function(d) {
d3.select(this)
.append("text").style("pointer-events", "none")
.text(function(d){return d.occurrence + " occurences";});
d3.select(this)
.transition().duration(300)
.style("background-color", "#EE3B3B");
})
.on("mouseout", function(d) {
d3.select(this)
.select("text").remove();
d3.select(this)
.transition().duration(300)
.style("background-color", "DarkRed");
});
Complete example here. Alternatively, you can use different namespaces for the event handlers:
.on("mouseover.text", function(d) {
// etc
});
.on("mouseover.color", function(d) {
// etc
});
Complete example here.

d3.js Add labels in Chord diagram

I am new to this kind of chord visualization. I am working on a sample http://bl.ocks.org/mbostock/4062006:
I would like to add "black", "blonde","brown","red" as labels in the respective chord. How is this possible.
I tried something like this but is not working:
var textLabel = d3.scale.ordinal().range(['Black','Blonde','Brown','Red']);
svg.append("g").selectAll("path")
.data(chord.groups)
.enter()
.append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
svg.append("g").append("svg:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.text(function(d,i) { return textLabel(i+1); })
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
You have forgotten to use the enter selection and also do not link the svg:textPath to an actual path in the SGV. To do this the path you want the text to follow needs to have been given an id attribute and you need to reference this in the textPath with an href attribute.
So you want to add the id attribute to the path you want the text to follow
.attr("id", function(d, i){return "group-" + i;})
You then want to do something like this to add textPath elements
svg.append("g").selectAll("text")
.data(chord.groups)
.enter()
.append("sgv:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.attr("xlink:href", function(d, i){return "#group-" + i;})
.text(function(d,i) {return textLabel(i+1);});
Finally with the colour black you will probably want to invert the text so you don't end up with black on black text.
.filter(function(d, i){return i === 0 ? true : false;})
.attr("style", "fill:white;");

Mouseover in a scatterplot of a second svg in D3

I am trying to create a page with a scatterplot, a network diagram, and a table. I was able to get the mousehandling to work on the network diagram and the table (with the help of #Superboggly at Link D3 force layout network diagram with table on mouseover). Now I am trying to get the mousehandling to work on a second svg with a scatterplot, and I think I'm messing up the referencing.
var mapit = svg2.selectAll("maprect")
.data(graph.nodes)
.enter().append("rect")
.attr("x", function(d) { return xScale(d.long); })
.attr("y", function(d) { return yScale(d.lat); })
.attr("height", 20)
.attr("width", 20)
.attr("fill", "cyan")
// This mouseover doesn't work, what am I missing?
.on("mouseover", function(d) {
d3.select(this).select("rect").style("fill", "orange");
})
.on("mouseout", function(d) {
d3.select(this).select("rect").style("fill", "cyan");
});
I'm new to D3 and to JavaScript, and am confused by the collection of ... mapit, svg2, maprect, graph.nodes, rect, ... that I pieced together from other folks' examples. Any suggestions?
The example is posted as a jsFiddle.
You were so close! Just remove the .select("rect") in the functions:
.on("mouseover", function(d) {
d3.select(this).style("fill", "orange");
})
.on("mouseout", function(d) {
d3.select(this).style("fill", "cyan");
});
updated fiddle.

show data of each circle of bubble chart in table d3.js

I made a bubble chart and is working fine.But i need and even based feature in which i click on each circle and the data related to that circle will show in tabular form in another div..
<div id="bubblechart"></div>
<div id="table"></div>
first div contain the bubble chart and working fine. table div is used as container for the table generated.
here is my code.
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.packageName); })
.on("mouseover", animateFirstStep)
.on("mouseout", animateSecondStep);
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.className; });
You can add an .on("click", clickFunction) to the node. This will work like your mouseover and mouseout lines.
In the clickFunction function, control the content of the target div using
document.getElementById('targetDiv').innerHTML = targetText;
or with jQuery
$("#targetDiv").html(targetText);

Resources