thekitchensink
thekitchensink

Reputation: 35

javascript variable does not pass correct value to jquery click event handler (probably a scoping issue)

This is my first question on stackoverflow so hopefully I'm doing it right.

I ran into an issue where a variable was passing a seemingly strange value through a click event. I figured out a different way to do it, but I'm curious as to why my original method wasn't working. I have a feeling it is a weird scoping rule of JS, so if someone could clarify, that would be great. The code was supposed to switch back and forth between two tabs on a click event. I'm sorry if this has already been answered, but in looking at others' questions I couldn't really tell if it was the same issue that I was having.

This was my original code, where at program start tab1 had the class active-tab:

$("#tab1").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
                        tab1Clicked: true}, changeTab);
$("#tab2").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
                        tab1Clicked: false}, changeTab);

and elsewhere

function changeTab(event) {
    var tab1Active = event.data.activeTab;
    var tab1WasClicked = event.data.tab1Clicked;

    if(tab1Active) {
        if(tab1WasClicked)
            alert("tab1 active & clicked, no change");
        else {
            alert("tab1 active, tab2 clicked, change");
            $("#tab1").removeClass("active-tab");
            $("#tab2").addClass("active-tab");
        }
    }
    else {//tab2 is active
        if(tab1WasClicked) {
            alert("tab2 active, tab1 clicked, change");
            $("#tab2").removeClass("active-tab");
            $("#tab1").addClass("active-tab");
        }
        else
            alert("tab2 active & clicked, no change");
    }        
}

The problem was that, although the .hasClass calls returned the correct result, the value of event.data.activeTab always turned out to be true, so once tab2 got clicked it never made tab1 active again because it always thought it already was, even though the class did in fact get removed. I solved this by passing only tab1Clicked through event.data and just checking $("#tab1").hasClass("active-tab") directly in the function changeTab, which is probably what I should have been doing from the beginning, but still, can someone explain to me why this other method didn't work equally well?

Upvotes: 2

Views: 152

Answers (1)

Pointy
Pointy

Reputation: 413757

The "data" expressions are evaluated once, at the point where the event handler is set up. They aren't (and can't be) re-evaluated for each actual event. This code:

$("#tab1").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
                    tab1Clicked: true}, changeTab);

is evaluated by computing the value expressions for that data object. What's passed to the jQuery .on() function therefore is an object with two properties, each with a fixed value (booleans, in this case). They'll never change after that, because there's no trace of the expressions that initialized the property values.

In this case, the simplest solution is to simply move the tests into the function, as you say.

Upvotes: 2

Related Questions