You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
8.4 KiB
284 lines
8.4 KiB
define(["exports", "module", "react", "classnames", "./BootstrapMixin", "./utils/ValidComponentChildren"], function (exports, module, _react, _classnames, _BootstrapMixin, _utilsValidComponentChildren) { |
|
"use strict"; |
|
|
|
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; |
|
|
|
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 = _interopRequire(_react); |
|
|
|
var cloneElement = _react.cloneElement; |
|
|
|
var classNames = _interopRequire(_classnames); |
|
|
|
var BootstrapMixin = _interopRequire(_BootstrapMixin); |
|
|
|
var ValidComponentChildren = _interopRequire(_utilsValidComponentChildren); |
|
|
|
var Carousel = React.createClass({ |
|
displayName: "Carousel", |
|
|
|
mixins: [BootstrapMixin], |
|
|
|
propTypes: { |
|
slide: React.PropTypes.bool, |
|
indicators: React.PropTypes.bool, |
|
interval: React.PropTypes.number, |
|
controls: React.PropTypes.bool, |
|
pauseOnHover: React.PropTypes.bool, |
|
wrap: React.PropTypes.bool, |
|
onSelect: React.PropTypes.func, |
|
onSlideEnd: React.PropTypes.func, |
|
activeIndex: React.PropTypes.number, |
|
defaultActiveIndex: React.PropTypes.number, |
|
direction: React.PropTypes.oneOf(["prev", "next"]) |
|
}, |
|
|
|
getDefaultProps: function getDefaultProps() { |
|
return { |
|
slide: true, |
|
interval: 5000, |
|
pauseOnHover: true, |
|
wrap: true, |
|
indicators: true, |
|
controls: true |
|
}; |
|
}, |
|
|
|
getInitialState: function getInitialState() { |
|
return { |
|
activeIndex: this.props.defaultActiveIndex == null ? 0 : this.props.defaultActiveIndex, |
|
previousActiveIndex: null, |
|
direction: null |
|
}; |
|
}, |
|
|
|
getDirection: function getDirection(prevIndex, index) { |
|
if (prevIndex === index) { |
|
return null; |
|
} |
|
|
|
return prevIndex > index ? "prev" : "next"; |
|
}, |
|
|
|
componentWillReceiveProps: function componentWillReceiveProps(nextProps) { |
|
var activeIndex = this.getActiveIndex(); |
|
|
|
if (nextProps.activeIndex != null && nextProps.activeIndex !== activeIndex) { |
|
clearTimeout(this.timeout); |
|
this.setState({ |
|
previousActiveIndex: activeIndex, |
|
direction: nextProps.direction != null ? nextProps.direction : this.getDirection(activeIndex, nextProps.activeIndex) |
|
}); |
|
} |
|
}, |
|
|
|
componentDidMount: function componentDidMount() { |
|
this.waitForNext(); |
|
}, |
|
|
|
componentWillUnmount: function componentWillUnmount() { |
|
clearTimeout(this.timeout); |
|
}, |
|
|
|
next: function next(e) { |
|
if (e) { |
|
e.preventDefault(); |
|
} |
|
|
|
var index = this.getActiveIndex() + 1; |
|
var count = ValidComponentChildren.numberOf(this.props.children); |
|
|
|
if (index > count - 1) { |
|
if (!this.props.wrap) { |
|
return; |
|
} |
|
index = 0; |
|
} |
|
|
|
this.handleSelect(index, "next"); |
|
}, |
|
|
|
prev: function prev(e) { |
|
if (e) { |
|
e.preventDefault(); |
|
} |
|
|
|
var index = this.getActiveIndex() - 1; |
|
|
|
if (index < 0) { |
|
if (!this.props.wrap) { |
|
return; |
|
} |
|
index = ValidComponentChildren.numberOf(this.props.children) - 1; |
|
} |
|
|
|
this.handleSelect(index, "prev"); |
|
}, |
|
|
|
pause: function pause() { |
|
this.isPaused = true; |
|
clearTimeout(this.timeout); |
|
}, |
|
|
|
play: function play() { |
|
this.isPaused = false; |
|
this.waitForNext(); |
|
}, |
|
|
|
waitForNext: function waitForNext() { |
|
if (!this.isPaused && this.props.slide && this.props.interval && this.props.activeIndex == null) { |
|
this.timeout = setTimeout(this.next, this.props.interval); |
|
} |
|
}, |
|
|
|
handleMouseOver: function handleMouseOver() { |
|
if (this.props.pauseOnHover) { |
|
this.pause(); |
|
} |
|
}, |
|
|
|
handleMouseOut: function handleMouseOut() { |
|
if (this.isPaused) { |
|
this.play(); |
|
} |
|
}, |
|
|
|
render: function render() { |
|
var classes = { |
|
carousel: true, |
|
slide: this.props.slide |
|
}; |
|
|
|
return React.createElement( |
|
"div", |
|
_extends({}, this.props, { |
|
className: classNames(this.props.className, classes), |
|
onMouseOver: this.handleMouseOver, |
|
onMouseOut: this.handleMouseOut }), |
|
this.props.indicators ? this.renderIndicators() : null, |
|
React.createElement( |
|
"div", |
|
{ className: "carousel-inner", ref: "inner" }, |
|
ValidComponentChildren.map(this.props.children, this.renderItem) |
|
), |
|
this.props.controls ? this.renderControls() : null |
|
); |
|
}, |
|
|
|
renderPrev: function renderPrev() { |
|
return React.createElement( |
|
"a", |
|
{ className: "left carousel-control", href: "#prev", key: 0, onClick: this.prev }, |
|
React.createElement("span", { className: "glyphicon glyphicon-chevron-left" }) |
|
); |
|
}, |
|
|
|
renderNext: function renderNext() { |
|
return React.createElement( |
|
"a", |
|
{ className: "right carousel-control", href: "#next", key: 1, onClick: this.next }, |
|
React.createElement("span", { className: "glyphicon glyphicon-chevron-right" }) |
|
); |
|
}, |
|
|
|
renderControls: function renderControls() { |
|
if (!this.props.wrap) { |
|
var activeIndex = this.getActiveIndex(); |
|
var count = ValidComponentChildren.numberOf(this.props.children); |
|
|
|
return [activeIndex !== 0 ? this.renderPrev() : null, activeIndex !== count - 1 ? this.renderNext() : null]; |
|
} |
|
|
|
return [this.renderPrev(), this.renderNext()]; |
|
}, |
|
|
|
renderIndicator: function renderIndicator(child, index) { |
|
var className = index === this.getActiveIndex() ? "active" : null; |
|
|
|
return React.createElement("li", { |
|
key: index, |
|
className: className, |
|
onClick: this.handleSelect.bind(this, index, null) }); |
|
}, |
|
|
|
renderIndicators: function renderIndicators() { |
|
var indicators = []; |
|
ValidComponentChildren.forEach(this.props.children, function (child, index) { |
|
indicators.push(this.renderIndicator(child, index), |
|
|
|
// Force whitespace between indicator elements, bootstrap |
|
// requires this for correct spacing of elements. |
|
" "); |
|
}, this); |
|
|
|
return React.createElement( |
|
"ol", |
|
{ className: "carousel-indicators" }, |
|
indicators |
|
); |
|
}, |
|
|
|
getActiveIndex: function getActiveIndex() { |
|
return this.props.activeIndex != null ? this.props.activeIndex : this.state.activeIndex; |
|
}, |
|
|
|
handleItemAnimateOutEnd: function handleItemAnimateOutEnd() { |
|
this.setState({ |
|
previousActiveIndex: null, |
|
direction: null |
|
}, function () { |
|
this.waitForNext(); |
|
|
|
if (this.props.onSlideEnd) { |
|
this.props.onSlideEnd(); |
|
} |
|
}); |
|
}, |
|
|
|
renderItem: function renderItem(child, index) { |
|
var activeIndex = this.getActiveIndex(); |
|
var isActive = index === activeIndex; |
|
var isPreviousActive = this.state.previousActiveIndex != null && this.state.previousActiveIndex === index && this.props.slide; |
|
|
|
return cloneElement(child, { |
|
active: isActive, |
|
ref: child.ref, |
|
key: child.key ? child.key : index, |
|
index: index, |
|
animateOut: isPreviousActive, |
|
animateIn: isActive && this.state.previousActiveIndex != null && this.props.slide, |
|
direction: this.state.direction, |
|
onAnimateOutEnd: isPreviousActive ? this.handleItemAnimateOutEnd : null |
|
}); |
|
}, |
|
|
|
handleSelect: function handleSelect(index, direction) { |
|
clearTimeout(this.timeout); |
|
|
|
var previousActiveIndex = this.getActiveIndex(); |
|
direction = direction || this.getDirection(previousActiveIndex, index); |
|
|
|
if (this.props.onSelect) { |
|
this.props.onSelect(index, direction); |
|
} |
|
|
|
if (this.props.activeIndex == null && index !== previousActiveIndex) { |
|
if (this.state.previousActiveIndex != null) { |
|
// If currently animating don't activate the new index. |
|
// TODO: look into queuing this canceled call and |
|
// animating after the current animation has ended. |
|
return; |
|
} |
|
|
|
this.setState({ |
|
activeIndex: index, |
|
previousActiveIndex: previousActiveIndex, |
|
direction: direction |
|
}); |
|
} |
|
} |
|
}); |
|
|
|
module.exports = Carousel; |
|
}); |