diff --git a/src/@ionic-native/plugins/google-maps/index.ts b/src/@ionic-native/plugins/google-maps/index.ts index 72965e1e48..948f08826f 100644 --- a/src/@ionic-native/plugins/google-maps/index.ts +++ b/src/@ionic-native/plugins/google-maps/index.ts @@ -375,6 +375,7 @@ export interface PolygonOptions { visible?: boolean; zIndex?: number; addHole?: Array>; + clickable?: boolean; } export interface PolylineOptions { @@ -384,6 +385,7 @@ export interface PolylineOptions { color?: string; width?: number; zIndex?: number; + clickable?: boolean; } export interface TileOverlayOptions { @@ -517,7 +519,6 @@ export const GoogleMapsMapTypeId: { [mapType: string]: MapType; } = { * }) * export class HomePage { * map: GoogleMap; - * mapElement: HTMLElement; * constructor(private googleMaps: GoogleMaps) { } * * ionViewDidLoad() { @@ -525,7 +526,6 @@ export const GoogleMapsMapTypeId: { [mapType: string]: MapType; } = { * } * * loadMap() { - * this.mapElement = document.getElementById('map'); * * let mapOptions: GoogleMapOptions = { * camera: { @@ -538,7 +538,7 @@ export const GoogleMapsMapTypeId: { [mapType: string]: MapType; } = { * } * }; * - * this.map = this.googleMaps.create(this.mapElement, mapOptions); + * this.map = this.googleMaps.create('map_canvas', mapOptions); * * // Wait the MAP_READY before using any methods. * this.map.one(GoogleMapsEvent.MAP_READY) @@ -623,9 +623,18 @@ export class GoogleMaps extends IonicNativePlugin { * @param options {any} Options * @return {GoogleMap} */ - create(element: string | HTMLElement, options?: GoogleMapOptions): GoogleMap { - let googleMap: GoogleMap = new GoogleMap(element, options); - googleMap.set('_overlays', new BaseArrayClass()); + create(element: string | HTMLElement | GoogleMapOptions, options?: GoogleMapOptions): GoogleMap { + if (element instanceof HTMLElement) { + if (element.getAttribute('__pluginMapId')) { + console.error('GoogleMaps', element.tagName + '[__pluginMapId=\'' + element.getAttribute('__pluginMapId') + '\'] has already map.'); + return; + } + } else if (typeof element === 'object') { + options = element; + element = null; + } + let googleMap: GoogleMap = new GoogleMap(element, options); + googleMap.set('_overlays', {}); return googleMap; } @@ -660,19 +669,17 @@ export class BaseClass { let overlay: Marker = this.get(args[args.length - 1].getId()); if (!overlay) { let markerJS: any = args[args.length - 1]; + let markerId: string = markerJS.getId(); let markerCluster: MarkerCluster = this; overlay = new Marker(markerCluster.getMap(), markerJS); - this.get('_overlays').push(markerJS.getId()); - this.set(markerJS.getId(), overlay); + this.get('_overlays')[markerId] = overlay; markerJS.one(markerJS.getId() + '_remove', () => { - let idx = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerJS.getId(), undefined); + this.get('_overlays')[markerId] = null; }); } args[args.length - 1] = overlay; } else { - args[args.length - 1] = this._objectInstance.getMap().get(args[args.length - 1].getId()); + args[args.length - 1] = this._objectInstance.getMap().get('_overlays')[args[args.length - 1].getId()]; } } observer.next(args); @@ -696,19 +703,17 @@ export class BaseClass { let overlay: Marker = this.get(args[args.length - 1].getId()); if (!overlay) { let markerJS: any = args[args.length - 1]; + let markerId: string = markerJS.getId(); let markerCluster: MarkerCluster = this; overlay = new Marker(markerCluster.getMap(), markerJS); - this.get('_overlays').push(markerJS.getId()); - this.set(markerJS.getId(), overlay); + this.get('_overlays')[markerId] = overlay; markerJS.one(markerJS.getId() + '_remove', () => { - let idx = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerJS.getId(), undefined); + this.get('_overlays')[markerId] = null; }); } args[args.length - 1] = overlay; } else { - args[args.length - 1] = this._objectInstance.getMap().get(args[args.length - 1].getId()); + args[args.length - 1] = this._objectInstance.getMap().get('_overlays')[args[args.length - 1].getId()]; } } resolve(args); @@ -757,19 +762,17 @@ export class BaseClass { let overlay: Marker = this.get(args[args.length - 1].getId()); if (!overlay) { let markerJS: any = args[args.length - 1]; + let markerId: string = markerJS.getId(); let markerCluster: MarkerCluster = this; overlay = new Marker(markerCluster.getMap(), markerJS); - this.get('_overlays').push(markerJS.getId()); - this.set(markerJS.getId(), overlay); + this.get('_overlays')[markerId] = overlay; markerJS.one(markerJS.getId() + '_remove', () => { - let idx = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerJS.getId(), undefined); + this.get('_overlays')[markerId] = null; }); } args[args.length - 1] = overlay; } else { - args[args.length - 1] = this._objectInstance.getMap().get(args[args.length - 1].getId()); + args[args.length - 1] = this._objectInstance.getMap().get('_overlays')[args[args.length - 1].getId()]; } } observer.next(args); @@ -793,19 +796,17 @@ export class BaseClass { let overlay: Marker = this.get(args[args.length - 1].getId()); if (!overlay) { let markerJS: any = args[args.length - 1]; + let markerId: string = markerJS.getId(); let markerCluster: MarkerCluster = this; overlay = new Marker(markerCluster.getMap(), markerJS); - this.get('_overlays').push(markerJS.getId()); - this.set(markerJS.getId(), overlay); + this.get('_overlays')[markerId] = overlay; markerJS.one(markerJS.getId() + '_remove', () => { - let idx = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerJS.getId(), undefined); + this.get('_overlays')[markerId] = null; }); } args[args.length - 1] = overlay; } else { - args[args.length - 1] = this._objectInstance.getMap().get(args[args.length - 1].getId()); + args[args.length - 1] = this._objectInstance.getMap().get('_overlays')[args[args.length - 1].getId()]; } } resolve(args); @@ -833,7 +834,7 @@ export class BaseClass { destroy(): void { let map: GoogleMap = this._objectInstance.getMap(); if (map) { - map.get('_overlays').set(this._objectInstance.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this._objectInstance.getId()]; } this._objectInstance.remove(); } @@ -873,26 +874,65 @@ export class BaseArrayClass extends BaseClass { * @param callback? {Function} */ @CordovaInstance({ sync: true }) - forEach(fn: ((element: T, index?: number) => void) | ((element: T, callback: () => void) => void), callback?: () => void): void {} + forEach(fn: (element: T, index?: number) => void): void {} /** * Iterate over each element, calling the provided callback. + * @param fn {Function} + * @return {Promise} + */ + @CordovaCheck() + forEachAsync(fn: ((element: T, callback: () => void) => void)): Promise { + return new Promise((resolve) => { + this._objectInstance.forEach(fn, resolve); + }); + } + + /** + * Iterate over each element, then return a new value. * Then you can get the results of each callback. * @param fn {Function} * @param callback? {Function} * @return {Array} returns a new array with the results */ @CordovaInstance({ sync: true }) - map(fn: Function, callback?: ((element: T, index: number) => T) | ((element: T, callback: (newElement: T) => void) => void)): T[] { return; } + map(fn: (element: T, index: number) => any): any[] { return; } + + /** + * Iterate over each element, calling the provided callback. + * Then you can get the results of each callback. + * @param fn {Function} + * @param callback? {Function} + * @return {Promise} returns a new array with the results + */ + @CordovaCheck() + mapAsync(fn: ((element: T, callback: (newElement: any) => void) => void)): Promise { + return new Promise((resolve) => { + this._objectInstance.map(fn, resolve); + }); + } /** * The filter() method creates a new array with all elements that pass the test implemented by the provided function. * @param fn {Function} * @param callback? {Function} - * @return {Array} returns a new array with the results + * @return {Array} returns a new filtered array */ @CordovaInstance({ sync: true }) - filter(fn: Function, callback?: ((element: T, index: number) => T) | ((element: T, callback: (newElement: T) => void) => void)): T[] { return; } + filter(fn: (element: T, index: number) => boolean): T[] { return; } + + /** + * The filterAsync() method creates a new array with all elements that pass the test implemented by the provided function. + * @param fn {Function} + * @param callback? {Function} + * @return {Promise} returns a new filtered array + */ + @CordovaCheck() + filterAsync(fn: (element: T, callback: (result: boolean) => void) => void): Promise { + return new Promise((resolve) => { + this._objectInstance.filter(fn, resolve); + }); + } /** * Returns a reference to the underlying Array. @@ -1349,10 +1389,69 @@ export class GoogleMap extends BaseClass { constructor(element: string | HTMLElement, options?: GoogleMapOptions) { super(); if (checkAvailability(GoogleMaps.getPluginRef(), null, GoogleMaps.getPluginName()) === true) { - if (typeof element === 'string') { - element = document.getElementById(element); + if (element instanceof HTMLElement) { + this._objectInstance = GoogleMaps.getPlugin().Map.getMap(element, options); + } else if (typeof element === 'string') { + let dummyObj: any = new (GoogleMaps.getPlugin().BaseClass)(); + this._objectInstance = dummyObj; + let onListeners: any[] = []; + let oneListeners: any[] = []; + let _origAddEventListener: any = this._objectInstance.addEventListener; + let _origAddEventListenerOnce: any = this._objectInstance.addEventListenerOnce; + this._objectInstance.addEventListener = (eventName: string, fn: () => void) => { + if (eventName === GoogleMapsEvent.MAP_READY) { + _origAddEventListener.call(dummyObj, eventName, fn); + } else { + onListeners.push([dummyObj, fn]); + } + }; + this._objectInstance.on = this._objectInstance.addEventListener; + + this._objectInstance.addEventListenerOnce = (eventName: string, fn: () => void) => { + if (eventName === GoogleMapsEvent.MAP_READY) { + _origAddEventListenerOnce.call(dummyObj, eventName, fn); + } else { + oneListeners.push([dummyObj, fn]); + } + }; + this._objectInstance.one = this._objectInstance.addEventListenerOnce; + (new Promise((resolve, reject) => { + let count: number = 0; + let timer: any = setInterval(() => { + let target = document.querySelector('.show-page #' + element); + if (target) { + clearInterval(timer); + resolve(target); + } else { + if (count++ < 20) { + return; + } + clearInterval(timer); + this._objectInstance.remove(); + console.error('Can not find the element [#' + element + ']'); + reject(); + } + }, 100); + })) + .then((target: any) => { + this._objectInstance = GoogleMaps.getPlugin().Map.getMap(target, options); + this._objectInstance.one(GoogleMapsEvent.MAP_READY, () => { + this.set('_overlays', {}); + onListeners.forEach((args) => { + this.on.apply(this, args); + }); + oneListeners.forEach((args) => { + this.one.apply(this, args); + }); + dummyObj.trigger(GoogleMapsEvent.MAP_READY); + }); + }) + .catch(() => { + this._objectInstance = null; + }); + } else if (element === null && options) { + this._objectInstance = GoogleMaps.getPlugin().Map.getMap(null, options); } - this._objectInstance = GoogleMaps.getPlugin().Map.getMap(element, options); } } @@ -1360,8 +1459,14 @@ export class GoogleMap extends BaseClass { * Changes the map div * @param domNode */ - @CordovaInstance({ sync: true }) - setDiv(domNode?: HTMLElement): void { } + @InstanceCheck() + setDiv(domNode?: HTMLElement | string): void { + if (typeof domNode === 'string') { + this._objectInstance.setDiv(document.querySelector('.show-page #' + domNode)); + } else { + this._objectInstance.setDiv(domNode); + } + } /** * Returns the map HTML element @@ -1517,9 +1622,12 @@ export class GoogleMap extends BaseClass { */ @CordovaInstance() remove(): Promise { - this.get('_overlays').forEach((overlayId: string) => this.set(overlayId, null)); - this.get('_overlays').empty(); - this.set('_overlays', undefined); + if (this.get('_overlays')) { + Object.keys(this.get('_overlays')).forEach((overlayId: string) => { + this.get('_overlays')[overlayId] = null; + delete this.get('_overlays')[overlayId]; + }); + } return new Promise((resolve) => { this._objectInstance.remove(() => resolve()); }); @@ -1531,8 +1639,12 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() clear(): Promise { - this.get('_overlays').forEach((overlayId: string) => this.set(overlayId, null)); - this.get('_overlays').empty(); + if (this.get('_overlays')) { + Object.keys(this.get('_overlays')).forEach((overlayId: string) => { + this.get('_overlays')[overlayId] = null; + delete this.get('_overlays')[overlayId]; + }); + } return new Promise((resolve) => { this._objectInstance.clear(() => resolve()); }); @@ -1627,14 +1739,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addMarker(options, (marker: any) => { if (marker) { - let markerId: string = marker.getId(); + let overlayId: string = marker.getId(); const overlay: Marker = new Marker(this, marker); - this.get('_overlays').push(markerId); - this.set(markerId, overlay); - marker.one(markerId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerId, undefined); + this.get('_overlays')[overlayId] = overlay; + marker.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1649,13 +1761,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addMarkerCluster(options, (markerCluster: any) => { if (markerCluster) { + let overlayId = markerCluster.getId(); const overlay = new MarkerCluster(this, markerCluster); - this.get('_overlays').push(markerCluster.getId()); - this.set(markerCluster.getId(), overlay); + this.get('_overlays')[overlayId] = overlay; markerCluster.one('remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(markerCluster.getId(), undefined); + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); markerCluster.set('_overlays', new BaseArrayClass()); resolve(overlay); @@ -1675,14 +1788,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addCircle(options, (circle: any) => { if (circle) { - let circleId: string = circle.getId(); + let overlayId: string = circle.getId(); const overlay = new Circle(this, circle); - this.get('_overlays').push(circleId); - this.set(circleId, overlay); - circle.one(circleId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(circleId, undefined); + this.get('_overlays')[overlayId] = overlay; + circle.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1701,14 +1814,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addPolygon(options, (polygon: any) => { if (polygon) { - let polygonId: string = polygon.getId(); + let overlayId: string = polygon.getId(); const overlay = new Polygon(this, polygon); - this.get('_overlays').push(polygonId); - this.set(polygonId, overlay); - polygon.one(polygonId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(polygonId, undefined); + this.get('_overlays')[overlayId] = overlay; + polygon.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1727,14 +1840,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addPolyline(options, (polyline: any) => { if (polyline) { - let polylineId: string = polyline.getId(); + let overlayId: string = polyline.getId(); const overlay = new Polyline(this, polyline); - this.get('_overlays').push(polylineId); - this.set(polylineId, overlay); - polyline.one(polylineId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(polylineId, undefined); + this.get('_overlays')[overlayId] = overlay; + polyline.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1752,14 +1865,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addTileOverlay(options, (tileOverlay: any) => { if (tileOverlay) { - let tileOverlayId: string = tileOverlay.getId(); + let overlayId: string = tileOverlay.getId(); const overlay = new TileOverlay(this, tileOverlay); - this.get('_overlays').push(tileOverlayId); - this.set(tileOverlayId, overlay); - tileOverlay.one(tileOverlayId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(tileOverlayId, undefined); + this.get('_overlays')[overlayId] = overlay; + tileOverlay.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1777,14 +1890,14 @@ export class GoogleMap extends BaseClass { return new Promise((resolve, reject) => { this._objectInstance.addGroundOverlay(options, (groundOverlay: any) => { if (groundOverlay) { - let groundOverlayId: string = groundOverlay.getId(); + let overlayId: string = groundOverlay.getId(); const overlay = new GroundOverlay(this, groundOverlay); - this.get('_overlays').push(groundOverlayId); - this.set(groundOverlayId, overlay); - groundOverlay.one(groundOverlayId + '_remove', () => { - let idx: number = this.get('_overlays').indexOf(overlay); - this.get('_overlays').removeAt(idx); - this.set(groundOverlayId, undefined); + this.get('_overlays')[overlayId] = overlay; + groundOverlay.one(overlayId + '_remove', () => { + if (this.get('_overlays')) { + this.get('_overlays')[overlayId] = null; + overlay.destroy(); + } }); resolve(overlay); } else { @@ -1822,6 +1935,7 @@ export class GoogleMap extends BaseClass { // }); // }); // } + } /** @@ -1938,7 +2052,7 @@ export class GroundOverlay extends BaseClass { */ @CordovaCheck() remove(): void { - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); } @@ -1953,18 +2067,11 @@ export class GroundOverlay extends BaseClass { pluginRef: 'plugin.google.maps.HtmlInfoWindow', repo: '' }) -export class HtmlInfoWindow extends IonicNativePlugin { - private _objectInstance: any; +export class HtmlInfoWindow extends BaseClass { - constructor(initialData?: any) { + constructor() { super(); - if (checkAvailability(HtmlInfoWindow.getPluginRef(), null, HtmlInfoWindow.getPluginName()) === true) { - if (initialData instanceof GoogleMaps.getPlugin().HtmlInfoWindow) { - this._objectInstance = initialData; - } else { - this._objectInstance = new (HtmlInfoWindow.getPlugin())(); - } - } + this._objectInstance = new (GoogleMaps.getPlugin().HtmlInfoWindow)(); } /** @@ -1977,9 +2084,10 @@ export class HtmlInfoWindow extends IonicNativePlugin { /** * Set your HTML contents. * @param content {any} String containing text or HTML element + * @param cssOptions? {any} CSS styles for the container element of HTMLInfoWindow */ @CordovaInstance() - setContent(content: string | Element): void {} + setContent(content: string | Element, cssOptions?: any): void {} /** * Open the htmlInfoWindow @@ -2122,7 +2230,7 @@ export class Marker extends BaseClass { */ @CordovaCheck() remove(): void { - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); } @@ -2244,7 +2352,7 @@ export class MarkerCluster extends BaseClass { @InstanceCheck() remove(): void { this._objectInstance.set('_overlays', undefined); - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); } @@ -2295,8 +2403,10 @@ export class Polygon extends BaseClass { * You can modify the points. * @return {BaseArrayClass} */ - @CordovaInstance({ sync: true }) - getPoints(): BaseArrayClass { return; } + @CordovaCheck() + getPoints(): BaseArrayClass { + return new BaseArrayClass(this._objectInstance.getPoints()); + } /** * Change the polygon holes. @@ -2310,8 +2420,15 @@ export class Polygon extends BaseClass { * You can modify the holes. * @return {BaseArrayClass} */ - @CordovaInstance({ sync: true }) - getHoles(): BaseArrayClass { return; } + @CordovaCheck() + getHoles(): BaseArrayClass { + let holes: ILatLng[][] = this._objectInstance.getPoints(); + let results: BaseArrayClass = new BaseArrayClass(); + holes.forEach((hole: ILatLng[]) => { + results.push(hole); + }); + return results; + } /** * Change the filling color (inner color) @@ -2387,7 +2504,7 @@ export class Polygon extends BaseClass { */ @InstanceCheck() remove(): void { - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); } @@ -2456,9 +2573,12 @@ export class Polyline extends BaseClass { /** * Return an instance of the BaseArrayClass * You can modify the points. + * @return {BaseArrayClass} */ - @CordovaInstance({ sync: true }) - getPoints(): BaseArrayClass { return; } + @CordovaCheck() + getPoints(): BaseArrayClass { + return new BaseArrayClass(this._objectInstance.getPoints()); + } /** * When true, edges of the polyline are interpreted as geodesic and will follow the curvature of the Earth. @@ -2548,7 +2668,7 @@ export class Polyline extends BaseClass { */ @InstanceCheck() remove(): void { - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); } @@ -2647,7 +2767,7 @@ export class TileOverlay extends BaseClass { */ @CordovaCheck() remove(): void { - this._objectInstance.getMap().get('_overlays').set(this.getId(), undefined); + delete this._objectInstance.getMap().get('_overlays')[this.getId()]; this._objectInstance.remove(); this.destroy(); }