Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit f0ad663

Browse files
committed
fix(panel): Allow clickOutsideToClose to work with propagateContainerEvents
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 #9388
1 parent e3619e6 commit f0ad663

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

src/components/panel/panel.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ angular
1414
* PUBLIC DOCUMENTATION *
1515
*****************************************************************************/
1616

17+
1718
/**
1819
* @ngdoc service
1920
* @name $mdPanel
@@ -685,6 +686,7 @@ angular
685686
* MdPanelAnimation *
686687
*****************************************************************************/
687688

689+
688690
/**
689691
* @ngdoc type
690692
* @name MdPanelAnimation
@@ -1721,30 +1723,53 @@ MdPanelRef.prototype._configureEscapeToClose = function() {
17211723
*/
17221724
MdPanelRef.prototype._configureClickOutsideToClose = function() {
17231725
if (this.config['clickOutsideToClose']) {
1724-
var target = this.panelContainer;
1725-
var sourceElem;
1726+
var target = this.config['propagateContainerEvents'] ?
1727+
angular.element(document.body) :
1728+
this.panelContainer;
1729+
var sourceEl;
17261730

17271731
// Keep track of the element on which the mouse originally went down
17281732
// so that we can only close the backdrop when the 'click' started on it.
1729-
// A simple 'click' handler does not work,
1730-
// it sets the target object as the element the mouse went down on.
1733+
// A simple 'click' handler does not work, it sets the target object as the
1734+
// element the mouse went down on.
17311735
var mousedownHandler = function(ev) {
1732-
sourceElem = ev.target;
1736+
sourceEl = ev.target;
17331737
};
17341738

17351739
// We check if our original element and the target is the backdrop
17361740
// because if the original was the backdrop and the target was inside the
17371741
// panel we don't want to panel to close.
17381742
var self = this;
17391743
var mouseupHandler = function(ev) {
1740-
if (sourceElem === target[0] && ev.target === target[0]) {
1744+
if (self.config['propagateContainerEvents']) {
1745+
1746+
// We check if the sourceEl of the event is the panel element or one
1747+
// of it's children. If it is not, then close the panel.
1748+
var found = findSourceEl(
1749+
self.panelEl.find(sourceEl.tagName),
1750+
sourceEl
1751+
);
1752+
if (!found && self.panelEl[0] !== sourceEl) {
1753+
self.close();
1754+
}
1755+
1756+
} else if (sourceEl === target[0] && ev.target === target[0]) {
17411757
ev.stopPropagation();
17421758
ev.preventDefault();
17431759

17441760
self.close();
17451761
}
17461762
};
17471763

1764+
var findSourceEl = function(els, sourceEl) {
1765+
for (var el, i = 0; el = els[i]; i++) {
1766+
if (el === sourceEl) {
1767+
return true;
1768+
}
1769+
}
1770+
return false;
1771+
};
1772+
17481773
// Add listeners
17491774
target.on('mousedown', mousedownHandler);
17501775
target.on('mouseup', mouseupHandler);
@@ -1884,6 +1909,7 @@ MdPanelRef.prototype._animateClose = function() {
18841909
});
18851910
};
18861911

1912+
18871913
/**
18881914
* Registers a interceptor with the panel. The callback should return a promise,
18891915
* which will allow the action to continue when it gets resolved, or will
@@ -1914,6 +1940,7 @@ MdPanelRef.prototype.registerInterceptor = function(type, callback) {
19141940
return this;
19151941
};
19161942

1943+
19171944
/**
19181945
* Removes a registered interceptor.
19191946
* @param {string} type Type of interceptor to be removed.
@@ -2606,6 +2633,7 @@ MdPanelPosition.prototype._constrainToViewport = function(panelEl) {
26062633
}
26072634
};
26082635

2636+
26092637
/**
26102638
* Switches between 'start' and 'end'.
26112639
* @param {string} position Horizontal position of the panel
@@ -2795,6 +2823,7 @@ MdPanelAnimation.prototype.closeTo = function(closeTo) {
27952823
return this;
27962824
};
27972825

2826+
27982827
/**
27992828
* Specifies the duration of the animation in milliseconds.
28002829
* @param {number|{open: number, close: number}} duration
@@ -2820,6 +2849,7 @@ MdPanelAnimation.prototype.duration = function(duration) {
28202849
}
28212850
};
28222851

2852+
28232853
/**
28242854
* Returns the element and bounds for the animation target.
28252855
* @param {string|!Element|{top: number, left: number}} location
@@ -3037,6 +3067,7 @@ MdPanelAnimation.prototype._getBoundingClientRect = function(element) {
30373067
* Util Methods *
30383068
*****************************************************************************/
30393069

3070+
30403071
/**
30413072
* Returns the angular element associated with a css selector or element.
30423073
* @param el {string|!angular.JQLite|!Element}
@@ -3048,6 +3079,7 @@ function getElement(el) {
30483079
return angular.element(queryResult);
30493080
}
30503081

3082+
30513083
/**
30523084
* Gets the computed values for an element's translateX and translateY in px.
30533085
* @param {!angular.JQLite|!Element} el

src/components/panel/panel.spec.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,20 @@ describe('$mdPanel', function() {
542542
expect(PANEL_EL).not.toExist();
543543
});
544544

545+
it('should close when clickOutsideToClose set to true and ' +
546+
'propagateContainerEvents is also set to true', function() {
547+
var config = {
548+
propagateContainerEvents: true,
549+
clickOutsideToClose: true
550+
};
551+
552+
openPanel(config);
553+
554+
clickPanelContainer(angular.element(document.body));
555+
556+
expect(PANEL_EL).not.toExist();
557+
});
558+
545559
it('should not close when escapeToClose set to false', function() {
546560
openPanel();
547561

@@ -2823,12 +2837,12 @@ describe('$mdPanel', function() {
28232837
attachedElements.push(element);
28242838
}
28252839

2826-
function clickPanelContainer() {
2840+
function clickPanelContainer(container) {
28272841
if (!panelRef) {
28282842
return;
28292843
}
28302844

2831-
var container = panelRef.panelContainer;
2845+
var container = container || panelRef.panelContainer;
28322846

28332847
container.triggerHandler({
28342848
type: 'mousedown',

0 commit comments

Comments
 (0)