diff --git a/README.md b/README.md index 86845a3..9a26c23 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,15 @@ In this scenario the nav element will have the class `sn-affix` added when the u } ``` +A `[yOffset]` can also be applied. Here `sn-affix` will be added when the top of the viewport is within 200 pixels of the top of the nav. + +```html +
...
+ +``` + ### Minimise mode In this scenario the nav element will have the class `sn-minimise` added when the user scrolls 100px (the original height of the element) down the page. diff --git a/e2e/app.e2e-spec.ts b/e2e/app.e2e-spec.ts index 6f04b22..eed2c8f 100644 --- a/e2e/app.e2e-spec.ts +++ b/e2e/app.e2e-spec.ts @@ -1,36 +1,51 @@ import { AppPage } from './app.po'; import { browser, element, by } from 'protractor'; -describe('ScrollCollapse Lib E2E Tests', function () { +describe('ScrollCollapse Lib E2E Tests', function() { let page: AppPage; - beforeEach(() => page = new AppPage()); + beforeEach(() => (page = new AppPage())); beforeEach(() => page.navigateTo()); beforeEach(() => browser.executeScript('window.scrollTo(0,0)')); afterEach(() => { - browser.manage().logs().get('browser').then((browserLog: any[]) => { - expect(browserLog).toEqual([]); - }); + browser + .manage() + .logs() + .get('browser') + .then((browserLog: any[]) => { + expect(browserLog).toEqual([]); + }); }); describe('scroll direction', () => { it('should add scrolling direction class', () => { page.scrollTo(); - expect(page.getNavElement().getAttribute('class')).not.toContain('sn-scrolling-down'); - expect(page.getNavElement().getAttribute('class')).not.toContain('sn-scrolling-up'); + expect(page.getNavElement().getAttribute('class')).not.toContain( + 'sn-scrolling-down' + ); + expect(page.getNavElement().getAttribute('class')).not.toContain( + 'sn-scrolling-up' + ); page.scrollTo(0, 10); page.scrollTo(0, 200); - expect(page.getNavElement().getAttribute('class')).toContain('sn-scrolling-down'); - expect(page.getNavElement().getAttribute('class')).not.toContain('sn-scrolling-up'); - + expect(page.getNavElement().getAttribute('class')).toContain( + 'sn-scrolling-down' + ); + expect(page.getNavElement().getAttribute('class')).not.toContain( + 'sn-scrolling-up' + ); page.scrollTo(0, 100); - expect(page.getNavElement().getAttribute('class')).not.toContain('sn-scrolling-down'); - expect(page.getNavElement().getAttribute('class')).toContain('sn-scrolling-up'); + expect(page.getNavElement().getAttribute('class')).not.toContain( + 'sn-scrolling-down' + ); + expect(page.getNavElement().getAttribute('class')).toContain( + 'sn-scrolling-up' + ); }); }); @@ -38,10 +53,14 @@ describe('ScrollCollapse Lib E2E Tests', function () { it('should add "sn-minimise" class', () => { page.scrollTo(); page.scrollTo(0, 10); - expect(page.getNavElement().getAttribute('class')).not.toContain('sn-minimise'); + expect(page.getNavElement().getAttribute('class')).not.toContain( + 'sn-minimise' + ); page.scrollTo(0, 110); - expect(page.getNavElement().getAttribute('class')).toContain('sn-minimise'); + expect(page.getNavElement().getAttribute('class')).toContain( + 'sn-minimise' + ); }); }); @@ -49,11 +68,12 @@ describe('ScrollCollapse Lib E2E Tests', function () { it('should add "sn-affix" class', () => { page.scrollTo(); page.scrollTo(0, 10); - expect(page.getBarElement().getAttribute('class')).not.toContain('sn-affix'); + expect(page.getBarElement().getAttribute('class')).not.toContain( + 'sn-affix' + ); page.scrollTo(0, 768 * 3); expect(page.getBarElement().getAttribute('class')).toContain('sn-affix'); }); }); - }); diff --git a/e2e/app.po.ts b/e2e/app.po.ts index 58403da..7ac9f1c 100644 --- a/e2e/app.po.ts +++ b/e2e/app.po.ts @@ -17,4 +17,8 @@ export class AppPage { getBarElement() { return element(by.css('.bar')); } + + getOffsetBarElement() { + return element(by.css('.bar--offset')); + } } diff --git a/src/app/app.component.html b/src/app/app.component.html index e9ea83d..fe5c834 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -16,3 +16,12 @@

Scroll down ↓

+ + +
+
+ Classes applied when original Y position of element approaches yOffset. [yOffset]="200" +
+
+ +
diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 1fb1c60..f42dc67 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -53,6 +53,15 @@ z-index: 9999; } +.bar.bar--offset.sn-affix { + top: 100px; +} + +.bar.bar--offset.sn-minimise { + background-color: #586e5d; + height: 50px; +} + .spacer { height: 150vh; } diff --git a/src/app/scroll-collapse/scroll-collapse.directive.spec.ts b/src/app/scroll-collapse/scroll-collapse.directive.spec.ts index c3dc94c..843d64a 100644 --- a/src/app/scroll-collapse/scroll-collapse.directive.spec.ts +++ b/src/app/scroll-collapse/scroll-collapse.directive.spec.ts @@ -199,5 +199,42 @@ describe('ScrollCollapseDirective', () => { }); expect(directive.affixMode).toBeFalsy(); }); + + it('should factor in yOffset property when calculating affix mode', () => { + directive.originalHeight = 100; + directive.originalTop = 500; + directive.yOffset = 200; + directive.calculateAffixMode({ + scrollX: 0, + scrollY: 0, + width: 1366, + height: 768 + }); + expect(directive.affixMode).toBeFalsy(); + + directive.calculateAffixMode({ + scrollX: 0, + scrollY: 200, + width: 1366, + height: 768 + }); + expect(directive.affixMode).toBeFalsy(); + + directive.calculateAffixMode({ + scrollX: 0, + scrollY: 300, + width: 1366, + height: 768 + }); + expect(directive.affixMode).toBeTruthy(); + + directive.calculateAffixMode({ + scrollX: 0, + scrollY: 299, + width: 1366, + height: 768 + }); + expect(directive.affixMode).toBeFalsy(); + }); }); }); diff --git a/src/app/scroll-collapse/scroll-collapse.directive.ts b/src/app/scroll-collapse/scroll-collapse.directive.ts index 7bd0bc0..45d8f81 100644 --- a/src/app/scroll-collapse/scroll-collapse.directive.ts +++ b/src/app/scroll-collapse/scroll-collapse.directive.ts @@ -74,6 +74,17 @@ export class ScrollCollapseDirective implements AfterViewInit, OnDestroy { * @memberof ScrollCollapseDirective */ @Input() public debounce = 0; + /** + * Number of pixels before the elements originalTop + * position is scroll to that the sn-affix class will be applied. + * This value will need to take into account elements which become + * fixed above this element while scrolling as they reduce + * the height of the document and the scrollY number. + * + * @default 0 + * @memberof ScrollCollapseDirective + */ + @Input() public yOffset = 0; /** * Returns true if last scroll direction is UP * @@ -199,7 +210,7 @@ export class ScrollCollapseDirective implements AfterViewInit, OnDestroy { * @memberof ScrollCollapseDirective */ public calculateAffixMode(viewport: Viewport): void { - this.affixMode = viewport.scrollY >= this.originalTop; + this.affixMode = viewport.scrollY >= this.originalTop - this.yOffset; } /** * Return current viewport values