Skip to content

Commit 1747500

Browse files
committed
2 parents b05e0e0 + dde431d commit 1747500

File tree

3 files changed

+110
-30
lines changed

3 files changed

+110
-30
lines changed

lib/index.js

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,26 @@ var ReactGoogleAutocomplete = function (_React$Component) {
3535

3636
var _this = _possibleConstructorReturn(this, (ReactGoogleAutocomplete.__proto__ || Object.getPrototypeOf(ReactGoogleAutocomplete)).call(this, props));
3737

38+
_this.handleLoadScript = function () {
39+
var googleMapsScriptUrl = 'https://maps.googleapis.com/maps/api/js?key=' + _this.props.apiKey + '&libraries=places';
40+
41+
// Check if script exists already
42+
if (document.querySelectorAll('script[src="' + googleMapsScriptUrl + '"]').length > 0) {
43+
return Promise.resolve();
44+
}
45+
46+
_this.googleMapsScript = document.createElement('script');
47+
_this.googleMapsScript.src = googleMapsScriptUrl;
48+
49+
document.body.appendChild(_this.googleMapsScript);
50+
51+
return new Promise(function (resolve) {
52+
_this.googleMapsScript.addEventListener('load', function () {
53+
return resolve();
54+
});
55+
});
56+
};
57+
3858
_this.autocomplete = null;
3959
_this.event = null;
4060
return _this;
@@ -43,41 +63,56 @@ var ReactGoogleAutocomplete = function (_React$Component) {
4363
_createClass(ReactGoogleAutocomplete, [{
4464
key: 'componentDidMount',
4565
value: function componentDidMount() {
66+
var _this2 = this;
67+
4668
var _props = this.props,
4769
_props$types = _props.types,
4870
types = _props$types === undefined ? ['(cities)'] : _props$types,
4971
componentRestrictions = _props.componentRestrictions,
5072
bounds = _props.bounds,
73+
apiKey = _props.apiKey,
5174
_props$fields = _props.fields,
52-
fields = _props$fields === undefined ? ['address_components', 'geometry.location', 'place_id', 'formatted_address'] : _props$fields;
75+
fields = _props$fields === undefined ? ['address_components', 'geometry.location', 'place_id', 'formatted_address'] : _props$fields,
76+
_props$options = _props.options,
77+
options = _props$options === undefined ? {} : _props$options;
5378

54-
var config = {
79+
var config = _extends({}, options, {
5580
types: types,
5681
bounds: bounds,
5782
fields: fields
58-
};
83+
});
5984

6085
if (componentRestrictions) {
6186
config.componentRestrictions = componentRestrictions;
6287
}
6388

6489
this.disableAutofill();
6590

66-
this.autocomplete = new google.maps.places.Autocomplete(this.refs.input, config);
91+
var handleAutoComplete = function handleAutoComplete() {
92+
_this2.autocomplete = new google.maps.places.Autocomplete(_this2.refs.input, config);
6793

68-
this.event = this.autocomplete.addListener('place_changed', this.onSelected.bind(this));
94+
_this2.event = _this2.autocomplete.addListener('place_changed', _this2.onSelected.bind(_this2));
95+
};
96+
97+
if (apiKey) {
98+
this.handleLoadScript().then(function () {
99+
return handleAutoComplete();
100+
});
101+
} else {
102+
handleAutoComplete();
103+
}
69104
}
70105
}, {
71106
key: 'disableAutofill',
72107
value: function disableAutofill() {
73-
var _this2 = this;
108+
var _this3 = this;
74109

75110
// Autofill workaround adapted from https://stackoverflow.com/questions/29931712/chrome-autofill-covers-autocomplete-for-google-maps-api-v3/49161445#49161445
76111
if (window.MutationObserver) {
77112
var observerHack = new MutationObserver(function () {
78113
observerHack.disconnect();
79-
if (_this2.refs && _this2.refs.input) {
80-
_this2.refs.input.autocomplete = _this2.props.inputAutocompleteValue || 'new-password';
114+
if (_this3.refs && _this3.refs.input) {
115+
_this3.refs.input.autocomplete = _this3.props.inputAutocompleteValue || 'new-password';
81116
}
82117
});
83118
observerHack.observe(this.refs.input, {
@@ -106,7 +141,9 @@ var ReactGoogleAutocomplete = function (_React$Component) {
106141
types = _props2.types,
107142
componentRestrictions = _props2.componentRestrictions,
108143
bounds = _props2.bounds,
109-
rest = _objectWithoutProperties(_props2, ['onPlaceSelected', 'types', 'componentRestrictions', 'bounds']);
144+
options = _props2.options,
145+
apiKey = _props2.apiKey,
146+
rest = _objectWithoutProperties(_props2, ['onPlaceSelected', 'types', 'componentRestrictions', 'bounds', 'options', 'apiKey']);
110147

111148
return _react2.default.createElement('input', _extends({ ref: 'input' }, rest));
112149
}
@@ -117,11 +154,22 @@ var ReactGoogleAutocomplete = function (_React$Component) {
117154

118155
ReactGoogleAutocomplete.propTypes = {
119156
onPlaceSelected: _propTypes2.default.func,
120-
types: _propTypes2.default.array,
157+
types: _propTypes2.default.arrayOf(_propTypes2.default.string),
121158
componentRestrictions: _propTypes2.default.object,
122159
bounds: _propTypes2.default.object,
123160
fields: _propTypes2.default.array,
124-
inputAutocompleteValue: _propTypes2.default.string
161+
inputAutocompleteValue: _propTypes2.default.string,
162+
options: _propTypes2.default.shape({
163+
componentRestrictions: _propTypes2.default.object,
164+
bounds: _propTypes2.default.object,
165+
location: _propTypes2.default.object,
166+
offset: _propTypes2.default.number,
167+
origin: _propTypes2.default.object,
168+
radius: _propTypes2.default.number,
169+
sessionToken: _propTypes2.default.object,
170+
types: _propTypes2.default.arrayOf(_propTypes2.default.string)
171+
}),
172+
apiKey: _propTypes2.default.string
125173
};
126174
exports.default = ReactGoogleAutocomplete;
127175

@@ -131,16 +179,16 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
131179
function ReactCustomGoogleAutocomplete(props) {
132180
_classCallCheck(this, ReactCustomGoogleAutocomplete);
133181

134-
var _this3 = _possibleConstructorReturn(this, (ReactCustomGoogleAutocomplete.__proto__ || Object.getPrototypeOf(ReactCustomGoogleAutocomplete)).call(this, props));
182+
var _this4 = _possibleConstructorReturn(this, (ReactCustomGoogleAutocomplete.__proto__ || Object.getPrototypeOf(ReactCustomGoogleAutocomplete)).call(this, props));
135183

136-
_this3.service = new google.maps.places.AutocompleteService();
137-
return _this3;
184+
_this4.service = new google.maps.places.AutocompleteService();
185+
return _this4;
138186
}
139187

140188
_createClass(ReactCustomGoogleAutocomplete, [{
141189
key: 'onChange',
142190
value: function onChange(e) {
143-
var _this4 = this;
191+
var _this5 = this;
144192

145193
var _props$types2 = this.props.types,
146194
types = _props$types2 === undefined ? ['(cities)'] : _props$types2;
@@ -149,9 +197,9 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
149197
if (e.target.value) {
150198
this.service.getPlacePredictions({ input: e.target.value, types: types }, function (predictions, status) {
151199
if (status === 'OK' && predictions && predictions.length > 0) {
152-
_this4.props.onOpen(predictions);
200+
_this5.props.onOpen(predictions);
153201
} else {
154-
_this4.props.onClose();
202+
_this5.props.onClose();
155203
}
156204
});
157205
} else {
@@ -161,29 +209,29 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
161209
}, {
162210
key: 'componentDidMount',
163211
value: function componentDidMount() {
164-
var _this5 = this;
212+
var _this6 = this;
165213

166214
if (this.props.input.value) {
167215
this.placeService = new google.maps.places.PlacesService(this.refs.div);
168216
this.placeService.getDetails({ placeId: this.props.input.value }, function (e, status) {
169217
if (status === 'OK') {
170-
_this5.refs.input.value = e.formatted_address;
218+
_this6.refs.input.value = e.formatted_address;
171219
}
172220
});
173221
}
174222
}
175223
}, {
176224
key: 'render',
177225
value: function render() {
178-
var _this6 = this;
226+
var _this7 = this;
179227

180228
return _react2.default.createElement(
181229
'div',
182230
null,
183231
_react2.default.cloneElement(this.props.input, _extends({}, this.props, {
184232
ref: 'input',
185233
onChange: function onChange(e) {
186-
_this6.onChange(e);
234+
_this7.onChange(e);
187235
}
188236
})),
189237
_react2.default.createElement('div', { ref: 'div' })

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-google-autocomplete",
3-
"version": "1.1.4",
3+
"version": "1.2.4",
44
"description": "React component for google autocomplete.",
55
"main": "index.js",
66
"scripts": {

src/index.js

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default class ReactGoogleAutocomplete extends React.Component {
1919
sessionToken: PropTypes.object,
2020
types: PropTypes.arrayOf(PropTypes.string)
2121
}),
22+
apiKey: PropTypes.string
2223
};
2324

2425
constructor(props) {
@@ -32,6 +33,7 @@ export default class ReactGoogleAutocomplete extends React.Component {
3233
types = ['(cities)'],
3334
componentRestrictions,
3435
bounds,
36+
apiKey,
3537
fields = [
3638
'address_components',
3739
'geometry.location',
@@ -53,15 +55,23 @@ export default class ReactGoogleAutocomplete extends React.Component {
5355

5456
this.disableAutofill();
5557

56-
this.autocomplete = new google.maps.places.Autocomplete(
57-
this.refs.input,
58-
config
59-
);
58+
const handleAutoComplete = () => {
59+
this.autocomplete = new google.maps.places.Autocomplete(
60+
this.refs.input,
61+
config
62+
);
6063

61-
this.event = this.autocomplete.addListener(
62-
'place_changed',
63-
this.onSelected.bind(this)
64-
);
64+
this.event = this.autocomplete.addListener(
65+
'place_changed',
66+
this.onSelected.bind(this)
67+
);
68+
};
69+
70+
if (apiKey) {
71+
this.handleLoadScript().then(() => handleAutoComplete());
72+
} else {
73+
handleAutoComplete();
74+
}
6575
}
6676

6777
disableAutofill() {
@@ -90,13 +100,35 @@ export default class ReactGoogleAutocomplete extends React.Component {
90100
}
91101
}
92102

103+
handleLoadScript = () => {
104+
const googleMapsScriptUrl = `https://maps.googleapis.com/maps/api/js?key=${this.props.apiKey}&libraries=places`;
105+
106+
// Check if script exists already
107+
if (
108+
document.querySelectorAll(`script[src="${googleMapsScriptUrl}"]`).length >
109+
0
110+
) {
111+
return Promise.resolve();
112+
}
113+
114+
this.googleMapsScript = document.createElement('script');
115+
this.googleMapsScript.src = googleMapsScriptUrl;
116+
117+
document.body.appendChild(this.googleMapsScript);
118+
119+
return new Promise((resolve) => {
120+
this.googleMapsScript.addEventListener('load', () => resolve());
121+
});
122+
};
123+
93124
render() {
94125
const {
95126
onPlaceSelected,
96127
types,
97128
componentRestrictions,
98129
bounds,
99130
options,
131+
apiKey,
100132
...rest
101133
} = this.props;
102134

0 commit comments

Comments
 (0)