1

I'm writing an application and I need to return a class of an element that I have clicked on.

Problem is that once I click on an element, I also get all of it's parents classes.

Code I use to retrieve class names:

$('div').click(function () {
    console.log($(this).attr("class"));
});

This is a sample of elements:

<div class="parent">
    <div class="child">
        Bla bla bla
    </div>
</div>

Once I click on a .child div, it returns me both .child and .parent class names.

I suppose there should be an easy way to fix this, but after a couple of hours of research I couldn't find anything.

gdoron is supporting Monica
  • 142,542
  • 55
  • 282
  • 355
Alvydas
  • 354
  • 1
  • 5
  • 15

7 Answers7

5

You need to prevent the event from bubbling to the parent elements, use return false;

$('div').click(function (e) {
    console.log($(this).attr("class"));
    return false; // or e.stopPropagation();

});    

return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object. ........

Read this excellent answer for more info.

With <div> there is now difference between e.stopPropagation() and return false because <div> doesn't have a default click event like <a> or <button> do.

Community
  • 1
  • 1
gdoron is supporting Monica
  • 142,542
  • 55
  • 282
  • 355
2

Don't bind to all <div> elements on the page. That's quite inefficient.

Instead...

  • use event delegation using .on(), binding one handler to the body

  • have the delegation selector test for 'div'

  • then get the .className from the this that was clicked


$('body').on('click', 'div', function(e) {
    console.log(this.className);
    e.stopPropagation();
});

So now you have one handler doing the work for all <div> elements.

If you're using an older version of jQuery, use .delegate() instead of .on().

$('body').delegate('div', 'click', function(e) {
    console.log(this.className);
    e.stopPropagation();
});

EDIT: Updated to use this instead of e.target as suggested by @gdoron.

Community
  • 1
  • 1
  • If the selector of the delegate is 'div' won't it just be `this`? Anyway are you sure that attaching a dynamic delegate to 'body' is more efficient than bind an event to all the divs? It's hard to believe. – gdoron is supporting Monica Jan 31 '12 at 18:03
  • @gdoron: If there are many divs on the page that should get the same handler, then it will require less memory overhead to bind only one. There is more processing to do per click, but click events don't happen frequently like scroll or mousemove events. But you're right, I could just use `this`. For some reason I was thinking there would be issues with the nested elements, but it seems that there are not. –  Jan 31 '12 at 18:08
  • @gdoron: Philosophical difference. :) –  Jan 31 '12 at 18:17
1

You need to prevent the click from "bubbling" up to its parent.

In native Javascript you would call ev.stopPropagation() but in jQuery handlers you can just return false in the event handler and jQuery then does the rest.

See JSFiddle for demo.

Alnitak
  • 325,660
  • 70
  • 395
  • 481
0

You added click event to all DIV elements but you need only one.

$('div.child').click(function () {
    console.log($(this).attr("class"));
});
Māris Kiseļovs
  • 16,389
  • 5
  • 39
  • 48
0

try to use return false

$('div').click(function() {
    console.log($(this).attr("class"));
    return false;
});
Mattia Larentis
  • 182
  • 1
  • 6
0

You can stop propagation using event.stopPropagation();

$('div').click(function (e) {
    console.log($(this).attr("class"));
    e.stopPropagation();
});
Jamie Dixon
  • 51,570
  • 19
  • 123
  • 158
0

It's because you have included elements. And function executes twice. Once in .child and once in .parent Try,

<div class="parent">BLA BLA</div>
<div class="child">bla bla bla</div>

And see the difference.

sly
  • 149
  • 1
  • 5