Skip to content

Commit

Permalink
BackToTop alwaysVisible should listen to scroll on element, when prov…
Browse files Browse the repository at this point in the history
…ided [#160151510]

Signed-off-by: Sarah Weinstein <sweinstein@pivotal.io>
  • Loading branch information
reidmit authored and Ming Xiao committed Sep 5, 2018
1 parent 0cb028f commit d8e544c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
45 changes: 38 additions & 7 deletions spec/pivotal-ui-react/back-to-top/back-to-top_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ describe('BackToTop', () => {
});

describe('without scrollableId', () => {
let subject;

beforeEach(done => {
ReactDOM.render(<BackToTop className="foo" id="bar" style={{fontSize: '200px'}}/>, root);
spyOn(window, 'addEventListener').and.callThrough();
spyOn(window, 'removeEventListener').and.callThrough();
subject = ReactDOM.render(<BackToTop className="foo" id="bar" style={{fontSize: '200px'}}/>, root);

jasmine.clock().uninstall();
setTimeout(() => {
Expand All @@ -30,6 +34,10 @@ describe('BackToTop', () => {
}, 0);
});

it('adds an event listener to the window', () => {
expect(window.addEventListener).toHaveBeenCalledWith('scroll', subject.updateScroll);
});

it('passes down the className, id, and style properties', () => {
expect('.pui-back-to-top').toHaveClass('foo');
expect('.pui-back-to-top').toHaveProp('id', 'bar');
Expand All @@ -54,6 +62,11 @@ describe('BackToTop', () => {
expect('.pui-back-to-top').toHaveStyle({display: 'inline', opacity: 1, 'font-size': '200px'});
});

it('removes an event listener from the window', () => {
ReactDOM.unmountComponentAtNode(root);
expect(window.removeEventListener).toHaveBeenCalledWith('scroll', subject.updateScroll);
});

describe('when the scroll top is less than 400', () => {
beforeEach(() => {
MockNow.tick(BackToTop.FADE_DURATION);
Expand Down Expand Up @@ -107,13 +120,22 @@ describe('BackToTop', () => {
});

describe('with a scrollableId', () => {
let scrollableId;
let scrollableId, element, updateScroll;

beforeEach(done => {
scrollableId = 'scrollable';
element = jasmine.createSpyObj('element', ['addEventListener', 'removeEventListener']);
spyOn(document, 'getElementById').and.returnValue(element);
ReactDOM.render(<div id={scrollableId} style={{height: '100px', maxHeight: '100px', overflowY: 'scroll'}}>
<div {...{height: '500px'}}/>
<BackToTop {...{className: 'foo', id: 'bar', style: {fontSize: '500px'}, scrollableId}}/>
<BackToTop {...{
ref: el => {
if (el) updateScroll = el.updateScroll;
},
className: 'foo',
id: 'bar',
style: {fontSize: '500px'}, scrollableId
}}/>
</div>, root);

jasmine.clock().uninstall();
Expand All @@ -125,23 +147,32 @@ describe('BackToTop', () => {
}, 0);
});

it('adds an event listener to the element', () => {
expect(element.addEventListener).toHaveBeenCalledWith('scroll', updateScroll);
});

it('removes an event listener from the window', () => {
ReactDOM.unmountComponentAtNode(root);
expect(element.removeEventListener).toHaveBeenCalledWith('scroll', updateScroll);
});

describe('when the back to top link is clicked', () => {
beforeEach(() => {
$('.pui-back-to-top').simulate('click');
});

it('calls getScrollTop', () => {
expect(ScrollTop.getScrollTop).toHaveBeenCalledWith(window.scrollable, document);
expect(ScrollTop.getScrollTop).toHaveBeenCalledWith(element, document);
});

it('calls setScrollTop', () => {
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(100, window.scrollable, document);
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(100, element, document);
MockNow.tick(BackToTop.SCROLL_DURATION / 2);
MockRaf.next();
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(12.5, window.scrollable, document);
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(12.5, element, document);
MockNow.tick(BackToTop.SCROLL_DURATION / 2);
MockRaf.next();
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(0, window.scrollable, document);
expect(ScrollTop.setScrollTop).toHaveBeenCalledWith(0, element, document);
});

it('animates the body scroll to the top', () => {
Expand Down
7 changes: 5 additions & 2 deletions src/react/back-to-top/back-to-top.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ export class BackToTop extends mixin(React.PureComponent).with(Animation) {
componentDidMount() {
require('../../css/back-to-top');
this.updateScroll = throttle(this.updateScroll, 100);
window.addEventListener('scroll', this.updateScroll);
const {scrollableId} = this.props;
const element = scrollableId && document.getElementById(scrollableId);
if (element) element.addEventListener('scroll', this.updateScroll);
else window.addEventListener('scroll', this.updateScroll);
privates.set(this, {element});
}

componentWillUnmount() {
window.removeEventListener('scroll', this.updateScroll);
const {element} = privates.get(this);
if (element) element.removeEventListener('scroll', this.updateScroll);
else window.removeEventListener('scroll', this.updateScroll);
}

updateScroll = () => {
Expand Down

0 comments on commit d8e544c

Please sign in to comment.