ng-agm-core-lib
Version:
Angular components for Google Maps
1,288 lines (1,271 loc) • 173 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, LOCALE_ID, Optional, Inject, Directive, Input, EventEmitter, Output, Self, Component, PLATFORM_ID, ContentChildren, QueryList, forwardRef, NgModule } from '@angular/core';
import { Observable, BehaviorSubject, from, timer, ReplaySubject, bindCallback, of, throwError, fromEventPattern, merge, Subject } from 'rxjs';
import { flatMap, sample, switchMap, map, shareReplay, multicast, startWith, skip, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { isPlatformServer } from '@angular/common';
class MapsAPILoader {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MapsAPILoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MapsAPILoader });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MapsAPILoader, decorators: [{
type: Injectable
}] });
/**
* Wrapper class that handles the communication with the Google Maps Javascript
* API v3
*/
class GoogleMapsAPIWrapper {
_loader;
_zone;
_map;
_mapResolver;
constructor(_loader, _zone) {
this._loader = _loader;
this._zone = _zone;
this._map =
new Promise((resolve) => { this._mapResolver = resolve; });
}
createMap(el, mapOptions) {
return this._zone.runOutsideAngular(() => {
return this._loader.load().then(() => {
const map = new google.maps.Map(el, mapOptions);
this._mapResolver(map);
return;
});
});
}
setMapOptions(options) {
return this._zone.runOutsideAngular(() => {
this._map.then((m) => { m.setOptions(options); });
});
}
/**
* Creates a google map marker with the map context
*/
createMarker(options = {}, addToMap = true) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => {
if (addToMap) {
options.map = map;
}
return new google.maps.Marker(options);
});
});
}
createInfoWindow(options) {
return this._zone.runOutsideAngular(() => {
return this._map.then(() => new google.maps.InfoWindow(options));
});
}
/**
* Creates a google.map.Circle for the current map.
*/
createCircle(options) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => {
options.map = map;
return new google.maps.Circle(options);
});
});
}
/**
* Creates a google.map.Rectangle for the current map.
*/
createRectangle(options) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => {
options.map = map;
return new google.maps.Rectangle(options);
});
});
}
createPolyline(options) {
return this._zone.runOutsideAngular(() => {
return this.getNativeMap().then((map) => {
const line = new google.maps.Polyline(options);
line.setMap(map);
return line;
});
});
}
createPolygon(options) {
return this._zone.runOutsideAngular(() => {
return this.getNativeMap().then((map) => {
const polygon = new google.maps.Polygon(options);
polygon.setMap(map);
return polygon;
});
});
}
/**
* Creates a new google.map.Data layer for the current map
*/
createDataLayer(options) {
return this._zone.runOutsideAngular(() => {
return this._map.then(m => {
const data = new google.maps.Data(options);
data.setMap(m);
return data;
});
});
}
/**
* Creates a TransitLayer instance for a map
* @returns a new transit layer object
*/
createTransitLayer() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => {
const newLayer = new google.maps.TransitLayer();
newLayer.setMap(map);
return newLayer;
});
});
}
/**
* Creates a BicyclingLayer instance for a map
* @returns a new bicycling layer object
*/
createBicyclingLayer() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => {
const newLayer = new google.maps.BicyclingLayer();
newLayer.setMap(map);
return newLayer;
});
});
}
/**
* Determines if given coordinates are insite a Polygon path.
*/
containsLocation(latLng, polygon) {
return this._map.then(() => google.maps.geometry.poly.containsLocation(latLng, polygon));
}
subscribeToMapEvent(eventName) {
return new Observable((observer) => {
this._map.then(m => m.addListener(eventName, (...evArgs) => this._zone.run(() => observer.next(evArgs))));
});
}
clearInstanceListeners() {
return this._zone.runOutsideAngular(() => {
this._map.then((map) => {
google.maps.event.clearInstanceListeners(map);
});
});
}
setCenter(latLng) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.setCenter(latLng));
});
}
getZoom() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.getZoom());
});
}
getBounds() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.getBounds());
});
}
getMapTypeId() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.getMapTypeId());
});
}
setZoom(zoom) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.setZoom(zoom));
});
}
getCenter() {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.getCenter());
});
}
panTo(latLng) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.panTo(latLng));
});
}
panBy(x, y) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.panBy(x, y));
});
}
fitBounds(latLng, padding) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.fitBounds(latLng, padding));
});
}
panToBounds(latLng, padding) {
return this._zone.runOutsideAngular(() => {
return this._map.then((map) => map.panToBounds(latLng, padding));
});
}
/**
* Returns the native Google Maps Map instance. Be careful when using this instance directly.
*/
getNativeMap() { return this._map; }
/**
* Triggers the given event name on the map instance.
*/
triggerMapEvent(eventName) {
return this._map.then((m) => google.maps.event.trigger(m, eventName));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GoogleMapsAPIWrapper, deps: [{ token: MapsAPILoader }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GoogleMapsAPIWrapper });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GoogleMapsAPIWrapper, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: MapsAPILoader }, { type: i0.NgZone }] });
class CircleManager {
_apiWrapper;
_zone;
_circles = new Map();
constructor(_apiWrapper, _zone) {
this._apiWrapper = _apiWrapper;
this._zone = _zone;
}
addCircle(circle) {
this._circles.set(circle, this._apiWrapper.getNativeMap().then(() => this._apiWrapper.createCircle({
center: { lat: circle.latitude, lng: circle.longitude },
clickable: circle.clickable,
draggable: circle.draggable,
editable: circle.editable,
fillColor: circle.fillColor,
fillOpacity: circle.fillOpacity,
radius: circle.radius,
strokeColor: circle.strokeColor,
strokeOpacity: circle.strokeOpacity,
strokePosition: google.maps.StrokePosition[circle.strokePosition],
strokeWeight: circle.strokeWeight,
visible: circle.visible,
zIndex: circle.zIndex,
})));
}
/**
* Removes the given circle from the map.
*/
removeCircle(circle) {
return this._circles.get(circle).then((c) => {
c.setMap(null);
this._circles.delete(circle);
});
}
async setOptions(circle, options) {
return this._circles.get(circle).then((c) => {
const actualParam = options.strokePosition;
options.strokePosition = google.maps.StrokePosition[actualParam];
c.setOptions(options);
});
}
getBounds(circle) {
return this._circles.get(circle).then((c) => c.getBounds());
}
getCenter(circle) {
return this._circles.get(circle).then((c) => c.getCenter());
}
getRadius(circle) {
return this._circles.get(circle).then((c) => c.getRadius());
}
setCenter(circle) {
return this._circles.get(circle).then(c => c.setCenter({ lat: circle.latitude, lng: circle.longitude }));
}
setEditable(circle) {
return this._circles.get(circle).then(c => c.setEditable(circle.editable));
}
setDraggable(circle) {
return this._circles.get(circle).then(c => c.setDraggable(circle.draggable));
}
setVisible(circle) {
return this._circles.get(circle).then(c => c.setVisible(circle.visible));
}
setRadius(circle) {
return this._circles.get(circle).then(c => c.setRadius(circle.radius));
}
getNativeCircle(circle) {
return this._circles.get(circle);
}
createEventObservable(eventName, circle) {
return new Observable((observer) => {
let listener = null;
this._circles.get(circle).then((c) => {
listener = c.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
return () => {
if (listener !== null) {
listener.remove();
}
};
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CircleManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CircleManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CircleManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
/**
* Manages all Data Layers for a Google Map instance.
*/
class DataLayerManager {
_wrapper;
_zone;
_layers = new Map();
constructor(_wrapper, _zone) {
this._wrapper = _wrapper;
this._zone = _zone;
}
/**
* Adds a new Data Layer to the map.
*/
addDataLayer(layer) {
const newLayer = this._wrapper.createDataLayer({
style: layer.style,
})
.then(d => {
if (layer.geoJson) {
// NOTE: accessing "features" on google.maps.Data is undocumented
this.getDataFeatures(d, layer.geoJson).then(features => d.features = features);
}
return d;
});
this._layers.set(layer, newLayer);
}
deleteDataLayer(layer) {
this._layers.get(layer).then(l => {
l.setMap(null);
this._layers.delete(layer);
});
}
updateGeoJson(layer, geoJson) {
this._layers.get(layer).then(l => {
l.forEach(feature => {
l.remove(feature);
// NOTE: accessing "features" on google.maps.Data is undocumented
const index = l.features.indexOf(feature, 0);
if (index > -1) {
l.features.splice(index, 1);
}
});
this.getDataFeatures(l, geoJson).then(features => l.features = features);
});
}
setDataOptions(layer, options) {
this._layers.get(layer).then(l => {
l.setControlPosition(options.controlPosition);
l.setControls(options.controls);
l.setDrawingMode(options.drawingMode);
l.setStyle(options.style);
});
}
/**
* Creates a Google Maps event listener for the given DataLayer as an Observable
*/
createEventObservable(eventName, layer) {
return new Observable((observer) => {
this._layers.get(layer).then((d) => {
d.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
/**
* Extract features from a geoJson using google.maps Data Class
* @param d : google.maps.Data class instance
* @param geoJson : url or geojson object
*/
getDataFeatures(d, geoJson) {
return new Promise((resolve, reject) => {
if (typeof geoJson === 'object') {
try {
const features = d.addGeoJson(geoJson);
resolve(features);
}
catch (e) {
reject(e);
}
}
else if (typeof geoJson === 'string') {
d.loadGeoJson(geoJson, null, resolve);
}
else {
reject(`Impossible to extract features from geoJson: wrong argument type`);
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataLayerManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataLayerManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataLayerManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
/**
* Class to implement when you what to be able to make it work with the auto fit bounds feature
* of AGM.
*/
class FitBoundsAccessor {
}
/**
* The FitBoundsService is responsible for computing the bounds of the a single map.
*/
class FitBoundsService {
bounds$;
_boundsChangeSampleTime$ = new BehaviorSubject(200);
_includeInBounds$ = new BehaviorSubject(new Map());
constructor(loader) {
this.bounds$ = from(loader.load()).pipe(flatMap(() => this._includeInBounds$), sample(this._boundsChangeSampleTime$.pipe(switchMap(time => timer(0, time)))), map(includeInBounds => this._generateBounds(includeInBounds)), shareReplay(1));
}
_generateBounds(includeInBounds) {
const bounds = new google.maps.LatLngBounds();
includeInBounds.forEach(b => bounds.extend(b));
return bounds;
}
addToBounds(latLng) {
const id = this._createIdentifier(latLng);
if (this._includeInBounds$.value.has(id)) {
return;
}
const boundsMap = this._includeInBounds$.value;
boundsMap.set(id, latLng);
this._includeInBounds$.next(boundsMap);
}
removeFromBounds(latLng) {
const boundsMap = this._includeInBounds$.value;
boundsMap.delete(this._createIdentifier(latLng));
this._includeInBounds$.next(boundsMap);
}
changeFitBoundsChangeSampleTime(timeMs) {
this._boundsChangeSampleTime$.next(timeMs);
}
getBounds$() {
return this.bounds$;
}
_createIdentifier(latLng) {
return `${latLng.lat}+${latLng.lng}`;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FitBoundsService, deps: [{ token: MapsAPILoader }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FitBoundsService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FitBoundsService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: MapsAPILoader }] });
class AgmGeocoder {
geocoder$;
constructor(loader) {
const connectableGeocoder$ = new Observable(subscriber => {
loader.load().then(() => subscriber.next());
})
.pipe(map(() => this._createGeocoder()), multicast(new ReplaySubject(1)));
connectableGeocoder$.connect(); // ignore the subscription
// since we will remain subscribed till application exits
this.geocoder$ = connectableGeocoder$;
}
geocode(request) {
return this.geocoder$.pipe(switchMap((geocoder) => this._getGoogleResults(geocoder, request)));
}
_getGoogleResults(geocoder, request) {
const geocodeObservable = bindCallback(geocoder.geocode);
return geocodeObservable(request).pipe(switchMap(([results, status]) => {
if (status === google.maps.GeocoderStatus.OK) {
return of(results);
}
return throwError(status);
}));
}
_createGeocoder() {
return new google.maps.Geocoder();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AgmGeocoder, deps: [{ token: MapsAPILoader }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AgmGeocoder, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AgmGeocoder, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: MapsAPILoader }] });
class WindowRef {
getNativeWindow() { return window; }
}
class DocumentRef {
getNativeDocument() { return document; }
}
const BROWSER_GLOBALS_PROVIDERS = [WindowRef, DocumentRef];
var GoogleMapsScriptProtocol;
(function (GoogleMapsScriptProtocol) {
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["HTTP"] = 1] = "HTTP";
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["HTTPS"] = 2] = "HTTPS";
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["AUTO"] = 3] = "AUTO";
})(GoogleMapsScriptProtocol || (GoogleMapsScriptProtocol = {}));
/**
* Token for the config of the LazyMapsAPILoader. Please provide an object of type {@link
* LazyMapsAPILoaderConfig}.
*/
const LAZY_MAPS_API_CONFIG = new InjectionToken('angular-google-maps LAZY_MAPS_API_CONFIG');
class LazyMapsAPILoader extends MapsAPILoader {
localeId;
_scriptLoadingPromise;
_config;
_windowRef;
_documentRef;
_SCRIPT_ID = 'agmGoogleMapsApiScript';
callbackName = `agmLazyMapsAPILoader`;
constructor(config = null, w, d, localeId) {
super();
this.localeId = localeId;
this._config = config || {};
this._windowRef = w;
this._documentRef = d;
}
load() {
const window = this._windowRef.getNativeWindow();
if (window.google && window.google.maps) {
// Google maps already loaded on the page.
return Promise.resolve();
}
if (this._scriptLoadingPromise) {
return this._scriptLoadingPromise;
}
// this can happen in HMR situations or Stackblitz.io editors.
const scriptOnPage = this._documentRef.getNativeDocument().getElementById(this._SCRIPT_ID);
if (scriptOnPage) {
this._assignScriptLoadingPromise(scriptOnPage);
return this._scriptLoadingPromise;
}
const script = this._documentRef.getNativeDocument().createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.id = this._SCRIPT_ID;
script.src = this._getScriptSrc(this.callbackName);
this._assignScriptLoadingPromise(script);
this._documentRef.getNativeDocument().body.appendChild(script);
return this._scriptLoadingPromise;
}
_assignScriptLoadingPromise(scriptElem) {
this._scriptLoadingPromise = new Promise((resolve, reject) => {
this._windowRef.getNativeWindow()[this.callbackName] = () => {
resolve();
};
scriptElem.onerror = (error) => {
reject(error);
};
});
}
_getScriptSrc(callbackName) {
const protocolType = (this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;
let protocol;
switch (protocolType) {
case GoogleMapsScriptProtocol.AUTO:
protocol = '';
break;
case GoogleMapsScriptProtocol.HTTP:
protocol = 'http:';
break;
case GoogleMapsScriptProtocol.HTTPS:
protocol = 'https:';
break;
}
const hostAndPath = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';
const queryParams = {
v: this._config.apiVersion || 'quarterly',
callback: callbackName,
key: this._config.apiKey,
client: this._config.clientId,
channel: this._config.channel,
libraries: this._config.libraries,
region: this._config.region,
language: this._config.language || (this.localeId !== 'en-US' ? this.localeId : null),
};
const params = Object.keys(queryParams)
.filter((k) => queryParams[k] != null)
.filter((k) => {
// remove empty arrays
return !Array.isArray(queryParams[k]) ||
(Array.isArray(queryParams[k]) && queryParams[k].length > 0);
})
.map((k) => {
// join arrays as comma seperated strings
const i = queryParams[k];
if (Array.isArray(i)) {
return { key: k, value: i.join(',') };
}
return { key: k, value: queryParams[k] };
})
.map((entry) => {
return `${entry.key}=${entry.value}`;
})
.join('&');
return `${protocol}//${hostAndPath}?${params}`;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyMapsAPILoader, deps: [{ token: LAZY_MAPS_API_CONFIG, optional: true }, { token: WindowRef }, { token: DocumentRef }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyMapsAPILoader });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyMapsAPILoader, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [LAZY_MAPS_API_CONFIG]
}] }, { type: WindowRef }, { type: DocumentRef }, { type: undefined, decorators: [{
type: Inject,
args: [LOCALE_ID]
}] }] });
class MarkerManager {
_mapsWrapper;
_zone;
_markers = new Map();
constructor(_mapsWrapper, _zone) {
this._mapsWrapper = _mapsWrapper;
this._zone = _zone;
}
async convertAnimation(uiAnim) {
if (uiAnim === null) {
return null;
}
else {
return this._mapsWrapper.getNativeMap().then(() => google.maps.Animation[uiAnim]);
}
}
deleteMarker(markerDirective) {
const markerPromise = this._markers.get(markerDirective);
if (markerPromise == null) {
// marker already deleted
return Promise.resolve();
}
return markerPromise.then((marker) => {
return this._zone.run(() => {
marker.setMap(null);
this._markers.delete(markerDirective);
});
});
}
updateMarkerPosition(marker) {
return this._markers.get(marker).then((m) => m.setPosition({ lat: marker.latitude, lng: marker.longitude }));
}
updateTitle(marker) {
return this._markers.get(marker).then((m) => m.setTitle(marker.title));
}
updateLabel(marker) {
return this._markers.get(marker).then((m) => { m.setLabel(marker.label); });
}
updateDraggable(marker) {
return this._markers.get(marker).then((m) => m.setDraggable(marker.draggable));
}
updateIcon(marker) {
return this._markers.get(marker).then((m) => m.setIcon(marker.iconUrl));
}
updateOpacity(marker) {
return this._markers.get(marker).then((m) => m.setOpacity(marker.opacity));
}
updateVisible(marker) {
return this._markers.get(marker).then((m) => m.setVisible(marker.visible));
}
updateZIndex(marker) {
return this._markers.get(marker).then((m) => m.setZIndex(marker.zIndex));
}
updateClickable(marker) {
return this._markers.get(marker).then((m) => m.setClickable(marker.clickable));
}
async updateAnimation(marker) {
const m = await this._markers.get(marker);
m.setAnimation(await this.convertAnimation(marker.animation));
}
addMarker(marker) {
const markerPromise = new Promise(async (resolve) => this._mapsWrapper.createMarker({
position: { lat: marker.latitude, lng: marker.longitude },
label: marker.label,
draggable: marker.draggable,
icon: marker.iconUrl,
opacity: marker.opacity,
visible: marker.visible,
zIndex: marker.zIndex,
title: marker.title,
clickable: marker.clickable,
animation: await this.convertAnimation(marker.animation),
}).then(resolve));
this._markers.set(marker, markerPromise);
}
getNativeMarker(marker) {
return this._markers.get(marker);
}
createEventObservable(eventName, marker) {
return new Observable(observer => {
this._markers.get(marker).then(m => m.addListener(eventName, e => this._zone.run(() => observer.next(e))));
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MarkerManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MarkerManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MarkerManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
class InfoWindowManager {
_mapsWrapper;
_zone;
_markerManager;
_infoWindows = new Map();
constructor(_mapsWrapper, _zone, _markerManager) {
this._mapsWrapper = _mapsWrapper;
this._zone = _zone;
this._markerManager = _markerManager;
}
deleteInfoWindow(infoWindow) {
const iWindow = this._infoWindows.get(infoWindow);
if (iWindow == null) {
// info window already deleted
return Promise.resolve();
}
return iWindow.then((i) => {
return this._zone.run(() => {
i.close();
this._infoWindows.delete(infoWindow);
});
});
}
setPosition(infoWindow) {
return this._infoWindows.get(infoWindow).then((i) => i.setPosition({
lat: infoWindow.latitude,
lng: infoWindow.longitude,
}));
}
setZIndex(infoWindow) {
return this._infoWindows.get(infoWindow)
.then((i) => i.setZIndex(infoWindow.zIndex));
}
open(infoWindow) {
return this._infoWindows.get(infoWindow).then((w) => {
if (infoWindow.hostMarker != null) {
return this._markerManager.getNativeMarker(infoWindow.hostMarker).then((marker) => {
return this._mapsWrapper.getNativeMap().then((map) => w.open(map, marker));
});
}
return this._mapsWrapper.getNativeMap().then((map) => w.open(map));
});
}
close(infoWindow) {
return this._infoWindows.get(infoWindow).then((w) => w.close());
}
setOptions(infoWindow, options) {
return this._infoWindows.get(infoWindow).then((i) => i.setOptions(options));
}
addInfoWindow(infoWindow) {
const options = {
content: infoWindow.content,
maxWidth: infoWindow.maxWidth,
zIndex: infoWindow.zIndex,
disableAutoPan: infoWindow.disableAutoPan,
};
if (typeof infoWindow.latitude === 'number' && typeof infoWindow.longitude === 'number') {
options.position = { lat: infoWindow.latitude, lng: infoWindow.longitude };
}
const infoWindowPromise = this._mapsWrapper.createInfoWindow(options);
this._infoWindows.set(infoWindow, infoWindowPromise);
}
/**
* Creates a Google Maps event listener for the given InfoWindow as an Observable
*/
createEventObservable(eventName, infoWindow) {
return new Observable((observer) => {
this._infoWindows.get(infoWindow).then((i) => {
i.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoWindowManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }, { token: MarkerManager }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoWindowManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoWindowManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }, { type: MarkerManager }] });
/**
* Manages all KML Layers for a Google Map instance.
*/
class KmlLayerManager {
_wrapper;
_zone;
_layers = new Map();
constructor(_wrapper, _zone) {
this._wrapper = _wrapper;
this._zone = _zone;
}
/**
* Adds a new KML Layer to the map.
*/
addKmlLayer(layer) {
const newLayer = this._wrapper.getNativeMap().then(m => {
return new google.maps.KmlLayer({
clickable: layer.clickable,
map: m,
preserveViewport: layer.preserveViewport,
screenOverlays: layer.screenOverlays,
suppressInfoWindows: layer.suppressInfoWindows,
url: layer.url,
zIndex: layer.zIndex,
});
});
this._layers.set(layer, newLayer);
}
setOptions(layer, options) {
this._layers.get(layer).then(l => l.setOptions(options));
}
deleteKmlLayer(layer) {
this._layers.get(layer).then(l => {
l.setMap(null);
this._layers.delete(layer);
});
}
/**
* Creates a Google Maps event listener for the given KmlLayer as an Observable
*/
createEventObservable(eventName, layer) {
return new Observable((observer) => {
this._layers.get(layer).then((m) => {
m.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KmlLayerManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KmlLayerManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KmlLayerManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
/**
* This class manages Transit and Bicycling Layers for a Google Map instance.
*/
class LayerManager {
_wrapper;
_layers = new Map();
constructor(_wrapper) {
this._wrapper = _wrapper;
}
/**
* Adds a transit layer to a map instance.
* @param layer - a TransitLayer object
* @param _options - TransitLayerOptions options
* @returns void
*/
addTransitLayer(layer) {
const newLayer = this._wrapper.createTransitLayer();
this._layers.set(layer, newLayer);
}
/**
* Adds a bicycling layer to a map instance.
* @param layer - a bicycling layer object
* @param _options - BicyclingLayer options
* @returns void
*/
addBicyclingLayer(layer) {
const newLayer = this._wrapper.createBicyclingLayer();
this._layers.set(layer, newLayer);
}
/**
* Deletes a map layer
* @param layer - the layer to delete
*/
deleteLayer(layer) {
return this._layers.get(layer).then(currentLayer => {
currentLayer.setMap(null);
this._layers.delete(layer);
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LayerManager, deps: [{ token: GoogleMapsAPIWrapper }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LayerManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LayerManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }] });
/**
* When using the NoOpMapsAPILoader, the Google Maps API must be added to the page via a `<script>`
* Tag.
* It's important that the Google Maps API script gets loaded first on the page.
*/
class NoOpMapsAPILoader {
load() {
if (!window.google || !window.google.maps) {
throw new Error('Google Maps API not loaded on page. Make sure window.google.maps is available!');
}
return Promise.resolve();
}
}
function createMVCEventObservable(array) {
const eventNames = ['insert_at', 'remove_at', 'set_at'];
return fromEventPattern(handler => eventNames.map(eventName => array.addListener(eventName, (index, previous) => handler.apply(array, [{ newArr: array.getArray(), eventName, index, previous }]))), (_handler, evListeners) => evListeners.forEach(evListener => evListener.remove()));
}
class MvcArrayMock {
vals = [];
listeners = {
remove_at: [],
insert_at: [],
set_at: [],
};
clear() {
for (let i = this.vals.length - 1; i >= 0; i--) {
this.removeAt(i);
}
}
getArray() {
return [...this.vals];
}
getAt(i) {
return this.vals[i];
}
getLength() {
return this.vals.length;
}
insertAt(i, elem) {
this.vals.splice(i, 0, elem);
this.listeners.insert_at.forEach(listener => listener(i));
}
pop() {
const deleted = this.vals.pop();
this.listeners.remove_at.forEach(listener => listener(this.vals.length, deleted));
return deleted;
}
push(elem) {
this.vals.push(elem);
this.listeners.insert_at.forEach(listener => listener(this.vals.length - 1));
return this.vals.length;
}
removeAt(i) {
const deleted = this.vals.splice(i, 1)[0];
this.listeners.remove_at.forEach(listener => listener(i, deleted));
return deleted;
}
setAt(i, elem) {
const deleted = this.vals[i];
this.vals[i] = elem;
this.listeners.set_at.forEach(listener => listener(i, deleted));
}
forEach(callback) {
this.vals.forEach(callback);
}
addListener(eventName, handler) {
const listenerArr = this.listeners[eventName];
listenerArr.push(handler);
return {
remove: () => {
listenerArr.splice(listenerArr.indexOf(handler), 1);
},
};
}
bindTo() { throw new Error('Not implemented'); }
changed() { throw new Error('Not implemented'); }
get() { throw new Error('Not implemented'); }
notify() { throw new Error('Not implemented'); }
set() { throw new Error('Not implemented'); }
setValues() { throw new Error('Not implemented'); }
unbind() { throw new Error('Not implemented'); }
unbindAll() { throw new Error('Not implemented'); }
}
class PolygonManager {
_mapsWrapper;
_zone;
_polygons = new Map();
constructor(_mapsWrapper, _zone) {
this._mapsWrapper = _mapsWrapper;
this._zone = _zone;
}
addPolygon(path) {
const polygonPromise = this._mapsWrapper.createPolygon({
clickable: path.clickable,
draggable: path.draggable,
editable: path.editable,
fillColor: path.fillColor,
fillOpacity: path.fillOpacity,
geodesic: path.geodesic,
paths: path.paths,
strokeColor: path.strokeColor,
strokeOpacity: path.strokeOpacity,
strokeWeight: path.strokeWeight,
visible: path.visible,
zIndex: path.zIndex,
});
this._polygons.set(path, polygonPromise);
}
updatePolygon(polygon) {
const m = this._polygons.get(polygon);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => this._zone.run(() => { l.setPaths(polygon.paths); }));
}
setPolygonOptions(path, options) {
return this._polygons.get(path).then((l) => { l.setOptions(options); });
}
deletePolygon(paths) {
const m = this._polygons.get(paths);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => {
return this._zone.run(() => {
l.setMap(null);
this._polygons.delete(paths);
});
});
}
getPath(polygonDirective) {
return this._polygons.get(polygonDirective)
.then((polygon) => polygon.getPath().getArray());
}
getPaths(polygonDirective) {
return this._polygons.get(polygonDirective)
.then((polygon) => polygon.getPaths().getArray().map((p) => p.getArray()));
}
createEventObservable(eventName, path) {
return new Observable((observer) => {
this._polygons.get(path).then((l) => {
l.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
async createPathEventObservable(agmPolygon) {
const polygon = await this._polygons.get(agmPolygon);
const paths = polygon.getPaths();
const pathsChanges$ = createMVCEventObservable(paths);
return pathsChanges$.pipe(startWith({ newArr: paths.getArray() }), // in order to subscribe to them all
switchMap(parentMVEvent => merge(... // rest parameter
parentMVEvent.newArr.map((chMVC, index) => createMVCEventObservable(chMVC)
.pipe(map(chMVCEvent => ({ parentMVEvent, chMVCEvent, pathIndex: index })))))
.pipe(// start the merged ob with an event signinifing change to parent
startWith({ parentMVEvent, chMVCEvent: null, pathIndex: null }))), skip(1), // skip the manually added event
map(({ parentMVEvent, chMVCEvent, pathIndex }) => {
let retVal;
if (!chMVCEvent) {
retVal = {
newArr: parentMVEvent.newArr.map(subArr => subArr.getArray().map(latLng => latLng.toJSON())),
eventName: parentMVEvent.eventName,
index: parentMVEvent.index,
};
if (parentMVEvent.previous) {
retVal.previous = parentMVEvent.previous.getArray();
}
}
else {
retVal = {
newArr: parentMVEvent.newArr.map(subArr => subArr.getArray().map(latLng => latLng.toJSON())),
pathIndex,
eventName: chMVCEvent.eventName,
index: chMVCEvent.index,
};
if (chMVCEvent.previous) {
retVal.previous = chMVCEvent.previous;
}
}
return retVal;
}));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolygonManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolygonManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolygonManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
class PolylineManager {
_mapsWrapper;
_zone;
_polylines = new Map();
constructor(_mapsWrapper, _zone) {
this._mapsWrapper = _mapsWrapper;
this._zone = _zone;
}
static _convertPoints(line) {
const path = line._getPoints().map((point) => {
return { lat: point.latitude, lng: point.longitude };
});
return path;
}
static _convertPath(path) {
const symbolPath = google.maps.SymbolPath[path];
if (typeof symbolPath === 'number') {
return symbolPath;
}
else {
return path;
}
}
static _convertIcons(line) {
const icons = line._getIcons().map(agmIcon => ({
fixedRotation: agmIcon.fixedRotation,
offset: agmIcon.offset,
repeat: agmIcon.repeat,
icon: {
anchor: new google.maps.Point(agmIcon.anchorX, agmIcon.anchorY),
fillColor: agmIcon.fillColor,
fillOpacity: agmIcon.fillOpacity,
path: PolylineManager._convertPath(agmIcon.path),
rotation: agmIcon.rotation,
scale: agmIcon.scale,
strokeColor: agmIcon.strokeColor,
strokeOpacity: agmIcon.strokeOpacity,
strokeWeight: agmIcon.strokeWeight,
},
}));
// prune undefineds;
icons.forEach(icon => {
Object.entries(icon).forEach(([key, val]) => {
if (typeof val === 'undefined') {
delete icon[key];
}
});
if (typeof icon.icon.anchor.x === 'undefined' ||
typeof icon.icon.anchor.y === 'undefined') {
delete icon.icon.anchor;
}
});
return icons;
}
addPolyline(line) {
const polylinePromise = this._mapsWrapper.getNativeMap()
.then(() => [PolylineManager._convertPoints(line),
PolylineManager._convertIcons(line)])
.then(([path, icons]) => this._mapsWrapper.createPolyline({
clickable: line.clickable,
draggable: line.draggable,
editable: line.editable,
geodesic: line.geodesic,
strokeColor: line.strokeColor,
strokeOpacity: line.strokeOpacity,
strokeWeight: line.strokeWeight,
visible: line.visible,
zIndex: line.zIndex,
path,
icons,
}));
this._polylines.set(line, polylinePromise);
}
updatePolylinePoints(line) {
const path = PolylineManager._convertPoints(line);
const m = this._polylines.get(line);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => this._zone.run(() => l.setPath(path)));
}
async updateIconSequences(line) {
await this._mapsWrapper.getNativeMap();
const icons = PolylineManager._convertIcons(line);
const m = this._polylines.get(line);
if (m == null) {
return;
}
return m.then(l => this._zone.run(() => l.setOptions({ icons })));
}
setPolylineOptions(line, options) {
return this._polylines.get(line).then((l) => { l.setOptions(options); });
}
deletePolyline(line) {
const m = this._polylines.get(line);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => {
return this._zone.run(() => {
l.setMap(null);
this._polylines.delete(line);
});
});
}
async getMVCPath(agmPolyline) {
const polyline = await this._polylines.get(agmPolyline);
return polyline.getPath();
}
async getPath(agmPolyline) {
return (await this.getMVCPath(agmPolyline)).getArray();
}
createEventObservable(eventName, line) {
return new Observable((observer) => {
this._polylines.get(line).then((l) => {
l.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
async createPathEventObservable(line) {
const mvcPath = await this.getMVCPath(line);
return createMVCEventObservable(mvcPath);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolylineManager, deps: [{ token: GoogleMapsAPIWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolylineManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PolylineManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: GoogleMapsAPIWrapper }, { type: i0.NgZone }] });
class RectangleManager {
_apiWrapper;
_zone;
_rectangles = new Map();
constructor(_apiWrapper, _zone) {
this._apiWrapper = _apiWrapper;
this._zone = _zone;
}
addRectangle(rectangle) {
this._rectangles.set(rectangle, this._apiWrapper.getNativeMap().then(() => this._apiWrapper.createRectangle({
bounds: {
north: rectangle.north,
east: rectangle.east,
south: rectangle.south,
west: rectangle.west,
},
clickable: rectangle.clickable,
draggable: rectangle.draggable,
editable: rectangle.editable,
fillColor: rectangle.fillColor,
fillOpacity: rectangle.fillOpacity,
strokeColor: rectangle.strokeColor,
strokeOpacity: rectangle.strokeOpacity,
strokePosition: google.maps.StrokePosition[rectangle.strokePosition],
strokeWeight: rectangle.strokeWeight,
visible: rectangle.visible,
zIndex: rectangle.zIndex,
})));
}
/**
* Removes the given rectangle from the map.
*/
removeRectangle(rectangle) {
return this._rectangles.get(rectangle).then((r) => {
r.setMap(null);
this._rectangles.delete(rectangle);
});
}
setOptions(rectangle, options) {
return this._rectangles.get(rectangle).then((r) => {
const actualStrokePosition = options.strokePosition;
options.strokePosition = google.maps.StrokePosition[actualStrokePosition];
r.setOptions(options);
});
}
getBounds(rectangle) {
return this._rectangles.get(rectangle).then((r) => r.getBounds());
}
setBounds(rectangle) {
return this._rectangles.get(rectangle).then((r) => {
return r.setBounds({
north: rectangle.north,
east: rectangle.east,
south: rectangle.south,
west: rectangle.west,
});
});
}
setEditable(rectangle) {
return this._rectangles.get(rectangle).then((r) => {
return r.setEditable(rectangle.editable);
});
}
setDraggable(rectangle) {
return this._rectangles.get(rectangle).then((r) => {
return r.setDraggable(rectangle.draggable);
});
}
setVisible(rectangle) {
return this._rectangles.get(rectangle).then((r) => {
return r.setVisible(rectangle.visible);
});
}
createEventObservable(eventName, rectangle) {
return new Observable((subsrciber) => {
let listener = null;
this._rectangles.get(rectangle)