/** @jsx React.DOM */
// In this example we also have two components - a picture and
// a picture list. The pictures are fetched from Instagram via AJAX.
var Picture = React.createClass({
// This component doesn't hold any state - it simply transforms
// whatever was passed as attributes into HTML that represents a picture.
clickHandler: function(){
// When the component is clicked, trigger the onClick handler that
// was passed as an attribute when it was constructed:
this.props.onClick(this.props.ref);
},
render: function(){
var cls = 'picture ' + (this.props.favorite ? 'favorite' : '');
return (
<div className={cls} onClick={this.clickHandler}>
<img src={this.props.src} width="200" title={this.props.title} />
</div>
);
}
});
var PictureList = React.createClass({
getInitialState: function(){
// The pictures array will be populated via AJAX, and
// the favorites one when the user clicks on an image:
return { pictures: [], favorites: [] };
},
componentDidMount: function(){
// When the component loads, send a jQuery AJAX request
var self = this;
// API endpoint for Instagram's popular images for the day
var url = 'https://api.instagram.com/v1/media/popular?client_id=' + this.props.apiKey + '&callback=?';
$.getJSON(url, function(result){
if(!result || !result.data || !result.data.length){
return;
}
var pictures = result.data.map(function(p){
return {
id: p.id,
url: p.link,
src: p.images.low_resolution.url,
title: p.caption ? p.caption.text : '',
favorite: false
};
});
// Update the component's state. This will trigger a render.
// Note that this only updates the pictures property, and does
// not remove the favorites array.
self.setState({ pictures: pictures });
});
},
pictureClick: function(id){
// id holds the ID of the picture that was clicked.
// Find it in the pictures array, and add it to the favorites
var favorites = this.state.favorites,
pictures = this.state.pictures;
for(var i = 0; i < pictures.length; i++){
// Find the id in the pictures array
if(pictures[i].id == id) {
if(pictures[i].favorite){
return this.favoriteClick(id);
}
// Add the picture to the favorites array,
// and mark it as a favorite:
favorites.push(pictures[i]);
pictures[i].favorite = true;
break;
}
}
// Update the state and trigger a render
this.setState({pictures: pictures, favorites: favorites});
},
favoriteClick: function(id){
// Find the picture in the favorites array and remove it. After this,
// find the picture in the pictures array and mark it as a non-favorite.
var favorites = this.state.favorites,
pictures = this.state.pictures;
for(var i = 0; i < favorites.length; i++){
if(favorites[i].id == id) break;
}
// Remove the picture from favorites array
favorites.splice(i, 1);
for(i = 0; i < pictures.length; i++){
if(pictures[i].id == id) {
pictures[i].favorite = false;
break;
}
}
// Update the state and trigger a render
this.setState({pictures: pictures, favorites: favorites});
},
render: function() {
var self = this;
var pictures = this.state.pictures.map(function(p){
return <Picture ref={p.id} src={p.src} title={p.title} favorite={p.favorite} onClick={self.pictureClick} />
});
if(!pictures.length){
pictures = <p>Loading images..</p>;
}
var favorites = this.state.favorites.map(function(p){
return <Picture ref={p.id} src={p.src} title={p.title} favorite={true} onClick={self.favoriteClick} />
});
if(!favorites.length){
favorites = <p>Click an image to mark it as a favorite.</p>;
}
return (
<div>
<h1>Popular Instagram pics</h1>
<div className="pictures"> {pictures} </div>
<h1>Your favorites</h1>
<div className="favorites"> {favorites} </div>
</div>
);
}
});
// Render the PictureList component, and add it to body.
// I am using an API key for a Instagram test ap. Please generate and
// use your own from here http://instagram.com/developer/
React.renderComponent(
<PictureList apiKey="642176ece1e7445e99244cec26f4de1f" />,
document.body
);
<script src="http://fb.me/react-js-fiddle-integration.js"></script>
* {
padding:0;
margin:0;
}
html{
font:14px normal Arial, sans-serif;
color:#626771;
background-color:#fff;
}
body{
padding:20px;
text-align: center;
}
h1{
font-size: 18px;
margin-bottom: 30px;
padding-top: 20px;
}
div.picture{
display: inline-block;
margin: 5px;
cursor:pointer;
position: relative;
}
div.picture.favorite:after{
content: '❤';
position: absolute;
font-size: 80px;
line-height: 200px;
color: #FF224D;
width: 100%;
text-align: center;
left: 0;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
font-weight: bold;
}
.pictures, .favorites{
white-space: nowrap;
overflow-y: auto;
margin-bottom: 20px;
height: 230px;
background-color: #F3F3F3;
}
.pictures p, .favorites p {
padding-top: 100px;
font-size: 13px;
}
External resources loaded into this fiddle: