Becklyn / mojave

A library of commonly used JavaScript tools and helpers by Becklyn
BSD 3-Clause "New" or "Revised" License
5 stars 3 forks source link

`live` doesn't act like `on` for nested elements #63

Closed keichinger closed 7 years ago

keichinger commented 7 years ago

Reproducing

The following HTML is given:

<a href="..." class="my-awesome-link">
    <strong>Some label</strong>
</a>

Trying to capture click events using on is working as expected:

on(find(".my-awesome-link", this.someHtmlContainer), "click", (event) => {
    event.preventDefault();
    console.log(event);
});

Clicking either the <a> or the <strong> is producing a print to the console. However, with live it doesn't work:

live(this.someHtmlContainer, ".my-awesome-link", "click", (event) => {
    event.preventDefault();
    console.log(event);
});

Expected behaviour

The expected behaviour is that live should also be able to capture clicks on the nested <strong> element so I don't have to explicitly click the <a> and nothing else.

apfelbox commented 7 years ago

Thank you.

The cause of this problem is, that only the direct event source is checked, whether it matches the selector and it doesn't check anything in between. So in your example the triggering node is a nested node of your selector.

A fix would be something like modifying the delegate event callback to expand the checks to something like this:

  1. check whether the source matches. If yes -> callback
  2. check whether there is a closest with the given selector between *) the source and the node. If yes -> callback
  3. else -> skip

*) This is up for debate, whether this should trigger:

// Element.matches(element,  ".element") === true
delegate(element, ".element", "click", () => console.log("ohai"));
trigger(element, "click");

or whether only real children should match the delegate.

apfelbox commented 7 years ago

Only real children trigger, as this is the common implementation and a sensible default. This is already implemented in master.