OSDN Git Service

464d1b025234491e91509b753da854bfcb4bd674
[bytom/bytom-dashboard.git] / src / features / shared / components / Autocomplete / AutocompleteField.jsx
1 import React from 'react'
2 import styles from './AutocompleteField.scss'
3 import Autosuggest from 'react-autosuggest'
4 import actions from 'actions'
5
6 class AutocompleteField extends React.Component {
7   constructor() {
8     super()
9
10     this.state = {
11       suggestions: []
12     }
13
14     this.getSuggestionValue = this.getSuggestionValue.bind(this)
15     this.renderSuggestion = this.renderSuggestion.bind(this)
16     this.onSuggestionsFetchRequested = this.onSuggestionsFetchRequested.bind(this)
17     this.onSuggestionsClearRequested = this.onSuggestionsClearRequested.bind(this)
18   }
19
20   getSuggestions(value) {
21     const escapedValue = (value.trim()).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
22
23     if (escapedValue === '') {
24       return []
25     }
26
27     const regex = new RegExp('^' + escapedValue, 'i')
28
29     const suggestions = this.props.items.filter(item => regex.test(item.alias))
30     suggestions.sort((a,b) => a.alias.localeCompare(b.alias))
31
32     return suggestions
33   }
34
35   getSuggestionValue(suggestion) {
36     return suggestion.alias
37   }
38
39   renderSuggestion(suggestion) {
40     return (
41       <div onMouseOver={() => this.props.fieldProps.onChange(suggestion.alias)}>
42         <span>{suggestion.alias}</span>
43       </div>
44     )
45   }
46
47   onSuggestionsFetchRequested({ value }) {
48     if (this.props.autocompleteIsLoaded) {
49       this.setState({suggestions: this.getSuggestions(value)})
50     } else {
51       this.props.fetchAll().then(() => {
52         this.setState({suggestions: this.getSuggestions(value)})
53         this.props.didLoadAutocomplete()
54       })
55     }
56   }
57
58   onSuggestionsClearRequested() {
59     this.setState({
60       suggestions: []
61     })
62   }
63
64   keyCheck(event) {
65     // Fills input with top suggestion if suggestions are present and key
66     // pressed was either tab (keyCode 9), or enter/return (keyCode 13)
67     const suggestions = this.state.suggestions
68     if (suggestions.length > 0 && (event.keyCode == 9 || event.keyCode == 13)) {
69
70       // Prevent form submission if key pressed was enter/return
71       event.keyCode == 13 && event.preventDefault()
72
73       const suggestion = suggestions[0]['alias']
74       const input = this.props.fieldProps.value.toLowerCase()
75       if (suggestion.toLowerCase().startsWith(input)) {
76         this.props.fieldProps.onChange(suggestion)
77       }
78     }
79   }
80
81   render() {
82     const { suggestions } = this.state
83     const { fieldProps } = this.props
84
85     return (
86       <Autosuggest
87         theme={styles}
88         suggestions={suggestions}
89         onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
90         onSuggestionsClearRequested={this.onSuggestionsClearRequested}
91         onSuggestionSelected={(event) => event.preventDefault()}
92         getSuggestionValue={this.getSuggestionValue}
93         renderSuggestion={this.renderSuggestion}
94         focusFirstSuggestion={true}
95         inputProps={{
96           className: `form-control ${this.props.className}`,
97           ...fieldProps,
98           value: fieldProps.value,
99           placeholder: this.props.placeholder,
100           disabled: this.props.disabled,
101           onChange: (event, { newValue }) => fieldProps.onChange(newValue),
102           onKeyDown: (event) => this.keyCheck(event)}}
103       />
104     )
105   }
106 }
107
108 export default AutocompleteField
109
110 export const mapStateToProps = (type) => (state) => ({
111   autocompleteIsLoaded: state[type].autocompleteIsLoaded,
112   items: Object.keys(state[type].items).map(k => state[type].items[k])
113 })
114
115 export const mapDispatchToProps = (type) => (dispatch) => ({
116   didLoadAutocomplete: () => dispatch(actions[type].didLoadAutocomplete),
117   fetchAll: () => dispatch(actions[type].fetchAll())
118 })