Question

When a user clicks on a link, I'm trying to check if that link's container has a class of active assigned to it.

But I think I'm having a problem with scoping, as while the visual style is applied by the browser, the click isn't seeing that class assignment when it's triggered.

I've created a jsfiddle replicating the problem. Enlightenment much appreciated.

Was it helpful?

Solution

$link is out of scope for the annoynmous function inside your handler. You need to use $(this) inside the click handler instead:

$links.each( function(i) {
    $link = $(this);
    $link.click( function(e) {
        e.preventDefault();
        console.log('L' + i + ': ' + $(this).parent().hasClass('active'));
    });
});

See the updated jsFiddle.


You can also use event data to act as closures if you have to solve this without using $(this), for example:

$links.each( function(i) {
    $link = $(this);
    $link.click({ link : $link }, function(e) {
        e.preventDefault();
        //console.log('L' + i + ': ' + $(this).parent().hasClass('active'));
        e.data.link.parent();
    });
});

OTHER TIPS

Or you could use on

$controls.on("click", "a", function(e) {
    e.preventDefault();
    var theParent = $(this).parent();
    //if you need 'i' here it is
    var i = $.inArray(theParent[0], $controls);
    console.log('L' + i + ': ' + theParent.hasClass('active'));
});

http://jsfiddle.net/F69nh/6/

Simplify your JavaScript like so:

var $controls = $('#controls li');
var $links = $('a', $controls);
var $control, $link;

$controls.each( function(i) {
    $control = $(this);
    if (i == 0) {
        $control.addClass('active');
    }
    console.log('C' + i + ': ' + $control.hasClass('active'));
});

$links.click(function(e) {
    e.preventDefault();
    console.log('L' + $(this).index() + ': ' + $(this).parent().hasClass('active'));
});

One solution could be to use the var keyword to reduce the scope of your variable :

$links.each(function () {
    var $link = $(this);
    ...
});

Global scope demo :

var a = 1;
function f(v) { a = v; };
console.log(a); // 1
f(2);
console.log(a); // 2

Local scope demo :

var a = 1;
function f(v) { var a = v; };
console.log(a); // 1
f(2);
console.log(a); // 1

Check this great post about javascript scoping.

Here's another approach for a possible menu: http://jsfiddle.net/earthdesigner/7uxcg/1/

The javascript portion:

$(document).ready(function(){
    $('nav a').click(function(){
        $('nav li').removeClass('active');
        $(this).parent().addClass('active');
    })  
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top