├── tests
├── .eslintrc
└── index-test.js
├── .gitignore
├── .travis.yml
├── demo
└── src
│ └── index.js
├── nwb.config.js
├── package.json
├── README.md
└── src
└── index.js
/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /demo/dist
3 | /es6
4 | /lib
5 | /node_modules
6 | /umd
7 | npm-debug.log
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 4.2
6 |
7 | cache:
8 | directories:
9 | - node_modules
10 |
11 | before_install:
12 | - npm install codecov.io coveralls
13 |
14 | after_success:
15 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
16 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
17 |
18 | branches:
19 | only:
20 | - master
21 |
--------------------------------------------------------------------------------
/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {render} from 'react-dom'
3 |
4 | import Component from '../../src'
5 |
6 | let Demo = React.createClass({
7 | yourCallback(searchResults) {
8 | console.log('searchResults are: ', searchResults);
9 | },
10 |
11 | render() {
12 | return
13 |
18 |
19 | }
20 | })
21 |
22 | render(, document.querySelector('#demo'))
23 |
--------------------------------------------------------------------------------
/tests/index-test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/nwb.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // Let nwb know this is a React component module when generic build commands
3 | // are used.
4 | type: 'react-component',
5 |
6 | // Should nwb create a UMD build for this module?
7 | umd: true,
8 | // The name of the global variable the UMD build of this module will export
9 | global: 'material-ui-youtube-autocomplete',
10 | // Mapping from the npm package names of this module's peerDependencies to the
11 | // global variables they're expected to be available as for use by the UMD
12 | // build.
13 | externals: {
14 | 'react': 'React'
15 | },
16 |
17 | // Should nwb create a build with untranspiled ES6 modules for tree-shaking
18 | // module bundlers? If you change your mind later, add or remove this line in
19 | // package.json: "jsnext:main": "es6/index.js"
20 | jsNext: true
21 | }
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "material-ui-youtube-autocomplete",
3 | "version": "1.2.1",
4 | "description": "material-ui-youtube-autocomplete React component",
5 | "main": "lib/index.js",
6 | "jsnext:main": "es6/index.js",
7 | "files": [
8 | "css",
9 | "es6",
10 | "lib",
11 | "umd"
12 | ],
13 | "scripts": {
14 | "build": "nwb build",
15 | "clean": "nwb clean",
16 | "start": "nwb serve",
17 | "test": "nwb test"
18 | },
19 | "dependencies": {
20 | "jsonp": "^0.2.0",
21 | "material-ui": "^0.15.1",
22 | "react": "^15.1.0",
23 | "react-dom": "^15.1.0",
24 | "react-tap-event-plugin": "^1.0.0",
25 | "youtube-finder": "^1.0.0"
26 | },
27 | "devDependencies": {
28 | "nwb": "0.7.x"
29 | },
30 | "author": "",
31 | "homepage": "",
32 | "license": "MIT",
33 | "repository": "https://github.com/hackingbeauty/material-ui-youtube-autocomplete",
34 | "keywords": [
35 | "react-component"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # material-ui-youtube-autocomplete
2 |
3 | A React.js Autcomplete complete component inspired by Material-UI.
4 |
5 |
6 | ## Demo
7 |
8 | See this [compenent in action](https://videonotepad.com)
9 |
10 | ## Installation
11 |
12 | `npm install --save material-ui-youtube-autocomplete`
13 |
14 |
15 | ## Features
16 |
17 | - Material-UI stylized search input
18 | - Auto-suggest drop-down as user types (suggested results come from Youtube)
19 | - Retrieve collection of video search results from Youtube
20 |
21 |
22 | ## Usage
23 |
24 | ```js
25 | import YoutubeAutcomplete from 'material-ui-youtube-autocomplete';
26 |
27 | 50. Number of video search results you want
30 | placeHolder={string} // defaults -> "Search Youtube"
31 | callback={function} // callback to execute when search results are retrieved
32 | />
33 | ```
34 |
35 | ## Example
36 |
37 | ```js
38 | import YoutubeAutocomplete from 'material-ui-youtube-autocomplete';
39 |
40 | class Example extends React.Component {
41 | render() {
42 | return (
43 |
49 | );
50 | }
51 |
52 | _onSearchResultsFound(results) {
53 | // Results is an array of retreived search results from Youtube.
54 | // Do what you want with the results here.
55 | }
56 | }
57 | ```
58 |
59 | ## License
60 |
61 | MIT
62 |
63 | ## Course
64 |
65 | Are you looking to build a professional app for the Web using React & Redux?
66 |
67 | Check out my course ["How to Write a Single Page Application".](http://www.singlepageapplication.com)
68 |
69 | www.singlepageapplication.com
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { AutoComplete } from 'material-ui';
3 | import JSONP from 'jsonp';
4 | import YoutubeFinder from 'youtube-finder';
5 | import getMuiTheme from 'material-ui/styles/getMuiTheme';
6 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
7 | import injectTapEventPlugin from 'react-tap-event-plugin';
8 |
9 | injectTapEventPlugin();
10 |
11 | const googleAutoSuggestURL = '//suggestqueries.google.com/complete/search?client=youtube&ds=yt&q=';
12 |
13 | class MaterialUIAutocomplete extends Component {
14 | constructor(props) {
15 | super(props);
16 | this.onUpdateInput = this.onUpdateInput.bind(this);
17 | this.onNewRequest = this.onNewRequest.bind(this);
18 | this.YoutubeClient = YoutubeFinder.createClient({ key: this.props.apiKey });
19 | this.state = {
20 | dataSource : [],
21 | inputValue : ''
22 | }
23 | }
24 |
25 | performSearch() {
26 | const
27 | self = this,
28 | url = googleAutoSuggestURL + this.state.inputValue;
29 |
30 | if(this.state.inputValue !== '') {
31 | JSONP(url, function(error, data) {
32 | let searchResults, retrievedSearchTerms;
33 |
34 | if(error) return console.log(error);
35 |
36 | searchResults = data[1];
37 |
38 | retrievedSearchTerms = searchResults.map(function(result) {
39 | return result[0];
40 | });
41 |
42 | self.setState({
43 | dataSource : retrievedSearchTerms
44 | });
45 | });
46 | }
47 | }
48 |
49 | onUpdateInput(inputValue) {
50 | const self = this;
51 |
52 | this.setState({
53 | inputValue : inputValue
54 | },function(){
55 | self.performSearch();
56 | });
57 | }
58 |
59 | onNewRequest(searchTerm) {
60 | const
61 | self = this,
62 | params = {
63 | part : 'id,snippet',
64 | type : 'video',
65 | q : this.state.inputValue,
66 | maxResults : this.props.maxResults <= 50 ? this.props.maxResults : '50'
67 | }
68 |
69 | this.YoutubeClient.search(params, function(error,results) {
70 | if(error) return console.log(error);
71 | self.props.callback(results.items,searchTerm);
72 | self.setState({
73 | dataSource : [],
74 | inputValue : ''
75 | });
76 | });
77 | }
78 |
79 | render() {
80 | return
81 |
89 |
90 | }
91 | }
92 |
93 |
94 | export default MaterialUIAutocomplete;
95 |
--------------------------------------------------------------------------------