1

Originally I was doing this:

button.addEventListener('click', function(e) {
    e.preventDefault();
    var clickedButton = this;
}

However, I need to listen out for a button which is dynamically added to the DOM. So now I am doing this:

document.addEventListener('click', function(e) {
    if (e.target.nodeName == "BUTTON") {
        e.preventDefault();
        var clickedButton = e.target;
    }
}

This works in the case of:

<button>Click me</button>

However, it doesn't work with:

<button><i class="icon"></i></button>

The reason it doesn't work is because e.target ends up as I instead of BUTTON, however I need to specifically target the button. Some buttons might contain an icon, whilst others might be just text, and some could be a combination of the two.

MrCarrot
  • 2,546
  • 1
  • 23
  • 29
  • The reason for that, is because there are a number of Ajax calls which can create buttons in various different places throughout the app. It's a pain to remember to have to re-add the listener in all areas where a button could be added to the document – MrCarrot Jun 14 '21 at 16:34

2 Answers2

1

You should check also .closest('button')

document.addEventListener('click', function(e) {
  if (e.target.nodeName == "BUTTON" || e.target.closest('button')) {
    e.preventDefault();
    var clickedButton = e.target;
    console.log(e.target)
  }
})
<button><i class="icon">ss</i></button>

suggestion: better match className instead of element name

prasanth
  • 22,145
  • 4
  • 29
  • 53
  • Thank you! I didn't realise, but `closest()` appears to include the element itself, and its parents. So no need for the dual check, `e.target.closest('button')` is sufficient and does what I need. Regarding your suggestion, I'm not actually targeting by element name, I just did that in the example to keep things simple. – MrCarrot Jun 14 '21 at 16:47
1

You can use CSS to disable click events on any elements nested inside a button:

Before:

document.addEventListener('click', function(e) {
    console.log(e.target);
    
    if (e.target.nodeName == "BUTTON") {
        console.log("stop");
        e.preventDefault();
        var clickedButton = e.target;
    }
})
.icon {
  background-color: purple;
  color: white;
}
<button>Click me</button>
<br/>
<button><i class="icon">image here</i></button>

After:

document.addEventListener('click', function(e) {
    console.log(e.target);
    
    if (e.target.nodeName == "BUTTON") {
        console.log("stop");
        e.preventDefault();
        var clickedButton = e.target;
    }
})
.icon {
  background-color: purple;
  color: white;
}

/* disable clicks */
button * {
  pointer-events: none;
}
<button>Click me</button>
<br/>
<button><i class="icon">image here</i></button>
VLAZ
  • 26,331
  • 9
  • 49
  • 67