Skip to content

Commit

Permalink
refactor: initializer to instance initializer and ensure usage of inj…
Browse files Browse the repository at this point in the history
…ected global libraries instead of using window to get them (esbanarango#113)
  • Loading branch information
dmuneras authored May 25, 2020
1 parent 2b23856 commit 55be6a5
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 81 deletions.
103 changes: 74 additions & 29 deletions addon/components/place-autocomplete-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,27 @@ import {
isEqual,
isBlank
} from '@ember/utils';
import { scheduleOnce, run } from "@ember/runloop";
import { later } from '@ember/runloop';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import { getOwner } from '@ember/application';

const RETRY_WINDOW = 100;

export default Component.extend({
/* SERVICES
---------------------------------------------------------------------------*/
placeAutocompleteManagerService: service('google-place-autocomplete/manager'),

/* COMPUTED PROPERTIES
---------------------------------------------------------------------------*/
isGoogleAvailable: computed('google', function() {
return !!this.google;
}),

isGoogleMapsAvailable: computed('isGoogleAvailable', function() {
return this.isGoogleAvailable && this.google.maps;
}),

/* HOOKS
---------------------------------------------------------------------------*/
Expand All @@ -25,32 +38,46 @@ export default Component.extend({
init() {
this._super(...arguments);
this._applyDefaults();

const owner = getOwner(this);
const google = owner.lookup('google:main');
const navigator = owner.lookup('navigator:main');

this.setProperties({ google, navigator });
},

/**
* @description Initialize component after is has been added to the DOM
*/
didInsertElement() {
this._super(...arguments);
// TODO: check if a block was passed to avoid trying to set
// the data attributes
this._bindDataAttributesToInput();
scheduleOnce('afterRender', this, 'setupComponent');
this.setupComponent();

this.get('placeAutocompleteManagerService').register();
},

/**
* @description Clean up component before removing it from the DOM
*/
willDestroy() {
if (isPresent(this.autocomplete)) {
let google = this.google || ((window) ? window.google : null);
this.get('placeAutocompleteManagerService').register();
const google = this.google;

this.get('placeAutocompleteManagerService').unregister();

if(google && google.maps && google.maps.event) {
google.maps.event.clearInstanceListeners(this.autocomplete);
this.get('placeAutocompleteManagerService').removePlacesAutoCompleteContainersIfRequired();

this
.get('placeAutocompleteManagerService')
.removePlacesAutoCompleteContainersIfRequired();
}
}
},

/**
* Acts as an observer an updates the autocomplete instance with any
* @description Acts as an observer an updates the autocomplete instance with any
* updated options that have been passed into the component.
*/
didReceiveAttrs() {
Expand All @@ -60,16 +87,15 @@ export default Component.extend({
},

/**
* Returns an object containing any options that are to be passed to the autocomplete instance.
* @description Returns an object containing any options that are
* to be passed to the autocomplete instance.
* @see https://developers.google.com/maps/documentation/javascript/places-autocomplete#set_search_area
*/
getOptions() {
const google = this.google || ((window) ? window.google : null);
const placeIdOnly = this.placeIdOnly || false;

const google = this.google;
const options = { types: this._typesToArray() };

if (this.latLngBnds && Object.keys(this.latLngBnds).length === 2){
// @see https://developers.google.com/maps/documentation/javascript/places-autocomplete#set_search_area
const { sw, ne } = this.latLngBnds;
options.bounds = new google.maps.LatLngBounds(sw, ne);
}
Expand All @@ -80,7 +106,7 @@ export default Component.extend({

if (this.fields) {
options.fields = this.this._fieldsToArray();
} else if (placeIdOnly) {
} else if (this.placeIdOnly) {
options.fields = ['place_id', 'name', 'types'];
}

Expand All @@ -90,18 +116,18 @@ export default Component.extend({
// Wait until the google library is loaded by calling this method
// every 100ms
setupComponent() {
if (document && window && window.google && window.google.maps) {
if (document && this.isGoogleAvailable && this.isGoogleMapsAvailable) {
this.setAutocomplete();
if (this.withGeoLocate) {
this.geolocateAndSetBounds();
}
this.autocomplete.addListener('place_changed', () => {
run(() => this.placeChanged());
this.placeChanged();
});

} else {
if (!this.isDestroyed && !this.isDestroying) {
run.later(this, 'setupComponent', 100);
later(this, 'setupComponent', RETRY_WINDOW);
}
}
},
Expand All @@ -122,15 +148,25 @@ export default Component.extend({
}
},

// @see https://developers.google.com/maps/documentation/javascript/places-autocomplete#set_search_area
/**
* @see https://developers.google.com/maps/documentation/javascript/places-autocomplete#set_search_area
*/
geolocateAndSetBounds() {
let navigator = this.navigator || ((window) ? window.navigator : null);
let autocomplete = this.autocomplete;
if (navigator && navigator.geolocation && isPresent(autocomplete)) {
navigator.geolocation.getCurrentPosition((position) => {
const google = this.google || window.google;
const geolocation = { lat: position.coords.latitude, lng: position.coords.longitude };
const circle = new google.maps.Circle({ center: geolocation, radius: position.coords.accuracy });
const { autocomplete } = this;

if (this.navigator && this.navigator.geolocation && isPresent(autocomplete)) {
this.navigator.geolocation.getCurrentPosition((position) => {
const google = this.google;
const geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};

const circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});

autocomplete.setBounds(circle.getBounds());
});
}
Expand Down Expand Up @@ -182,15 +218,16 @@ export default Component.extend({

_applyDefaults() {
const defaultProperties = {
layout: layout,
layout,
disabled: false,
inputClass: 'place-autocomplete--input',
types: undefined,
restrictions: {},
tabindex: 0,
withGeoLocate: false,
setValueWithProperty: undefined,
preventSubmit: false
preventSubmit: false,
placeIdOnly: false
};

for(let property in defaultProperties) {
Expand All @@ -201,9 +238,17 @@ export default Component.extend({
},

_bindDataAttributesToInput() {
let properties = Object.keys(this).filter((prop) => prop.indexOf('data-') >= 0) || [];
let input = document.getElementById(this.elementId).getElementsByTagName('input')[0];
if (!window || !document) {
return false;
}

const componentProperties = Object.keys(this) || [];
const properties = componentProperties.filter((prop) => prop.indexOf('data-') >= 0);
const input = document.getElementById(this.elementId).getElementsByTagName('input')[0];

properties.forEach((property) => input.setAttribute(property, this.get(property)));

return true;
},

actions: {
Expand Down
12 changes: 0 additions & 12 deletions addon/initializers/register-google.js

This file was deleted.

10 changes: 10 additions & 0 deletions addon/instance-initializers/google.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function initialize(appInstance) {
if(window && window.google){
appInstance.register('google:main', window.google, { instantiate: false });
}
}

export default {
name: 'register-google',
initialize
};
10 changes: 10 additions & 0 deletions addon/instance-initializers/navigator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function initialize(appInstance) {
if(window && window.google){
appInstance.register('navigator:main', window.navigator, { instantiate: false });
}
}

export default {
name: 'register-navigator',
initialize
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default, initialize } from 'ember-place-autocomplete/initializers/register-google';
export { default, initialize } from 'ember-place-autocomplete/instance-initializers/google';
1 change: 1 addition & 0 deletions app/instance-initializers/navigator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, initialize } from 'ember-place-autocomplete/instance-initializers/navigator';
6 changes: 6 additions & 0 deletions tests/dummy/app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,9 @@ a {
.documentation-hero .docs-max-w-sm.docs-mx-auto{
max-width: 100%;
}

// TESTS

#tests-body {
background: #fff;
}
2 changes: 1 addition & 1 deletion tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
</head>
<body>
<body id="tests-body">
{{content-for "body"}}
{{content-for "test-body"}}

Expand Down
28 changes: 16 additions & 12 deletions tests/unit/components/place-autocomplete-field-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('Unit | Component | PlaceAutocompleteField', function() {
geolocation: false
};
component.setProperties({
navigator: navigator,
navigator,
autocomplete: {
setBounds() {
expect().fail();
Expand All @@ -67,22 +67,25 @@ describe('Unit | Component | PlaceAutocompleteField', function() {
});

it('get geolocate is available', function() {
let component = this.owner.lookup('component:place-autocomplete-field');
let google = {};
const component = this.owner.lookup('component:place-autocomplete-field');
const google = {};
const Circle = function(center, radio) {
this.center = center;
this.radio = radio;
return {
getBounds() {
return {c: this.center, r: this.radio};
}
};
};

google.maps = {
Circle(center, radio) {
this.center = center;
this.radio = radio;
return {
getBounds() {
return {c: this.center, r: this.radio};
}
};
},
Circle,
__gjsload__() {
return true;
}
};

component.set('google', google);
component.set('autocomplete', {
setBounds: function (circle) {
Expand All @@ -95,6 +98,7 @@ describe('Unit | Component | PlaceAutocompleteField', function() {
expect(circle).to.be.ok;
}
});

component.geolocateAndSetBounds();
});
});
26 changes: 0 additions & 26 deletions tests/unit/initializers/register-google-test.js

This file was deleted.

0 comments on commit 55be6a5

Please sign in to comment.