diff --git a/js/components/ascribe_slides_container/slides_container.js b/js/components/ascribe_slides_container/slides_container.js index 34653133..cbb2c167 100644 --- a/js/components/ascribe_slides_container/slides_container.js +++ b/js/components/ascribe_slides_container/slides_container.js @@ -1,94 +1,42 @@ 'use strict'; -import React from 'react'; +import React from 'react/addons'; import { History } from 'react-router'; -import ReactAddons from 'react/addons'; import SlidesContainerBreadcrumbs from './slides_container_breadcrumbs'; -let SlidesContainer = React.createClass({ - propTypes: { - children: React.PropTypes.arrayOf(React.PropTypes.element), - forwardProcess: React.PropTypes.bool.isRequired, +const { arrayOf, element, bool, shape, string, object } = React.PropTypes; - glyphiconClassNames: React.PropTypes.shape({ - pending: React.PropTypes.string, - complete: React.PropTypes.string +const SlidesContainer = React.createClass({ + propTypes: { + children: arrayOf(element), + forwardProcess: bool.isRequired, + + glyphiconClassNames: shape({ + pending: string, + complete: string }), - location: React.PropTypes.object + location: object }, mixins: [History], getInitialState() { - // handle queryParameters - let queryParams = this.props.location.query; - let slideNum = -1; - let startFrom = -1; - - // We can actually need to check if slide_num is present as a key in queryParams. - // We do not really care about its value though... - if(queryParams && 'slide_num' in queryParams) { - slideNum = parseInt(queryParams.slide_num, 10); - } - // if slide_num is not set, this will be done in componentDidMount - - // the query param 'start_from' removes all slide children before the respective number - // Also, we use the 'in' keyword for the same reason as above in 'slide_num' - if(queryParams && 'start_from' in queryParams) { - startFrom = parseInt(queryParams.start_from, 10); - } - return { - slideNum, - startFrom, - containerWidth: 0, - historyLength: window.history.length + containerWidth: 0 }; }, componentDidMount() { - // check if slide_num was defined, and if not then default to 0 - let queryParams = this.props.location.query; - - // We use 'in' to check if the key is present in the user's browser url bar, - // we do not really care about its value at this point - if(!('slide_num' in queryParams)) { - - // we're first requiring all the other possible queryParams and then set - // the specific one we need instead of overwriting them - queryParams.slide_num = 0; - - this.history.replaceState(null, this.props.location.pathname, queryParams); - } - - // init container width this.handleContainerResize(); // 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); - }, - componentWillReceiveProps() { - let queryParams = this.props.location.query; - - // also check if start_from was updated - // This applies for example when the user tries to submit a already existing piece - // (starting from slide 1 for example) and then clicking on + NEW WORK - if(queryParams && !('start_from' in queryParams)) { - this.setState({ - startFrom: -1 - }); - } - }, - - componentDidUpdate() { - let queryParams = this.props.location.query; - - // check if slide_num was defined, and if not then default to 0 - this.setSlideNum(queryParams.slide_num); + // Initially, we need to dispatch 'resize' once to render correctly + window.dispatchEvent(new Event('resize')); }, componentWillUnmount() { @@ -104,79 +52,26 @@ let SlidesContainer = React.createClass({ // When the start_from parameter is used, this.setSlideNum can not simply be used anymore. nextSlide() { - let nextSlide = this.state.slideNum + 1; + const slideNum = parseInt(this.props.location.query.slide_num, 10); + let nextSlide = slideNum + 1; this.setSlideNum(nextSlide); }, - // We let every one from the outsite set the page number of the slider, - // though only if the slideNum is actually in the range of our children-list. - setSlideNum(slideNum) { - - // we do not want to overwrite other queryParams + setSlideNum(nextSlideNum) { let queryParams = this.props.location.query; + queryParams.slide_num = nextSlideNum; - // slideNum can in some instances be not a number, - // therefore we have to parse it to one and make sure that its not NaN - slideNum = parseInt(slideNum, 10); - - // if slideNum is not a number (even after we parsed it to one) and there has - // never been a transition to another slide (this.state.slideNum ==== -1 indicates that) - // then we want to "replace" (in this case append) the current url with ?slide_num=0 - if(isNaN(slideNum) && this.state.slideNum === -1) { - slideNum = 0; - queryParams.slide_num = slideNum; - - this.history.replaceState(null, this.props.location.pathname, queryParams); - this.setState({slideNum: slideNum}); - return; - - // slideNum always represents the future state. So if slideNum and - // this.state.slideNum are equal, there is no sense in redirecting - } else if(slideNum === this.state.slideNum) { - return; - - // if slideNum is within the range of slides and none of the previous cases - // where matched, we can actually do transitions - } else if(slideNum >= 0 || slideNum < this.customChildrenCount()) { - - if(slideNum !== this.state.slideNum - 1) { - // Bootstrapping the component, getInitialState is called once to save - // the tabs history length. - // In order to know if we already pushed a new state on the history stack or not, - // we're comparing the old history length with the new one and if it didn't change then - // we push a new state on it ONCE (ever). - // Otherwise, we're able to use the browsers history.forward() method - // to keep the stack clean - - if(this.props.forwardProcess) { - queryParams.slide_num = slideNum; - this.history.pushState(null, this.props.location.pathname, queryParams); - } else { - if(this.state.historyLength === window.history.length) { - queryParams.slide_num = slideNum; - this.history.pushState(null, this.props.location.pathname, queryParams); - } else { - window.history.forward(); - } - } - } - - this.setState({ - slideNum: slideNum - }); - - } else { - throw new Error('You\'re calling a page number that is out of range: ' + slideNum); - } + this.history.pushState(null, this.props.location.pathname, queryParams); }, // breadcrumbs are defined as attributes of the slides. // To extract them we have to read the DOM element's attributes extractBreadcrumbs() { + const startFrom = parseInt(this.props.location.query.start_from, 10) || -1; let breadcrumbs = []; - ReactAddons.Children.map(this.props.children, (child, i) => { - if(child && i >= this.state.startFrom && child.props['data-slide-title']) { + React.Children.map(this.props.children, (child, i) => { + if(child && i >= startFrom && child.props['data-slide-title']) { breadcrumbs.push(child.props['data-slide-title']); } }); @@ -189,9 +84,11 @@ let SlidesContainer = React.createClass({ // Therefore React.Children.count does not work anymore and we // need to implement our own method. customChildrenCount() { + const startFrom = parseInt(this.props.location.query.start_from, 10) || -1; let count = 0; + React.Children.forEach(this.props.children, (child, i) => { - if(i >= this.state.startFrom) { + if(i >= startFrom) { count++; } }); @@ -210,7 +107,7 @@ let SlidesContainer = React.createClass({ return ( @@ -223,12 +120,13 @@ let SlidesContainer = React.createClass({ // Since we need to give the slides a width, we need to call ReactAddons.addons.cloneWithProps // Also, a key is nice to have! renderChildren() { - return ReactAddons.Children.map(this.props.children, (child, i) => { + const startFrom = parseInt(this.props.location.query.start_from, 10) || -1; + return React.Children.map(this.props.children, (child, i) => { // 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 - if(child && i >= this.state.startFrom) { - return ReactAddons.addons.cloneWithProps(child, { + if(child && i >= startFrom) { + return React.addons.cloneWithProps(child, { className: 'ascribe-slide', style: { width: this.state.containerWidth @@ -244,7 +142,7 @@ let SlidesContainer = React.createClass({ }, render() { - let spacing = this.state.containerWidth * this.state.slideNum; + let spacing = this.state.containerWidth * parseInt(this.props.location.query.slide_num, 10); let translateXValue = 'translateX(' + (-1) * spacing + 'px)'; /* @@ -278,4 +176,4 @@ let SlidesContainer = React.createClass({ } }); -export default SlidesContainer; +export default SlidesContainer; \ No newline at end of file