|
@@ -1,102 +1,138 @@
|
|
import fuse from 'fuse.js'
|
|
import fuse from 'fuse.js'
|
|
|
|
+import theme from '../styles/theme'
|
|
|
|
|
|
-const dummyResults = [{
|
|
|
|
|
|
+const dummyResults = [
|
|
|
|
+ {
|
|
title: 'good :-)',
|
|
title: 'good :-)',
|
|
text: 'a good text.',
|
|
text: 'a good text.',
|
|
link: 'good'
|
|
link: 'good'
|
|
-}, {
|
|
|
|
|
|
+ },
|
|
|
|
+ {
|
|
title: 'bad :-(',
|
|
title: 'bad :-(',
|
|
text: 'a bad text.',
|
|
text: 'a bad text.',
|
|
link: 'bad'
|
|
link: 'bad'
|
|
-}]
|
|
|
|
|
|
+ }
|
|
|
|
+]
|
|
|
|
|
|
class Search extends React.Component {
|
|
class Search extends React.Component {
|
|
- state = {
|
|
|
|
- active: false,
|
|
|
|
- query: '',
|
|
|
|
- results: []
|
|
|
|
- }
|
|
|
|
|
|
+ state = {
|
|
|
|
+ active: false,
|
|
|
|
+ query: '',
|
|
|
|
+ results: []
|
|
|
|
+ }
|
|
|
|
|
|
- focus = ev => {
|
|
|
|
- this.setState({ active: true })
|
|
|
|
- }
|
|
|
|
|
|
+ focus = ev => {
|
|
|
|
+ this.setState({ active: true })
|
|
|
|
+ }
|
|
|
|
|
|
- blur = ev => {
|
|
|
|
- this.setState({ active: false })
|
|
|
|
- }
|
|
|
|
|
|
+ blur = ev => {
|
|
|
|
+ this.setState({ active: false })
|
|
|
|
+ }
|
|
|
|
|
|
- change = ev => {
|
|
|
|
- const { value } = ev.target
|
|
|
|
- this.setState({ query: ev.target.value })
|
|
|
|
- const fuseOptions = {
|
|
|
|
- shouldSort: true,
|
|
|
|
- includeMatches: true,
|
|
|
|
- threshold: 0.3,
|
|
|
|
- location: true,
|
|
|
|
- keys: ['title', 'text', 'link']
|
|
|
|
- }
|
|
|
|
- const fuseInst = new fuse(dummyResults, fuseOptions)
|
|
|
|
- const searchResults = fuseInst.search(value)
|
|
|
|
- console.log(dummyResults, searchResults)
|
|
|
|
- if (value) {
|
|
|
|
- this.setState({
|
|
|
|
- results: searchResults
|
|
|
|
- })
|
|
|
|
- } else {
|
|
|
|
- this.setState({ results: [] })
|
|
|
|
- }
|
|
|
|
|
|
+ change = ev => {
|
|
|
|
+ const { value } = ev.target
|
|
|
|
+ this.setState({ query: ev.target.value })
|
|
|
|
+ const fuseOptions = {
|
|
|
|
+ shouldSort: true,
|
|
|
|
+ includeMatches: true,
|
|
|
|
+ threshold: 0.3,
|
|
|
|
+ location: true,
|
|
|
|
+ keys: ['title', 'text', 'link']
|
|
|
|
+ }
|
|
|
|
+ const fuseInst = new fuse(dummyResults, fuseOptions)
|
|
|
|
+ const searchResults = fuseInst.search(value)
|
|
|
|
+ console.log(dummyResults, searchResults)
|
|
|
|
+ if (value) {
|
|
|
|
+ this.setState({
|
|
|
|
+ results: searchResults
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ this.setState({ results: [] })
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- render() {
|
|
|
|
- return (
|
|
|
|
- <>
|
|
|
|
- <div id='searchbar'>
|
|
|
|
- <input
|
|
|
|
- type="text"
|
|
|
|
- placeholder="Search.."
|
|
|
|
- onFocus={this.focus}
|
|
|
|
- onBlur={this.blur}
|
|
|
|
- onChange={this.change}
|
|
|
|
- />
|
|
|
|
- <button type="submit">Search</button>
|
|
|
|
- {(this.state.active && this.state.query) && (this.state.results ?
|
|
|
|
- (
|
|
|
|
- <ul id='searchresults'>
|
|
|
|
- {this.state.results.map(result => <Result key={result.title} {...result} />)}
|
|
|
|
- </ul>
|
|
|
|
- ) : (
|
|
|
|
- <p>Nothing found.</p>
|
|
|
|
- )
|
|
|
|
- )}
|
|
|
|
- </div>
|
|
|
|
|
|
+ clear = ev => {
|
|
|
|
+ this.setState({ query: '' })
|
|
|
|
+ }
|
|
|
|
|
|
- <style jsx>
|
|
|
|
- {`
|
|
|
|
- input[type=text] {
|
|
|
|
- float: right;
|
|
|
|
- padding: 6px;
|
|
|
|
- border: none;
|
|
|
|
- margin-top: 8px;
|
|
|
|
- margin-right: 16px;
|
|
|
|
- font-size: 17px;
|
|
|
|
- }
|
|
|
|
- `}
|
|
|
|
- </style>
|
|
|
|
- </>
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
|
|
+ render () {
|
|
|
|
+ return (
|
|
|
|
+ <>
|
|
|
|
+ <div id='searchbar'>
|
|
|
|
+ <input
|
|
|
|
+ type='text'
|
|
|
|
+ placeholder='Search..'
|
|
|
|
+ onFocus={this.focus}
|
|
|
|
+ onBlur={this.blur}
|
|
|
|
+ onChange={this.change}
|
|
|
|
+ value={this.state.query}
|
|
|
|
+ />
|
|
|
|
+ <button
|
|
|
|
+ style={{ display: this.state.query ? 'block' : 'none' }}
|
|
|
|
+ onClick={this.clear}
|
|
|
|
+ >
|
|
|
|
+ x
|
|
|
|
+ </button>
|
|
|
|
+ <button type='submit' disabled={!this.state.query}>
|
|
|
|
+ <span>Search</span>
|
|
|
|
+ </button>
|
|
|
|
+ {this.state.active &&
|
|
|
|
+ this.state.query &&
|
|
|
|
+ (this.state.results ? (
|
|
|
|
+ <ul id='searchresults'>
|
|
|
|
+ {this.state.results.map(result => (
|
|
|
|
+ <Result key={result.title} {...result} />
|
|
|
|
+ ))}
|
|
|
|
+ </ul>
|
|
|
|
+ ) : (
|
|
|
|
+ <p>Nothing found.</p>
|
|
|
|
+ ))}
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <style jsx>
|
|
|
|
+ {`
|
|
|
|
+ #searchbar {
|
|
|
|
+ border: 1px solid ${theme.colors.lightgrey};
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ input[type='text'] {
|
|
|
|
+ border: none;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ button {
|
|
|
|
+ font-weight: 900;
|
|
|
|
+ background: transparent;
|
|
|
|
+ color: ${theme.colors.darkgrey};
|
|
|
|
+ border: none;
|
|
|
|
+ padding: 0.3em 1.8em;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ box-shadow: none;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ button[type='submit'] {
|
|
|
|
+ content: '';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ button > span {
|
|
|
|
+ display: none;
|
|
|
|
+ }
|
|
|
|
+ `}
|
|
|
|
+ </style>
|
|
|
|
+ </>
|
|
|
|
+ )
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
const Result = props => {
|
|
const Result = props => {
|
|
- const { item, matches } = props
|
|
|
|
- return (
|
|
|
|
- <li>
|
|
|
|
- <a href={item.link}>
|
|
|
|
- <h3>{item.title}</h3>
|
|
|
|
- <p>{item.text}</p>
|
|
|
|
- </a>
|
|
|
|
- </li>
|
|
|
|
- )
|
|
|
|
|
|
+ const { item, matches } = props
|
|
|
|
+ return (
|
|
|
|
+ <li>
|
|
|
|
+ <a href={item.link}>
|
|
|
|
+ <h3>{item.title}</h3>
|
|
|
|
+ <p>{item.text}</p>
|
|
|
|
+ </a>
|
|
|
|
+ </li>
|
|
|
|
+ )
|
|
}
|
|
}
|
|
|
|
|
|
-export default Search
|
|
|
|
|
|
+export default Search
|