Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Independent Info Window component #5

Merged
merged 5 commits into from
Oct 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,31 @@ with the main `g-map` component.
{{/g-map}}
```

## Map with Info Windows

Those Info Windows will be open right after component is rendered
and will be closed forever after user closes them. You can specify
optional `onClose` action to tear down anything you need when Info Window
has been closed by user.

```handlebars
{{#g-map lat=37.7833 lng=-122.4167 zoom=12 as |context|}}
{{#g-map-infowindow context lat=37.7733 lng=-122.4067}}
<h1>Info Window with Block</h1>
<p>Text with {{bound}} variables</p>
<button {{action "do"}}>Do</button>
{{/g-map-infowindow}}
{{g-map-infowindow context lat=37.7733 lng=-122.4067
title="Blockless form" message="Plain text."}}
{{g-map-infowindow context lat=37.7733 lng=-122.4067
title="With action set"
onClose="myOnCloseAction"}}
{{g-map-infowindow context lat=37.7733 lng=-122.4067
title="With closure action set"
onClose=(action "myOnCloseAction")}}
{{/g-map}}
```

## Map fits to show all initial Markers

`shouldFit` attribute overrides `lat`, `lng`, `zoom` settings.
Expand All @@ -65,19 +90,19 @@ with the main `g-map` component.
{{/g-map}}
```

## Map with Markers and optional Info Windows
## Map with Markers and bound Info Windows

Markers can have optional Info Windows activated on click.
To provide content for Info Window you should call `g-map-marker`
in block form with `withInfowindow` flag set to `true`.
Markers can have bound Info Windows activated on click.
To properly bind Info Window with Marker you should call `g-map-marker`
in block form and set context of Info Window to the one provided by Marker.

```handlebars
{{#g-map lat=37.7833 lng=-122.4167 zoom=12 as |context|}}
{{g-map-marker context lat=37.7933 lng=-122.4167}}
{{#g-map-marker context lat=37.7833 lng=-122.4267 withInfowindow=true}}
<h2>Infowindow header</h2>
<p>Text with {{bound}} variables</p>
<button {{action "do"}}>Do</button>
{{#g-map-marker context lat=37.7833 lng=-122.4267 as |markerContext|}}
{{#g-map-infowindow markerContext}}
<h2>Bound Info Window</h2>
{{/g-map-infowindow}}
{{/g-map-marker}}
{{/g-map}}
```
Expand Down
120 changes: 120 additions & 0 deletions addon/components/g-map-infowindow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Ember from 'ember';
import layout from '../templates/components/g-map-infowindow';
import GMapComponent from './g-map';
import GMapMarkerComponent from './g-map-marker';

const { isEmpty, isPresent, observer, computed, run, assert, typeOf } = Ember;

const GMapInfowindowComponent = Ember.Component.extend({
layout: layout,
classNames: ['g-map-marker'],

map: computed.alias('mapContext.map'),
marker: computed.alias('mapContext.marker'),

init() {
this._super(arguments);

let mapContext = this.get('mapContext');
let hasMap = mapContext instanceof GMapComponent;
let hasMarker = mapContext instanceof GMapMarkerComponent;
assert('Must be inside {{#g-map}} or {{#g-map-marker}} components with context set',
hasMarker || hasMap);

this.set('hasMarker', hasMarker);
},

didInsertElement() {
this._super();
if (isEmpty(this.get('infowindow'))) {
let infowindow = this.buildInfowindow();
this.set('infowindow', infowindow);
}
this.setPosition();
this.setMap();
this.setMarker();
},

willDestroyElement() {
this.close();
},

buildInfowindow() {
let infowindow = new google.maps.InfoWindow({
content: this.get('element'),
disableAutoPan: true
});

if (isPresent(this.get('attrs.onClose'))) {
this.attachCloseEvent(infowindow);
}
return infowindow;
},

attachCloseEvent(infowindow) {
infowindow.addListener('closeclick', () => {
const { onClose } = this.attrs;
if (typeOf(onClose) === 'function') {
onClose();
} else {
this.sendAction('onClose');
}
});
},

close() {
let infowindow = this.get('infowindow');
if (isPresent(infowindow)) {
infowindow.close();
}
},

mapWasSet: observer('map', function() {
run.once(this, 'setMap');
}),

setMap() {
let map = this.get('map');
let hasMarker = this.get('hasMarker');
let infowindow = this.get('infowindow');

if (isPresent(infowindow) && isPresent(map) && !hasMarker) {
infowindow.open(map);
}
},

markerWasSet: observer('marker', function() {
run.once(this, 'setMarker');
}),

setMarker() {
let map = this.get('map');
let marker = this.get('marker');
let infowindow = this.get('infowindow');

if (isPresent(infowindow) && isPresent(map) && isPresent(marker)) {
marker.addListener('click', () => infowindow.open(map, marker));
}
},

coordsChanged: observer('lat', 'lng', function() {
run.once(this, 'setPosition');
}),

setPosition() {
let infowindow = this.get('infowindow');
let lat = this.get('lat');
let lng = this.get('lng');

if (isPresent(infowindow) && isPresent(lat) && isPresent(lng)) {
let position = new google.maps.LatLng(lat, lng);
infowindow.setPosition(position);
}
}
});

GMapInfowindowComponent.reopenClass({
positionalParams: ['mapContext']
});

export default GMapInfowindowComponent;
20 changes: 0 additions & 20 deletions addon/components/g-map-marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ const GMapMarkerComponent = Ember.Component.extend({
let mapContext = this.get('mapContext');
assert('Must be inside {{#g-map}} component with context set', mapContext instanceof GMapComponent);

if (isEmpty(this.get('withInfowindow'))) {
this.set('withInfowindow', false);
}
this.register();
},

Expand Down Expand Up @@ -63,23 +60,6 @@ const GMapMarkerComponent = Ember.Component.extend({

if (isPresent(marker) && isPresent(map)) {
marker.setMap(map);
if (this.get('withInfowindow')) {
this.setInfowindow();
}
}
},

setInfowindow() {
let map = this.get('map');
let marker = this.get('marker');

if (isPresent(marker) && isPresent(map)) {
let infowindow = new google.maps.InfoWindow({
content: this.get('element')
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
}
},

Expand Down
6 changes: 6 additions & 0 deletions addon/templates/components/g-map-infowindow.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{#if hasBlock}}
{{yield}}
{{else}}
<h1>{{title}}</h1>
<p>{{message}}</p>
{{/if}}
2 changes: 1 addition & 1 deletion addon/templates/components/g-map-marker.hbs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{yield}}
{{yield this}}
1 change: 1 addition & 0 deletions app/components/g-map-infowindow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-g-map/components/g-map-infowindow';
14 changes: 4 additions & 10 deletions tests/dummy/app/controllers/application.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import Ember from 'ember';

export default Ember.Controller.extend({
firstMarker: {
lat: 37.7933,
lng: -122.4167
},

secondMarker: {
lat: 37.7733,
lng: -122.4167
},

randomVariable: 111,

actions: {
refresh() {
this.set('randomVariable', Math.floor(Math.random() * 1000));
},

onInfowindowClosed() {
window.alert('Info Window Closed!');
}
}
});
29 changes: 20 additions & 9 deletions tests/dummy/app/templates/application.hbs
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
<h2 id="title">Ember-g-map Component</h2>

{{#g-map shouldFit=true as |context|}}
{{g-map-marker context lat=37.7933 lng=-122.4167}}
{{g-map-marker context lat=37.7933 lng=-122.4467}}

{{#g-map-marker context lat=37.7733 lng=-122.4167 withInfowindow=true}}
<h1>Pretty Infowindow!</h1>
<p>It can has bound variables:</p>
<p>Random: {{randomVariable}}</p>
{{#g-map-marker context lat=37.7433 lng=-122.3867 as |markerContext|}}
{{#g-map-infowindow markerContext}}
<h1>Bound InfoWindow</h1>
<p>This InfoWindow is bound to a marker.</p>
<p>It can has bound variables:</p>
<p>Random: {{randomVariable}}</p>

<p>And elements with actions:</p>
<button {{action "refresh"}}>Refresh</button>
<p>And elements with actions:</p>
<button {{action "refresh"}}>Refresh</button>
{{/g-map-infowindow}}
{{/g-map-marker}}

{{#g-map-infowindow context lat=37.7333 lng=-122.4367 onClose="onInfowindowClosed"}}
<h1>Independent InfoWindow</h1>
<p>This InfoWindow can be placed anywhere on the map.</p>
{{/g-map-infowindow}}

{{g-map-infowindow context title="Blockless Infowindow" message="Contains plain text"
lat=37.7633 lng=-122.4367 onClose=(action "onInfowindowClosed")}}

{{g-map-route context
originLat=37.7933 originLng=-122.4167
destinationLat=37.7733 destinationLng=-122.4167}}
originLat=37.7933 originLng=-122.4467
destinationLat=37.7433 destinationLng=-122.3867}}
{{/g-map}}
54 changes: 54 additions & 0 deletions tests/integration/components/g-map-infowindow-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('g-map-infowindow', 'Integration | Component | g map infowindow', {
integration: true
});

test('it renders inside {{g-map}} component', function(assert) {
assert.expect(2);

this.render(hbs`
{{#g-map as |context|}}
{{g-map-infowindow context}}
{{/g-map}}
`);

assert.equal(this.$().text().trim(), '');

this.render(hbs`
{{#g-map as |context|}}
{{#g-map-infowindow context}}
template block text
{{/g-map-infowindow}}
{{/g-map}}
`);

assert.equal(this.$().text().trim(), 'template block text');
});

test('it renders inside {{g-map-marker}} component', function(assert) {
assert.expect(2);

this.render(hbs`
{{#g-map as |context|}}
{{#g-map-marker context as |markerContext|}}
{{g-map-infowindow markerContext}}
{{/g-map-marker}}
{{/g-map}}
`);

assert.equal(this.$().text().trim(), '');

this.render(hbs`
{{#g-map as |context|}}
{{#g-map-marker context as |markerContext|}}
{{#g-map-infowindow markerContext}}
template block text
{{/g-map-infowindow}}
{{/g-map-marker}}
{{/g-map}}
`);

assert.equal(this.$().text().trim(), 'template block text');
});
Loading