skip to Main Content

I have a pretty basic Bootstrap button on my page. I have an event listener listening for clicks on this button. I have an image tag as the content of the button. When a user clicks the button, the event listener fires as desired. However, if the button click lands on the image within the button, the image intercepts the click and the button click event listener doesn’t fire. How can I get the button to detect a click on both itself, and its content (e.g. the image tag)?

<button type="button" class="btn btn-custom" id="navLogoButtonLeft">
    <!-- dev tools indicate clicks land on this <img> and never make it to the <button> -->
    <img class="icon" src="img/icon.png">
</button>

Note, this is a Twitter Bootstrap button, but I’m not sure that has any bearing on the problem.

Here is the JS, by request.

var navLogoButtonLeft;

function initNav() {
    navLogoButtonLeft = document.getElementById('navLogoButtonLeft');

    // note, I've tried both 'true' and 'false' here
    navLogoButtonLeft.addEventListener('click', handleClick, true);
}

// this method does fire, but clickEvent is the <img>, not the <button>
function handleClick(clickEvent) {
    if(clickEvent.target == navLogoButtonLeft) {
        // this line cannot be reached
        window.location = './';
        return;
    }
}

window.addEventListener('load', initNav, false);

3

Answers


  1. you could just add the same event listener to the image tag to get the desired effect.

    Though you could also go to a more technical level
    and add a class that sets pointer-events: none; in the CSS and add that class to the end of your img tag

    Login or Signup to reply.
  2. Try do the inverse (and using the bubble effect) then try apply the listner to the img (in my sample I simply change the position of the id associated the listener)

    <button type="button" class="btn btn-custom" >
      // dev tools indicate clicks land on this <img> and never make
      //   it to the <button>
       <img class="icon" src="img/icon.png"  id="navLogoButtonRight"   >
    </button>
    
    Login or Signup to reply.
  3. Your dev tools are correct. When you click on the image in your button, the event target actually is the image. Nevertheless, the click event should bubble up and finally make the button’s event listener fire.

    So, if your HTML is correct (the // comments for example would break it), and you correctly added the event listener like

    var btn = document.querySelector('#navLogoButtonRight');
    
    btn.addEventListener('click', function (ev) {
     ev.stopPropagation();
     console.log('Event listener for element ' + ev.currentTarget.nodeName + '#' + ev.currentTarget.id + ' fired.');
     console.log('Clicked on ' + ev.target.nodeName);
    });
    

    the event listener should fire on click on the button as well as on any of its child elements. ev.stopPropagation(); in the handler stops the event from bubbling up any further. See a working example here: https://jsfiddle.net/quj56hq5/

    If you have to set pointer-events: none; for this to work, there’s definitely something wrong with your code or some Twitter Bootstrap JS gets in the way.

    Update

    After the JS was added by the question’s author the real cause of the problem showed. It is the line

    if(clickEvent.targe‌​t == navLogoButtonLeft) {
    

    that keeps the handler’s code from being executed when the image is clicked, because .target always is the clicked element while .currentTarget always is the element the listener was originally attached to.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search