2015-07-02 13:31:35 +02:00
|
|
|
'use strict';
|
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
import React from 'react/addons';
|
2015-11-25 15:01:23 +01:00
|
|
|
import { History, Lifecycle } from 'react-router';
|
2015-07-02 13:31:35 +02:00
|
|
|
|
2015-08-19 18:36:23 +02:00
|
|
|
import SlidesContainerBreadcrumbs from './slides_container_breadcrumbs';
|
|
|
|
|
2015-09-10 14:00:59 +02:00
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
const { arrayOf, element, bool, shape, string, object } = React.PropTypes;
|
|
|
|
|
|
|
|
const SlidesContainer = React.createClass({
|
2015-07-02 13:31:35 +02:00
|
|
|
propTypes: {
|
2015-10-14 14:22:53 +02:00
|
|
|
children: arrayOf(element),
|
|
|
|
forwardProcess: bool.isRequired,
|
2015-08-19 18:23:04 +02:00
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
glyphiconClassNames: shape({
|
|
|
|
pending: string,
|
|
|
|
complete: string
|
2015-10-01 11:16:38 +02:00
|
|
|
}),
|
2015-11-25 15:01:23 +01:00
|
|
|
location: object,
|
|
|
|
pageExitWarning: string
|
2015-07-02 13:31:35 +02:00
|
|
|
},
|
|
|
|
|
2015-11-25 15:01:23 +01:00
|
|
|
mixins: [History, Lifecycle],
|
2015-07-02 14:42:04 +02:00
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
getInitialState() {
|
|
|
|
return {
|
2015-11-25 15:01:23 +01:00
|
|
|
containerWidth: 0,
|
|
|
|
pageExitWarning: null
|
2015-07-02 13:31:35 +02:00
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
// we're using an event listener on window here,
|
|
|
|
// as it was not possible to listen to the resize events of a dom node
|
|
|
|
window.addEventListener('resize', this.handleContainerResize);
|
2015-08-19 15:30:48 +02:00
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
// Initially, we need to dispatch 'resize' once to render correctly
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
2015-07-21 15:05:42 +02:00
|
|
|
},
|
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
componentWillUnmount() {
|
|
|
|
window.removeEventListener('resize', this.handleContainerResize);
|
|
|
|
},
|
|
|
|
|
2015-11-25 15:01:23 +01:00
|
|
|
routerWillLeave() {
|
|
|
|
return this.props.pageExitWarning;
|
|
|
|
},
|
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
handleContainerResize() {
|
|
|
|
this.setState({
|
2015-07-29 11:23:25 +02:00
|
|
|
// +30 to get rid of the padding of the container which is 15px + 15px left and right
|
|
|
|
containerWidth: this.refs.containerWrapper.getDOMNode().offsetWidth + 30
|
2015-07-02 13:31:35 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2015-08-19 15:54:13 +02:00
|
|
|
// When the start_from parameter is used, this.setSlideNum can not simply be used anymore.
|
2015-10-14 16:20:51 +02:00
|
|
|
nextSlide(additionalQueryParams) {
|
|
|
|
const slideNum = parseInt(this.props.location.query.slide_num, 10) || 0;
|
2016-01-05 17:27:25 +01:00
|
|
|
this.setSlideNum(slideNum + 1, additionalQueryParams);
|
2015-08-19 15:54:13 +02:00
|
|
|
},
|
|
|
|
|
2015-10-14 16:20:51 +02:00
|
|
|
setSlideNum(nextSlideNum, additionalQueryParams = {}) {
|
2016-01-05 17:27:25 +01:00
|
|
|
const { location: { pathname } } = this.props;
|
|
|
|
const query = Object.assign({}, this.props.location.query, additionalQueryParams, { slide_num: nextSlideNum });
|
|
|
|
|
|
|
|
this.history.push({ pathname, query });
|
2015-07-02 13:56:24 +02:00
|
|
|
},
|
|
|
|
|
2015-08-24 11:22:44 +02:00
|
|
|
// breadcrumbs are defined as attributes of the slides.
|
|
|
|
// To extract them we have to read the DOM element's attributes
|
2015-08-19 14:11:03 +02:00
|
|
|
extractBreadcrumbs() {
|
2015-10-14 14:22:53 +02:00
|
|
|
const startFrom = parseInt(this.props.location.query.start_from, 10) || -1;
|
2016-01-05 17:27:25 +01:00
|
|
|
const breadcrumbs = [];
|
2015-08-19 14:11:03 +02:00
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
React.Children.map(this.props.children, (child, i) => {
|
|
|
|
if(child && i >= startFrom && child.props['data-slide-title']) {
|
2015-08-19 15:30:48 +02:00
|
|
|
breadcrumbs.push(child.props['data-slide-title']);
|
|
|
|
}
|
2015-08-19 14:11:03 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
return breadcrumbs;
|
|
|
|
},
|
|
|
|
|
2015-08-24 11:22:44 +02:00
|
|
|
// If startFrom is defined as a URL parameter, this can manipulate
|
|
|
|
// the number of children that are injected into the DOM.
|
|
|
|
// Therefore React.Children.count does not work anymore and we
|
|
|
|
// need to implement our own method.
|
2015-08-19 15:30:48 +02:00
|
|
|
customChildrenCount() {
|
2015-10-14 14:22:53 +02:00
|
|
|
const startFrom = parseInt(this.props.location.query.start_from, 10) || -1;
|
2015-08-19 15:30:48 +02:00
|
|
|
let count = 0;
|
2015-10-14 14:22:53 +02:00
|
|
|
|
2015-08-19 15:30:48 +02:00
|
|
|
React.Children.forEach(this.props.children, (child, i) => {
|
2015-10-14 14:22:53 +02:00
|
|
|
if(i >= startFrom) {
|
2015-08-19 15:30:48 +02:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return count;
|
|
|
|
},
|
|
|
|
|
2015-08-19 14:11:03 +02:00
|
|
|
renderBreadcrumbs() {
|
|
|
|
let breadcrumbs = this.extractBreadcrumbs();
|
2015-08-19 15:30:48 +02:00
|
|
|
let numOfChildren = this.customChildrenCount();
|
2015-08-19 14:11:03 +02:00
|
|
|
|
|
|
|
// check if every child/slide has a title,
|
|
|
|
// otherwise do not display the breadcrumbs at all
|
2015-08-19 15:30:48 +02:00
|
|
|
// Also, if there is only one child, do not display the breadcrumbs
|
|
|
|
if(breadcrumbs.length === numOfChildren && breadcrumbs.length > 1 && numOfChildren > 1) {
|
2015-08-17 12:18:40 +02:00
|
|
|
return (
|
2015-08-19 18:36:23 +02:00
|
|
|
<SlidesContainerBreadcrumbs
|
|
|
|
breadcrumbs={breadcrumbs}
|
2015-10-14 16:20:51 +02:00
|
|
|
slideNum={parseInt(this.props.location.query.slide_num, 10) || 0}
|
2015-08-19 18:36:23 +02:00
|
|
|
numOfSlides={breadcrumbs.length}
|
|
|
|
containerWidth={this.state.containerWidth}
|
|
|
|
glyphiconClassNames={this.props.glyphiconClassNames}/>
|
2015-08-17 12:18:40 +02:00
|
|
|
);
|
2015-08-19 14:11:03 +02:00
|
|
|
} else {
|
|
|
|
return null;
|
2015-08-17 12:18:40 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
// Since we need to give the slides a width, we need to call ReactAddons.addons.cloneWithProps
|
|
|
|
// Also, a key is nice to have!
|
|
|
|
renderChildren() {
|
2015-10-14 14:22:53 +02:00
|
|
|
const startFrom = parseInt(this.props.location.query.start_from, 10) || -1;
|
2015-08-19 18:36:23 +02:00
|
|
|
|
2015-10-14 14:22:53 +02:00
|
|
|
return React.Children.map(this.props.children, (child, i) => {
|
2015-08-19 15:30:48 +02:00
|
|
|
// since the default parameter of startFrom is -1, we do not need to check
|
|
|
|
// if its actually present in the url bar, as it will just not match
|
2015-10-14 14:22:53 +02:00
|
|
|
if(child && i >= startFrom) {
|
|
|
|
return React.addons.cloneWithProps(child, {
|
2015-08-19 15:30:48 +02:00
|
|
|
className: 'ascribe-slide',
|
|
|
|
style: {
|
|
|
|
width: this.state.containerWidth
|
|
|
|
},
|
|
|
|
key: i
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Abortions are bad mkay
|
|
|
|
return null;
|
|
|
|
}
|
2015-08-19 18:36:23 +02:00
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
render() {
|
2015-10-14 16:20:51 +02:00
|
|
|
let spacing = this.state.containerWidth * parseInt(this.props.location.query.slide_num, 10) || 0;
|
2015-09-01 09:34:29 +02:00
|
|
|
let translateXValue = 'translateX(' + (-1) * spacing + 'px)';
|
2015-08-27 18:11:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
According to the react documentation,
|
|
|
|
all browser vendor prefixes need to be upper cases in the beginning except for
|
|
|
|
the Microsoft one *bigfuckingsurprise*
|
|
|
|
https://facebook.github.io/react/tips/inline-styles.html
|
|
|
|
*/
|
|
|
|
|
2015-07-02 13:31:35 +02:00
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className="container ascribe-sliding-container-wrapper"
|
|
|
|
ref="containerWrapper">
|
2015-08-19 14:11:03 +02:00
|
|
|
{this.renderBreadcrumbs()}
|
2015-07-02 13:31:35 +02:00
|
|
|
<div
|
|
|
|
className="container ascribe-sliding-container"
|
|
|
|
style={{
|
2015-08-19 15:54:13 +02:00
|
|
|
width: this.state.containerWidth * this.customChildrenCount(),
|
2015-08-27 18:11:47 +02:00
|
|
|
transform: translateXValue,
|
|
|
|
WebkitTransform: translateXValue,
|
|
|
|
MozTransform: translateXValue,
|
|
|
|
OTransform: translateXValue,
|
|
|
|
mstransform: translateXValue
|
2015-07-02 13:31:35 +02:00
|
|
|
}}>
|
2015-08-17 12:18:40 +02:00
|
|
|
<div className="row">
|
|
|
|
{this.renderChildren()}
|
|
|
|
</div>
|
2015-07-02 13:31:35 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-01-05 17:27:25 +01:00
|
|
|
export default SlidesContainer;
|