finnaly created a carousel

This commit is contained in:
Senad Uka
2015-01-28 07:16:48 +01:00
parent 1445e8f702
commit 906c29b22f
8 changed files with 352 additions and 37 deletions

View File

@@ -0,0 +1,36 @@
var AppDispatcher = require('../dispatcher/appDispatcher');
var ItemDetailsConstants = require('../constants/itemDetailsConstants');
// Define action methods
var ItemDetailsActions = {
loadItemWithDetails: function() {
AppDispatcher.handleAction({
actionType: ItemDetailsConstants.LOAD_ITEM_WITH_DETAILS
})
},
nextCarouselImage: function() {
AppDispatcher.handleAction({
actionType: ItemDetailsConstants.NEXT_CAROUSEL_IMAGE
})
},
previousCarouselImage: function() {
AppDispatcher.handleAction({
actionType: ItemDetailsConstants.PREVIOUS_CAROUSEL_IMAGE
})
},
selectCarouselImage: function(index) {
AppDispatcher.handleAction({
actionType: ItemDetailsConstants.SELECT_CAROUSEL_IMAGE,
index: index
})
}
};
module.exports = ItemDetailsActions;

View File

@@ -15,9 +15,6 @@ var ItemMultimediaDescriptions = React.createClass({
);
}
//getInitialState: function () {
//return { descriptions: [] };
//}
});

View File

@@ -1,8 +1,8 @@
var React = require('react'),
ItemMultiMediaDescriptions = require('./itemMultiMediaDescriptions'),
ItemActions = require('../../actions/itemActions'),
NavigationStore = require('../../stores/NavigationStore'),
ItemStore = require('../../stores/itemStore');
Carousel = require('../shared/carousel'),
ItemDetailsActions = require('../../actions/itemDetailsActions'),
NavigationStore = require('../../stores/navigationStore'),
ItemDetailsStore = require('../../stores/itemDetailsStore');
var Router = require('react-router');
@@ -13,47 +13,59 @@ var ItemWithDetailsPage = React.createClass({
return (
<div className="item-with-details row-fluid center">
<div className="span3">
<div className="item-with-details row-fluid center">
<div className="span3">
<h3> {this.state.item.get('name')} </h3>
<div>
<div className='h4'> {this.state.item.get('list_price')} KM</div>
<div> {this.state.item.get('description')}</div>
<div className='h4'> {this.state.item.get('list_price')} KM</div>
<div> {this.state.item.get('description')}</div>
</div>
<ItemMultiMediaDescriptions descriptions={this.state.item.get('multi_media_descriptions')} />
</div>
<div className="span4">
<Carousel images={this.state.images}
selected={this.state.currentImage}
onClickLeft={this.onClickLeft}
onClickRight={this.onClickRight}
onSelectImage={this.onSelectImage} />
</div>
<div className="span4">
quantitative descriptions
</div>
</div>
) ;
</div>
);
},
// Add change listeners to stores
componentDidMount: function() {
ItemStore.addChangeListener(this._onChange);
ItemDetailsStore.addChangeListener(this._onChange);
NavigationStore.addChangeListener(this._onChange);
ItemActions.loadItemWithDetails();
ItemDetailsActions.loadItemWithDetails();
},
onClickLeft: function() {
ItemDetailsActions.previousCarouselImage();
},
onClickRight: function() {
ItemDetailsActions.nextCarouselImage();
},
onSelectImage: function(i) {
ItemDetailsActions.selectCarouselImage(i);
},
_onChange: function () {
if (this.isMounted()) {
this.setState({
item: ItemStore.getLoadedItemWithDetails()
});
this.setState(ItemDetailsStore.getState());
}
},
getInitialState: function () {
return {
item : ItemStore.getLoadedItemWithDetails()
};
return ItemDetailsStore.getState();
}
});

View File

@@ -0,0 +1,51 @@
var React = require("react");
var Carousel = React.createClass({
propTypes: {
images: React.PropTypes.array.isRequired,
selected: React.PropTypes.number.isRequired,
onClickLeft: React.PropTypes.func.isRequired,
onClickRight: React.PropTypes.func.isRequired,
onSelectImage: React.PropTypes.func.isRequired
},
render: function() {
var left = this.props.selected * 300 * -1,
ulStyle = {
width: this.props.images.length * 300,
"-ms-transform": "translate(" + left + "px,0px)",
"-webkit-transform": "translate(" + left + "px,0px)",
transform: "translate(" + left + "px,0px)"
};
return (
<div>
<span className="arrow left"
onClick={this.props.onClickLeft}>&#x25C4;</span>
<div className="carousel-stage">
<ul style={ulStyle} className="carousel-list">
{this.props.images.map(function(image, i) {
return <li key={i}><img src={image} /></li>;
})}
</ul>
<ul className="dots">
{this.props.images.map(function(image, i) {
var activeClass = i === this.props.selected ? "active" : "";
return <li key={i}
className={"circle " + activeClass}
onClick={this.onClickDot.bind(this, i)}></li>;
}.bind(this))}
</ul>
</div>
<span className="arrow right"
onClick={this.props.onClickRight}>&#x25BA;</span>
</div>
)
},
onClickDot: function(index) {
this.props.onSelectImage(index);
}
});
module.exports = Carousel;

View File

@@ -0,0 +1,9 @@
var keyMirror = require('react/lib/keyMirror');
// Define action constants
module.exports = keyMirror({
LOAD_ITEM_WITH_DETAILS: null,
NEXT_CAROUSEL_IMAGE: null,
PREVIOUS_CAROUSEL_IMAGE: null,
SELECT_CAROUSEL_IMAGE: null
});

View File

@@ -0,0 +1,72 @@
* {
box-sizing: border-box;
}
.application-container {
width: 400px;
margin: 0 auto;
}
.arrow,
.circle {
cursor: pointer;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.arrow {
position: relative;
top: -100px;
padding: 10px;
}
.carousel-stage {
width: 300px;
height: 200px;
border: 1px solid black;
overflow: hidden;
display: inline-block;
position: relative;
}
.carousel-stage ul.carousel-list {
display: inline-block;
list-style: none;
padding: 0;
margin: 0;
position: relative;
transition: 300ms ease-in-out;
}
.carousel-stage ul.carousel-list li {
display: inline-block;
width: 300px;
height: 200px;
float: left;
}
.carousel-stage ul.carousel-list li img {
object-fit: cover;
object-position: center center;
width: 300px;
height: 200px;
}
.carousel-stage ul.dots {
width: 300px;
list-style: none;
padding: 0;
margin: 0;
position: absolute;
bottom: 0;
text-align: center;
}
.carousel-stage ul.dots li {
display: inline-block;
width: 14px;
height: 14px;
background-color: white;
margin: 2px;
border-radius: 50%;
line-height: 5px;
border: 2px solid black;
}
.carousel-stage ul.dots li.active {
background-color: #ccc;
}

View File

@@ -0,0 +1,147 @@
var AppDispatcher = require('../dispatcher/appDispatcher');
var EventEmitter = require('events').EventEmitter;
var ItemDetailsConstants = require('../constants/itemDetailsConstants');
var ItemWithDetails = require('../models/itemWithDetails');
var _ = require('underscore');
var _itemWithDetails = new ItemWithDetails();
var _images = [];
var _currentImage = 0;
var _animating = false;
var _count;
var getItemIdFromUrl = function() {
// ugly but it seems to me that
// router does not want to expose its
// state (for phylosophical reasons)
var url = document.URL;
var itemIdRegex = /artikal\/(\d+)\//g;
var match = itemIdRegex.exec(url);
console.log(match);
return match[1];
};
var fetchItemWithDetails = function() {
var id = getItemIdFromUrl();
if (id !== undefined && _itemWithDetails.id !== id) {
var item = new ItemWithDetails({
id: id
});
item.fetch({
success: function() {
_itemWithDetails = item;
_images = (_itemWithDetails.get("multi_media_descriptions") || []).map(function(mmd) {
return mmd.url;
});
_count = _images.length;
_currentImage = 0;
_animating = false;
ItemWithDetailsStore.emitChange();
}
});
}
};
var handlNextImage = function() {
if (_animating) return;
var next = _currentImage + 1;
if (next >= _count) next = 0;
handleSelectImage(next);
};
var handlePrevImage = function() {
if (_animating) return;
var next = _currentImage - 1;
if (next < 0) next = _count - 1;
handleSelectImage(next);
};
var handleSelectImage = function(index) {
if (_animating) return;
_animating = true;
_currentImage = index;
setTimeout(function() {
_animating = false;
}, 300);
};
// Extend ItemWithDetailsStore with EventEmitter to add eventing capabilities
var ItemWithDetailsStore = _.extend({}, EventEmitter.prototype, {
getState: function() {
return {
item: _itemWithDetails,
images: _images,
currentImage: _currentImage,
count: _count
}
},
// item with details
getLoadedItemWithDetails: function() {
return _itemWithDetails;
},
// Emit Change event
emitChange: function() {
console.log("Emitting change!");
this.emit('change');
},
// Add change listener
addChangeListener: function(callback) {
this.on('change', callback);
},
// Remove change listener
removeChangeListener: function(callback) {
this.removeListener('change', callback);
}
});
// Register callback with AppDispatcher
AppDispatcher.register(function(payload) {
var action = payload.action;
var text;
switch (action.actionType) {
case ItemDetailsConstants.LOAD_ITEM_WITH_DETAILS:
fetchItemWithDetails();
break;
case ItemDetailsConstants.NEXT_CAROUSEL_IMAGE:
handlNextImage();
break;
case ItemDetailsConstants.PREVIOUS_CAROUSEL_IMAGE:
handlePrevImage();
break;
case ItemDetailsConstants.SELECT_CAROUSEL_IMAGE:
handleSelectImage(action.index);
break;
default:
return true;
}
// If action was responded to, emit change event
ItemWithDetailsStore.emitChange();
return true;
});
module.exports = ItemWithDetailsStore;

View File

@@ -8,16 +8,7 @@ var _ = require('underscore');
// Extend ItemStore with EventEmitter to add eventing capabilities
var NavigationStore = _.extend({}, EventEmitter.prototype, {
getItemIdFromUrl: function () {
// ugly but it seems to me that
// router does not want to expose its
// state
var url = document.URL;
var itemIdRegex = /artikal\/(\d+)\//;
var match = itemIdRegex.exec(url);
console.log(match);
return match[0];
},
// Emit Change event
emitChange: function() {