1
+ require ( './Carousel.scss' )
2
+ import classNames from 'classnames'
3
+
4
+ import React , { Component } from 'react'
5
+ import ReactDOM from 'react-dom'
6
+
7
+ import LeftArrowIcon from '../Icons/LeftArrowIcon'
8
+ import RightArrowIcon from '../Icons/RightArrowIcon'
9
+
10
+ export default class Carousel extends Component {
11
+ componentWillMount ( ) {
12
+ this . handleResize = this . handleResize . bind ( this )
13
+ window . addEventListener ( 'resize' , this . handleResize )
14
+ this . handlePageUp = this . handlePageUp . bind ( this )
15
+ this . handlePageDown = this . handlePageDown . bind ( this )
16
+ this . setState ( { firstVisibleItem : this . props . firstVisibleItem || 0 } )
17
+ }
18
+
19
+ componentWillUnmount ( ) {
20
+ window . removeEventListener ( 'resize' , this . handleResize )
21
+ }
22
+
23
+ handleResize ( ) {
24
+ this . validatePagers ( )
25
+ }
26
+
27
+ componentDidMount ( ) {
28
+ this . validatePagers ( )
29
+ }
30
+
31
+ componentDidUpdate ( ) {
32
+ this . validatePagers ( )
33
+ }
34
+
35
+ validatePagers ( ) {
36
+ const pageDownClass = classNames (
37
+ 'page-down' ,
38
+ { hidden : this . state . firstVisibleItem === 0 }
39
+ )
40
+ const pageUpClass = classNames (
41
+ 'page-up' ,
42
+ { hidden : this . lastElementVisible ( this . state . firstVisibleItem ) }
43
+ )
44
+ const node = ReactDOM . findDOMNode ( this )
45
+ const pageDownNode = node . querySelector ( '.page-down' )
46
+ const pageUpNode = node . querySelector ( '.page-up' )
47
+ pageDownNode . className = pageDownClass
48
+ pageUpNode . className = pageUpClass
49
+ }
50
+
51
+
52
+ lastElementVisible ( firstVisibleItem ) {
53
+ const node = ReactDOM . findDOMNode ( this )
54
+ const parentNode = node . parentNode
55
+ const maxWidth = parentNode . getBoundingClientRect ( ) . width
56
+ const visibleAreaNode = node . querySelector ( '.visible-area' )
57
+ visibleAreaNode . style . width = maxWidth + 'px'
58
+ const itemNodes = visibleAreaNode . children
59
+ let width = 0
60
+ if ( firstVisibleItem > 0 ) {
61
+ // if first item is not visible, account 20px for page-down element
62
+ width += 20
63
+ // account the right margin for page-down (see Carousel.scss)
64
+ width += 15
65
+ }
66
+ for ( let i = 0 ; i < itemNodes . length ; i ++ ) {
67
+ const itemNode = itemNodes [ i ]
68
+ width += itemNode . getBoundingClientRect ( ) . width
69
+ if ( i < itemNodes . length - 1 ) {
70
+ // account 30px for every carousel-item (see Carousel.scss)
71
+ width += 30
72
+ }
73
+ if ( width > maxWidth ) {
74
+ return false
75
+ }
76
+ }
77
+ return true
78
+ }
79
+
80
+ handlePageUp ( ) {
81
+ if ( ! this . lastElementVisible ( this . state . firstVisibleItem + 1 ) ) {
82
+ const nextFirstVisibleItem = this . state . firstVisibleItem + 1
83
+ this . setState ( { firstVisibleItem : nextFirstVisibleItem } )
84
+ }
85
+ }
86
+
87
+ handlePageDown ( ) {
88
+ if ( this . state . firstVisibleItem > 0 ) {
89
+ const nextFirstVisibleItem = this . state . firstVisibleItem - 1
90
+ this . setState ( { firstVisibleItem : nextFirstVisibleItem } )
91
+ }
92
+ }
93
+
94
+ render ( ) {
95
+ const carouselItem = ( item , idx ) => {
96
+ if ( idx < this . state . firstVisibleItem ) {
97
+ return
98
+ }
99
+
100
+ return (
101
+ < div key = { idx } className = "carousel-item" >
102
+ { item }
103
+ </ div >
104
+ )
105
+ }
106
+
107
+ return (
108
+ < div className = "Carousel" >
109
+ < div className = "page-down" onClick = { this . handlePageDown } >
110
+ < LeftArrowIcon fill = "#FFFFFF" />
111
+ </ div >
112
+ < div className = "visible-area" >
113
+ { this . props . children . map ( carouselItem ) }
114
+ </ div >
115
+ < div className = "page-up" onClick = { this . handlePageUp } >
116
+ < RightArrowIcon fill = "#FFFFFF" />
117
+ </ div >
118
+ </ div >
119
+ )
120
+ }
121
+ }
0 commit comments