summaryrefslogtreecommitdiff
blob: aad845ca81c0863a579df08715e5a0d53774151f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
 * External dependencies
 */
import { __ } from '@wordpress/i18n';
import { Component, createRef } from '@wordpress/element';
import { BaseControl, TextControl } from '@wordpress/components';

/**
 * Internal dependencies
 */
import Lookup from '../lookup';

const placeholderText = __( 'Add a marker…', 'jetpack' );

export class LocationSearch extends Component {
	constructor() {
		super( ...arguments );

		this.textRef = createRef();
		this.containerRef = createRef();
		this.state = {
			isEmpty: true,
		};
		this.autocompleter = {
			name: 'placeSearch',
			options: this.search,
			isDebounced: true,
			getOptionLabel: option => <span>{ option.place_name }</span>,
			getOptionKeywords: option => [ option.place_name ],
			getOptionCompletion: this.getOptionCompletion,
		};
	}
	componentDidMount() {
		setTimeout( () => {
			this.containerRef.current.querySelector( 'input' ).focus();
		}, 50 );
	}
	getOptionCompletion = option => {
		const { value } = option;
		const point = {
			placeTitle: value.text,
			title: value.text,
			caption: value.place_name,
			id: value.id,
			coordinates: {
				longitude: value.geometry.coordinates[ 0 ],
				latitude: value.geometry.coordinates[ 1 ],
			},
		};
		this.props.onAddPoint( point );
		return value.text;
	};

	search = value => {
		const { apiKey, onError } = this.props;
		const url =
			'https://api.mapbox.com/geocoding/v5/mapbox.places/' +
			encodeURI( value ) +
			'.json?access_token=' +
			apiKey;
		return new Promise( function( resolve, reject ) {
			const xhr = new XMLHttpRequest();
			xhr.open( 'GET', url );
			xhr.onload = function() {
				if ( xhr.status === 200 ) {
					const res = JSON.parse( xhr.responseText );
					resolve( res.features );
				} else {
					const res = JSON.parse( xhr.responseText );
					onError( res.statusText, res.responseJSON.message );
					reject( new Error( 'Mapbox Places Error' ) );
				}
			};
			xhr.send();
		} );
	};
	onReset = () => {
		this.textRef.current.value = null;
	};
	render() {
		const { label } = this.props;
		return (
			<div ref={ this.containerRef }>
				<BaseControl label={ label } className="components-location-search">
					<Lookup completer={ this.autocompleter } onReset={ this.onReset }>
						{ ( { isExpanded, listBoxId, activeId, onChange, onKeyDown } ) => (
							<TextControl
								placeholder={ placeholderText }
								ref={ this.textRef }
								onChange={ onChange }
								aria-expanded={ isExpanded }
								aria-owns={ listBoxId }
								aria-activedescendant={ activeId }
								onKeyDown={ onKeyDown }
							/>
						) }
					</Lookup>
				</BaseControl>
			</div>
		);
	}
}

LocationSearch.defaultProps = {
	onError: () => {},
};

export default LocationSearch;