15

Here is a simple example of the problem:

<body>
  <button id="parent"  onclick="alert('parent')">
      <span id="child" onclick="alert('child')">Authenticate</span>
  </button>
</body>

In Chrome this alerts "child" then "parent", but in IE/FF we only get "Parent".

Clearly this can be fixed in a number of ways (change button to div, remove span etc.), but I wanted to find out if there was a way to make this work (i.e. alert "child") without changing the HTML.

Thanks!

PS: Tried JQuery and that has same behaviour.

  • Sounds like in one browser the event bubbles to the top, in the other not. Or something like that... I'm not an expert in 'event bubbling', but that's the search term I think will yield results! – Jonathan Nicol Jun 17 '12 at 06:54
  • @JonathanNicol, this is not event bubbling, it's event tunnelling. – Zephyr was a Friend of Mine Jun 17 '12 at 06:56
  • 6
    Putting a clickable element inside a ` – mu is too short Jun 17 '12 at 07:10
  • just to say, in firefox if you replace the buttons with divs, it alerts "child" then "parent" : http://jsfiddle.net/mageek/gcB6w/1/ – Alexandre Khoury Jun 17 '12 at 08:40
  • @muistooshort, the scenario is that we want the styling and semantics of the parent button element, but we want to compose the button itself using an arbitrary number of child elements - each of which should be clickable. – Zephyr was a Friend of Mine Jun 17 '12 at 12:01
  • 4
    Sorry but that still doesn't make any sense. A `` and `` are [explicitly forbidden](http://dev.w3.org/html5/markup/button.submit.html#button.submit-constraints) so I suspect that you will never get this to work. You're trying to abuse ` – mu is too short Jun 17 '12 at 17:27
  • @muistooshort, works in Chrome. I don't think it is abuse:it gives a designer the flexibility to style the innards of a button. But really, I'd rather not get involved in a theoretical debate ATM. Thanks for trying. – Zephyr was a Friend of Mine Jun 17 '12 at 17:37
  • 1
    How would you expect a screen reader to deal with such a bizarre construct? I fail to see what click events have to do with styling. You're making a mistake, rethink your design. – mu is too short Jun 17 '12 at 18:05
  • Perhaps a little visual experiment might help. Think about the fried egg you may have had for breakfast this morning. Now we'd like you to be able to poke the yolk of that egg with your finger and get a reaction, at the same time we'd like a similar behaviour when you decide to poke the egg-white. We could replace the egg-white with a div, but then it wouldn't react like a button. Whether this is aesthetically pleasing or not, really, is subjective - I personally prefer poached eggs. – Zephyr was a Friend of Mine Jun 18 '12 at 10:09
  • 2
    Your code gives [undefined behaviour by definition](http://stackoverflow.com/a/17253457/1729885). – Niels Keurentjes Jan 07 '14 at 10:33
  • have you seen [this](http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false) – Enermis Jan 07 '14 at 10:36
  • Check this post : http://stackoverflow.com/questions/14689879/span-inside-button-is-not-clickable-in-ff – christof13 Feb 17 '14 at 15:11

2 Answers2

2

As @muistooshort said, handling click events inside other click events seems unnatural. I also think you have to rethink your design.

That being said, you can handle a single click event on your main container and then check which element was the source of the click

This would be the way to go, considering your use case, imo:

$('your-button-container').click(function(event){
    console.log(event.originalEvent.srcElement);
});

Make the necessary checks on event.originalEvent.srcElement and act accordingly.

Edit: Not using JQuery, it would go like this:

yourButtonContainer.addEventListener(function(event){
    console.log(event.srcElement);
});
Antoine Combes
  • 1,444
  • 8
  • 13
  • The specified answer is not working for Firefox Version and works just in Chrome and Safari. So, not a generic fix. – Akansh Nov 01 '18 at 21:10
0

As mentioned by a few users, it is not good practice to nest buttons like that, but for educational purposes, I'd do it this way:

HTML:

<body>
  <button id="parent" onclick="callFn(event, 'parent')">
    <span id="child" onclick="callFn(event, 'child')">Authenticate</span>
  </button>
</body>

JS:

window.callFn = function(evt, type) {
  if (type === 'child') {
    alert(type);
  }
}

JS Fiddle: https://jsfiddle.net/4vo3arpf/4/

kayasky
  • 638
  • 1
  • 9
  • 16