import { Component , ElementRef , Output , EventEmitter , SimpleChanges , OnInit , OnDestroy , OnChanges , } from '@angular/core' ; import { Subject } from 'rxjs' ; import { debounceTime , tap } from 'rxjs/operators' ; import { NguiMap } from '../services/ngui-map' ; import { NguiMapComponent } from './ngui-map.component' ; const INPUTS = [ 'position' ] ; const OUTPUTS = [ 'animationChanged' , 'click' , 'clickableChanged' , 'cursorChanged' , 'dblclick' , 'drag' , 'dragend' , 'draggableChanged' , 'dragstart' , 'flatChanged' , 'iconChanged' , 'mousedown' , 'mouseout' , 'mouseover' , 'mouseup' , 'positionChanged' , 'rightclick' , 'shapeChanged' , 'titleChanged' , 'visibleChanged' , 'zindexChanged' , 'map_click' , 'map_mouseover' , 'map_mouseout' , 'map_mouseup' , 'map_mousedown' , 'map_drag' , 'map_dragend' ] ; /**
 * Wrapper to a create extend OverlayView at runtime, only after google maps is loaded.
 * Otherwise throws a google is unknown error.
 */ function getCustomMarkerOverlayView ( htmlEl , position ) { class CustomMarkerOverlayView extends google . maps . OverlayView { private htmlEl : HTMLElement ; private position : any ; private zIndex : string ; private visible : boolean = true ; constructor ( htmlEl , position ) { super ( ) ; this . htmlEl = htmlEl ; this . position = position ; } onAdd ( ) { this . getPanes ( ) . overlayMouseTarget . appendChild ( this . htmlEl ) ; this . htmlEl . style . position = 'absolute' ; } draw ( ) { this . setPosition ( this . position ) ; this . setZIndex ( this . zIndex ) ; this . setVisible ( this . visible ) ; } onRemove ( ) { } getPosition ( ) { return this . position ; } setPosition = ( position ? ) => { this . htmlEl . style . visibility = 'hidden' ; if ( position . constructor . name === 'Array' ) { this . position = new google . maps . LatLng ( position [ 0 ] , position [ 1 ] ) ; } else if ( typeof position === 'string' ) { let geocoder = new google . maps . Geocoder ( ) ; geocoder . geocode ( { address : position } , ( results , status ) => { if ( status === google . maps . GeocoderStatus . OK ) { console . log ( 'setting custom marker position from address' , position ) ; this . setPosition ( results [ 0 ] . geometry . location ) ; } else { console . log ( 'Error in custom marker geo coding, position' ) ; } } ) ; } else if ( position && typeof position . lng === 'function' ) { this . position = position ; } if ( this . getProjection ( ) && typeof this . position . lng === 'function' ) { let positionOnMap = ( ) => { let projection = this . getProjection ( ) ; if ( ! projection ) { return ; } let posPixel = projection . fromLatLngToDivPixel ( this . position ) ; let x = Math . round ( posPixel . x - ( this . htmlEl . offsetWidth / 2 ) ) ; let y = Math . round ( posPixel . y - this . htmlEl . offsetHeight / 2 ) ; this . htmlEl . style . left = x + 'px' ; this . htmlEl . style . top = y + 'px' ; this . htmlEl . style . visibility = 'visible' ; } ; if ( this . htmlEl . offsetWidth && this . htmlEl . offsetHeight ) { positionOnMap ( ) ; } else { setTimeout ( ( ) => positionOnMap ( ) ) ; } } } ; setZIndex ( zIndex ) { zIndex && ( this . zIndex = zIndex ) ; this . htmlEl . style . zIndex = this . zIndex ; } setVisible ( visible ) { this . htmlEl . style . display = visible ? 'inline-block' : 'none' ; this . visible = visible ; } } return new CustomMarkerOverlayView ( htmlEl , position ) ; } @ Component ( { selector : 'ngui-map > custom-marker' , inputs : INPUTS , outputs : OUTPUTS , template : `
    <ng-content></ng-content>
  ` , } ) export class CustomMarker implements OnInit , OnDestroy , OnChanges { @ Output ( ) initialized$ : EventEmitter < any > = new EventEmitter ( ) ; public inputChanges$ = new Subject ( ) ; private el : HTMLElement ; private mapObject : any ; constructor ( private nguiMapComponent , private elementRef , private nguiMap ) { this . elementRef . nativeElement . style . display = 'none' ; OUTPUTS . forEach ( output => this [ output ] = new EventEmitter ( ) ) ; } ngOnInit ( ) { if ( this . nguiMapComponent . mapIdledOnce ) { this . initialize ( ) ; } else { this . nguiMapComponent . mapReady$ . subscribe ( map => this . initialize ( ) ) ; } } ngOnChanges ( changes ) { this . inputChanges$ . next ( changes ) ; } ngOnDestroy ( ) { this . inputChanges$ . complete ( ) ; this . nguiMapComponent . removeFromMapObjectGroup ( 'CustomMarker' , this . mapObject ) ; if ( this . mapObject ) { this . nguiMap . clearObjectEvents ( OUTPUTS , this , 'mapObject' ) ; } } private initialize ( ) { console . log ( 'custom-marker is being initialized' ) ; this . el = this . elementRef . nativeElement ; this . mapObject = getCustomMarkerOverlayView ( this . el , this [ 'position' ] ) ; this . mapObject . setMap ( this . nguiMapComponent . map ) ; this . nguiMap . setObjectEvents ( OUTPUTS , this , 'mapObject' ) ; this . inputChanges$ . pipe ( debounceTime ( 1000 ) , tap ( ( changes ) => this . nguiMap . updateGoogleObject ( this . mapObject , changes ) ) ) . subscribe ( ) ; this . nguiMapComponent . addToMapObjectGroup ( 'CustomMarker' , this . mapObject ) ; this . initialized$ . emit ( this . mapObject ) ; } }