knitevision
knitevision

Reputation: 3143

jQuery: propagating events & actions

Sorry for the wrong title.

JSFiddle Link

Description:

I have 2 events attached to the same element that has different classes depending on it's state.

The first click event adds an expanded class and change it's text (for visibility purposes only).

The second click event is attached to the element modified by expanded class.

The Problem:

The second click event never fires. Doesn't remove the class and changes the text.


If you try it without event.stopPropagationit instantly fires both first & second click events, with first one doesn't do any visual change to the element.

jQuery

$('button').click(function() {
    $(this).addClass('expanded');
    $(this).text('Expanded class added');
    event.stopPropagation();
});
$(document).on('click','button.expanded', function() {
    $(this).removeClass('expanded');
    $(this).text('Expanded class removed')
});

The question: How do I properly execute the click events with both of them doing what they are supposed to?

Upvotes: 2

Views: 43

Answers (4)

A. Wolff
A. Wolff

Reputation: 74420

  1. Bind event on button
  2. Check if the clicked button has class expanded, if present remove it else add it.
  3. Update the innerText of the clicked element. The ternary operator used $(this).hasClass('expanded') ? "added" : "removed") will return "added" if the button has class expanded added(in second step), otherwise returns "removed".

Code:

$(document).on('click', 'button', function () {
    $(this).toggleClass('expanded') // Toggle `expanded` class of the clicked button
        .text('Expanded class ' + ($(this).hasClass('expanded') ? "added" : "removed")); // Update text
});

-DEMO-

EDIT: for the fun, to set the text button content, you can use CSS pseudo elements:

$(document).on('click','button', function() {
	$(this).toggleClass('expanded');
});
button:not([class]):before {
  content: "Click me"
}
button.expanded:after {
  content: "added";
}
button[class]:not(.expanded):after {
  content: "removed";
}
button[class]:before {
  content: "Expanded class "
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button></button>

Upvotes: 4

Yehuda Schwartz
Yehuda Schwartz

Reputation: 3503

this should do it for you

$(document).on('click', 'button', function (event) {
    $(this).toggleClass('expanded')
    if($(this).hasClass('expanded')) {
        $(this).text('Expanded class added');
    } else {
        $($this).text('Expanded class removed')
    }
    return false;
});

Upvotes: 0

Prakash
Prakash

Reputation: 576

Made this little clean and robust.

$('button').click(function() {
  $(this).toggleClass("expanded");
  if ($(this).hasClass("expanded")) {
    $(this).text('Expanded class added');
  } else {
    $(this).text('Expanded class removed')
  }
  return false;
});
.expanded {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click me</button>

Upvotes: 0

andi
andi

Reputation: 6522

I think a simpler way to think about this is to put both handlers inside the delegated click event:

$(document).on('click','button', function(event) {
    if ($(event.target).hasClass('expanded')) {
        $(event.target).removeClass('expanded');
        $(event.target).text('Expanded class removed')
  }
  else {
        $(event.target).addClass('expanded');
        $(event.target).text('Expanded class added');
  }
  return false;
});

updated fiddle: https://jsfiddle.net/jvL8z2dw/4/

Upvotes: 3

Related Questions