3

I have a button that does the following:

  1. When pressed, the button removes a class (1) and adds another one (2). This works.
  2. When pressed again, I want to remove the second class (2) and add the first one (1). This does not work.

Sort of like a toggle.

This is the code:

HTML:

<button class="follow_btn btn btn-success" value="1">Follow</button>

CSS:

.btn {
    padding:1em;
}
.btn-success {
    background:green;
}
.btn-danger {
    background:red;
}

jQuery:

$('.follow_btn').on("click", function () {
    var this_btn = $(this);
    this_btn.removeClass("btn-success follow_btn").addClass("btn-danger unfollow_btn");
});

$('.unfollow_btn').on("click", function () {
    var this_btn = $(this);
    this_btn.removeClass("btn-danger unfollow_btn").addClass("btn-success follow_btn");
});

and a JSFiddle showing my problem:

http://jsfiddle.net/thedarklord1939/pGuue/

Why is this doing not working? If this is not clear enough, I will elaborate. Thank you.

Tiffany Lowe
  • 729
  • 1
  • 9
  • 26
  • possible duplicate of [Events triggered by dynamically generated element are not captured by event handler](http://stackoverflow.com/questions/12829963/events-triggered-by-dynamically-generated-element-are-not-captured-by-event-hand) – Felix Kling Feb 23 '14 at 22:47

4 Answers4

2

I have a working jsfiddle here, this is because of a problem binding elements that don't exist when you execute the code that binds events. Tell me if it's clear or not, I can be more detailed.

So this is the key: $(document).on("click", '.unfollow_btn', function () {

Lorenzo S
  • 1,375
  • 11
  • 23
2

It was already said about event delagation, so I will propose one more way to do it even shorter using toggleClass (we need two of them because we need to toggle two pairs at the same time):

$('.follow_btn').on("click", function () {
    $(this).toggleClass('unfollow_btn follow_btn').toggleClass('btn-danger btn-success')
});

Demo: http://jsfiddle.net/pGuue/3/

And the final touch, how to execute different code depending on current button class:

$('.follow_btn').on("click", function () {

    if ($(this).hasClass('follow_btn')) {
        alert('Follow');    
    }
    else {
        alert('Unfollow');
    }

    $(this).toggleClass('unfollow_btn follow_btn').toggleClass('btn-danger btn-success');
});

Demo: http://jsfiddle.net/pGuue/4/

dfsq
  • 182,609
  • 24
  • 222
  • 242
  • Thank you! This code was just the tip of an iceberg. I actually have some AJAX interacting with a database on click. I do not know enough to make it as efficient as this (I do not know if it's possible to do so with this method) but thanks again. – Tiffany Lowe Feb 23 '14 at 22:10
  • The initial selector needs to be for both classes or you miss any buttons stating as `unfollow_btn`. – Sam R Feb 23 '14 at 22:16
  • @SamR It's true. I will not correct my answer though, yours is actually better so you should get credits. – dfsq Feb 23 '14 at 22:17
1

The click handlers are only set once, so the button only has the follow click handler, and still has it even after you remove the follow_btn class.

You can solve this two ways:

1) Use the same click handler for both follow and unfollow, and check which it is when you execute the function:

$('.follow_btn, .unfollow_btn').on("click", function() {
    var $btn = $(this),
        isFollow = $btn.hasClass('follow_btn');

    $btn.toggleClass("btn-danger unfollow_btn btn-success follow_btn");

    if (isFollow) {
        ...
    } else {
        ...
    }
});

2) Use a delegate-style event handler, like Lorenzo suggests. If you go with this solution, it is preferable to use the closest object that contains all the buttons; otherwise the document-level event handler has to check every click that bubbles up to see if it matches follow-btn or unfollow-btn.

Sam R
  • 667
  • 3
  • 6
0

i dont think there is a need to listen to a click event on the whole document. here is my solution:

Jsfiddle

$('.follow_btn').on("click", function () {
    var this_btn = $(this);
    if(this_btn.hasClass("follow_btn")){
      this_btn.removeClass("btn-success follow_btn").addClass("btn-danger unfollow_btn");
    }
    else{
      this_btn.removeClass("btn-danger unfollow_btn").addClass("btn-success follow_btn");
    }
});
Gyandeep
  • 10,438
  • 3
  • 27
  • 40
  • This only works if all buttons start out as `follow_btn`. The initial selector needs to be for *both* or you risk missing some of the buttons. – Sam R Feb 23 '14 at 22:14