-
Notifications
You must be signed in to change notification settings - Fork 3.4k
update(panel): constrain panel to viewport boundries #9651
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2156,6 +2156,12 @@ MdPanelPosition.absPosition = { | |
LEFT: 'left' | ||
}; | ||
|
||
/** | ||
* Margin between the edges of a panel and the viewport. | ||
* @const {number} | ||
*/ | ||
MdPanelPosition.viewportMargin = 8; | ||
|
||
|
||
/** | ||
* Sets absolute positioning for the panel. | ||
|
@@ -2525,6 +2531,9 @@ MdPanelPosition.prototype._reduceTranslateValues = | |
* @private | ||
*/ | ||
MdPanelPosition.prototype._setPanelPosition = function(panelEl) { | ||
// Remove the class in case it has been added before. | ||
panelEl.removeClass('_md-panel-position-adjusted'); | ||
|
||
// Only calculate the position if necessary. | ||
if (this._absolute) { | ||
return; | ||
|
@@ -2539,12 +2548,49 @@ MdPanelPosition.prototype._setPanelPosition = function(panelEl) { | |
this._actualPosition = this._positions[i]; | ||
this._calculatePanelPosition(panelEl, this._actualPosition); | ||
if (this._isOnscreen(panelEl)) { | ||
break; | ||
return; | ||
} | ||
} | ||
|
||
// Class that can be used to re-style the panel if it was repositioned. | ||
panelEl.addClass('_md-panel-position-adjusted'); | ||
this._constrainToViewport(panelEl); | ||
}; | ||
|
||
|
||
/** | ||
* Constrains a panel's position to the viewport. | ||
* @param {!angular.JQLite} panelEl | ||
* @private | ||
*/ | ||
MdPanelPosition.prototype._constrainToViewport = function(panelEl) { | ||
var margin = MdPanelPosition.viewportMargin; | ||
|
||
if (this.getTop()) { | ||
var top = parseInt(this.getTop()); | ||
var bottom = panelEl[0].offsetHeight + top; | ||
var viewportHeight = this._$window.innerHeight; | ||
|
||
if (top < margin) { | ||
this._top = margin + 'px'; | ||
} else if (bottom > viewportHeight) { | ||
this._top = top - (bottom - viewportHeight + margin) + 'px'; | ||
} | ||
} | ||
|
||
if (this.getLeft()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is one case when the panel width is 100% in which there is no right side margin. Should the intent of this issue cover that scenario as well? Or is that something to handle as a separate issue or by the user of the md-panel? I am able to adjust using "withXPosition('align-left')"... but I am just wondering if you think this should be performed by the constrainToViewport method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. IMO the $mdPanel.newPanelPosition()
.relativeTo('something')
.addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.BELOW)
.addPanelPosition(this._mdPanel.xPosition.ALIGN_END, this._mdPanel.yPosition.BELOW)
.addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.ABOVE); This will try to position it start/below, end/below, start/above before resorting to constraining it. Also I think you asked yesterday about the "position adjusted" class. This is useful in the cases where the panel was constrained, because it allows you to do some specific styling (e.g. we use it in the datepicker to hide a part of the overlay). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do use multiple positions. The panel does not really go off the screen, but it touches the right edge of the viewport with no margin (so I set a negative offsetX). Thinking about it more, that could probably be handled by css instead. Thank you for this change. I am already trying out your changes. |
||
var left = parseInt(this.getLeft()); | ||
var right = panelEl[0].offsetWidth + left; | ||
var viewportWidth = this._$window.innerWidth; | ||
|
||
if (left < margin) { | ||
this._left = margin + 'px'; | ||
} else if (right > viewportWidth) { | ||
this._left = left - (right - viewportWidth + margin) + 'px'; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Switches between 'start' and 'end'. | ||
* @param {string} position Horizontal position of the panel | ||
|
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 md-datepicker code has a comment regarding "disabled body scrolling" which I think is applicable here as well. I need to understand the code more, but I think this may be a gap in the constrainToViewport implementation.
Comment from: https://github.com/angular/material/pull/9641/files#diff-31bf126782bc06608d149fe72237bf4eL640
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 doubt it, because the panel is always positioned relatively to the viewport (
position: fixed
). The current datepicker implementation positions the calendar relatively to the body (viaposition: absolute
).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.
ok, thank you.