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

Commit 80e87b5

Browse files
bradrichjelbourn
authored andcommitted
feat(panel): allow panels to be part of multiple groups. (#9830)
The groupName parameter has been changed from allowing only a string to allowing a string or an array of strings. All of the necessary functionality has been changed to accompany the array. Fixes #9565
1 parent c1eceaf commit 80e87b5

File tree

4 files changed

+286
-42
lines changed

4 files changed

+286
-42
lines changed

src/components/panel/demoGroups/index.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,43 @@ <h2>Toolbar with grouped panels (Maximum open: 2)</h2>
4141
can be useful in limiting the number of menu panels allowed open at a
4242
time, etc.
4343
</p>
44+
45+
<div layout="row">
46+
<div layout="column" flex>
47+
<h2>Multiple Groups</h2>
48+
<p>
49+
Panels can be added to multiple groups. The <code>groupName</code>
50+
parameter in the panel configuration can be a string or an array of
51+
strings. This allows for the functionality or constraints of multiple
52+
groups to apply to each created panel.
53+
</p>
54+
<p>
55+
To give an example, the menus within the toolbar above have been added
56+
to the <strong>toolbar</strong> and <strong>menus</strong> groups.
57+
The menus to the right have been added to the <strong>menus</strong>
58+
group as well. The maximum number of open panels within the
59+
<strong>toolbar</strong> group is <strong>2</strong>. Within the
60+
<strong>menus</strong> group it is <strong>3</strong>. Opening the
61+
menus to the right and more than one in the toolbar will result in
62+
the first opened panel to the right to close.
63+
</p>
64+
</div>
65+
<div style="width: 45px;"></div>
66+
<div layout="row" flex="nogrow">
67+
<md-button
68+
class="md-fab md-primary"
69+
aria-label="Tools"
70+
ng-click="ctrl.showContentMenu($event, ctrl.tools)">
71+
<md-icon md-svg-icon="img/icons/ic_build_24px.svg"></md-icon>
72+
</md-button>
73+
<md-button
74+
class="md-fab md-accent"
75+
aria-label="Code"
76+
ng-click="ctrl.showContentMenu($event, ctrl.code)">
77+
<md-icon md-svg-icon="img/icons/ic_code_24px.svg"></md-icon>
78+
</md-button>
79+
</div>
80+
</div>
4481
</md-content>
4582

4683
</div>

src/components/panel/demoGroups/script.js

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,48 @@
2828
'Sign Out'
2929
]
3030
};
31+
this.tools = {
32+
name: 'tools',
33+
items: [
34+
'Create',
35+
'Delete'
36+
]
37+
};
38+
this.code = {
39+
name: 'code',
40+
items: [
41+
'See Source',
42+
'See Commits'
43+
]
44+
};
45+
46+
this.menuTemplate = '' +
47+
'<div class="menu-panel" md-whiteframe="4">' +
48+
' <div class="menu-content">' +
49+
' <div class="menu-item" ng-repeat="item in ctrl.items">' +
50+
' <button class="md-button">' +
51+
' <span>{{item}}</span>' +
52+
' </button>' +
53+
' </div>' +
54+
' <md-divider></md-divider>' +
55+
' <div class="menu-item">' +
56+
' <button class="md-button" ng-click="ctrl.closeMenu()">' +
57+
' <span>Close Menu</span>' +
58+
' </button>' +
59+
' </div>' +
60+
' </div>' +
61+
'</div>';
62+
63+
$mdPanel.newPanelGroup('toolbar', {
64+
maxOpen: 2
65+
});
66+
67+
$mdPanel.newPanelGroup('menus', {
68+
maxOpen: 3
69+
});
3170

3271
this.showToolbarMenu = function($event, menu) {
33-
var template = '' +
34-
'<div class="menu-panel" md-whiteframe="4">' +
35-
' <div class="menu-content">' +
36-
' <div class="menu-item" ng-repeat="item in ctrl.items">' +
37-
' <button class="md-button">' +
38-
' <span>{{item}}</span>' +
39-
' </button>' +
40-
' </div>' +
41-
' <md-divider></md-divider>' +
42-
' <div class="menu-item">' +
43-
' <button class="md-button" ng-click="ctrl.closeMenu()">' +
44-
' <span>Close Menu</span>' +
45-
' </button>' +
46-
' </div>' +
47-
' </div>' +
48-
'</div>';
72+
var template = this.menuTemplate;
4973

5074
var position = $mdPanel.newPanelPosition()
5175
.relativeTo($event.srcElement)
@@ -54,10 +78,6 @@
5478
$mdPanel.yPosition.BELOW
5579
);
5680

57-
$mdPanel.newPanelGroup('toolbar', {
58-
maxOpen: 2
59-
});
60-
6181
var config = {
6282
id: 'toolbar_' + menu.name,
6383
attachTo: angular.element(document.body),
@@ -73,11 +93,42 @@
7393
focusOnOpen: false,
7494
zIndex: 100,
7595
propagateContainerEvents: true,
76-
groupName: 'toolbar'
96+
groupName: ['toolbar', 'menus']
7797
};
7898

7999
$mdPanel.open(config);
80-
}
100+
};
101+
102+
this.showContentMenu = function($event, menu) {
103+
var template = this.menuTemplate;
104+
105+
var position = $mdPanel.newPanelPosition()
106+
.relativeTo($event.srcElement)
107+
.addPanelPosition(
108+
$mdPanel.xPosition.ALIGN_START,
109+
$mdPanel.yPosition.BELOW
110+
);
111+
112+
var config = {
113+
id: 'content_' + menu.name,
114+
attachTo: angular.element(document.body),
115+
controller: PanelMenuCtrl,
116+
controllerAs: 'ctrl',
117+
template: template,
118+
position: position,
119+
panelClass: 'menu-panel-container',
120+
locals: {
121+
items: menu.items
122+
},
123+
openFrom: $event,
124+
focusOnOpen: false,
125+
zIndex: 100,
126+
propagateContainerEvents: true,
127+
groupName: 'menus'
128+
};
129+
130+
$mdPanel.open(config);
131+
};
81132
}
82133

83134
function PanelMenuCtrl(mdPanelRef) {

src/components/panel/panel.js

Lines changed: 41 additions & 19 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
@@ -155,10 +156,11 @@ angular
155156
* on when the panel closes. This is commonly the element which triggered
156157
* the opening of the panel. If you do not use `origin`, you need to control
157158
* the focus manually.
158-
* - `groupName` - `{string=}`: Name of a panel group. This group name is used
159-
* for configuring the number of open panels and identifying specific
160-
* behaviors for groups. For instance, all tooltips could be identified
161-
* using the same groupName.
159+
* - `groupName` - `{(string|!Array<string>)=}`: A group name or an array of
160+
* group names. The group name is used for creating a group of panels. The
161+
* group is used for configuring the number of open panels and identifying
162+
* specific behaviors for groups. For instance, all tooltips could be
163+
* identified using the same groupName.
162164
*
163165
* @returns {!MdPanelRef} panelRef
164166
*/
@@ -685,6 +687,7 @@ angular
685687
* MdPanelAnimation *
686688
*****************************************************************************/
687689

690+
688691
/**
689692
* @ngdoc type
690693
* @name MdPanelAnimation
@@ -895,7 +898,12 @@ MdPanelService.prototype.create = function(config) {
895898
this._config.scope.$on('$destroy', angular.bind(panelRef, panelRef.detach));
896899

897900
if (this._config.groupName) {
898-
panelRef.addToGroup(this._config.groupName);
901+
if (angular.isString(this._config.groupName)) {
902+
this._config.groupName = [this._config.groupName];
903+
}
904+
angular.forEach(this._config.groupName, function(group) {
905+
panelRef.addToGroup(group);
906+
});
899907
}
900908

901909
return panelRef;
@@ -987,7 +995,7 @@ MdPanelService.prototype.setGroupMaxOpen = function(groupName, maxOpen) {
987995
* @private
988996
*/
989997
MdPanelService.prototype._openCountExceedsMaxOpen = function(groupName) {
990-
if (groupName && this._groups[groupName]) {
998+
if (this._groups[groupName]) {
991999
var group = this._groups[groupName];
9921000
return group.maxOpen > 0 && group.openPanels.length > group.maxOpen;
9931001
}
@@ -1001,9 +1009,7 @@ MdPanelService.prototype._openCountExceedsMaxOpen = function(groupName) {
10011009
* @private
10021010
*/
10031011
MdPanelService.prototype._closeFirstOpenedPanel = function(groupName) {
1004-
if (groupName) {
1005-
this._groups[groupName].openPanels[0].close();
1006-
}
1012+
this._groups[groupName].openPanels[0].close();
10071013
};
10081014

10091015

@@ -1137,8 +1143,12 @@ MdPanelRef.prototype.open = function() {
11371143
var done = self._done(resolve, self);
11381144
var show = self._simpleBind(self.show, self);
11391145
var checkGroupMaxOpen = function() {
1140-
if (self._$mdPanel._openCountExceedsMaxOpen(self.config.groupName)) {
1141-
self._$mdPanel._closeFirstOpenedPanel(self.config.groupName);
1146+
if (self.config.groupName) {
1147+
angular.forEach(self.config.groupName, function(group) {
1148+
if (self._$mdPanel._openCountExceedsMaxOpen(group)) {
1149+
self._$mdPanel._closeFirstOpenedPanel(group);
1150+
}
1151+
});
11421152
}
11431153
};
11441154

@@ -1258,8 +1268,11 @@ MdPanelRef.prototype.detach = function() {
12581268
* Destroys the panel. The Panel cannot be opened again after this.
12591269
*/
12601270
MdPanelRef.prototype.destroy = function() {
1271+
var self = this;
12611272
if (this.config.groupName) {
1262-
this.removeFromGroup(this.config.groupName);
1273+
angular.forEach(this.config.groupName, function(group) {
1274+
self.removeFromGroup(group);
1275+
});
12631276
}
12641277
this.config.scope.$destroy();
12651278
this.config.locals = null;
@@ -1294,8 +1307,9 @@ MdPanelRef.prototype.show = function() {
12941307
var onOpenComplete = self.config['onOpenComplete'] || angular.noop;
12951308
var addToGroupOpen = function() {
12961309
if (self.config.groupName) {
1297-
var group = self._$mdPanel._groups[self.config.groupName];
1298-
group.openPanels.push(self);
1310+
angular.forEach(self.config.groupName, function(group) {
1311+
self._$mdPanel._groups[group].openPanels.push(self);
1312+
});
12991313
}
13001314
};
13011315

@@ -1336,11 +1350,14 @@ MdPanelRef.prototype.hide = function() {
13361350
};
13371351
var removeFromGroupOpen = function() {
13381352
if (self.config.groupName) {
1339-
var group = self._$mdPanel._groups[self.config.groupName];
1340-
var index = group.openPanels.indexOf(self);
1341-
if (index > -1) {
1342-
group.openPanels.splice(index, 1);
1343-
}
1353+
var group, index;
1354+
angular.forEach(self.config.groupName, function(group) {
1355+
group = self._$mdPanel._groups[group];
1356+
index = group.openPanels.indexOf(self);
1357+
if (index > -1) {
1358+
group.openPanels.splice(index, 1);
1359+
}
1360+
});
13441361
}
13451362
};
13461363
var focusOnOrigin = function() {
@@ -1884,6 +1901,7 @@ MdPanelRef.prototype._animateClose = function() {
18841901
});
18851902
};
18861903

1904+
18871905
/**
18881906
* Registers a interceptor with the panel. The callback should return a promise,
18891907
* which will allow the action to continue when it gets resolved, or will
@@ -1914,6 +1932,7 @@ MdPanelRef.prototype.registerInterceptor = function(type, callback) {
19141932
return this;
19151933
};
19161934

1935+
19171936
/**
19181937
* Removes a registered interceptor.
19191938
* @param {string} type Type of interceptor to be removed.
@@ -2169,6 +2188,7 @@ MdPanelPosition.prototype.absolute = function() {
21692188
return this;
21702189
};
21712190

2191+
21722192
/**
21732193
* Sets the value of a position for the panel. Clears any previously set
21742194
* position.
@@ -3037,6 +3057,7 @@ MdPanelAnimation.prototype._getBoundingClientRect = function(element) {
30373057
* Util Methods *
30383058
*****************************************************************************/
30393059

3060+
30403061
/**
30413062
* Returns the angular element associated with a css selector or element.
30423063
* @param el {string|!angular.JQLite|!Element}
@@ -3048,6 +3069,7 @@ function getElement(el) {
30483069
return angular.element(queryResult);
30493070
}
30503071

3072+
30513073
/**
30523074
* Gets the computed values for an element's translateX and translateY in px.
30533075
* @param {!angular.JQLite|!Element} el

0 commit comments

Comments
 (0)