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

Commit d64e4c1

Browse files
committed
update(panel): refactor positioning to allow multiple.
1 parent b1c1bde commit d64e4c1

File tree

2 files changed

+102
-70
lines changed

2 files changed

+102
-70
lines changed

src/components/panel/panel.js

Lines changed: 88 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,13 @@ angular
338338
* Overlapping the panel with an element:
339339
* `new MdPanelPosition()
340340
* .relativeTo(someElement)
341-
* .withPanelXPosition($mdPanel.xPosition.ALIGN_START)
342-
* .withPanelYPosition($mdPanel.yPosition.ALIGN_TOPS);`
341+
* .withPanelPosition($mdPanel.xPosition.ALIGN_START,
342+
* $mdPanel.yPosition.ALIGN_TOPS);`
343343
*
344344
* Aligning the panel with the bottom of an element:
345345
* `new MdPanelPosition()
346346
* .relativeTo(someElement)
347-
* .withPanelXPosition($mdPanel.xPosition.CENTER)
348-
* .withPanelYPosition($mdPanel.yPosition.BELOW);`
347+
* .withPanelPosition($mdPanel.xPosition.CENTER, $mdPanel.yPosition.BELOW);
349348
*/
350349

351350
/**
@@ -438,10 +437,11 @@ angular
438437

439438
/**
440439
* @ngdoc method
441-
* @name MdPanelPosition#withPanelXPosition
442-
* @param {string} xPosition
440+
* @name MdPanelPosition#withPanelPosition
441+
* @param {string} xpos
442+
* @param {string} ypos
443443
* @description
444-
* Sets the x position for the panel relative to another element.
444+
* Sets the x and y position for the panel relative to another element.
445445
* xPosition must be one of the following values available on
446446
* $mdPanel.xPosition:
447447
*
@@ -459,14 +459,7 @@ angular
459459
* C: CENTER
460460
* D: ALIGN_END (for LTR displays)
461461
* E: OFFSET_END (for LTR displays)
462-
*/
463-
464-
/**
465-
* @ngdoc method
466-
* @name MdPanelPosition#withPanelYPosition
467-
* @param {string} yPosition
468-
* @description
469-
* Sets the y position for the panel relative to another element.
462+
*
470463
* yPosition must be one of the following values available on
471464
* $mdPanel.yPosition:
472465
*
@@ -487,6 +480,16 @@ angular
487480
* J: ABOVE
488481
*/
489482

483+
/**
484+
* @ngdoc method
485+
* @name MdPanelPosition#tryPanelPositions
486+
* @description
487+
* Specify an ordered list of panel positions. The first position which
488+
* allows the panel to be completely on-screen will be chosen; the last position
489+
* will be chose whether it is on-screen or not.
490+
* @param {!Array<{y: string, x:string}>} posArray
491+
*/
492+
490493
/**
491494
* @ngdoc method
492495
* @name MdPanelPosition#withOffsetX
@@ -1090,7 +1093,7 @@ MdPanelRef.prototype._addStyles = function() {
10901093
return this._$q(function(resolve) {
10911094
self._panelContainer.css('z-index', self._config['zIndex']);
10921095
self._panelEl.css('z-index', self._config['zIndex'] + 1);
1093-
1096+
10941097
if (self._config['fullscreen']) {
10951098
self._panelEl.addClass('_md-panel-fullscreen');
10961099
resolve(self);
@@ -1436,11 +1439,8 @@ function MdPanelPosition() {
14361439
/** @private {!Array<string>} */
14371440
this._translateY = [];
14381441

1439-
/** @private {string} */
1440-
this._xPosition = '';
1441-
1442-
/** @private {string} */
1443-
this._yPosition = '';
1442+
/** @private {!Array<{x:string, y:string}>} */
1443+
this._positions = [];
14441444
}
14451445

14461446

@@ -1583,60 +1583,92 @@ MdPanelPosition.prototype.relativeTo = function(element) {
15831583

15841584

15851585
/**
1586-
* Sets the x position for the panel relative to another element.
1587-
* xPosition must be one of the MdPanelPosition.xPosition values.
1588-
*
1589-
* @param {string} xPosition
1590-
* @returns {MdPanelPosition}
1586+
* Sets the x and y postion for the panel relative to another element.
1587+
* @param {string} x must be one of the MdPanelPosition.xPosition values.
1588+
* @param {string} y must be one of the MdPanelPosition.yPosition values.
15911589
*/
1592-
MdPanelPosition.prototype.withPanelXPosition = function(xPosition) {
1590+
MdPanelPosition.prototype.withPanelPosition = function(x, y) {
15931591
if (!this._relativeToRect) {
1594-
throw new Error('withPanelXPosition can only be used with relative' +
1592+
throw new Error('withPanelPosition can only be used with relative ' +
15951593
'positioning. Set relativeTo first.');
15961594
}
15971595

1598-
var positionKeys = Object.keys(MdPanelPosition.xPosition);
1599-
var positionValues = [];
1600-
for (var key, i = 0; key = positionKeys[i]; i++) {
1601-
var position = MdPanelPosition.xPosition[key];
1602-
positionValues.push(position);
1603-
if (position === xPosition) {
1604-
this._xPosition = xPosition;
1605-
return this;
1606-
}
1607-
}
1596+
// validate
1597+
this._validateXPosition(x);
1598+
this._validateYPosition(y);
16081599

1609-
throw new Error('withPanelXPosition only accepts the following values:\n' +
1610-
positionValues.join(' | '));
1600+
this._positions.push({
1601+
x: x,
1602+
y: y,
1603+
});
1604+
return this;
16111605
};
16121606

16131607

16141608
/**
1615-
* Sets the y position for the panel relative to another element.
1616-
* yPosition must be one of the MdPanelPosition.yPosition values.
1617-
*
1618-
* @param {string} yPosition
1619-
* @returns {MdPanelPosition}
1609+
* Specify an ordered list of panel positions. The first position which
1610+
* allows the panel to be completely on-screen will be chosen; the last position
1611+
* will be chose whether it is on-screen or not.
1612+
* @param {!Array<{x:string, y:string}>} pos
16201613
*/
1621-
MdPanelPosition.prototype.withPanelYPosition = function(yPosition) {
1614+
MdPanelPosition.prototype.tryPanelPositions = function(posArray) {
16221615
if (!this._relativeToRect) {
1623-
throw new Error('withPanelYPosition can only be used with relative ' +
1616+
throw new Error('tryPanelPositions can only be used with relative ' +
16241617
'positioning. Set relativeTo first.');
16251618
}
16261619

1620+
// validate
1621+
for (var i = 0; i < pos.length; i++) {
1622+
this._validateXPosition(pos.x);
1623+
this._validateYPosition(pos.y);
1624+
};
1625+
1626+
this._positions = this._positions.concat(posArray);
1627+
return this;
1628+
};
1629+
1630+
1631+
MdPanelPosition.prototype._validateYPosition = function(ypos) {
1632+
// empty is ok
1633+
if (ypos == null) {
1634+
return true;
1635+
}
1636+
16271637
var positionKeys = Object.keys(MdPanelPosition.yPosition);
16281638
var positionValues = [];
16291639
for (var key, i = 0; key = positionKeys[i]; i++) {
16301640
var position = MdPanelPosition.yPosition[key];
16311641
positionValues.push(position);
1632-
if (position === yPosition) {
1633-
this._yPosition = yPosition;
1634-
return this;
1642+
1643+
if (position === ypos) {
1644+
return;
16351645
}
16361646
}
16371647

1638-
throw new Error('withPanelYPosition only accepts the following values:\n' +
1648+
throw new Error('Panel y position only accepts the following values:\n' +
1649+
positionValues.join(' | '));
1650+
};
1651+
1652+
1653+
MdPanelPosition.prototype._validateXPosition = function(xpos) {
1654+
// empty is ok
1655+
if (xpos == null) {
1656+
return true;
1657+
}
1658+
1659+
var positionKeys = Object.keys(MdPanelPosition.xPosition);
1660+
var positionValues = [];
1661+
for (var key, i = 0; key = positionKeys[i]; i++) {
1662+
var position = MdPanelPosition.xPosition[key];
1663+
positionValues.push(position);
1664+
if (position === xpos) {
1665+
return;
1666+
}
1667+
}
1668+
1669+
throw new Error('Panel x Position only accepts the following values:\n' +
16391670
positionValues.join(' | '));
1671+
16401672
};
16411673

16421674

@@ -1765,7 +1797,10 @@ MdPanelPosition.prototype._calculatePanelPosition = function(panelEl) {
17651797
var targetRight = targetBounds.right;
17661798
var targetWidth = targetBounds.width;
17671799

1768-
switch (this._xPosition) {
1800+
// TODO(gmoothart): intelligently pick the first on-screen position.
1801+
var pos = this._positions[0] || {};
1802+
1803+
switch (pos.x) {
17691804
case MdPanelPosition.xPosition.OFFSET_START:
17701805
// TODO(ErinCoughlan): Change OFFSET_START for rtl vs ltr.
17711806
this._left = targetLeft - panelWidth + 'px';
@@ -1792,7 +1827,7 @@ MdPanelPosition.prototype._calculatePanelPosition = function(panelEl) {
17921827
var targetBottom = targetBounds.bottom;
17931828
var targetHeight = targetBounds.height;
17941829

1795-
switch (this._yPosition) {
1830+
switch (pos.y) {
17961831
case MdPanelPosition.yPosition.ABOVE:
17971832
this._top = targetTop - panelHeight + 'px';
17981833
break;

src/components/panel/panel.spec.js

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,8 +1118,7 @@ describe('$mdPanel', function() {
11181118
it('with respect to an element', function() {
11191119
var position = mdPanelPosition
11201120
.relativeTo(myButton[0])
1121-
.withPanelXPosition(xPosition.ALIGN_START)
1122-
.withPanelYPosition(yPosition.ALIGN_TOPS);
1121+
.withPanelPosition(xPosition.ALIGN_START, yPosition.ALIGN_TOPS);
11231122

11241123
config['position'] = position;
11251124

@@ -1133,8 +1132,7 @@ describe('$mdPanel', function() {
11331132
it('with respect to a query selector', function() {
11341133
var position = mdPanelPosition
11351134
.relativeTo('button')
1136-
.withPanelXPosition(xPosition.ALIGN_START)
1137-
.withPanelYPosition(yPosition.ALIGN_TOPS);
1135+
.withPanelPosition(xPosition.ALIGN_START, yPosition.ALIGN_TOPS);
11381136

11391137
config['position'] = position;
11401138

@@ -1148,8 +1146,7 @@ describe('$mdPanel', function() {
11481146
it('with respect to a JQLite object', function() {
11491147
var position = mdPanelPosition
11501148
.relativeTo(myButton)
1151-
.withPanelXPosition(xPosition.ALIGN_START)
1152-
.withPanelYPosition(yPosition.ALIGN_TOPS);
1149+
.withPanelPosition(xPosition.ALIGN_START, yPosition.ALIGN_TOPS);
11531150

11541151
config['position'] = position;
11551152

@@ -1164,7 +1161,7 @@ describe('$mdPanel', function() {
11641161
it('above an element', function() {
11651162
var position = mdPanelPosition
11661163
.relativeTo(myButton)
1167-
.withPanelYPosition(yPosition.ABOVE);
1164+
.withPanelPosition(null, yPosition.ABOVE);
11681165

11691166
config['position'] = position;
11701167

@@ -1178,7 +1175,7 @@ describe('$mdPanel', function() {
11781175
it('top aligned with an element', function() {
11791176
var position = mdPanelPosition
11801177
.relativeTo(myButton)
1181-
.withPanelYPosition(yPosition.ALIGN_TOPS);
1178+
.withPanelPosition(null, yPosition.ALIGN_TOPS);
11821179

11831180
config['position'] = position;
11841181

@@ -1192,7 +1189,7 @@ describe('$mdPanel', function() {
11921189
it('centered with an element', function() {
11931190
var position = mdPanelPosition
11941191
.relativeTo(myButton)
1195-
.withPanelYPosition(yPosition.CENTER);
1192+
.withPanelPosition(null, yPosition.CENTER);
11961193

11971194
config['position'] = position;
11981195

@@ -1209,7 +1206,7 @@ describe('$mdPanel', function() {
12091206
it('bottom aligned with an element', function() {
12101207
var position = mdPanelPosition
12111208
.relativeTo(myButton)
1212-
.withPanelYPosition(yPosition.ALIGN_BOTTOMS);
1209+
.withPanelPosition(null, yPosition.ALIGN_BOTTOMS);
12131210

12141211
config['position'] = position;
12151212

@@ -1223,7 +1220,7 @@ describe('$mdPanel', function() {
12231220
it('below an element', function() {
12241221
var position = mdPanelPosition
12251222
.relativeTo(myButton)
1226-
.withPanelYPosition(yPosition.BELOW);
1223+
.withPanelPosition(null, yPosition.BELOW);
12271224

12281225
config['position'] = position;
12291226

@@ -1239,7 +1236,7 @@ describe('$mdPanel', function() {
12391236
it('offset to the left of an element', function() {
12401237
var position = mdPanelPosition
12411238
.relativeTo(myButton)
1242-
.withPanelXPosition(xPosition.OFFSET_START);
1239+
.withPanelPosition(xPosition.OFFSET_START, null);
12431240

12441241
config['position'] = position;
12451242

@@ -1253,7 +1250,7 @@ describe('$mdPanel', function() {
12531250
it('right aligned with an element', function() {
12541251
var position = mdPanelPosition
12551252
.relativeTo(myButton)
1256-
.withPanelXPosition(xPosition.ALIGN_END);
1253+
.withPanelPosition(xPosition.ALIGN_END, null);
12571254

12581255
config['position'] = position;
12591256

@@ -1267,7 +1264,7 @@ describe('$mdPanel', function() {
12671264
it('centered with an element', function() {
12681265
var position = mdPanelPosition
12691266
.relativeTo(myButton)
1270-
.withPanelXPosition(xPosition.CENTER);
1267+
.withPanelPosition(xPosition.CENTER, null);
12711268

12721269
config['position'] = position;
12731270

@@ -1284,7 +1281,7 @@ describe('$mdPanel', function() {
12841281
it('left aligned with an element', function() {
12851282
var position = mdPanelPosition
12861283
.relativeTo(myButton)
1287-
.withPanelXPosition(xPosition.ALIGN_START);
1284+
.withPanelPosition(xPosition.ALIGN_START, null);
12881285

12891286
config['position'] = position;
12901287

@@ -1298,7 +1295,7 @@ describe('$mdPanel', function() {
12981295
it('offset to the right of an element', function() {
12991296
var position = mdPanelPosition
13001297
.relativeTo(myButton)
1301-
.withPanelXPosition(xPosition.OFFSET_END);
1298+
.withPanelPosition(xPosition.OFFSET_END, null);
13021299

13031300
config['position'] = position;
13041301

@@ -1319,7 +1316,7 @@ describe('$mdPanel', function() {
13191316
var expression = function() {
13201317
mdPanelPosition
13211318
.relativeTo(myButton)
1322-
.withPanelXPosition('fake-x-position');
1319+
.withPanelPosition('fake-x-position', null);
13231320
};
13241321

13251322
expect(expression).toThrow();

0 commit comments

Comments
 (0)