2

Apologies for the vague title, it's kind of hard to explain in a line...

In any case, let's say I have a button with an action as defined by the data-action property. When the user clicks said button, something happens, and the button's action will change to its second state.

However, implementing this, I am finding that the event that is defined for that second state gets run automatically after the first state is triggered, as though the "click" persists past the function call and triggers the second event.

Here is a jsFiddle

One click should show the log 'transitioning to "foo"', and a second click should show the log 'transitioning to "bar"', but if you try it out, you'll see that both events are fired.

How can I stop this?

Edit: Thanks Dimitar for the help -

var action = ((this.retrieve('action', 'foo') != this.getProperty('data-action')) ? 'bar' : 'foo' );
if (action == 'foo') {
    console.log('executing "foo"');
    this.store('action', 'bar');
}
else {
    console.log('executing "bar"');
    this.store('action', 'foo');
}
1
  • edit is not.no need to go back to the dom after first run Commented Feb 17, 2012 at 19:47

2 Answers 2

2

like lorenzo said, when you delegate it and change the property, which is used as the delegation identifier, it sounds like an anti-pattern to me. I don't think that adding a delay is a good pattern either.

Either use a second property that you change on the element instead, or better yet, change a var that keeps state in element storage after initial event reads it from a property for performance.

$(document.body).addEvents({
    'click:relay([data-action=foo])': function() {
        this.store("action", ((this.retrieve("action") || this.get("data-action")) === 'foo') ? 'bar' : 'foo');
        this.set("html", 'State + ' + this.retrieve("action"));
    }
});
4
  • Interesting, I never thought of using element storage at all (or rather, I've never used element storage). I'll get back to you on this... Commented Feb 17, 2012 at 14:05
  • Thanks for the code snippet, Dimitar. I seems to have gotten it to work perfectly. I'll update the question to reflect the new code. Commented Feb 17, 2012 at 14:20
  • My last question is - how come you used $(document.body) instead of simply document.body? I was under the impression that the $(); attempted to find the element in question by reading the entire page, while document.body is already defined in the DOM... Commented Feb 17, 2012 at 14:24
  • 1
    IE. document.body is not extended by default in IE - so it may not have any methods attached to it until you pass it through a selector once. read up on it, other questions on that here. basically - Ie does not allow Element.prototype to be modded prior to 9 so mootools attaches element methods on the actual elements as you access them through a selector. Commented Feb 17, 2012 at 16:19
2

Nice situation :)

I saw that changing the order of event handlers declaration solve the problem for the first click (and postpone it for the next ones).

And, I think there is no issue on Mootools: you click the button, the event bubbles up the DOM to the body, the body check all its attach events (delegated, in your case) and stop at first because it finds a match for [data-action="bar"]. And the related function is executed. The body now continues to check for other delegation matches (it have no reason to stop!), and finds the second one [data-action="foo"] matching again.

I'm afraid you cannot avoid that without using some flag/state variable or delaying the function execution. I think this last one is the best, or at least the most concise, solution (if applicable, I don't know if the delay can cause you problems). If you delay the function execution a bit (in ms), you just jump over the delegation event checking. Demo here.

1
  • Thanks for the step-through of the problem. I can now better visualize what is happening. I initially thought of introducing a delay as well, although it seemed like a band-aid solution, and I only asked SO in case there were a more elegant solution. Thanks for your help! Commented Feb 17, 2012 at 14:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.