Created
January 18, 2017 09:42
-
-
Save fyyyyy/a5013633b927d00adc7cb596ed3296b1 to your computer and use it in GitHub Desktop.
react custom task carousel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| import _ from 'lodash'; | |
| import React from 'react'; | |
| import { PropTypes } from 'react'; | |
| import ReactDOM from 'react-dom'; | |
| import styleable from 'react-styleable'; | |
| import classNames from 'classnames/bind'; | |
| import css from './TaskCarousel.scss'; | |
| import TaskItem from './TaskItem'; | |
| let cx = classNames.bind(css); | |
| @styleable(css) | |
| class TaskCarousel extends React.Component { | |
| constructor(props) { | |
| super(props); | |
| this.state = { | |
| goTo: 0, | |
| scaleFactor: 5, | |
| tasks: [] | |
| }; | |
| } | |
| componentWillUnmount() { | |
| } | |
| rewindCarousel() { | |
| this.changeIndexTo(0); | |
| } | |
| // optional: scale task width according to task duration | |
| updateWidth() { | |
| /* get current carousel width */ | |
| var width = ReactDOM.findDOMNode(this).offsetWidth; | |
| this.setState({width}); | |
| } | |
| selectTaskByClick(e) { | |
| let index = Number(e.currentTarget.id); | |
| this.changeIndexTo(index); | |
| } | |
| prevTask() { | |
| let index = this.state.goTo - 1 > -1 ? this.state.goTo - 1 : 0; | |
| this.changeIndexTo(index); | |
| } | |
| nextTask() { | |
| let index = this.state.goTo + 1 < this.state.tasks.length ? this.state.goTo + 1 : this.state.goTo; | |
| this.changeIndexTo(index); | |
| } | |
| changeIndexTo(taskIndex) { | |
| this.setState({goTo: taskIndex}); | |
| let task = this.state.tasks[taskIndex]; | |
| // TODO: tell task that its active | |
| } | |
| componentWillReceiveProps(nextProps) { | |
| if (_.isEqual(this.state.tasks, nextProps.tasks)) { | |
| return; | |
| } | |
| this.setState({tasks: []}); | |
| this.updateWidth(); | |
| this.rewindCarousel(); | |
| } | |
| render() { | |
| let root = cx({ 'root': true /*, 'hidden': this.state.tasks.length === 0 */}); | |
| let taskNumber = 0; | |
| const taskItems = _.map(this.state.tasks, (task, index) => { | |
| taskNumber++; | |
| task.taskNumber = taskNumber; | |
| return <TaskItem | |
| task={task} | |
| index={index} | |
| key={task.task_id} | |
| onClick={this.selectTaskByClick.bind(this)} | |
| active={this.state.goTo === index} | |
| scaleFactor={this.state.scaleFactor} | |
| ></TaskItem>; | |
| }); | |
| return ( | |
| <div className={root}> | |
| <div className={css.carousel} ref="carousel" style={{marginLeft: calculateOffset(this.state) + 'px'}}> | |
| <div className={css.prev} onClick={this.prevTask.bind(this)} > | |
| <i className="fa fa-2x fa-arrow-left"></i> | |
| </div> | |
| <div className={css.next} onClick={this.nextTask.bind(this)} > | |
| <i className="fa fa-2x fa-arrow-right"></i> | |
| </div> | |
| {taskItems} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| } | |
| TaskCarousel.displayName = 'TaskCarousel'; | |
| TaskCarousel.propTypes = { | |
| tasks: PropTypes.array | |
| }; | |
| export default TaskCarousel; | |
| // optional: calculate task offset according to task.duration whith defines each task width. | |
| // Othwerwise use simpler calculation like offset = numberOfTasks * taskWidth | |
| function calculateOffset(state) { | |
| let offset = - _.sum(_.flatten(_.pluck(_.slice(state.tasks, 0, state.goTo), 'duration'))); | |
| /* scale factor */ | |
| offset /= state.scaleFactor; | |
| /* center */ | |
| offset += state.width / 2 - 40; | |
| return offset; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment