UNPKG

5.5 kBPlain TextView Raw
1import {Component, ElementRef, EventEmitter, OnChanges, OnDestroy, OnInit, SimpleChange} from '@angular/core';
2
3import {InfoWindowManager} from '../services/managers/info-window-manager';
4
5import {SebmGoogleMapMarker} from './google-map-marker';
6
7let infoWindowId = 0;
8
9/**
10 * SebmGoogleMapInfoWindow renders a info window inside a {@link SebmGoogleMapMarker} or standalone.
11 *
12 * ### Example
13 * ```typescript
14 * import { Component } from 'angular2/core';
15 * import { SebmGoogleMap, SebmGoogleMapMarker, SebmGoogleMapInfoWindow } from
16 * 'angular2-google-maps/core';
17 *
18 * @Component({
19 * selector: 'my-map-cmp',
20 * directives: [SebmGoogleMap, SebmGoogleMapMarker, SebmGoogleMapInfoWindow],
21 * styles: [`
22 * .sebm-google-map-container {
23 * height: 300px;
24 * }
25 * `],
26 * template: `
27 * <sebm-google-map [latitude]="lat" [longitude]="lng" [zoom]="zoom">
28 * <sebm-google-map-marker [latitude]="lat" [longitude]="lng" [label]="'M'">
29 * <sebm-google-map-info-window [disableAutoPan]="true">
30 * Hi, this is the content of the <strong>info window</strong>
31 * </sebm-google-map-info-window>
32 * </sebm-google-map-marker>
33 * </sebm-google-map>
34 * `
35 * })
36 * ```
37 */
38@Component({
39 selector: 'sebm-google-map-info-window',
40 inputs: ['latitude', 'longitude', 'disableAutoPan', 'isOpen', 'zIndex', 'maxWidth'],
41 outputs: ['infoWindowClose'],
42 template: `<div class='sebm-google-map-info-window-content'>
43 <ng-content></ng-content>
44 </div>
45 `
46})
47export class SebmGoogleMapInfoWindow implements OnDestroy, OnChanges, OnInit {
48 /**
49 * The latitude position of the info window (only usefull if you use it ouside of a {@link
50 * SebmGoogleMapMarker}).
51 */
52 latitude: number;
53
54 /**
55 * The longitude position of the info window (only usefull if you use it ouside of a {@link
56 * SebmGoogleMapMarker}).
57 */
58 longitude: number;
59
60 /**
61 * Disable auto-pan on open. By default, the info window will pan the map so that it is fully
62 * visible when it opens.
63 */
64 disableAutoPan: boolean;
65
66 /**
67 * All InfoWindows are displayed on the map in order of their zIndex, with higher values
68 * displaying in front of InfoWindows with lower values. By default, InfoWindows are displayed
69 * according to their latitude, with InfoWindows of lower latitudes appearing in front of
70 * InfoWindows at higher latitudes. InfoWindows are always displayed in front of markers.
71 */
72 zIndex: number;
73
74 /**
75 * Maximum width of the infowindow, regardless of content's width. This value is only considered
76 * if it is set before a call to open. To change the maximum width when changing content, call
77 * close, update maxWidth, and then open.
78 */
79 maxWidth: number;
80
81 /**
82 * Holds the marker that is the host of the info window (if available)
83 */
84 hostMarker: SebmGoogleMapMarker;
85
86 /**
87 * Holds the native element that is used for the info window content.
88 */
89 content: Node;
90
91 /**
92 * Sets the open state for the InfoWindow. You can also call the open() and close() methods.
93 */
94 isOpen: boolean = false;
95
96 /**
97 * Emits an event when the info window is closed.
98 */
99 infoWindowClose: EventEmitter<void> = new EventEmitter<void>();
100
101 private static _infoWindowOptionsInputs: string[] = ['disableAutoPan', 'maxWidth'];
102 private _infoWindowAddedToManager: boolean = false;
103 private _id: string = (infoWindowId++).toString();
104
105 constructor(private _infoWindowManager: InfoWindowManager, private _el: ElementRef) {}
106
107 ngOnInit() {
108 this.content = this._el.nativeElement.querySelector('.sebm-google-map-info-window-content');
109 this._infoWindowManager.addInfoWindow(this);
110 this._infoWindowAddedToManager = true;
111 this._updateOpenState();
112 this._registerEventListeners();
113 }
114
115 /** @internal */
116 ngOnChanges(changes: {[key: string]: SimpleChange}) {
117 if (!this._infoWindowAddedToManager) {
118 return;
119 }
120 if ((changes['latitude'] || changes['longitude']) && typeof this.latitude === 'number' &&
121 typeof this.longitude === 'number') {
122 this._infoWindowManager.setPosition(this);
123 }
124 if (changes['zIndex']) {
125 this._infoWindowManager.setZIndex(this);
126 }
127 if (changes['isOpen']) {
128 this._updateOpenState();
129 }
130 this._setInfoWindowOptions(changes);
131 }
132
133 private _registerEventListeners() {
134 this._infoWindowManager.createEventObservable('closeclick', this).subscribe(() => {
135 this.isOpen = false;
136 this.infoWindowClose.emit();
137 });
138 }
139
140 private _updateOpenState() {
141 this.isOpen ? this.open() : this.close();
142 }
143
144 private _setInfoWindowOptions(changes: {[key: string]: SimpleChange}) {
145 let options: {[propName: string]: any} = {};
146 let optionKeys = Object.keys(changes).filter(
147 k => SebmGoogleMapInfoWindow._infoWindowOptionsInputs.indexOf(k) !== -1);
148 optionKeys.forEach((k) => { options[k] = changes[k].currentValue; });
149 this._infoWindowManager.setOptions(this, options);
150 }
151
152 /**
153 * Opens the info window.
154 */
155 open(): Promise<void> { return this._infoWindowManager.open(this); }
156
157 /**
158 * Closes the info window.
159 */
160 close(): Promise<void> {
161 return this._infoWindowManager.close(this).then(() => { this.infoWindowClose.emit(); });
162 }
163
164 /** @internal */
165 id(): string { return this._id; }
166
167 /** @internal */
168 toString(): string { return 'SebmGoogleMapInfoWindow-' + this._id.toString(); }
169
170 /** @internal */
171 ngOnDestroy() { this._infoWindowManager.deleteInfoWindow(this); }
172}