From 4eabbfc0f2b393e1d35cb43aca92bdac795fa020 Mon Sep 17 00:00:00 2001 From: jquense Date: Tue, 17 Nov 2015 14:27:40 -0500 Subject: [PATCH] [added] affix state callbacks --- src/Affix.js | 22 ++++++++++++++++++++-- test/AffixSpec.js | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/Affix.js b/src/Affix.js index f1e6b5cc..a3717d67 100644 --- a/src/Affix.js +++ b/src/Affix.js @@ -127,7 +127,18 @@ class Affix extends React.Component { return; } - this.setState({affixed, position, top}); + let upperName = affixed === 'affix' + ? '' : affixed.charAt(0).toUpperCase() + affixed.substr(1); + + if (this.props['onAffix' + upperName]) { + this.props['onAffix' + upperName](); + } + + this.setState({affixed, position, top}, ()=>{ + if (this.props['onAffixed' + upperName]) { + this.props['onAffixed' + upperName](); + } + }); } updateStateAtBottom() { @@ -201,7 +212,14 @@ Affix.propTypes = { /** * Style to apply when at bottom */ - bottomStyle: React.PropTypes.object + bottomStyle: React.PropTypes.object, + + onAffix: React.PropTypes.func, + onAffixed: React.PropTypes.func, + onAffixTop: React.PropTypes.func, + onAffixedTop: React.PropTypes.func, + onAffixBottom: React.PropTypes.func, + onAffixedBottom: React.PropTypes.func }; Affix.defaultProps = { diff --git a/test/AffixSpec.js b/test/AffixSpec.js index e4250db3..b05c96a8 100644 --- a/test/AffixSpec.js +++ b/test/AffixSpec.js @@ -8,6 +8,7 @@ import { render } from './helpers'; describe('', () => { let mountPoint; + let handlers; // This makes the window very tall; hopefully enough to exhibit the affix // behavior. If this is insufficient, we should modify the Karma config to @@ -41,9 +42,18 @@ describe('', () => { Content.renderCount = 0; mountPoint = document.createElement('div'); document.body.appendChild(mountPoint); + handlers = { + onAffix: sinon.spy(), + onAffixed: sinon.spy(), + onAffixTop: sinon.spy(), + onAffixedTop: sinon.spy(), + onAffixBottom: sinon.spy(), + onAffixedBottom: sinon.spy() + }; }); afterEach(() => { + Object.keys(handlers).forEach(key => handlers[key].reset()); ReactDOM.unmountComponentAtNode(mountPoint); document.body.removeChild(mountPoint); window.scrollTo(0, 0); @@ -58,6 +68,7 @@ describe('', () => { const content = ReactTestUtils.findRenderedComponentWithType(instance, Content); + expect(content).to.exist; }); @@ -76,6 +87,7 @@ describe('', () => { affixStyle={{color: 'white'}} bottomClassName="affix-bottom" bottomStyle={{color: 'blue'}} + {...handlers} > @@ -88,14 +100,19 @@ describe('', () => { }); it('should render correctly at top', (done) => { - window.scrollTo(0, 99); + window.scrollTo(0, 101); requestAnimationFrame(() => { - expect(node.className).to.equal('affix-top'); - expect(node.style.position).to.not.be.ok; - expect(node.style.top).to.not.be.ok; - expect(node.style.color).to.equal('red'); - done(); + window.scrollTo(0, 99); + requestAnimationFrame(() => { + expect(node.className).to.equal('affix-top'); + expect(node.style.position).to.not.be.ok; + expect(node.style.top).to.not.be.ok; + expect(node.style.color).to.equal('red'); + expect(handlers.onAffixTop).to.been.calledOnce; + expect(handlers.onAffixedTop).to.been.calledOnce; + done(); + }); }); }); @@ -106,6 +123,9 @@ describe('', () => { expect(node.style.position).to.equal('fixed'); expect(node.style.top).to.not.be.ok; expect(node.style.color).to.equal('white'); + + expect(handlers.onAffix).to.been.calledOnce; + expect(handlers.onAffixed).to.been.calledOnce; done(); }); }); @@ -117,6 +137,9 @@ describe('', () => { expect(node.style.position).to.equal('absolute'); expect(node.style.top).to.equal('9900px'); expect(node.style.color).to.equal('blue'); + + expect(handlers.onAffixBottom).to.been.calledOnce; + expect(handlers.onAffixedBottom).to.been.calledOnce; done(); }); }); @@ -131,6 +154,7 @@ describe('', () => {