Skip to content

Commit dde431d

Browse files
authored
Merge pull request #71 from Riley-Brown/master
Added feature to load google maps script
2 parents 429b0c7 + ed1e203 commit dde431d

File tree

3 files changed

+93
-26
lines changed

3 files changed

+93
-26
lines changed

lib/index.js

Lines changed: 52 additions & 17 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,11 +63,14 @@ 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,
5275
fields = _props$fields === undefined ? ['address_components', 'geometry.location', 'place_id', 'formatted_address'] : _props$fields;
5376

@@ -63,21 +86,31 @@ var ReactGoogleAutocomplete = function (_React$Component) {
6386

6487
this.disableAutofill();
6588

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

68-
this.event = this.autocomplete.addListener('place_changed', this.onSelected.bind(this));
92+
_this2.event = _this2.autocomplete.addListener('place_changed', _this2.onSelected.bind(_this2));
93+
};
94+
95+
if (apiKey) {
96+
this.handleLoadScript().then(function () {
97+
return handleAutoComplete();
98+
});
99+
} else {
100+
handleAutoComplete();
101+
}
69102
}
70103
}, {
71104
key: 'disableAutofill',
72105
value: function disableAutofill() {
73-
var _this2 = this;
106+
var _this3 = this;
74107

75108
// Autofill workaround adapted from https://stackoverflow.com/questions/29931712/chrome-autofill-covers-autocomplete-for-google-maps-api-v3/49161445#49161445
76109
if (window.MutationObserver) {
77110
var observerHack = new MutationObserver(function () {
78111
observerHack.disconnect();
79-
if (_this2.refs && _this2.refs.input) {
80-
_this2.refs.input.autocomplete = _this2.props.inputAutocompleteValue || 'new-password';
112+
if (_this3.refs && _this3.refs.input) {
113+
_this3.refs.input.autocomplete = _this3.props.inputAutocompleteValue || 'new-password';
81114
}
82115
});
83116
observerHack.observe(this.refs.input, {
@@ -106,7 +139,8 @@ var ReactGoogleAutocomplete = function (_React$Component) {
106139
types = _props2.types,
107140
componentRestrictions = _props2.componentRestrictions,
108141
bounds = _props2.bounds,
109-
rest = _objectWithoutProperties(_props2, ['onPlaceSelected', 'types', 'componentRestrictions', 'bounds']);
142+
apiKey = _props2.apiKey,
143+
rest = _objectWithoutProperties(_props2, ['onPlaceSelected', 'types', 'componentRestrictions', 'bounds', 'apiKey']);
110144

111145
return _react2.default.createElement('input', _extends({ ref: 'input' }, rest));
112146
}
@@ -121,7 +155,8 @@ ReactGoogleAutocomplete.propTypes = {
121155
componentRestrictions: _propTypes2.default.object,
122156
bounds: _propTypes2.default.object,
123157
fields: _propTypes2.default.array,
124-
inputAutocompleteValue: _propTypes2.default.string
158+
inputAutocompleteValue: _propTypes2.default.string,
159+
apiKey: _propTypes2.default.string
125160
};
126161
exports.default = ReactGoogleAutocomplete;
127162

@@ -131,16 +166,16 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
131166
function ReactCustomGoogleAutocomplete(props) {
132167
_classCallCheck(this, ReactCustomGoogleAutocomplete);
133168

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

136-
_this3.service = new google.maps.places.AutocompleteService();
137-
return _this3;
171+
_this4.service = new google.maps.places.AutocompleteService();
172+
return _this4;
138173
}
139174

140175
_createClass(ReactCustomGoogleAutocomplete, [{
141176
key: 'onChange',
142177
value: function onChange(e) {
143-
var _this4 = this;
178+
var _this5 = this;
144179

145180
var _props$types2 = this.props.types,
146181
types = _props$types2 === undefined ? ['(cities)'] : _props$types2;
@@ -149,9 +184,9 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
149184
if (e.target.value) {
150185
this.service.getPlacePredictions({ input: e.target.value, types: types }, function (predictions, status) {
151186
if (status === 'OK' && predictions && predictions.length > 0) {
152-
_this4.props.onOpen(predictions);
187+
_this5.props.onOpen(predictions);
153188
} else {
154-
_this4.props.onClose();
189+
_this5.props.onClose();
155190
}
156191
});
157192
} else {
@@ -161,29 +196,29 @@ var ReactCustomGoogleAutocomplete = exports.ReactCustomGoogleAutocomplete = func
161196
}, {
162197
key: 'componentDidMount',
163198
value: function componentDidMount() {
164-
var _this5 = this;
199+
var _this6 = this;
165200

166201
if (this.props.input.value) {
167202
this.placeService = new google.maps.places.PlacesService(this.refs.div);
168203
this.placeService.getDetails({ placeId: this.props.input.value }, function (e, status) {
169204
if (status === 'OK') {
170-
_this5.refs.input.value = e.formatted_address;
205+
_this6.refs.input.value = e.formatted_address;
171206
}
172207
});
173208
}
174209
}
175210
}, {
176211
key: 'render',
177212
value: function render() {
178-
var _this6 = this;
213+
var _this7 = this;
179214

180215
return _react2.default.createElement(
181216
'div',
182217
null,
183218
_react2.default.cloneElement(this.props.input, _extends({}, this.props, {
184219
ref: 'input',
185220
onChange: function onChange(e) {
186-
_this6.onChange(e);
221+
_this7.onChange(e);
187222
}
188223
})),
189224
_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
@@ -9,6 +9,7 @@ export default class ReactGoogleAutocomplete extends React.Component {
99
bounds: PropTypes.object,
1010
fields: PropTypes.array,
1111
inputAutocompleteValue: PropTypes.string,
12+
apiKey: PropTypes.string
1213
};
1314

1415
constructor(props) {
@@ -22,6 +23,7 @@ export default class ReactGoogleAutocomplete extends React.Component {
2223
types = ['(cities)'],
2324
componentRestrictions,
2425
bounds,
26+
apiKey,
2527
fields = [
2628
'address_components',
2729
'geometry.location',
@@ -41,15 +43,23 @@ export default class ReactGoogleAutocomplete extends React.Component {
4143

4244
this.disableAutofill();
4345

44-
this.autocomplete = new google.maps.places.Autocomplete(
45-
this.refs.input,
46-
config
47-
);
46+
const handleAutoComplete = () => {
47+
this.autocomplete = new google.maps.places.Autocomplete(
48+
this.refs.input,
49+
config
50+
);
4851

49-
this.event = this.autocomplete.addListener(
50-
'place_changed',
51-
this.onSelected.bind(this)
52-
);
52+
this.event = this.autocomplete.addListener(
53+
'place_changed',
54+
this.onSelected.bind(this)
55+
);
56+
};
57+
58+
if (apiKey) {
59+
this.handleLoadScript().then(() => handleAutoComplete());
60+
} else {
61+
handleAutoComplete();
62+
}
5363
}
5464

5565
disableAutofill() {
@@ -78,12 +88,34 @@ export default class ReactGoogleAutocomplete extends React.Component {
7888
}
7989
}
8090

91+
handleLoadScript = () => {
92+
const googleMapsScriptUrl = `https://maps.googleapis.com/maps/api/js?key=${this.props.apiKey}&libraries=places`;
93+
94+
// Check if script exists already
95+
if (
96+
document.querySelectorAll(`script[src="${googleMapsScriptUrl}"]`).length >
97+
0
98+
) {
99+
return Promise.resolve();
100+
}
101+
102+
this.googleMapsScript = document.createElement('script');
103+
this.googleMapsScript.src = googleMapsScriptUrl;
104+
105+
document.body.appendChild(this.googleMapsScript);
106+
107+
return new Promise((resolve) => {
108+
this.googleMapsScript.addEventListener('load', () => resolve());
109+
});
110+
};
111+
81112
render() {
82113
const {
83114
onPlaceSelected,
84115
types,
85116
componentRestrictions,
86117
bounds,
118+
apiKey,
87119
...rest
88120
} = this.props;
89121

0 commit comments

Comments
 (0)