UNPKG

cruk-searchkit

Version:

Set of overriden and new searchkit components designed specifically for Cancer Research UK

246 lines (214 loc) 7.95 kB
import React from 'react'; import ReactDOM from 'react-dom'; import Geosuggest from 'react-geosuggest'; import { QueryAccessor, SearchkitComponent, SearchkitComponentProps, ReactComponentType, renderComponent } from 'searchkit'; import { CRUKSearchkitLocationAccessor } from './CRUKSearchkitLocationAccessor'; export default class CRUKSearchkitLocationInput extends SearchkitComponent { accessor:CRUKSearchkitLocationAccessor static propTypes = { queryDelay: React.PropTypes.number, placeholder: React.PropTypes.string, initialValue: React.PropTypes.string, radius: React.PropTypes.string, location: React.PropTypes.object, fixtures: React.PropTypes.array, ...SearchkitComponent.propTypes, } constructor(props) { super(props); this.state = { lat: null, lng: null, placeId: null, searchedAddress: null }; this.preformedSearch = false; this.onSuggestSelect = this.onSuggestSelect.bind(this); this.getSelectedLocation = this.getSelectedLocation.bind(this); this.onChange = this.onChange.bind(this); this.onFocus = this.onFocus.bind(this); this.onBlur = this.onBlur.bind(this); this.getSuggestLabel = this.getSuggestLabel.bind(this); this.onSuggestNoResults = this.onSuggestNoResults.bind(this); this.onKeyPress = this.onKeyPress.bind(this); this.updateParentState = this.updateParentState.bind(this); this.resetState = this.resetState.bind(this); this.locationSort = this.locationSort.bind(this); this.handleEmptyLabel = this.handleEmptyLabel.bind(this); } /** * When a suggest got selected * @param {Object} suggest The suggest */ onSuggestSelect(suggest) { const { searchedAddress } = this.state; this.setState({ lat: suggest.lat, lng: suggest.lng, placeId: suggest.placeId, searchedAddress: searchedAddress }, () => this.preformSearch(suggest)); this.refs.g_wrapper.className = 'cr-geosuggest-wrapper'; this.preformSearch(suggest); this.removeEmptyLabel(); } onChange(suggest) { this.refs.geoLoader.className = 'geoSuggestLoader activated' if (suggest === '') { this.refs.geoLoader.className = 'geoSuggestLoader' this.refs.g_wrapper.className = 'cr-geosuggest-wrapper cr-geosuggest-wrapper--active' this.resetState(this.preformSearch({ location: this.state })) } } resetState(callback) { const latLng = { lat: null, lng: null, placeId: null, searchedAddress: null } this.setState(latLng, callback) } onFocus(suggest) { this.refs.g_wrapper.className = 'cr-geosuggest-wrapper cr-geosuggest-wrapper--active' } onBlur(suggest) { this.refs.g_wrapper.className = 'cr-geosuggest-wrapper'; document.querySelector('.geosuggest__suggests').className = 'geosuggest__suggests geosuggest__suggests--hidden'; const exitingItem = document.getElementsByClassName('geosuggest-item--disabled'); if (exitingItem[0]) this.refs.geoSuggest.setState({ userInput: '' }); this.removeEmptyLabel(); } getSuggestLabel(suggest) { this.refs.geoLoader.className = 'geoSuggestLoader' this.refs.g_wrapper.className = 'cr-geosuggest-wrapper cr-geosuggest-wrapper--dropdown' return suggest.description } onSuggestNoResults(userInputs) { const self = this; if (this.refs.geoSuggest.refs.input.refs.input.value !== '') { setTimeout(function(){ self.handleEmptyLabel(); }, 1000); } } handleEmptyLabel() { const exitingItem = document.getElementsByClassName('geosuggest-item--disabled'); const resultList = document.querySelector('.geosuggest__suggests'); this.removeEmptyLabel(); const li = document.createElement('li'); li.className = 'geosuggest-item geosuggest-item--disabled'; li.innerHTML = 'No results'; resultList.className = 'geosuggest__suggests'; this.refs.geoLoader.className = 'geoSuggestLoader' resultList.appendChild(li); } removeEmptyLabel() { const resultList = document.querySelector('.geosuggest__suggests'); const exitingItem = document.getElementsByClassName('geosuggest-item--disabled'); if (exitingItem[0]) resultList.removeChild(exitingItem[0]); } updateParentState(argState) { if (Object.keys(argState[this.props.id]).length === 0) { this.resetState() } else { this.getSelectedLocation(argState) } } onKeyPress() { // this.refs.geoLoader.className = 'geoSuggestLoader activated' } getSelectedLocation(argState) { const geocoder = new window.google.maps.Geocoder() const self = this this.preformedSearch = true geocoder.geocode( { 'placeId' : argState[this.props.id].placeId }, function( results, status ) { if( status == google.maps.GeocoderStatus.OK && results[0].address_components) { self.setState({searchedAddress: self.buildAddressFormattedString(results[0].address_components)}) self.forceUpdate() } } ); } preformSearch(query) { const { lat, lng } = this.state; const sortKey = query.location.lat ? 'location' : 'date'; this.locationSort(sortKey); if ((query.location.lat == lat) && (query.location.lng == lng)) { this.accessor.state = this.accessor.state.clear() } else { this.accessor.state = this.accessor.state.setValue({ lat: query.location.lat, lng: query.location.lng, placeId: query.placeId, }) } this.searchkit.performSearch() } locationSort(sortValue = 'location') { const sortIndex = this.searchkit.accessors.accessors.map((v, i) => { return {i: i, v: v.key} }).filter(v => v.v === 'sort'); if (sortIndex.length > 0) this.searchkit.accessors.accessors[sortIndex[0].i].state = this.searchkit.accessors.accessors[sortIndex[0].i].state.setValue(sortValue); } buildAddressFormattedString(locations) { return locations .map((v, i, a) => v.long_name) .filter((v, i, a) => a.indexOf(v) === i && a.length > i + 1) .filter(function (v, i, a) { return a.filter(val => v !== val) .map(val => v.indexOf(val) === -1) .join('') .indexOf('false') === -1 }) .join(', '); } defineAccessor() { const { id, title, field, resultRadius } = this.props; const updateParentState = this.updateParentState return new CRUKSearchkitLocationAccessor(id, { id, title, field, resultRadius, updateParentState }); } /** * Render the example app. */ render() { const { searchedAddress } = this.state; const argState = this.accessor.getQueryObject(); if (!this.preformedSearch && argState[this.props.id] !== undefined && Object.keys(argState[this.props.id]).length > 0) { this.getSelectedLocation(argState); } const inputClassName = this.props.inputClassName + ' form-control'; return ( <div className="cr-geosuggest-wrapper" ref="g_wrapper"> <div className="form-group"> <Geosuggest queryDelay={this.props.queryDelay} ref="geoSuggest" placeholder={this.props.placeholder} initialValue={searchedAddress || this.props.initialValue} fixtures={this.props.fixtures} onSuggestSelect={this.onSuggestSelect} onSuggestNoResults={this.onSuggestNoResults} onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} onKeyPress={this.onKeyPress} getSuggestLabel={this.getSuggestLabel} location={this.props.location} radius={this.props.radius} country={this.props.country} inputClassName={inputClassName} /> <div className="geoSuggestLoader" ref="geoLoader"></div> </div> </div> ) } }