<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap@4.0.5" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script data-require="lodash.js@4.17.4" data-semver="4.17.4" src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
<script src="https://jspm.io/system@0.18.js"></script>
<script src="config.js"></script>
<script>
System.import('app').catch(console.error.bind(console));
</script>
</head>
<body>
<div id="app" class="container"></div>
</body>
</html>
.search-bar {
margin: 20px;
text-align: center;
}
.search-bar input {
border: 1px solid #ccc;
margin: 0 auto;
width: 75%;
}
.video-item img {
max-width: 64px;
}
.video-detail .details {
margin-top: 10px;
padding: 10px;
}
.media-heading {
margin-left:10px;
}
.list-group-item {
cursor: pointer;
border: none;
}
.list-group-item:hover {
background-color: #eee;
}
/*global System */
'use strict';
System.config({
transpiler: 'babel',
map: {
'react': 'https://unpkg.com/react@16.0.0/umd/react.production.min.js',
'react-dom': 'https://unpkg.com/react-dom@16.0.0/umd/react-dom.production.min.js',
'axios': 'https://unpkg.com/axios/dist/axios.min.js',
'youtube-api-search': 'https://unpkg.com/youtube-api-search@0.0.5/index.js',
'app': './src'
},
packages: {
app: {
main: './index.jsx',
defaultExtension: false,
},
}
});
//import _ from "lodash";
import React, { Component } from "react";
import ReactDOM from "react-dom";
import YTSearch from "youtube-api-search";
import SearchBar from "./components/search_bar.jsx";
import VideoDetail from "./components/video_detail.jsx";
import VideoList from "./components/video_list.jsx";
const API_KEY = "AIzaSyBgWEQ_Fbc4NW36c_Re03wf9FSw_MH5P44";
class App extends Component {
constructor(props) {
super(props);
this.state = {
videos: [],
selectedVideo: null
};
this.videoSearch("surfboards");
}
videoSearch(term) {
YTSearch({ key: API_KEY, term: term }, videos => {
this.setState({
videos: videos,
selectedVideo: videos[0]
});
});
}
render() {
const videoSearch = _.debounce(term => {
this.videoSearch(term);
}, 300);
return (
<div>
<SearchBar onSearchTermChange={videoSearch} />
<VideoDetail video={this.state.selectedVideo} />
<VideoList
onVideoSelect={selectedVideo => this.setState({ selectedVideo })}
videos={this.state.videos}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
import React from "react";
const VideoDetail = ({ video }) => {
if (!video) {
return (
<div>
Loading...
</div>
);
}
const videoId = video.id.videoId;
//const url = "https://www.youtube.com/embed/" + videoId;
const url = `https://www.youtube.com/embed/${videoId}`;
return (
<div className="video-detail col-md-8">
<div className="embed-responsive embed-responsive-16by9">
<iframe className="embed-responsive-item" src={url} />
</div>
<div className="details">
<div>{video.snippet.title}</div>
<div>{video.snippet.description}</div>
</div>
</div>
);
};
export default VideoDetail;
import React, { Component } from "react";
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { term: "" };
}
render() {
return (
<div className="search-bar">
<input
className="form-control"
onChange={event => this.onInputChange(event.target.value)}
placeholder="Search YouTube"
value={this.state.term}
/>
</div>
);
}
onInputChange(term) {
this.setState({ term });
this.props.onSearchTermChange(term);
}
}
export default SearchBar;
import React from "react";
const VideoListItem = ({ video, onVideoSelect }) => {
//const video = props.video;
//const onVideoSelect = props.onVideoSelect;
const imageUrl = video.snippet.thumbnails.default.url;
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title}</div>
</div>
</div>
</li>
);
};
export default VideoListItem;
import React from "react";
import VideoListItem from "./video_list_item.jsx";
const VideoList = props => {
const videoItems = props.videos.map(video => {
return (
<VideoListItem
onVideoSelect={props.onVideoSelect}
key={video.etag}
video={video}
/>
);
});
return (
<ul className="col-md-4 list-group">
{videoItems}
</ul>
);
};
export default VideoList;