Skip to content

feat(overlay): add scroll blocking strategy #4500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 15, 2017

Conversation

crisbeto
Copy link
Member

Adds the BlockScrollStrategy which, when activated, will prevent the user from scrolling. For now it is only used in the dialog.

Relates to #4093.

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label May 12, 2017
@crisbeto crisbeto self-assigned this May 12, 2017
Adds the `BlockScrollStrategy` which, when activated, will prevent the user from scrolling. For now it is only used in the dialog.

Relates to angular#4093.
* Strategy that will prevent the user from scrolling while the overlay is visible.
*/
export class BlockScrollStrategy implements ScrollStrategy {
private _prevHTMLStyles = { top: null, left: null };
Copy link
Member

Choose a reason for hiding this comment

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

_previousHtmlElementStyles ?

let forceScrollElement: HTMLElement;

beforeEach(async(() => {
TestBed.configureTestingModule({ imports: [OverlayModule] }).compileComponents();
Copy link
Member

Choose a reason for hiding this comment

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

No spaces inside object literals

TestBed.configureTestingModule({ imports: [OverlayModule] }).compileComponents();
}));

beforeEach(inject([ViewportRuler], (_viewportRuler: ViewportRuler) => {
Copy link
Member

Choose a reason for hiding this comment

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

Don't use _ for function params; for inject I'm fine with just doing something like vpr

// we have to skip them on iOS.
function skipUnreliableBrowser(spec: Function) {
return () => {
if (!platform.IOS) { spec(); }
Copy link
Member

Choose a reason for hiding this comment

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

I don't want to always skip iOS, since sometimes it does pass (and I think iOS 10 has this problem less frequently than iOS 9).

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'm not a fan of skipping tests either, but I couldn't find a decent way to even scroll the page on iOS 10.3. E.g. something as simple as this doesn't work:

it('should scroll down', () => {
  forceScrollElement.style.height = '3000px';

  window.scroll(0, 100);
  viewport._cacheViewportGeometry();
  expect(viewport.getViewportScrollPosition().top).toBe(100);
});

This renders the entire test pointless since we can't verify whether we're actually doing anything.

Copy link
Member

Choose a reason for hiding this comment

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

In that case I would call the function skipIOS and expand the comment to include that code snippet (just the window.scroll(0, 100); expect(viewport.getViewportScrollPosition().top).toBe(100); part) as reasoning for why it's skipped.

forceScrollElement.style.height = '3000px';

setScrollPosition(0, 100);
expect(viewport.getViewportScrollPosition().top).toBe(100,
Copy link
Member

Choose a reason for hiding this comment

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

Prefer breaking at the higher syntactic level, e.g.

expect(viewport.getViewportScrollPosition().top)
    .toBe(100, 'Expected viewport to be scrollable initially.');

// Used when disabling global scrolling.
.cdk-global-scrollblock {
position: fixed;
overflow-y: scroll;
Copy link
Member

Choose a reason for hiding this comment

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

Won't adding overflow-y: scroll cause a scrollbar to always appear, even if there wasn't one there already? This could lead to an app suddenly multiple scrollbars when a, e.g., a dialog is opened.

Copy link
Member Author

Choose a reason for hiding this comment

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

It will, but we don't activate the strategy unless there was a scrollbar in the first place.

Copy link
Member

Choose a reason for hiding this comment

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

Should add a comment mentioning that

viewport._cacheViewportGeometry();
}

});
Copy link
Member

Choose a reason for hiding this comment

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

I think we should have an e2e test w/ screenshots for this as well that actually attempts to scroll the page through user input.

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 agree, but wouldn't it be pointless since we only run the e2e tests against Chrome?

Copy link
Member

Choose a reason for hiding this comment

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

It's better than not having it; there were issues w/ the AngularJS version that manifested in Chrome.

@crisbeto
Copy link
Member Author

Added e2e tests and addressed the feedback @jelbourn.

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

LGTM, one minor comment

Also, I'm shocked that webdriver doesn't have anything to make scrolling happen other than window.scrollTo (just looked it up).

@@ -41,4 +41,17 @@
.mat-theme-loaded-marker {
display: none;
}

// Used when disabling global scrolling.
.cdk-global-scrollblock {
Copy link
Member

Choose a reason for hiding this comment

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

This should go into the cdk-overlay mixin

@crisbeto crisbeto added the action: merge The PR is ready for merge by the caretaker label May 15, 2017
@jelbourn jelbourn merged commit 6842046 into angular:master May 15, 2017
@xtianus79
Copy link

Hi @jelbourn is this where a user is using a dialog box or sidenav(panel) flyout and the overlay content still scrolls up and down? For now I used a method that alters the body element to position: fixed when opening one of these is opened up.

@tobias74
Copy link

How can I use the BlockScrollStrategy on a Select-Dropdown?

@willshowell
Copy link
Contributor

@tobias74 answered at https://stackoverflow.com/a/46893614/4811678

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants