Skip to content

Commit 7d1ba67

Browse files
committed
seperated SubContainer added direction option
1 parent c054aa8 commit 7d1ba67

File tree

3 files changed

+125
-93
lines changed

3 files changed

+125
-93
lines changed

.jshintrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"node" : true,
3+
"newcap": false,
4+
"esnext": true,
5+
"eqeqeq": true,
6+
"globalstrict": true,
7+
"noyield": true
8+
}

SubContainer.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
var SubContainer = React.createClass({
2+
displayName: 'React-Infinity',
3+
getInitialState: function () {
4+
return {
5+
transform: this.props.transform + ' scale(1)',
6+
opacity: '0'
7+
};
8+
},
9+
componentDidMount: function (argument) {
10+
this.setState({transform: this.props.transform + ' scale(1)', opacity: '1'});
11+
},
12+
componentWillReceiveProps: function (newProps) {
13+
this.setState({transform: newProps.transform + ' scale(1)'});
14+
},
15+
componentWillEnter: function (cb) {
16+
this.setState({transform: this.props.transform + ' scale(1)', opacity: '0'});
17+
setTimeout(cb, 100);
18+
},
19+
componentDidEnter: function () {
20+
this.setState({transform: this.props.transform + ' scale(1)', opacity: '1'});
21+
},
22+
componentWillLeave: function (cb) {
23+
this.setState({transform: this.props.transform + ' scale(1)', opacity: '0'});
24+
setTimeout(cb, 400);
25+
},
26+
render: function () {
27+
return React.DOM.div({style: s({
28+
position: 'absolute',
29+
top: '0',
30+
left: '0',
31+
transform: this.state.transform,
32+
width: this.props.width,
33+
height: this.props.height,
34+
transition: this.props.transition,
35+
opacity: this.state.opacity
36+
})},
37+
this.props.children
38+
);
39+
}
40+
});
41+
42+
module.exports = SubContainer;

index.js

Lines changed: 75 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,7 @@ var TransitionGroup = React.addons.TransitionGroup;
77
var Transitionable = require('./TransitionableBank');
88
var RAFList = require('./RAFList');
99

10-
var SubContainer = React.createClass({
11-
displayName: 'React-Infinity',
12-
getInitialState: function () {
13-
return {
14-
transform: this.props.transform + ' scale(1)',
15-
opacity: '0'
16-
};
17-
},
18-
componentDidMount: function (argument) {
19-
this.setState({transform: this.props.transform + ' scale(1)', opacity: '1'});
20-
},
21-
componentWillReceiveProps: function (newProps) {
22-
this.setState({transform: newProps.transform + ' scale(1)'});
23-
},
24-
componentWillEnter: function (cb) {
25-
this.setState({transform: this.props.transform + ' scale(1)', opacity: '0'});
26-
setTimeout(cb, 100);
27-
},
28-
componentDidEnter: function () {
29-
this.setState({transform: this.props.transform + ' scale(1)', opacity: '1'});
30-
},
31-
componentWillLeave: function (cb) {
32-
this.setState({transform: this.props.transform + ' scale(1)', opacity: '0'});
33-
setTimeout(cb, 400);
34-
},
35-
render: function () {
36-
return React.DOM.div({style: s({
37-
position: 'absolute',
38-
top: '0',
39-
left: '0',
40-
transform: this.state.transform,
41-
width: this.props.width,
42-
height: this.props.height,
43-
transition: this.props.transition,
44-
opacity: this.state.opacity
45-
})},
46-
this.props.children
47-
);
48-
}
49-
});
10+
var SubContainer = require('./SubContainer');
5011

5112
/*
5213
- The properties I can expect:
@@ -92,7 +53,8 @@ var Infinite = React.createClass({
9253
mobileWidth: 480,
9354
justifyOnMobile: true,
9455
margin: 0,
95-
scrollDelta: 0
56+
scrollDelta: 0,
57+
direction: 'vertical'
9658
};
9759
},
9860

@@ -128,18 +90,9 @@ var Infinite = React.createClass({
12890

12991
componentDidMount: function () {
13092

131-
// this.onResize = this.onResize.bind(this);
132-
// this.onScroll = this.onScroll.bind(this);
133-
13493
global.addEventListener('resize', this.onResize);
13594

13695
RAFList.bind(this.onScroll);
137-
//this.props.scrollContainer.addEventListener('scroll', this.onScroll);
138-
139-
// this.props.scrollContainer.addEventListener('touchstart', this.onTouchStart);
140-
// this.props.scrollContainer.addEventListener('touchmove', this.onTouchMove);
141-
// this.props.scrollContainer.addEventListener('touchend', this.onTouchEnd);
142-
// Causes Bad performance for now.
14396

14497
this.setState({
14598
loaded: true,
@@ -158,7 +111,7 @@ var Infinite = React.createClass({
158111
// move some logic here for visible element calculation.
159112

160113
// set flag for animation off
161-
if(this.state.extra.count % 20 === 0) {
114+
if(this.state.extra.count % 5 === 0) {
162115
var scrollTop = this.state.transitionable.get();
163116
if(this.state.scrollTop !== scrollTop){
164117
this.setState({scrollTop: scrollTop});
@@ -168,57 +121,16 @@ var Infinite = React.createClass({
168121

169122
},
170123

171-
// onTouchStart: function (evt) {
172-
// var startY = evt.touches[0].pageY;
173-
// this.setState({
174-
// startY: startY,
175-
// startScrollTop: this.state.scrollTop
176-
// });
177-
178-
// },
179-
// onTouchMove: function (evt) {
180-
181-
// var newY = evt.touches[0].pageY;
182-
// var delta = this.state.startY - newY;
183-
184-
// if(this.state.scrollTop === this.state.startScrollTop){
185-
// this.setState({
186-
// scrollDelta: delta
187-
// });
188-
// }
189-
190-
// },
191-
// onTouchEnd: function (evt) {
192-
// console.log(":( oh god, no more control!");
193-
// },
194-
195-
// willReceiveProps: function (argument) {
196-
// // set flag for animation on. Filtering content is completely external.
197-
// },
198-
199124
onResize: function () {
200125
this.setState({windowHeight: global.innerHeight, windowWidth: global.innerWidth});
201126
},
202127

203128
componentWillUnmount: function () {
204129
global.removeListener('resize', this.onResize);
205130
RAFList.unbind(this.onScroll);
206-
//this.props.scrollContainer.removeEventListener('scroll', this.onResize);
207-
208-
// this.props.scrollContainer.removeEventListener('touchstart', this.onTouchStart);
209-
// this.props.scrollContainer.removeEventListener('touchmove', this.onTouchMove);
210-
// this.props.scrollContainer.removeEventListener('touchend', this.onTouchEnd);
211131
},
212132

213-
render: function(){
214-
if(this.state.loaded === false){
215-
return React.DOM.div({className: 'infinite-container', style: {fontSize: '0', position: 'relative', textAlign: this.props.align}},
216-
this.props.data.map(function (elementData, i) {
217-
return React.DOM[this.props.component]({style: {display: 'inline-block', margin: '32px', verticalAlign: 'top'}}, this.props.childComponent(elementData));
218-
}.bind(this))
219-
);
220-
}
221-
133+
vertical: function(){
222134
var windowWidth = this.state.windowWidth;
223135
var windowHeight = this.state.windowHeight;
224136

@@ -267,6 +179,76 @@ var Infinite = React.createClass({
267179
},
268180
TransitionGroup(null, elementsToRender)
269181
);
182+
},
183+
184+
horizontal: function(){
185+
var windowWidth = this.state.windowWidth;
186+
var windowHeight = this.state.windowHeight;
187+
188+
var elementWidth = this.props.mobileWidth <= windowWidth ? this.props.elementWidth : this.props.elementMobileWidth;
189+
var elementHeight = this.props.mobileWidth <= windowWidth ? this.props.elementHeight : this.props.elementMobileHeight;
190+
var margin = this.props.margin;
191+
192+
if(!!this.props.justifyOnMobile && this.props.mobileWidth > windowWidth) {
193+
elementHeight = windowHeight;
194+
margin = 0;
195+
}
196+
197+
var elementsPerColumn = Math.max(1, Math.floor((windowHeight - margin) / (elementHeight + margin)));
198+
var extraSpace = windowHeight - elementsPerColumn * (elementHeight + margin) + margin;
199+
var offset = this.props.align === 'left' ? 0 :
200+
this.props.align === 'center' ? Math.round(extraSpace/2) : extraSpace;
201+
202+
var scrollLeft = this.state.scrollTop + this.state.scrollDelta;
203+
var columnsToLeft = Math.floor((scrollLeft - margin) / (elementHeight + margin));
204+
var visibleColumns = Math.ceil(((columnsToLeft * (elementWidth + margin)) + windowWidth)/(elementWidth + margin));
205+
206+
var extra = elementsPerColumn === 1 ? Math.ceil(visibleColumns/2) : 2;
207+
var lowerLimit = (columnsToLeft - extra) * elementsPerColumn;
208+
var higherLimit = (visibleColumns + extra * 2) * elementsPerColumn;
209+
210+
var elementsToRender = [];
211+
212+
this.props.data.forEach(function (obj, index) {
213+
if(index >= lowerLimit && index < higherLimit){
214+
var row = index % elementsPerColumn;
215+
var column = Math.floor(index / elementsPerColumn);
216+
elementsToRender.push(SubContainer({
217+
key: obj.id || obj._id,
218+
transform: 'translate('+ (offset + column * (elementWidth + margin)) +'px, '+ (margin + row * (elementHeight + margin)) +'px)',
219+
width: elementWidth + 'px',
220+
height: elementHeight + 'px',
221+
transition: this.props.transition
222+
}, this.props.childComponent(obj)));
223+
}
224+
}.bind(this));
225+
226+
return React.DOM.div({className: 'infinite-container', style: {
227+
height: (margin + (elementHeight + margin) * Math.ceil(this.props.data.length/elementsPerColumn)) + 'px',
228+
width: '100%',
229+
position: 'relative'}
230+
},
231+
TransitionGroup(null, elementsToRender)
232+
);
233+
},
234+
235+
render: function(){
236+
if(this.state.loaded === false){
237+
return React.DOM.div({className: 'infinite-container', style: {fontSize: '0', position: 'relative', textAlign: this.props.align}},
238+
this.props.data.map(function (elementData, i) {
239+
return React.DOM[this.props.component]({style: {display: 'inline-block', margin: '32px', verticalAlign: 'top'}}, this.props.childComponent(elementData));
240+
}.bind(this))
241+
);
242+
}
243+
244+
if(this.props.direction === 'horizontal') {
245+
return this.horizontal();
246+
} else if(this.props.direction === 'vertical') {
247+
return this.vertical();
248+
} else {
249+
console.warn('the prop `direction` must be either "vertical" or "horizontal". It is set to', this.props.direction);
250+
return this.vertical();
251+
}
270252

271253
}
272254

0 commit comments

Comments
 (0)