d3.select(this) works on mouseover, but not on function called in mouseover

  • A+
Category:Languages

I am new to javascript and currently struggling with selecting the this object while trying to do a d3 selection. I've made the following example, with a function I'm calling, and an on mousemove event:

function changeFont() {   d3.select(this)     .attr('font-size', '2em') }  ... .on('mousemove', function() {   var mouse = d3.mouse(this);   var xVal = mouse[0];    // this would work, but not when its called in a function   // d3.select(this)   //  .attr('font-size', '2em')    // this works   d3.select(this)    .attr("opacity", 1)    // this doesnt   changeFont() }); 

In my main script not shown here, I am organizing my code by writing functions that handle each of the mousemove, mouseover, etc. effects. However because of these functions, I am running into this problem where I can't do d3.select(this) inside of that mouseover function... Any thoughts on what I should be doing differently?

Should I pass this as a parameter to my changeFont() function? Or should I access this in a different way?

Thanks!


Although Andrew's answer might be the best fit if you take the question literally, I would like to add my two cents to it. Your real problem does not seem to be to get a hold of this, but to repeatedly get access to that element to apply you manipulations. Since fiddling around with this can be a pain in JavaScript it might be worth taking a slightly different approach by directly passing the selection instead. This will also improve performance as there is no need to re-select this over and over again.

First, let us slightly refactor your changeFont() function to accept a selection object.

function changeFont(selection) {   selection     .attr('font-size', '2em'); } 

Note, how this makes the function more generally applicable as it does not make any assumptions about the selection passed into it. It could be your d3.select(this), a selection containing multiple elements or any other D3 selection object. Additionally, you do not need to preserve the previous this scope.

There are basically two ways of calling this function.

  1. The obvious one will directly pass the selection as an argument when calling the function:

    const d3This = d3.select(this); changeFont(d3This); 
  2. Fortunately, there is a more elegant way of doing it by resorting to D3's own selection.call() which even allows for method chaining if you need to do multiple calls on the same selection.

    function changeFont(selection) { selection.attr("font-size", "2em"); } function changeFill(selection) { selection.attr("fill", "limegreen"); } function changeOpacity(selection) { selection.attr("opacity", "0.1"); }  // ... .on("mouseover", function() {   // Call the functions for this element.   d3.select(this)     .call(changeFont)     .call(changeFill)     .call(changeOpacity);    // Instead, you could also apply the same pattern to all texts.   d3.selectAll("text")     .call(changeFont)     .call(changeFill)     .call(changeOpacity);  } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: