Skip to content

Instantly share code, notes, and snippets.

@jonchretien
Created November 5, 2015 16:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonchretien/7a7053b940a0a934e172 to your computer and use it in GitHub Desktop.
Save jonchretien/7a7053b940a0a934e172 to your computer and use it in GitHub Desktop.
Learning React
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spotify Artist Search</title>
<link rel="stylesheet" type="text/css" href="https://developer.spotify.com/web-api/static/css/cached.css">
<style>
body {
padding: 20px;
}
#search-form, .form-control {
margin-bottom: 20px;
}
.cover {
width: 300px;
height: 300px;
display: inline-block;
background-size: cover;
}
.cover:hover {
cursor: pointer;
}
.cover.playing {
border: 5px solid #e45343;
}
</style>
</head>
<body>
<div class="container">
<h1>Search for an Artist</h1>
<p>Type an artist name and click on "Search". Then, click on any album from the results to play 30 seconds of its first track.</p>
<div id="content"></div>
</div><!-- /.container -->
<script src="js/bundle.spotify.js"></script>
</body>
</html>
{
"name": "hack-week-2015",
"version": "1.0.0",
"description": "Spotify Hack Week Project",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jon Chretien",
"license": "ISC",
"dependencies": {
"babel-preset-react": "^6.0.15",
"babelify": "^7.2.0",
"body-parser": "^1.14.1",
"express": "^4.13.3",
"react": "^0.14.2",
"react-dom": "^0.14.2"
},
"devDependencies": {
"browserify": "^12.0.1"
}
}
/**
* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var fs = require('fs');
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var COMMENTS_FILE = path.join(__dirname, 'comments.json');
app.set('port', (process.env.PORT || 3000));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/api/comments', function(req, res) {
fs.readFile(COMMENTS_FILE, function(err, data) {
res.setHeader('Cache-Control', 'no-cache');
res.json(JSON.parse(data));
});
});
app.post('/api/comments', function(req, res) {
fs.readFile(COMMENTS_FILE, function(err, data) {
var comments = JSON.parse(data);
comments.push(req.body);
fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) {
res.setHeader('Cache-Control', 'no-cache');
res.json(comments);
});
});
});
app.listen(app.get('port'), function() {
console.log('Server started: http://localhost:' + app.get('port') + '/');
});
var React = require('react');
var ReactDOM = require('react-dom');
var SearchBox = React.createClass({
handleCommentSubmit: function(query) {
fetch(this.props.url + '?q=' + query.artist + '&type=album')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
this.setState({data: data.albums.items});
}.bind(this));
}.bind(this)
)
.catch(function(err) {
console.error(this.props.url, status, err.toString());
}.bind(this));
},
getInitialState: function() {
return {
data: []
};
},
render: function() {
return (
<div className="search-box">
<SearchForm onCommentSubmit={this.handleCommentSubmit} />
<SearchResults data={this.state.data} />
</div>
);
}
});
var SearchForm = React.createClass({
handleSubmit: function(event) {
event.preventDefault();
var artist = this.refs.artist.value.trim();
if (!artist) {
return;
}
this.props.onCommentSubmit({artist: artist});
this.refs.artist.value = '';
return;
},
render: function() {
return (
<form id="search-form" onSubmit={this.handleSubmit}>
<input type="text" className="form-control" placeholder="Type an Artist Name" ref="artist" autofocus/>
<input type="submit" className="btn btn-primary" value="Search"/>
</form>
);
}
});
var SearchResults = React.createClass({
render: function() {
var nodes = this.props.data.map(function(album, i) {
return(
<li key={i}>
<img src={album.images[1].url} width={album.images[1].width} height={album.images[1].height} />
<p>{album.name}</p>
</li>
);
});
return (
<ul className="search-list list-unstyled">
{nodes}
</ul>
);
}
});
ReactDOM.render(
<SearchBox url="https://api.spotify.com/v1/search" />,
document.getElementById('content')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment