Famous/framework

Events on plain DOM elements triggered multiple times

Imti opened this issue · 0 comments

Imti commented

Base Example

FamousFramework.component('famous-tests:html-element-events', {
    behaviors: {
        '.container': {
            'size': [200, 200],
            'align': [0.5, 0.5],
            'mount-point': [0.5, 0.5]
        }
    },
    events: {
        '.button': {
            'click': function($event) {
                console.log('$event: ', $event);
                // Actual behavior: above gets logged three times
                // Expected behavior: above gets logged once
            }
        }
    },
    states: {},
    tree: `
        <node class="container">
            <button class="button"> Button 1 </button>
            <button class="button"> Button 2 </button>
            <button class="button"> Button 3 </button>
        </node>
    `
});

Problem:

Since the content of nodes are passed to the engine as strings, we can't attach events on to the plain dom elements. A workaround implemented by the framework is to crawl up the tree and attach the event on to the parent node containing the content. This will work for most cases. It breaks in this case since we end up having 3 click events getting attached to the parent node ('.container' in the above example).

Solution:

On the framework level, we can attach attributes to the underlying plain dom elements in our detached dom. We would still attach the event to the parent node, but when we get the event, we would read the current target and invoke its listeners. However, the event object we get back from the Famous Engine is stripped and we cannot read the currentTarget. Ultimately, this will require an update to the Famous Engine.

Temporary Workaround

In the meantime, wrap each html element in a node like so:

<node class="container">
    <node>  <button class="button"> Button 1 </button>  </node>
    <node>  <button class="button"> Button 2 </button>  </node>
    <node>  <button class="button"> Button 3 </button>  </node>
</node>

And attach events as normal.