-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Checks if an element is able to trigger an attached delegate click event - Fixes #134 #157
Conversation
ret &= dom.triggerMatchedListeners_(container, currElement, event, defFns); | ||
currElement = currElement.parentNode; | ||
} | ||
if (dom.isAbleToInteractWith_(currElement, event.type)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This diff seems kind of messy but I've only written this if
statement.
In my opinion, this method is becoming difficult to read. Maybe we can make improvements on it. I have some suggestions:
1 - We can create a new method for checking the isAbleToInteractWith_ condition before this handleDelegateEvent_ method, or, put the logic of the handleDelegateEvent_ in a new one.
2 - We can keep the checking of isAbleToInteractWith_ here, in this method, but above the code, and then, we can return the default value of the ret
variable. For me, it is strange to return the same variable in two cases, at the end of the code and at the beginning�, but, it is an options.
I would like to hear your opinion @mairatma.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this is getting more complex. I think that the complexity is coming mainly from the for/while loops though, not just this new if case, so ideally we should instead find a way to break this method into smaller parts. There could be a function that covers to logic of running the default listeners for example, a triggerDefaultFns_(event, defFns)
, and another for the while loop in the same way. This would clean this up a lot, don't you think?
If you wish you could do this in this pr, or it could be a separate pr sent later, so that we can merge this fix sooner. For this fix to get in, the only thing missing right now is a test :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is up to you, @mairatma. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have time then sending everything would be great :) But just make sure you add the test and I'll merge, even if the refactoring comes separately later.
80bcb9b
to
b5478ce
Compare
Branch updated @mairatma |
Just started reviewing :) |
var target = element.querySelector('.match'); | ||
target.dispatchEvent(eventObj); | ||
|
||
assert.strictEqual(0, listener.callCount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test just made me notice something weird. What this test is doing is:
- Creating a disabled button with a span content.
- Listening to clicks on the span.
- Checking that the listener isn't called.
The problem is that in the browser, that listener is supposed to be called. I just tried this same use case myself in Chrome, and clicking the span will still trigger the span's listener, it will only stop triggering the button's listener, since that's the element that was disabled.
So the fact that this test is passing shows that something is wrong with the logic. The logic should be such that the span will still trigger listeners, but not the disabled button. There should be a test that listens to delegate on the button (dom.delegate(element, 'click', 'button', listener)
for example), and makes sure that clicking the span does not cause that listener to be triggered. If the listener is on the span it should keep being triggered though, so this test should be kept, but also updated to check that the callCount
is 1, not 0.
This seems to be showing that isAbleToInteractWith_
is doing the wrong check. The link that you posted on the issue explaining how this should work seems to also be saying this. It basically says that a disabled element should prevent clicks on itself, and that disabled elements are only button, input, select or textarea that are disabled (not their children too). It also mentions descendants of disabled fieldset but I also tested this on Chrome, and could only reproduce when these descendants are also button, input, select or textarea, the others still get the event triggered regardless of the parent.
So I think that we need to change isAbleToInteractWith_
to only return false if the given node is button, input, select or textarea, and is either disabled or a child of a disabled fieldset. Then, in handleDelegateEvent_
this should be called for each listener triggered in each element, not just for the first target, so probably inside triggerListeners_
instead of handleDelegateEvent_
.
Let me know if you have any questions about this, it's hard to explain it all in a single comment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, @mairatma. You are totally right. I will fix it. Thx for your help.
Guys, we should be careful with very custom methods to not become too specific. |
Which one in particular do you mean, @eduardolundgren? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes, I think this is closer to the expected behavior now 😄.
There's just one more thing related to the behavior that I've commented inline, and some other minor comments for improvements.
Other than those, could you just rename the most recent commit to explain in more detail what it's doing? It helps to have good commit titles when looking at the commit history. Also, we have a pattern of always having titles as if they're starting with the word It
, indicating that this is what it
(the commit) does. So instead of having something like Fix indentation
it would be Fixes indentation
.
@@ -318,7 +318,7 @@ function handleDelegateEvent_(event) { | |||
var limit = event.currentTarget.parentNode; | |||
var defFns = []; | |||
|
|||
while (currElement && currElement !== limit && !event.stopped) { | |||
while (currElement && isAbleToInteractWith_(currElement, event.type) && currElement !== limit && !event.stopped) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting this check here will cause us to stop propagation of the event to all elements after the disabled one, but I've just checked here in Chrome and the browser actually keeps bubbling the event upwards in this case, it only skips the disabled element itself, not its parents too. To make that work as expected I believe this check needs to be inside triggerMatchedListeners_
instead of here, so that the loop can keep going on even when the event is not triggered for a given element.
@@ -265,11 +265,11 @@ export function delegate(element, eventName, selectorOrTarget, callback, opt_def | |||
function isAbleToInteractWith_(node, eventName) { | |||
var currElement = node; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method could be simplified now by using the parent
function in this file, for example:
function isAbleToInteractWith_(node, eventName) {
var matchesSelector = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'FIELDSET'];
if (eventName === 'click' && matchesSelector.indexOf(currElement.tagName) > -1) {
return node.disabled || parent(node, 'fieldset[disabled]');
}
return true;
}
It will be a bit less performant than using indexOf
for the fieldset too, but it'll be much easier to understand and maintain, so I think it's worth it. @eduardolundgren will probably like it best too, he said the code looked more complex than it should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally agree with you, @mairatma. I would suggest you to use this approach�.
assert.strictEqual(0, listener4.callCount); | ||
}); | ||
|
||
it('should not trigger dom click event to an element which its valid parent is disabled', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording on this description sounds a bit weird in English right now, starting from the which
word. It also makes it seem as if any parent would cause this, on any child, when it should only happen for form control elements with fieldset parents. Could you replace it with something more like:
should not trigger dom click event on a form control with a disabled fieldset parent
Same goes for other descriptions that are using which
in a similar way to this.
assert.strictEqual(0, listener4.callCount); | ||
}); | ||
|
||
it('should trigger listeners of the click event for non-disabled elements even its parent being disabled', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording here is also a bit weird, it's missing the word with
after even
, like:
should trigger listeners of the click event for non-disabled elements even with its parent being disabled
Don't worry about it though, we're not native English speakers, we get it wrong from time to time, but it's good to help each other out so we can improve these descriptions whenever we can 😃.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @mairatma. And feel free to correct me as much as you can. I really care about improving my English skills. 😃
550cd89
to
3f65d31
Compare
3f65d31
to
a70fd40
Compare
Just started reviewing :) |
No description provided.