freshyill
freshyill

Reputation: 393

jQuery removeClass() not working

I might just blame this on lack of sleep, but I'm having a hell of a time removing a class from some links.

Here's what's happening: I'm adding a class to a bunch of links when I check a checkbox, and then I hope to remove remove the class by unchecking the checkbox.

Also involved: Changing a class on the checkbox, which does work when I uncheck it. It just doesn't also remove the classes.

Here it is on jsFiddle

$(document).ready(function() {
    var revealer = $('.revealer .reveal');
    var hider = $('.revealer .hide');
    var days = $('.days li a');
    var revealed = $('.days li a.revealed');

    $(revealer).change(function() {
        $(this).toggleClass('reveal hide');
        $(days).each(function(i) {
            var day = $(this);
            setTimeout(function() {

                // $(day).toggleClass('revealed'); Toggle would work, but I don't want the delay when removing the class
                $(day).addClass('revealed');
            }, 300 * i);
        });
    });

    $(hider).change(function() {
        $(this).toggleClass('reveal hide');
        $(revealed).removeClass('revealed');
    });

});

In the jsFiddle, each link's background fades to black, one at a time. That much works. Unchecking should fade them all back to normal at once, but it doesn't.

Upvotes: 0

Views: 15327

Answers (4)

Andy Ray
Andy Ray

Reputation: 32076

There is no element with .hide as a class, so hider is never populated. As a quick and dumb fix, change

$(day).addClass('revealed');

to

$(day).toggleClass('revealed');

and delete your $(hider).change function

Then the checkbox in the fiddle works to some extent, and I'm sure you can figure it out from there.

Upvotes: 0

Pipalayan Nayak
Pipalayan Nayak

Reputation: 957

As others have pointed out, your code has the following issue:

  1. You are caching the jquery objects and binding the functions to them. So this is a problem because at the time of function binding, there is no element in the dom which satisfies the selector e.g $('.revealer .hide'). If you want to use these selectors, then you would have to use live function in jquery. http://api.jquery.com/live/

2.Else you can use an id selector on the checkbox and bind your functions accordingly.

Upvotes: 0

numbers1311407
numbers1311407

Reputation: 34072

The problem is that you're trying to cache states, rather than elements.

At the start of your script you cache $('.revealer .reveal') and $('.revealer .hide'), which are states that one element toggles between. It just doesn't work this way.

What happens is that you cache the matched element as revealer, and bind the first change function to it. What you think you're caching as hider is an empty set, as there is no matching element at the time your script loads. So your 2nd bind does nothing.

What you should do instead is change your change function to react differently based on the current class of the .revealer, or use live in place of typical binding, which does essentially what you are trying to do (essentially it watches for selector patterns, rather than binding to elements).

Upvotes: 1

mu is too short
mu is too short

Reputation: 434955

Your problem is that there is no .revealer .hide when this runs:

var hider = $('.revealer .hide');

So hider is an empty list. You have similar problems with your other selectors: selectors match elements in the DOM as the DOM is when you use the selector. So when you say $('.revealer .hide').change(...) you're binding a change handler to whatever elements currently match .revealer .hide, if the elements that match change in the future then your change handler will not be bound to them (but see below for the standard solution to this sort of problem); similarly, if you remove the hide class from your checkbox and then put it back later (i.e. toggleClass) then your original change handler will still be bound to your checkbox: changes to the element's classes do not affect which handlers are or are not bound to it.

If we get rid of your cached selectors and switch your change handlers to use live then things will work:

$('.revealer .reveal').live('change', function() {
    $(this).toggleClass('reveal hide');
    $('.days li a').each(function(i) {
        var day = $(this);
        setTimeout(function() {
           day.addClass('revealed');
        }, 300 * i);
    });
});

$('.revealer .hide').live('change', function() {
    $(this).toggleClass('reveal hide');
    $('.days li a.revealed').removeClass('revealed');
});

Live version: http://jsfiddle.net/ambiguous/FaZkR/

The live and delegate functions act as proxies, they capture and redirect events based on the current state of the DOM rather than the state of the DOM when you are initially called.

Upvotes: 2

Related Questions