diff --git a/README.md b/README.md index e3934488..e1c5b35f 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ The best Swiper component for React Native. - [x] Custom pagination style +- [x] State inject + ## Changelogs - **[v1.2.2]** @@ -167,7 +169,7 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Basic -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | horizontal | true | `bool` | If `true`, the scroll view's children are arranged horizontally in a row instead of vertically in a column. | | loop | true | `bool` | Set to `true` to enable continuous loop mode. | @@ -177,7 +179,7 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Custom basic style & content -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | width | - | `number` | If no specify default enable fullscreen mode by `flex: 1`. | | height | - | `number` | If no specify default fullscreen mode by `flex: 1`. | @@ -185,17 +187,17 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Pagination -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | showsPagination | true | `bool` | Set to `true` make pagination visible. | | paginationStyle | {...} | `style` | Custom styles will merge with the default styles. | -| renderPagination | - | `function` | Complete control how to render pagination with two params (`index`, `total`) ref to `this.state.index` / `this.state.total`, For example: show numbers instead of dots. | +| renderPagination | - | `function` | Complete control how to render pagination with three params (`index`, `total`, `context`) ref to `this.state.index` / `this.state.total` / `this`, For example: show numbers instead of dots. | | dot | `` | `element` | Allow custom the dot element. | | activeDot | `` | `element` | Allow custom the active-dot element. | #### Autoplay -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | autoplay | true | `bool` | Set to `true` enable auto play mode. | | autoplayTimeout | 2.5 | `number` | Delay between auto play transitions (in second). | @@ -203,7 +205,7 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Control buttons -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | showsButtons | true | `bool` | Set to `true` make control buttons visible. | | buttonWrapperStyle | `{backgroundColor: 'transparent', flexDirection: 'row', position: 'absolute', top: 0, left: 0, flex: 1, paddingHorizontal: 10, paddingVertical: 10, justifyContent: 'space-between', alignItems: 'center'}` | `style` | Custom styles. | @@ -212,14 +214,14 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Props of Children -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | style | {...} | `style` | Custom styles will merge with the default styles. | | title | {...} | `element` | If this parameter is not specified, will not render the title. | #### Basic props of `` -| Prop | Default | Type | Describe | +| Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| | horizontal | true | `bool` | If `true`, the scroll view's children are arranged horizontally in a row instead of vertically in a column. | | pagingEnabled | true | `bool` | If true, the scroll view stops on multiples of the scroll view's size when scrolling. This can be used for horizontal pagination. | @@ -234,16 +236,34 @@ AppRegistry.registerComponent('swiper', () => swiper) #### Supported ScrollResponder -| Prop | Default | Type | Describe | +| Prop | Params | Type | Description | | :------------ |:---------------:| :---------------:| :-----| -| onMomentumScrollBegin | - | `function` | When animation begins after letting up | -| onMomentumScrollEnd | - | `function` | Makes no sense why this occurs first during bounce | -| onTouchStartCapture | - | `function` | Immediately after `onMomentumScrollEnd` | -| onTouchStart | - | `function` | Same, but bubble phase | -| onTouchEnd | - | `function` | You could hold the touch start for a long time | -| onResponderRelease | - | `function` | When lifting up - you could pause forever before * lifting | - -> @see: https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollResponder.js +| onMomentumScrollBegin | `e` / `state` / `context` | `function` | When animation begins after letting up | +| onMomentumScrollEnd | `e` / `state` / `context` | `function` | Makes no sense why this occurs first during bounce | +| onTouchStartCapture | `e` / `state` / `context` | `function` | Immediately after `onMomentumScrollEnd` | +| onTouchStart | `e` / `state` / `context` | `function` | Same, but bubble phase | +| onTouchEnd | `e` / `state` / `context` | `function` | You could hold the touch start for a long time | +| onResponderRelease | `e` / `state` / `context` | `function` | When lifting up - you could pause forever before * lifting | + +> Note: each ScrollResponder be injected with two params: `state` and `context`, you can get `state` and `this`(ref to swiper's context) from params, for example: + +```jsx +var swiper = React.createClass({ + _onMomentumScrollEnd: function (e, state, context) { + console.log(state, context.state) + }, + render: function() { + return ( + + ) + } +}) +``` + +> More ScrollResponder info, see: https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollResponder.js ### Examples diff --git a/dist/index.js b/dist/index.js index e68526ee..20553335 100644 --- a/dist/index.js +++ b/dist/index.js @@ -192,6 +192,10 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d */ autoplayTimer: null, + componentWillMount: function componentWillMount() { + this.props = this.injectState(this.props); + }, + componentDidMount: function componentDidMount() { this.autoplay(); }, @@ -227,7 +231,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d }); this.setTimeout(function () { - _this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag.call(_this2, e); + _this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag(e, _this2.state, _this2); }); }, @@ -251,7 +255,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d _this3.autoplay(); // if `onMomentumScrollEnd` registered will be called here - _this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd.call(_this3, e); + _this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd(e, _this3.state, _this3); }); }, @@ -400,6 +404,37 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d ); }, + /** + * Inject state to ScrollResponder + * @param {object} props origin props + * @return {object} props injected props + */ + injectState: function injectState(props) { + var _this5 = this; + + /* const scrollResponders = [ + 'onMomentumScrollBegin', + 'onTouchStartCapture', + 'onTouchStart', + 'onTouchEnd', + 'onResponderRelease', + ]*/ + + for (var prop in props) { + // if(~scrollResponders.indexOf(prop) + if (typeof props[prop] === 'function' && prop !== 'onMomentumScrollEnd' && prop !== 'renderPagination' && prop !== 'onScrollBeginDrag') { + (function () { + var originResponder = props[prop]; + props[prop] = function (e) { + return originResponder(e, _this5.state, _this5); + }; + })(); + } + } + + return props; + }, + /** * Default render * @return {object} react-dom @@ -456,7 +491,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d onMomentumScrollEnd: this.onScrollEnd }), pages ), - props.showsPagination && (props.renderPagination ? this.props.renderPagination.call(this, state.index, state.total) : this.renderPagination()), + props.showsPagination && (props.renderPagination ? this.props.renderPagination(state.index, state.total, this) : this.renderPagination()), this.renderTitle(), this.props.showsButtons && this.renderButtons() ); diff --git a/examples/examples/basic.js b/examples/examples/basic.js index 5f12884d..6990b700 100644 --- a/examples/examples/basic.js +++ b/examples/examples/basic.js @@ -35,9 +35,15 @@ var styles = StyleSheet.create({ }) var swiper = React.createClass({ + _onMomentumScrollEnd: function (e, state, context) { + // you can get `state` and `this`(ref to swiper's context) from params + console.log(state, context.state) + }, render: function() { return ( - + Hello Swiper diff --git a/examples/examples/index.js b/examples/examples/index.js index 2d8c114d..5b532aa6 100644 --- a/examples/examples/index.js +++ b/examples/examples/index.js @@ -192,6 +192,10 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d */ autoplayTimer: null, + componentWillMount: function componentWillMount() { + this.props = this.injectState(this.props); + }, + componentDidMount: function componentDidMount() { this.autoplay(); }, @@ -227,7 +231,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d }); this.setTimeout(function () { - _this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag.call(_this2, e); + _this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag(e, _this2.state, _this2); }); }, @@ -251,7 +255,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d _this3.autoplay(); // if `onMomentumScrollEnd` registered will be called here - _this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd.call(_this3, e); + _this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd(e, _this3.state, _this3); }); }, @@ -400,6 +404,37 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d ); }, + /** + * Inject state to ScrollResponder + * @param {object} props origin props + * @return {object} props injected props + */ + injectState: function injectState(props) { + var _this5 = this; + + /* const scrollResponders = [ + 'onMomentumScrollBegin', + 'onTouchStartCapture', + 'onTouchStart', + 'onTouchEnd', + 'onResponderRelease', + ]*/ + + for (var prop in props) { + // if(~scrollResponders.indexOf(prop) + if (typeof props[prop] === 'function' && prop !== 'onMomentumScrollEnd' && prop !== 'renderPagination' && prop !== 'onScrollBeginDrag') { + (function () { + var originResponder = props[prop]; + props[prop] = function (e) { + return originResponder(e, _this5.state, _this5); + }; + })(); + } + } + + return props; + }, + /** * Default render * @return {object} react-dom @@ -456,7 +491,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d onMomentumScrollEnd: this.onScrollEnd }), pages ), - props.showsPagination && (props.renderPagination ? this.props.renderPagination.call(this, state.index, state.total) : this.renderPagination()), + props.showsPagination && (props.renderPagination ? this.props.renderPagination(state.index, state.total, this) : this.renderPagination()), this.renderTitle(), this.props.showsButtons && this.renderButtons() ); diff --git a/examples/examples/swiper.js b/examples/examples/swiper.js index 09906e2d..8980e4cc 100644 --- a/examples/examples/swiper.js +++ b/examples/examples/swiper.js @@ -60,7 +60,7 @@ var swiper = React.createClass({ } activeDot={} paginationStyle={{ diff --git a/examples/examples/swiper_number.js b/examples/examples/swiper_number.js index 86aed02f..8f0144e2 100644 --- a/examples/examples/swiper_number.js +++ b/examples/examples/swiper_number.js @@ -25,7 +25,7 @@ var styles = StyleSheet.create({ } }) -var renderPagination = function (index, total) { +var renderPagination = function (index, total, context) { return ( { - this.props.onScrollBeginDrag && this.props.onScrollBeginDrag.call(this, e) + this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e, this.state, this) }) }, @@ -250,7 +254,7 @@ export default React.createClass({ this.autoplay() // if `onMomentumScrollEnd` registered will be called here - this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd.call(this, e) + this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e, this.state, this) }) }, @@ -387,6 +391,35 @@ export default React.createClass({ ) }, + /** + * Inject state to ScrollResponder + * @param {object} props origin props + * @return {object} props injected props + */ + injectState(props) { +/* const scrollResponders = [ + 'onMomentumScrollBegin', + 'onTouchStartCapture', + 'onTouchStart', + 'onTouchEnd', + 'onResponderRelease', + ]*/ + + for(let prop in props) { + // if(~scrollResponders.indexOf(prop) + if(typeof props[prop] === 'function' + && prop !== 'onMomentumScrollEnd' + && prop !== 'renderPagination' + && prop !== 'onScrollBeginDrag' + ) { + let originResponder = props[prop] + props[prop] = (e) => originResponder(e, this.state, this) + } + } + + return props + }, + /** * Default render * @return {object} react-dom @@ -434,7 +467,7 @@ export default React.createClass({ {pages} {props.showsPagination && (props.renderPagination - ? this.props.renderPagination.call(this, state.index, state.total) + ? this.props.renderPagination(state.index, state.total, this) : this.renderPagination())} {this.renderTitle()} {this.props.showsButtons && this.renderButtons()}