UNPKG

novo-elements

Version:

Bullhorn's NOVO Element Repository for Angular 2

395 lines (366 loc) 15.5 kB
// NG2 import { Component, PLATFORM_ID, Inject, Input, Output, Optional, EventEmitter, OnInit, OnChanges, SimpleChanges, ElementRef } from '@angular/core'; import { NovoSearchBoxElement } from '../search/SearchBox'; import { isPlatformBrowser, isPlatformServer } from '@angular/common'; import { GlobalRef } from '../../services/global/global.service'; import { GooglePlacesService } from './places.service'; export interface Settings { geoPredictionServerUrl?: string; geoLatLangServiceUrl?: string; geoLocDetailServerUrl?: string; geoCountryRestriction?: any; geoTypes?: any; geoLocation?: any; geoRadius?: number; serverResponseListHierarchy?: any; serverResponseatLangHierarchy?: any; serverResponseDetailHierarchy?: any; resOnSearchButtonClickOnly?: boolean; useGoogleGeoApi?: boolean; inputPlaceholderText?: string; inputString?: string; showSearchButton?: boolean; showRecentSearch?: boolean; showCurrentLocation?: boolean; recentStorageName?: string; noOfRecentSearchSave?: number; currentLocIconUrl?: string; searchIconUrl?: string; locationIconUrl?: string; } @Component({ selector: 'google-places-list', template: ` <novo-list direction="vertical"> <novo-list-item *ngFor="let data of queryItems;let $index = index" (click)="selectedListNode($event, $index)"> <item-header> <item-avatar icon="location"></item-avatar> <item-title>{{data.structured_formatting?.main_text ? data.structured_formatting.main_text : data.description}}</item-title> </item-header> <item-content>{{data.structured_formatting?.secondary_text}}</item-content> </novo-list-item> </novo-list> ` }) export class PlacesListComponent implements OnInit, OnChanges { @Input() userSettings: Settings; @Input() term: string = ''; @Output() termChange: EventEmitter<any> = new EventEmitter<any>(); @Output() select: EventEmitter<any> = new EventEmitter<any>(); public locationInput: string = ''; public gettingCurrentLocationFlag: boolean = false; public dropdownOpen: boolean = false; public recentDropdownOpen: boolean = false; public queryItems: any = []; public isSettingsError: boolean = false; public settingsErrorMsg: string = ''; public settings: Settings = {}; private moduleinit: boolean = false; private selectedDataIndex: number = -1; private recentSearchData: any = []; private userSelectedOption: any = ''; private defaultSettings: Settings = { geoPredictionServerUrl: '', geoLatLangServiceUrl: '', geoLocDetailServerUrl: '', geoCountryRestriction: [], geoTypes: [], geoLocation: [], geoRadius: 0, serverResponseListHierarchy: [], serverResponseatLangHierarchy: [], serverResponseDetailHierarchy: [], resOnSearchButtonClickOnly: false, useGoogleGeoApi: true, inputPlaceholderText: 'Enter Area Name', inputString: '', showSearchButton: true, showRecentSearch: true, showCurrentLocation: true, recentStorageName: 'recentSearches', noOfRecentSearchSave: 5, currentLocIconUrl: '', searchIconUrl: '', locationIconUrl: '' }; constructor( @Inject(PLATFORM_ID) private platformId: Object, private _elmRef: ElementRef, private _global: GlobalRef, private _googlePlacesService: GooglePlacesService ) { } ngOnInit(): any { if (!this.moduleinit) { this.moduleInit(); } } ngOnChanges(): any { this.moduleinit = true; this.moduleInit(); this.searchinputCallback(null); } //function called when click event happens in input box. (Binded with view) searchinputClickCallback(event: any): any { event.target.select(); this.searchinputCallback(event); } //function called when there is a change in input. (Binded with view) searchinputCallback(event: any): any { let inputVal: any = this.locationInput; if (inputVal) { this.getListQuery(inputVal); } else { this.queryItems = []; if (this.userSelectedOption) { this.userQuerySubmit('false'); } this.userSelectedOption = ''; if (this.settings.showRecentSearch) { this.showRecentSearch(); } else { this.dropdownOpen = false; } } } //function to execute when user hover over autocomplete list.(binded with view) activeListNode(index: number): any { for (let i: number = 0; i < this.queryItems.length; i++) { if (index === i) { this.queryItems[i].active = true; this.selectedDataIndex = index; } else { this.queryItems[i].active = false; } } } //function to execute when user select the autocomplete list.(binded with view) selectedListNode(event: MouseEvent, index: number): any { this.dropdownOpen = false; if (this.recentDropdownOpen) { this.setRecentLocation(this.queryItems[index]); } else { this.getPlaceLocationInfo(this.queryItems[index]); } } //function to close the autocomplete list when clicked outside. (binded with view) closeAutocomplete(event: any): any { if (!this._elmRef.nativeElement.contains(event.target)) { this.selectedDataIndex = -1; this.dropdownOpen = false; } } //function to manually trigger the callback to parent component when clicked search button. userQuerySubmit(selectedOption?: any): any { let _userOption: any = selectedOption === 'false' ? '' : this.userSelectedOption; if (_userOption) { this.select.emit(this.userSelectedOption); } else { //this.select.emit(false); } } //function to get user current location from the device. currentLocationSelected(): any { if (isPlatformBrowser(this.platformId)) { this.gettingCurrentLocationFlag = true; this.dropdownOpen = false; this._googlePlacesService.getGeoCurrentLocation().then((result: any) => { if (!result) { this.gettingCurrentLocationFlag = false; } else { this.getCurrentLocationInfo(result); } }); } } //module initialization happens. function called by ngOninit and ngOnChange private moduleInit(): any { this.settings = this.setUserSettings(); //condition to check if Radius is set without location detail. if (this.settings.geoRadius) { if (this.settings.geoLocation.length !== 2) { this.isSettingsError = true; this.settingsErrorMsg = this.settingsErrorMsg + 'Radius should be used with GeoLocation. Please use "geoLocation" key to set lat and lng. '; } } //condition to check if lat and lng is set and radious is not set then it will set to 20,000KM by default if ((this.settings.geoLocation.length === 2) && !this.settings.geoRadius) { this.settings.geoRadius = 20000000; } if (this.settings.showRecentSearch) { this.getRecentLocations(); } if (!this.settings.useGoogleGeoApi) { if (!this.settings.geoPredictionServerUrl) { this.isSettingsError = true; this.settingsErrorMsg = this.settingsErrorMsg + 'Prediction custom server url is not defined. Please use "geoPredictionServerUrl" key to set. '; } if (!this.settings.geoLatLangServiceUrl) { this.isSettingsError = true; this.settingsErrorMsg = this.settingsErrorMsg + 'Latitude and longitude custom server url is not defined. Please use "geoLatLangServiceUrl" key to set. '; } if (!this.settings.geoLocDetailServerUrl) { this.isSettingsError = true; this.settingsErrorMsg = this.settingsErrorMsg + 'Location detail custom server url is not defined. Please use "geoLocDetailServerUrl" key to set. '; } } this.locationInput = this.term; } //function to process the search query when pressed enter. private processSearchQuery(): any { if (this.queryItems.length) { if (this.selectedDataIndex > -1) { this.selectedListNode(null, this.selectedDataIndex); } else { this.selectedListNode(null, 0); } } } //function to set user settings if it is available. private setUserSettings(): Settings { let _tempObj: any = {}; if (this.userSettings && typeof (this.userSettings) === 'object') { let keys: string[] = Object.keys(this.defaultSettings); for (let value of keys) { _tempObj[value] = (this.userSettings[value] !== undefined) ? this.userSettings[value] : this.defaultSettings[value]; } return _tempObj; } else { return this.defaultSettings; } } //function to get the autocomplete list based on user input. private getListQuery(value: string): any { this.recentDropdownOpen = false; if (this.settings.useGoogleGeoApi) { let _tempParams: any = { 'query': value, 'countryRestriction': this.settings.geoCountryRestriction, 'geoTypes': this.settings.geoTypes }; if (this.settings.geoLocation.length === 2) { _tempParams.geoLocation = this.settings.geoLocation; _tempParams.radius = this.settings.geoRadius; } this._googlePlacesService.getGeoPrediction(_tempParams).then((result) => { this.updateListItem(result); }); } else { this._googlePlacesService.getPredictions(this.settings.geoPredictionServerUrl, value).then((result) => { result = this.extractServerList(this.settings.serverResponseListHierarchy, result); this.updateListItem(result); }); } } //function to extratc custom data which is send by the server. private extractServerList(arrayList: any, data: any): any { if (arrayList.length) { let _tempData: any = data; for (let key of arrayList) { _tempData = _tempData[key]; } return _tempData; } else { return data; } } //function to update the predicted list. private updateListItem(listData: any): any { this.queryItems = listData ? listData : []; this.dropdownOpen = true; } //function to show the recent search result. private showRecentSearch(): any { this.recentDropdownOpen = true; this.dropdownOpen = true; this._googlePlacesService.getRecentList(this.settings.recentStorageName).then((result: any) => { if (result) { this.queryItems = result; } else { this.queryItems = []; } }); } // //function to navigate through list when up and down keyboard key is pressed; // private navigateInList(keyCode: number): any { // let arrayIndex: number = 0; // //arrow down // if (keyCode === 40) { // if (this.selectedDataIndex >= 0) { // arrayIndex = ((this.selectedDataIndex + 1) <= (this.queryItems.length - 1)) ? (this.selectedDataIndex + 1) : 0; // } // this.activeListNode(arrayIndex); // } else if (keyCode === 38) {//arrow up // if (this.selectedDataIndex >= 0) { // arrayIndex = ((this.selectedDataIndex - 1) >= 0) ? (this.selectedDataIndex - 1) : (this.queryItems.length - 1); // } else { // arrayIndex = this.queryItems.length - 1; // } // this.activeListNode(arrayIndex); // } else { // this.processSearchQuery(); // } // } //function to execute to get location detail based on latitude and longitude. private getCurrentLocationInfo(latlng: any): any { if (this.settings.useGoogleGeoApi) { this._googlePlacesService.getGeoLatLngDetail(latlng).then((result: any) => { if (result) { this.setRecentLocation(result); } this.gettingCurrentLocationFlag = false; }); } else { this._googlePlacesService.getLatLngDetail(this.settings.geoLatLangServiceUrl, latlng.lat, latlng.lng).then((result: any) => { if (result) { result = this.extractServerList(this.settings.serverResponseatLangHierarchy, result); this.setRecentLocation(result); } this.gettingCurrentLocationFlag = false; }); } } //function to retrive the location info based on goovle place id. private getPlaceLocationInfo(selectedData: any): any { if (this.settings.useGoogleGeoApi) { this._googlePlacesService.getGeoPlaceDetail(selectedData.place_id).then((data: any) => { if (data) { this.setRecentLocation(data); } }); } else { this._googlePlacesService.getPlaceDetails(this.settings.geoLocDetailServerUrl, selectedData.place_id).then((result: any) => { if (result) { result = this.extractServerList(this.settings.serverResponseDetailHierarchy, result); this.setRecentLocation(result); } }); } } //function to store the selected user search in the localstorage. private setRecentLocation(data: any): any { data = JSON.parse(JSON.stringify(data)); data.description = data.description ? data.description : data.formatted_address; data.active = false; this.selectedDataIndex = -1; this.locationInput = data.description; if (this.settings.showRecentSearch) { this._googlePlacesService.addRecentList(this.settings.recentStorageName, data, this.settings.noOfRecentSearchSave); this.getRecentLocations(); } this.userSelectedOption = data; //below code will execute only when user press enter or select any option selection and it emit a callback to the parent component. if (!this.settings.resOnSearchButtonClickOnly) { this.select.emit(data); this.termChange.emit(data); } } //function to retrive the stored recent user search from the localstorage. private getRecentLocations(): any { this._googlePlacesService.getRecentList(this.settings.recentStorageName).then((data: any) => { this.recentSearchData = (data && data.length) ? data : []; }); } }