Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { Component } from 'react'
- /*
- Usage:
- <SearchBox
- database= <array of { name, ..other props }> // name field required for filtering results
- onResultSelect= (result) => {} <callback function that receives clicked result as param, triggered when a result is selected>
- optional props:
- id= <your-id-name>
- width = <width of search box>
- initValue= <initial value of input>
- resetOnFocus= <boolean, whether search input always empties on focus>
- />
- */
- export default class SearchBox extends Component {
- constructor(props){
- super(props);
- }
- componentWillMount() {
- let init = this.props.initValue ? this.props.initValue : ''
- this.setState({
- isLoading: false,
- results: [],
- value: init,
- placeholder: true,
- lastValid: init
- })
- }
- escapeRegExp = (string) => {
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
- }
- showHideResults = (show) => {
- const search = document.getElementById(`${this.props.id}`)
- const results = search.getElementsByClassName('results')[0]
- results.style.display = show ? 'block' : 'none'
- }
- resetComponent = (empty=false) => {
- this.setState({
- results: [],
- isLoading: false,
- value: empty ? '' : this.state.lastValid,
- placeholder: true
- })
- }
- handleFocus = () =>{
- if(this.props.resetOnFocus) this.setState({ value: '' })
- this.showHideResults(true)
- }
- handleBlur = () =>{
- this.showHideResults(false)
- this.resetComponent()
- }
- handleChange = (e) =>{
- if(this.state.isLoading) clearTimeout(this.state.loadResults)
- let value = e.target.value
- this.setState({
- placeholder: false,
- isLoading: true,
- value
- });
- this.setState({
- loadResults: setTimeout(() => {
- if(value.length < 1) {
- this.resetComponent(true)
- return
- }else{
- const re = new RegExp('.*'+ this.escapeRegExp(value) +'.*', 'i')
- let results = this.props.database.filter(({name}) => name.match(re))
- this.setState({
- isLoading: false,
- results
- })
- }
- }, 300)})
- }
- handleResultSelect = (result) => {
- this.setState({
- lastValid: result.name
- })
- this.props.onResultSelect(result)
- }
- render() {
- const { isLoading, value, results, placeholder } = this.state;
- const { width, id } = this.props;
- return (
- <div id={id} style={{ width, position: 'relative' }}>
- <div className='input'>
- <input
- value = {this.state.value}
- type='text'
- onFocus={this.handleFocus}
- onBlur={this.handleBlur}
- onChange={this.handleChange}
- />
- </div>
- <div className='results' style={{display: 'none', position: 'absolute'}}>
- {isLoading &&
- <div className='loading'>
- Loading....
- </div>
- }
- {!isLoading && placeholder &&
- <div className='placeholder'>
- Search for something...
- </div>
- }
- {!isLoading && !placeholder && results.length < 1 &&
- <div className='empty'>
- No matches
- </div>
- }
- { !isLoading && !placeholder &&
- results.map((result, i) =>{
- return (
- <SearchResult
- key={i}
- value={result}
- onResultSelect={this.handleResultSelect}
- />
- )
- })
- }
- </div>
- </div>
- )
- }
- }
- class SearchResult extends Component {
- constructor(props){
- super(props);
- this.handleClick = this.handleClick.bind(this);
- }
- handleClick(){
- this.props.onResultSelect(this.props.value);
- }
- render(){
- const { value } = this.props
- return(
- <div className='result' onMouseDown={this.handleClick}>
- {value.name}
- </div>
- )
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement