Emily's original code was correct. When you call selection.on(type,
listener), you are registering a *listener* callback function for
events of the specified *type* on the given *selection*. So, the
correct form is:
.on("mouseover", onMouseOver)
This does not immediately call onMouseOver; notice that there are no
parens following it. Instead, the function is being passed as an
object, so that selection.on can register for later callback when a
mouseover event is triggered. You can think of it just like plain
JavaScript:
element.onmouseover = onMouseOver;
The other thing to note is that when you register a listener with
selection.on, the listener will be called with two arguments: the data
(d) and the index (i). So the value of `d` within the onMouseOver
function in the original code Emily posted should be the data bound to
the selection. If the value of `d` is undefined, then something else
is likely happening—something unbinding the data from those elements,
say by selection.datum(null) or an inadvertent parent.select(child)
which overwrites the data on the first element. It's tough to say
without seeing the full code.
The listener (onMouseOver) is also called with a specific `this`
context: the element that received the mouseover event. Sometimes it's
useful to access this element within the listener function, say to
d3.select(this) and then style it.
If you change the code to this:
.on("mouseover", function(d) { onMouseOver(d); })
You haven't changed the value of `d`, but now you've lost the `this`
context and dropped the second argument `i`. So there's no reason to
do that. You could use a closure as Ger suggested to capture the data
(and make it continue to work even if the data is unbound from the
selected elements), but I think that's overkill and there's likely a
problem elsewhere that needs fixing.
One last thing. If you call selection.data() with no arguments, it
returns the array of data for the first group. (See nested selections
[1] for details.) If you just want the first datum, then call
selection.datum() instead. But, you shouldn't need to
d3.select(this).datum(), since the value of `d` passed to your
listener function is exactly the same thing. If it's not, then you
need to find where the data is being unbound elsewhere in your code.
Mike
[1]
http://bost.ocks.org/mike/nest/