twreporter-react
Version:
React-Redux site for The Reporter Foundation in Taiwan
139 lines (131 loc) • 5.02 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class Carousel extends _react.Component {
constructor(props) {
super(props);
this.state = { slide: 1, dragging: null, sliding: false, offset: 0 }; // slide index start from 1
this.setTimer = this.setTimer.bind(this);
this.events = {
onTouchStart: this.onDraggingStart.bind(this),
onTouchMove: this.onDraggingMove.bind(this),
onTouchEnd: this.onDraggingEnd.bind(this),
onTouchCancel: this.onDraggingEnd.bind(this),
onClick: this.onClick.bind(this),
onTransitionEnd: this.onTransitionEnd.bind(this)
};
}
componentDidMount() {
this.setTimer();
}
componentWillUnmount() {
window.clearInterval(this.timer);
}
onTransitionEnd() {
// this will not be triggered when document.hidden
let { slide } = this.state;
const count = _react.Children.count(this.props.children);
if (slide == count + 1) slide = 1;
if (slide == 0) slide = count;
this.setState({ slide, sliding: false }, this.setTimer);
}
setTimer() {
const interval = this.props.autoplayInteval;
if (_react.Children.count(this.props.children) > 1 && interval && interval > 0) {
window.clearInterval(this.timer);
this.timer = window.setInterval(this.changeSlide.bind(this, this.state.slide + 1), interval);
}
}
changeSlide(slide) {
if (document.hidden) return; // run only when page is visible
if (slide && slide >= 0 && slide <= _react2.default.Children.count(this.props.children) + 1) this.setState({ slide, sliding: true, dragging: null }, this.setTimer);
}
onDraggingStart(event) {
if (event.touches) this.setState({ dragging: {
x: event.touches[0].pageX,
y: event.touches[0].pageY
}, offset: 0 });
}
onDraggingMove(event) {
const { sliding, dragging } = this.state;
if (sliding || !dragging || !event.touches) return;
const x = event.touches[0].pageX;
const y = event.touches[0].pageY;
const offset = x - dragging.x;
if (Math.abs(y - dragging.y) < Math.abs(offset)) event.preventDefault();
this.setState({ offset });
}
onDraggingEnd(event) {
const { slide, offset, dragging } = this.state;
if (!dragging) return;
const target = Math.abs(offset) > this.refs.slider.clientWidth / 5 ? offset > 0 ? slide - 1 : slide + 1 : slide;
this.setState({ dragging: null }, this.changeSlide.bind(this, target));
}
onClick(event) {
if (Math.abs(this.state.offset) < 25) return; // trigger click in a small distance
event.preventDefault();
event.stopPropagation();
event.nativeEvent.stopPropagation();
}
render() {
const { children, className, switcher, indicator } = this.props;
const { slide, sliding, dragging, offset } = this.state;
const slides = _react.Children.map(children, child => _react2.default.cloneElement(child, { key: child.key + '_clone' }));
const enabled = _react.Children.count(children) > 1;
const prevSlide = this.changeSlide.bind(this, slide - 1);
const nextSlide = this.changeSlide.bind(this, slide + 1);
return _react2.default.createElement(
'div',
{ className: ['slider', className || ''].join(' '), style: {
position: 'relative',
overflowX: 'hidden',
willChange: 'transform'
} },
_react2.default.createElement(
'ul',
_extends({ ref: 'slider', style: {
display: 'flex',
transform: enabled ? dragging && offset !== 0 ? 'translateX(calc(' + offset * 1 + 'px - ' + slide * 100 + '%))' : 'translateX(-' + slide * 100 + '%)' : null,
transition: sliding ? 'transform .8s ease-in-out' : 'none'
} }, this.events),
enabled && _react.Children.map(slides.slice(-1).concat(children, slides.slice(0, 1)), (item, index) => _react2.default.createElement(
'li',
{ className: slide == index ? 'active' : null, style: {
flexBasis: '100%',
flexShrink: 0
} },
item
)) || _react2.default.createElement(
'li',
null,
children
)
),
enabled && switcher && _react2.default.createElement(
'menu',
null,
_react2.default.createElement('button', { className: 'prev', onClick: prevSlide }),
_react2.default.createElement('button', { className: 'next', onClick: nextSlide })
),
enabled && indicator && _react2.default.createElement(
'ol',
null,
_react.Children.map(children, (item, index) => _react2.default.createElement(
'li',
{ className: slide == index + 1 ? 'active' : null },
_react2.default.createElement(
'button',
{ onClick: this.changeSlide.bind(this, index + 1) },
index
)
))
)
);
}
}
exports.default = Carousel;