-
Notifications
You must be signed in to change notification settings - Fork 3.4k
fix(panel): clickOutsideToClose with propagateContainerEvents #9886
fix(panel): clickOutsideToClose with propagateContainerEvents #9886
Conversation
src/components/panel/panel.js
Outdated
| var found = false; | ||
| angular.forEach(elems, function(elem) { | ||
| if (elem === sourceElem) { | ||
| found = true; |
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.
How about this? It quits early when it finds a match and removes the extra variable.
var findSourceEl = function(els, sourceEl) {
for (var el, i = 0; el = els[i]; i++) {
if (el === sourceEl) {
return true;
}
});
return false;
};
src/components/panel/panel.js
Outdated
|
|
||
| // We check if the sourceElem of the event is the panel element or one | ||
| // of it's children. If it is not, then close the panel. | ||
| var found = findSourceElem( |
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.
El instead of Elem. We use el throughout this file, so it's strange to switch naming conventions here.
src/components/panel/panel.spec.js
Outdated
|
|
||
| openPanel(config); | ||
|
|
||
| clickOutsideOfPanel(); |
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.
Can this be clickPanelContainer? Or can clickPanelContainer be updated so you're not duplicating logic. (The only thing that's changing is the element you're clicking on. Maybe something like this?
function clickPanelContainer(rootEl) {
rootEl = rootEl || document.body;
const selector = '.md-panel:not(._md-panel-backdrop)';
angular.element(rootEl).find(selector).parent().simulate('click');
angular.element(rootEl).find(selector).parent().simulate('mousedown');
angular.element(rootEl).find(selector).parent().simulate('mouseup');
flushPanel();
}
Benefits of this version is that you don't need the panelRef, which removes one of the if statements. I know this version can replace the current one and you won't need to change any tests.
or
function clickPanelContainer(container) {
container = container || angular.element('.md-panel-outer-wrapper');
container.triggerHandler({
type: 'mousedown',
target: container[0]
});
container.triggerHandler({
type: 'mouseup',
target: container[0]
});
flushPanel();
}
639cdaf to
f0ad663
Compare
src/components/panel/panel.js
Outdated
|
|
||
| // We check if the sourceEl of the event is the panel element or one | ||
| // of it's children. If it is not, then close the panel. | ||
| var found = findSourceEl( |
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 could simplify it and avoid the loop if you did something like this:
var found = sourceEl === self.panelEl[0] || self.panelEl[0].contains(sourceEl);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 was looking for the .contains() method and didn't realize that I would have to access the element to get to it. Good catch and I appreciate you showing it to me.
| clickOutsideToClose: true | ||
| }; | ||
|
|
||
| openPanel(config); |
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 might make the test slightly more robust if you had a check that the PANEL_EL exists, right after opening it. This should avoid cases where the test will pass, if the openPanel function didn't open it up for some reason.
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 open panel result is pretty well tested in the tests that proceed this one. You will also notice in the test right before this one, should close when clickOutsideToClose set to true does not expect the PANEL_EL to exist before it expects it to be closed. I went with that understanding to write this one.
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.
While it's true that the opening logic is well tested, we should try to keep the tests as independent as possible.
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.
@crisbeto I go back and forth on this one. Because the open existence is tested earlier, we get a better test signal when opens fails because the failure is in the test that tests open. If we write it in every test, then all will fail and the messages don't point to the actual problem.
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 wouldn't say it's necessary for every test, but it makes sense for this one since the test would fail if there isn't an open panel. This may be down to personal preference, though.
src/components/panel/panel.spec.js
Outdated
| } | ||
|
|
||
| var container = panelRef.panelContainer; | ||
| var container = container || panelRef.panelContainer; |
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's a bad practise to have variables with the same name as function arguments.
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 should actually read as container = container || panelRef.panelContainer. I forgot to remove the var before it.
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.
Alright, it makes sense without the var.
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.
@ThomasBurleson I think that there was some confusion as we extended this function. Previously, the container variable was declared internally and assigned to the panelRef.panelContainer. Now, you are able to pass in a container to click on. But, if you don't pass one in, it needs to still assign it to the default panelRef.panelContainer.
f0ad663 to
360d631
Compare
crisbeto
left a 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.
LGTM 👍
360d631 to
1f18e4c
Compare
ErinCoughlan
left a 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.
LGTM
| clickOutsideToClose: true | ||
| }; | ||
|
|
||
| openPanel(config); |
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.
@crisbeto I go back and forth on this one. Because the open existence is tested earlier, we get a better test signal when opens fails because the failure is in the test that tests open. If we write it in every test, then all will fail and the messages don't point to the actual problem.
src/components/panel/panel.spec.js
Outdated
|
|
||
| openPanel(config); | ||
|
|
||
| clickPanelContainer(angular.element(document.body)); |
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.
Can you move the angular.element part to the clickPanelContainer? I don't think it particularly matters for this test, so it seems to fit better in the helper method.
I'm wondering if we want something like getElement to make this more flexible.
material/test/angular-material-spec.js
Line 287 in 72d0685
| function getElement(el) { |
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.
Went ahead and added this one, as I thought that it was a more extended implementation and useful.
…Events If both the `clickOutsideToClose` and `propagateContainerEvents` parameters are set to true within the panel configuration, then the panel will be closed when a click happens outside of the panel. Fixes angular#9388
1f18e4c to
76bb9b6
Compare
|
@ThomasBurleson This is ready for merge. |
|
@ThomasBurleson Checking on the status of this PR. |
If both the
clickOutsideToCloseandpropagateContainerEventsparameters are set to true within the panel configuration, then the panel will be closed when a click happens outside of the panel.Fixes #9388