Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

update(panel): constrain panel to viewport boundries #9651

Merged
merged 1 commit into from
Oct 16, 2016

Conversation

crisbeto
Copy link
Member

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 #9641.

Fixes #7878.

@crisbeto crisbeto self-assigned this Sep 20, 2016
@crisbeto crisbeto force-pushed the 7878/panel-constrain branch 2 times, most recently from 2505bd8 to 1284aa9 Compare September 20, 2016 21:22
@crisbeto crisbeto added needs: review This PR is waiting on review from the team and removed needs: work labels Sep 20, 2016
* Margin between the edges of the panel and the viewport
* @type {number}
*/
this.viewportMargin = MdPanelPosition.viewportMargin;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this one needs to be re-exported via $mdPanel, since there are no values for people to access or change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason was to expose it to the unit tests. It can also be a global variable there that can be easily changed if tests start failing because of the wrong margin.

@@ -1767,6 +1773,12 @@ MdPanelPosition.absPosition = {
LEFT: 'left'
};

/**
* Margin between the edges of a panel and the viewport.
* @type {number}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use @const?

* Margin between the edges of a panel and the viewport.
* @type {number}
*/
MdPanelPosition.viewportMargin = 5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 -> 8 (everything in Material design is based on 8s.)

https://material.google.com/layout/responsive-ui.html#responsive-ui-grid

@ThomasBurleson ThomasBurleson added in progress Mainly for in progress PRs, but may be used for issues that require multiple PRs and removed needs: review This PR is waiting on review from the team labels Sep 21, 2016
@ThomasBurleson ThomasBurleson added this to the 1.1.2 milestone Sep 21, 2016
@crisbeto crisbeto added the needs: rebase This PR needs to be rebased on the latest commits from master and conflicts need to be resolved label Sep 21, 2016
@crisbeto crisbeto removed the needs: rebase This PR needs to be rebased on the latest commits from master and conflicts need to be resolved label Sep 21, 2016
@crisbeto
Copy link
Member Author

Included the feedback from Erin.

Copy link
Contributor

@ErinCoughlan ErinCoughlan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@crisbeto crisbeto added the needs: rebase This PR needs to be rebased on the latest commits from master and conflicts need to be resolved label Sep 26, 2016
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.
@crisbeto crisbeto added needs: review This PR is waiting on review from the team and removed needs: rebase This PR needs to be rebased on the latest commits from master and conflicts need to be resolved labels Sep 26, 2016
@crisbeto
Copy link
Member Author

@ThomasBurleson this should be ready for presubmit.

@ThomasBurleson ThomasBurleson added needs: presubmit and removed in progress Mainly for in progress PRs, but may be used for issues that require multiple PRs needs: review This PR is waiting on review from the team labels Oct 10, 2016
}
}

if (this.getLeft()) {
Copy link

@henrymana henrymana Oct 11, 2016

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

@crisbeto crisbeto Oct 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. IMO the constrainToViewport method is a last-ditch effort to keep the panel in the viewport and it may not be successful (e.g. the element is wider than the viewport). Before mdPanel resorts to it, it tries all of the available positions to see which one stays in the viewport. If you want a bit more control, you can add extra positions via addPanelPosition and it'll try those first. Here's an example:

$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).

Choose a reason for hiding this comment

The 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.

@henrymana
Copy link

I noticed earlier that the md-panel position is not updated when disableParentScroll is set to true (and as a result the panel falls outside the viewport boundaries). In my case the md-panel is at the bottom of the screen and this results in part of the panel being offscreen.

The panel is positioned correctly within the viewport when disableParentScroll is set to false.

Looking at the code, I can see this was a pre-existing behavior. I haven't finished debugging but the issue may have to do with the positionUpdate performed when the onScroll event handler is added in line 1783 ( this._$window.addEventListener('scroll', onScroll, true) ).

Should re-positioning work when the parent scroll is disabled? Should I open a separate issue to handle this?

@crisbeto
Copy link
Member Author

I'm not sure about it, but it would be great if you made an issue so it's easier to track and discuss. It does sound strange though.

@henrymana
Copy link

Ok, I will create a small test to replicate and create a new issue later in the week. Thank you.

MdPanelPosition.prototype._constrainToViewport = function(panelEl) {
var margin = MdPanelPosition.viewportMargin;

if (this.getTop()) {

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

If ng-material has disabled body scrolling (for example, if a dialog is open),
then it's possible that the already-scrolled body has a negative top/left. In this case,
we want to treat the "real" top as (0 - bodyRect.top). In a normal scrolling situation,
though, the top of the viewport should just be the body's scroll position.

Copy link
Member Author

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 (via position: absolute).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, thank you.

@henrymana
Copy link

I am no longer able to replicate the issue I mentioned earlier with disableParentScroll (I had a fresh checkout of the master branch and your branch only.). I am not sure why it failed earlier but it seems to be working now. Thank you again.

@kara kara added pr: merge ready This PR is ready for a caretaker to review and removed needs: presubmit labels Oct 16, 2016
@kara kara merged commit d464904 into angular:master Oct 16, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
pr: merge ready This PR is ready for a caretaker to review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants