terriajs
Version:
Geospatial data visualization platform.
111 lines (94 loc) • 3.61 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import debounce from 'lodash.debounce';
import Icon from "../Icon.jsx";
import Styles from './search-box.scss';
const DEBOUNCE_INTERVAL = 2000;
/**
* Simple dumb search box component that leaves the actual execution of searches to the component that renders it. Note
* that just like an input, this calls onSearchTextChanged when the value is changed, and expects that its parent
* component will listen for this and update searchText with the new value.
*/
export default createReactClass({
displayName: 'SearchBox',
propTypes: {
/** Called when the search changes, after a debounce of {@link DEBOUNCE_INTERVAL} ms */
onSearchTextChanged: PropTypes.func.isRequired,
/** Called when an actual search is triggered, either by clicking the button or pressing Enter */
onDoSearch: PropTypes.func.isRequired,
/** The search text to display in the search box */
searchText: PropTypes.string.isRequired,
/** Called when the search box receives focus */
onFocus: PropTypes.func,
placeholder: PropTypes.string,
onClear: PropTypes.func,
alwaysShowClear: PropTypes.bool,
autoFocus: PropTypes.bool
},
getDefaultProps() {
return {
placeholder: 'Search',
alwaysShowClear: false,
autoFocus: false
};
},
/* eslint-disable-next-line camelcase */
UNSAFE_componentWillMount() {
this.searchWithDebounce = debounce(this.search, DEBOUNCE_INTERVAL);
},
componentWillUnmount() {
this.removeDebounce();
},
hasValue() {
return this.props.searchText.length > 0;
},
search() {
this.removeDebounce();
this.props.onDoSearch();
},
removeDebounce() {
this.searchWithDebounce.cancel();
},
handleChange(event) {
const value = event.target.value;
this.props.onSearchTextChanged(value);
this.searchWithDebounce();
},
clearSearch() {
this.props.onSearchTextChanged('');
this.search();
if (this.props.onClear) {
this.props.onClear();
}
},
onKeyDown(event) {
if (event.keyCode === 13) {
this.search();
}
},
render() {
const clearButton = (
<button type='button' className={Styles.searchClear} onClick={this.clearSearch}><Icon glyph={Icon.GLYPHS.close}/></button>
);
return (
<form className={Styles.searchData} autoComplete='off' onSubmit={event => event.preventDefault()}>
<label htmlFor='search' className={Styles.formLabel}>
<Icon glyph={Icon.GLYPHS.search}/>
</label>
<input id='search'
type='text'
name='search'
value={this.props.searchText}
onChange={this.handleChange}
onFocus={this.props.onFocus}
onKeyDown={this.onKeyDown}
className={Styles.searchField}
placeholder={this.props.placeholder}
autoComplete='off'
autoFocus={this.props.autoFocus} />
{(this.props.alwaysShowClear || this.hasValue()) && clearButton}
</form>
);
}
});