tomtomtom
tomtomtom

Reputation: 1522

modify circle elements by event listener on text matching id of circle

first of all sorry for the long title, I couldn't come up with a better one to explain my problem.
What I have is a scatterplot, with circles that have different ids based on the d.FamilyName column in my csv. Some circles share the same id.
On the right of that scatterplot, I set up a div, containing a list of all the d.Familyname values, nested to have them show just once. The id of every text is also set by d.FamilyName.
To improve readability of the scatterplot, since it has many values, I was planning to add an event listener on mouseover on the text, which should then modify the radius of the circles sharing the same id as the text.
Every circle is plotted inside the var circle and the text is plotted inside a div, here's the code for the circle and the text part:

var circle = svg.append("g")
                .attr("id", "circles")
                .selectAll("circle")
                .data(dataset)
                .enter()
                .append("circle")
                .attr("cx", function (d) { return x(d.SquadraturaInterna_o); })
                .attr("cy", function (d) { return y(d.SquadraturaEsterna_o); })
                .attr("r", 2)

After the radius attribute there's an event listener to show other values of the specified circle (the name and coordinates) but they are not relevant to my problem I think. The text part:

d3.select("#elenco")
.select("#value")
.selectAll("text")
.data(nested)
.enter()
.append("p")
.append("text")
.attr("id", function (i) { return (i).key; })
.text(function (i) { return (i).key; })
.on("mouseover", function (d, i) {
            if (this.id == circle.id) 
            {d3.select("circle")
                .attr("r", 5);
            }
            else {d3.select("circle").attr("r", 1);}

        ;})
.on("mouseout", function (d, i) {
            d3.selectAll("circle")
                .attr("r", 2);
    });

The problem is of course on the if statement in the mouseover.
Any hint on how to solve this would be really appreciated, thanks!

EDIT: Thanks to @Lars' reply I was able to make this work with a little edit to his code, like so:

.on("mouseover", function (d) {
    var sel = this.id;
    circle.filter(function() { return this.id === sel; }).attr("r", 5); })
.on("mouseout", function (d, i) {
            d3.selectAll("circle")
                .attr("r", 2); }
    );

Upvotes: 0

Views: 142

Answers (2)

Lars Kotthoff
Lars Kotthoff

Reputation: 109242

As an alternative to @musically_ut's approach, you can also use the .filter() function to modify only the elements you want.

.on("mouseover", function(d) {
    circle.filter(function() { return this.id === d.FamilyName; }).attr("r", 5);
})
.on("mouseout", function(d) {
    circle.filter(function() { return this.id === d.FamilyName; }).attr("r", 1);
})

Upvotes: 2

musically_ut
musically_ut

Reputation: 34288

I think you are looking for this:

    .on("mouseover", function (d, i) {
        circles.attr('r', function (circle_d, i) { 
            return (d.id == circle_d.id) ? 5 : 1; 
        });
    })

In D3, the this in the accessor functions refers to the DOM element. If you wanted to compare the id of the DOM element with circle's data's ids, then you could do something like this kind: d3.select(this).attr('id') == circle_d.id (cache d3.select(this).attr('id') for performance reasons).

Upvotes: 2

Related Questions