Skip to content

Commit fa5c22e

Browse files
committed
update(panel): constrain panel to viewport boundries
Prevents the panel from going outside the viewport by adjusting the position. If developers want more control over how the panel gets repositioned, they can specify addition fallback positions via `addPanelPosition`. Related to angular#9641. Fixes angular#7878.
1 parent 1b9245a commit fa5c22e

File tree

2 files changed

+239
-94
lines changed

2 files changed

+239
-94
lines changed

src/components/panel/panel.js

+47-1
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,12 @@ MdPanelPosition.absPosition = {
21562156
LEFT: 'left'
21572157
};
21582158

2159+
/**
2160+
* Margin between the edges of a panel and the viewport.
2161+
* @const {number}
2162+
*/
2163+
MdPanelPosition.viewportMargin = 8;
2164+
21592165

21602166
/**
21612167
* Sets absolute positioning for the panel.
@@ -2525,6 +2531,9 @@ MdPanelPosition.prototype._reduceTranslateValues =
25252531
* @private
25262532
*/
25272533
MdPanelPosition.prototype._setPanelPosition = function(panelEl) {
2534+
// Remove the class in case it has been added before.
2535+
panelEl.removeClass('_md-panel-position-adjusted');
2536+
25282537
// Only calculate the position if necessary.
25292538
if (this._absolute) {
25302539
return;
@@ -2539,12 +2548,49 @@ MdPanelPosition.prototype._setPanelPosition = function(panelEl) {
25392548
this._actualPosition = this._positions[i];
25402549
this._calculatePanelPosition(panelEl, this._actualPosition);
25412550
if (this._isOnscreen(panelEl)) {
2542-
break;
2551+
return;
25432552
}
25442553
}
2554+
2555+
// Class that can be used to re-style the panel if it was repositioned.
2556+
panelEl.addClass('_md-panel-position-adjusted');
2557+
this._constrainToViewport(panelEl);
25452558
};
25462559

25472560

2561+
/**
2562+
* Constrains a panel's position to the viewport.
2563+
* @param {!angular.JQLite} panelEl
2564+
* @private
2565+
*/
2566+
MdPanelPosition.prototype._constrainToViewport = function(panelEl) {
2567+
var margin = MdPanelPosition.viewportMargin;
2568+
2569+
if (this.getTop()) {
2570+
var top = parseInt(this.getTop());
2571+
var bottom = panelEl[0].offsetHeight + top;
2572+
var viewportHeight = this._$window.innerHeight;
2573+
2574+
if (top < margin) {
2575+
this._top = margin + 'px';
2576+
} else if (bottom > viewportHeight) {
2577+
this._top = top - (bottom - viewportHeight + margin) + 'px';
2578+
}
2579+
}
2580+
2581+
if (this.getLeft()) {
2582+
var left = parseInt(this.getLeft());
2583+
var right = panelEl[0].offsetWidth + left;
2584+
var viewportWidth = this._$window.innerWidth;
2585+
2586+
if (left < margin) {
2587+
this._left = margin + 'px';
2588+
} else if (right > viewportWidth) {
2589+
this._left = left - (right - viewportWidth + margin) + 'px';
2590+
}
2591+
}
2592+
};
2593+
25482594
/**
25492595
* Switches between 'start' and 'end'.
25502596
* @param {string} position Horizontal position of the panel

0 commit comments

Comments
 (0)