Daniyal Shahrokhian
Daniyal Shahrokhian

Reputation: 383

D3 function to be called on mouse click (weird behaviour)

I was wondering if you could help me out with a doubt I have regarding D3. I have spent all night fixing a bug, and after fixing it I still don't understand what's going on.

Refeer to the following code:

svg = d3.select("body")
        .append("svg")
        .attr("width", window.bboxWidth)
        .attr("height", window.bboxHeight)
        .attr("style", "cursor:crosshair")
        .on("click", addSite())

function addSite() {
    console.log("hue")
}

and it's variant with the function declared inline

svg = d3.select("body")
    .append("svg")
    .attr("width", window.bboxWidth)
    .attr("height", window.bboxHeight)
    .attr("style", "cursor:crosshair")
    .on("click", function() {
        console.log("hue")
    })

I don't understand why, but if I use the first variant, the code is executed without clicking, and in the second case it works perfectly. I create the svg inside an init function that is called onload() of the body of the HTML.

This gave a headache, because I was trying to use d3.mouse(this) to retrieve the coordinates of the mouse and it was giving me the error "TypeError t is null" (even when using select("svg") instead of this. After discovering this I realized that it was giving me such error because the method was being called without having anything initialized.

Upvotes: 2

Views: 106

Answers (1)

LeartS
LeartS

Reputation: 2896

The two are not equivalent. the parenthesis after addSite() call the addSite function, which means that the return value will be passed as the callback to .on, and not the addSite function itself!

The same thing would happen in the second snippet if you add () after the inline definition: the inline function would be called immediately and its return value (so, nothing) would be passed as callback to .on, exactly like your first snippet.

Just pass addSite without parenthesis:

svg = d3.select("body")
        .append("svg")
        .attr("width", window.bboxWidth)
        .attr("height", window.bboxHeight)
        .attr("style", "cursor:crosshair")
        .on("click", addSite)  // Don't call it! 

function addSite() {
    console.log("hue")
}

Upvotes: 2

Related Questions