Skip to content

Commit

Permalink
Merge pull request #91 from thoresuenert/pu/address-geometry-viewport…
Browse files Browse the repository at this point in the history
…-support

add geometry viewport support to g-address-marker
  • Loading branch information
steveszc committed Apr 14, 2017
2 parents d7f2fad + c03339a commit 02c01f8
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ with the main `g-map` component. You can also set optional attributes:
- `draggable` boolean option,
- `onClick` action to track all `click` events on that marker,
- `onDrag` action to track all `dragend` events on that marker (callback receives new `lat` and `lng` in attributes).
- `viewport` optional google.maps.LatLngBounds, provides an optimized map viewport for the marker. This is generally provided by the [google geocoder](https://developers.google.com/maps/documentation/javascript/3.exp/reference#PlaceGeometry)

```handlebars
{{#g-map lat=37.7833 lng=-122.4167 zoom=12 as |context|}}
Expand Down Expand Up @@ -227,7 +228,8 @@ one Info Window is open at each moment for Markers of each group.
## Marker bound to address query

Proxy `g-map-address-marker` component takes address string as parameter
and translates it to lat/lng under the hood.
and translates it to lat/lng/viewport under the hood.
The viewport is used internally to fit the map and can be passed as optional parameter.

Optional `onLocationChange` action hook will send you back coordinates
of the latest address search result and the raw array of
Expand All @@ -245,7 +247,9 @@ ENV['g-map'] = {
```javascript
actions: {
onLocationChangeHandler(lat, lng, results) {
const { viewport } = results[0].geometry;
Ember.Logger.log(`lat: ${lat}, lng: ${lng}`);
Ember.Logger.log(`viewport: ${viewport}`);
Ember.Logger.debug(results);
}
}
Expand Down
2 changes: 2 additions & 0 deletions addon/components/g-map-address-marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ const GMapAddressMarkerComponent = Ember.Component.extend({
if (!this.destroyed) {
const lat = results[0].geometry.location.lat();
const lng = results[0].geometry.location.lng();
const { viewport } = results[0].geometry;

this.set('lat', lat);
this.set('lng', lng);
this.set('viewport', viewport);
this.sendOnLocationChange(lat, lng, results);
}
},
Expand Down
25 changes: 15 additions & 10 deletions addon/components/g-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,22 @@ export default Ember.Component.extend({
return isPresent(marker.get('lat')) && isPresent(marker.get('lng'));
});

if (markers.length > 0
&& (typeof FastBoot === 'undefined')) {
const map = this.get('map');
const bounds = new google.maps.LatLngBounds();
const points = markers.map((marker) => {
return new google.maps.LatLng(marker.get('lat'), marker.get('lng'));
});

points.forEach((point) => bounds.extend(point));
map.fitBounds(bounds);
if (markers.length === 0
|| (typeof FastBoot !== 'undefined')) {
return;
}

const map = this.get('map');
const bounds = new google.maps.LatLngBounds();

markers.forEach((marker) => {
if (isPresent(marker.get('viewport'))) {
bounds.union(marker.get('viewport'));
} else {
bounds.extend(new google.maps.LatLng(marker.get('lat'), marker.get('lng')));
}
});
map.fitBounds(bounds);
},

groupMarkerClicked(marker, group) {
Expand Down
4 changes: 2 additions & 2 deletions addon/templates/components/g-map-address-marker.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{#if hasBlock}}
{{#g-map-marker mapContext lat=lat lng=lng icon=icon label=label group=group title=title onClick=onClick onDrag=onDrag as |markerContext|}}
{{#g-map-marker mapContext lat=lat lng=lng viewport=viewport icon=icon label=label group=group title=title onClick=onClick onDrag=onDrag as |markerContext|}}
{{yield markerContext}}
{{/g-map-marker}}
{{else}}
{{g-map-marker mapContext lat=lat lng=lng icon=icon label=label title=title group=group onClick=onClick onDrag=onDrag}}
{{g-map-marker mapContext lat=lat lng=lng viewport=viewport icon=icon label=label title=title group=group onClick=onClick onDrag=onDrag}}
{{/if}}
23 changes: 23 additions & 0 deletions tests/unit/components/g-map-address-marker-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,31 @@ test('it sets `lat` & `lng` of the first provided result on `updateLocation`', f

assert.equal(component.get('lat'), 12);
assert.equal(component.get('lng'), -20);
assert.equal(component.get('viewport'), undefined);
});

test('it sets `lat` & `lng` & `viewport` on `updateLocation`', function(assert) {
const results = [{
geometry: {
location: {
lat: () => 12,
lng: () => -20
},
viewport: {
b: 14,
f: 15
}
}
}];

run(() => component.set('attrs', {}));
run(() => component.updateLocation(results));

assert.equal(component.get('lat'), 12);
assert.equal(component.get('lng'), -20);
assert.equal(component.get('viewport.b'), 14);
assert.equal(component.get('viewport.f'), 15);
});
test('it calls `sendOnLocationChange` on `updateLocation`', function() {
const results = [{
geometry: {
Expand Down
9 changes: 7 additions & 2 deletions tests/unit/components/g-map-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,21 +289,23 @@ test('it doesn\'t trigger `fitToMarkers` with markersFitMode !== "live"', functi
test('it calls `fitBounds` of google map on `fitToMarkers`', function() {
const firstMarker = Ember.Object.create({ lat: 1, lng: 2 });
const secondMarker = Ember.Object.create({ lat: 3, lng: 4 });
const thirdMarker = Ember.Object.create({ lat: 5, lng: 6, viewport: { b: 7, f: 8 } });
const component = this.subject();
this.render();

fakeMapObject.fitBounds = sinon.stub();

const fakeLatLngBounds = {
extend: sinon.stub()
extend: sinon.stub(),
union: sinon.stub()
};
sinon.stub(google.maps, 'LatLngBounds').returns(fakeLatLngBounds);

const stubbedLatLng = sinon.stub(google.maps, 'LatLng');
stubbedLatLng.onCall(0).returns(firstMarker);
stubbedLatLng.onCall(1).returns(secondMarker);

run(() => component.set('markers', [firstMarker, secondMarker]));
run(() => component.set('markers', [firstMarker, secondMarker, thirdMarker]));
run(() => component.fitToMarkers());
sinon.assert.calledOnce(google.maps.LatLngBounds);

Expand All @@ -315,6 +317,9 @@ test('it calls `fitBounds` of google map on `fitToMarkers`', function() {
sinon.assert.calledWith(fakeLatLngBounds.extend, firstMarker);
sinon.assert.calledWith(fakeLatLngBounds.extend, secondMarker);

sinon.assert.calledOnce(fakeLatLngBounds.union);
sinon.assert.calledWith(fakeLatLngBounds.union, thirdMarker.viewport);

sinon.assert.calledOnce(fakeMapObject.fitBounds);
sinon.assert.calledWith(fakeMapObject.fitBounds, fakeLatLngBounds);

Expand Down

0 comments on commit 02c01f8

Please sign in to comment.