user3502374
user3502374

Reputation: 779

how to not fire its children when parent is clicked? (vanilla javascript)

[Final Edit: I feel compel to response as I learned a LOT from this post(mainly through you guys, and I spend more time understanding CSS.. but at the end, I really don't have any good idea how to make this work.. other than really destroying the basic structure of html.. which I didn't want to do. but I did... (for whatever reason #parent>* { color: black } would not work when I click on child)..

Here's what i did but if you now know what I was trying to do.. please see if you can correct me w/ real answer as I feel like this can't be this hackery to get it going.

CSS

.red {
    color: red;
}

div[id*="child"] {
    color: black;
}

div [id*="alterChild"]{
    color: green;

JS

;(function(){

    let parentId = document.getElementById('parent');

    parentId.addEventListener('click', function(e){
        if (e.target.id === 'parent') {
            e.target.className = "red";
        } else {
            e.target.setAttribute("id", "alterChild");
        }
    },false);
})(

HTML

<div id="main">MAIN
    <div id="parent">parent
        <div id="child1">child1</div>
        <div id="child2">child2</div>
        <div id="child3">child3</div>
    </div>
</div

__________END OF FINAL EDIT___________

So I want to fire only on parent when parent is clicked. Below code, it fires on parent + all its children. How can I prevent this? I try w/ stop/prevent both before and after to see if I have any luck.

Please advise.

        <div id="main">MAIN
            <div id="parent">parent
                <div id="child1">child1</div>
                <div id="child2">child2</div>
                <div id="child3">child3</div>
            </div>
        </div>

      ;(function(){

        let parentId = document.getElementById('parent');

        parentId.addEventListener('click', function(e){
            e.stopPropagation();
            e.preventDefault();
            e.target.className = "red";
            e.stopPropagation();
            e.preventDefault();

        },false);
    })()

Upvotes: 0

Views: 672

Answers (5)

tauzN
tauzN

Reputation: 6931

Check that the current target is the expected element:

document.getElementById("overlay").addEventListener("click", (event) => {
  if (event.target.id === "overlay") {
    document.getElementById("overlay").style.display = "none";
  }
})

Upvotes: 0

user128511
user128511

Reputation:

  • when click on parent, only parent should get class "red". (and not it's children).

The issue here is your CSS style is applying to the children. CSS stands for Cascading Style Sheet where "Cascading" means "applies to children"

After clicking parent you end up with this

.red {
  color: red;
}
<div id="main">MAIN
    <div id="parent" class="red">parent
        <div id="child1">child1</div>
        <div id="child2">child2</div>
        <div id="child3">child3</div>
    </div>
</div>

The fact that the children changed to red has nothing to do with events. It's normal for children to change based on their parent's CSS

If you want to children to not inherit the color of their parent you need to set their color explicitly

.red {
  color: red;
}
#parent>* {  
  color: black;
}

/* these would also work

    div[id^=child]  
    #child1, #child2, #child3
    #parent>div

*/
<div id="main">MAIN
    <div id="parent" class="red">parent
        <div id="child1">child1</div>
        <div id="child2">child2</div>
        <div id="child3">child3</div>
    </div>
</div>

Example:

;
(function() {

  const parentId = document.getElementById('parent');

  parentId.addEventListener('click', function(e) {
    e.target.className = "red";
  }, false);
})()
.red {
  color: red;
}
#parent>* {
  color: black;
}
<div id="main">MAIN
  <div id="parent">parent
    <div id="child1">child1</div>
    <div id="child2">child2</div>
    <div id="child3">child3</div>
  </div>
</div>

  • When any child is clicked, no parent should be red nor any other none clicked child

This is a different issue. When you click any child the event listener will be triggered. e.target will be the element that was actually clicked on so if you clicked a child it will be that child

One way to solve this would be to check the target is the parent.

      const parentId = document.getElementById('parent');

      parentId.addEventListener('click', function(e) {
        if (e.target === parentId) {
          e.target.className = "red";
        }
      }, false);

Upvotes: 1

displayName
displayName

Reputation: 1106

You need to stop propagation on children click

<html>

  <head></head>

  <body>
    <div id="main">MAIN
      <div id="parent">parent
        <div id="child1">child1</div>
        <div id="child2">child2</div>
        <div id="child3">child3</div>
      </div>
    </div>
    <script>
      (function() {
        let parent = document.getElementById('parent');
        parent.addEventListener('click', function(e) {
          console.log('parent clicked');
        }, false);
        const children = document.querySelectorAll('#parent>div');
        children.forEach(child => {
          child.addEventListener('click', function(e) {
            console.log('child clicked');
            e.stopPropagation();
          })
        })
      })()

    </script>
  </body>

</html>

https://jsfiddle.net/1xnow7jz/

Upvotes: 0

Felix Kling
Felix Kling

Reputation: 816404

You can check inside the handler whether the element that triggered the event (the target) is the element the handler is bound to (this):

parentId.addEventListener('click', function(e){
  if (e.target === this) {
    e.target.className = "red";
  }
}, false);

https://developer.mozilla.org/en-US/docs/Web/API/Event/target

Upvotes: 0

Dacre Denny
Dacre Denny

Reputation: 30360

There are a few ways to achieve this - one approach would be to examine the id attribute of the currentTarget on the event object for the users click action:

const div1 = document.createElement('div');
div1.className = 'foo';

let mainId = document.getElementById('main');
let parentId = document.getElementById('parent');

parentId.addEventListener('click', function(e) {

  /* Check the id of the currentTarget element to see if it's the "parent" */
  if (e.currentTarget.id === 'parent') {

    /* .. and if so, assing the "red" class */
    e.target.className = "red";
  } else {

    /* ..otherwise, stop event propagation and behaviour */
    e.stopPropagation();
    e.preventDefault();
  }

}, false);
.red {
  background: red;
}

#parent {
  padding: 1rem;
}

#child1,
#child2,
#child3 {
  background: yellow;
}
<body>
  <div id="main">MAIN
    <div id="parent">parent
      <div id="child1">child1</div>
      <div id="child2">child2</div>
      <div id="child3">child3</div>
    </div>
  </div>

Upvotes: 0

Related Questions