ngx-autocom-place
Version:
Angular GoogleMaps Places Api Autocomplete Directive
236 lines (229 loc) • 11.4 kB
JavaScript
import { __awaiter } from 'tslib';
import { Injectable, EventEmitter, Directive, ElementRef, Output, Input, NgModule } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
class NgxAutocomPlaceService {
constructor() {
this.autocompleteService = new google.maps.places.AutocompleteService();
this.placeService = new google.maps.places.PlacesService(document.createElement('div'));
}
getPredictions(value, options) {
if (!this.sessionToken) {
this.sessionToken = new google.maps.places.AutocompleteSessionToken();
}
const request = Object.assign({ input: value, sessionToken: this.sessionToken }, options);
return new Promise((resolve, reject) => {
this.autocompleteService.getPlacePredictions(request, (results, status) => {
if (status !== google.maps.places.PlacesServiceStatus.OK && status !== google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
reject(status);
return;
}
else {
resolve(results);
}
});
});
}
getPlaceDetails(placeId) {
return new Promise((resolve, reject) => {
this.placeService.getDetails({
placeId,
sessionToken: this.sessionToken,
}, (result, status) => {
this.sessionToken = null;
if (status !== google.maps.places.PlacesServiceStatus.OK) {
reject(status);
return;
}
resolve(result);
});
});
}
}
NgxAutocomPlaceService.decorators = [
{ type: Injectable }
];
NgxAutocomPlaceService.ctorParameters = () => [];
class NgxAutocomPlaceDirective {
constructor(el, ngxAutocomplaceService) {
this.el = el;
this.ngxAutocomplaceService = ngxAutocomplaceService;
this.points = [];
this.selectedPlace = new EventEmitter();
this.predictions = new EventEmitter();
this.options = {
types: ["geocode"] // 'establishment' / 'address' / 'geocode'
};
this.handleEnterKeydown = true;
this.hideResultDropdown = false;
this.debounceTime = 150;
this.downArrowIndex = -1;
}
;
ngOnInit() {
return __awaiter(this, void 0, void 0, function* () {
if (this.el.nativeElement instanceof HTMLInputElement) {
this.inputElement = this.el.nativeElement;
}
else if (this.el.nativeElement.tagName === 'ION-INPUT') {
this.inputElement = yield this.el.nativeElement.getInputElement();
}
else if (this.el.nativeElement.tagName === 'ION-SEARCHBAR') {
this.inputElement = yield this.el.nativeElement.getInputElement();
}
else {
return;
}
const styles = document.createElement('style');
styles.innerHTML = ` beginBrowserAutofill{0%{}to{}} endBrowserAutofill{0%{}to{}}.pac-container{background-color:#fff;position:absolute!important;z-index:1000;border-radius:2px;border-top:1px solid #d9d9d9;font-family:Arial,sans-serif;box-shadow:0 2px 6px rgba(0,0,0,0.3);-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.pac-logo:after{content:"";padding:1px 1px 1px 0;height:18px;box-sizing:border-box;text-align:right;display:block;background-image:url(https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white3.png);background-position:right;background-repeat:no-repeat;background-size:120px 14px}.hdpi.pac-logo:after{background-image:url(https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white3_hdpi.png)}.pac-item{cursor:default;padding:0 4px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:30px;text-align:left;border-top:1px solid #e6e6e6;font-size:11px;color:#999}.pac-item:hover{background-color:#fafafa}.pac-item-selected,.pac-item-selected:hover{background-color:#ebf2fe}.pac-matched{font-weight:700}.pac-item-query{font-size:13px;padding-right:3px;color:#000}.pac-icon{width:15px;height:20px;margin-right:7px;margin-top:6px;display:inline-block;vertical-align:top;background-image:url(https://maps.gstatic.com/mapfiles/api-3/images/autocomplete-icons.png);background-size:34px}.hdpi .pac-icon{background-image:url(https://maps.gstatic.com/mapfiles/api-3/images/autocomplete-icons_hdpi.png)}.pac-icon-search{background-position:-1px -1px}.pac-item-selected .pac-icon-search{background-position:-18px -1px}.pac-icon-marker{background-position:-1px -161px}.pac-item-selected .pac-icon-marker{background-position:-18px -161px}.pac-placeholder{color:gray}.pac-target-input:-webkit-autofill{animation-name:beginBrowserAutofill}.pac-target-input:not(:-webkit-autofill){animation-name:endBrowserAutofill}`;
var ref = document.querySelector('script');
ref.parentNode.insertBefore(styles, ref);
this.inputElement.addEventListener('blur', () => {
this.blurEvent();
});
this.inputSubscription = fromEvent(this.inputElement, 'input').pipe(debounceTime(this.debounceTime)).subscribe((_e) => {
this.inputEvent(_e);
});
this.inputElement.addEventListener('keydown', (e) => {
this.keydownEvent(e);
});
});
}
createPacContainer(input, results) {
this.resultPacContainer = document.createElement('div');
const inputRect = input.getBoundingClientRect();
this.resultPacContainer.classList.add('pac-container', 'pac-logo', 'hdpi');
this.resultPacContainer.style.position = 'absolute';
this.resultPacContainer.style.top = inputRect.bottom + 'px';
this.resultPacContainer.style.left = inputRect.left + 'px';
this.resultPacContainer.style.width = (inputRect.right - inputRect.left) + 'px';
results.forEach(element => {
this.resultPacContainer.appendChild(this.createPacItem(element.place_id, element.structured_formatting.main_text, element.structured_formatting.secondary_text, element.structured_formatting.main_text_matched_substrings[0].length));
});
document.querySelector('body').appendChild(this.resultPacContainer);
}
createPacItem(placeId, mainText, secondaryText, matchMainOffset) {
const item = document.createElement('div');
item.classList.add('pac-item');
item.id = placeId;
const spanIcon = document.createElement('span');
spanIcon.classList.add('pac-icon', 'pac-icon-marker');
const spanContentMatch = document.createElement('span');
spanContentMatch.classList.add('pac-item-query');
const spanContentMatched = document.createElement('span');
spanContentMatched.classList.add('pac-matched');
spanContentMatched.innerText = mainText.substr(0, matchMainOffset);
spanContentMatch.appendChild(spanContentMatched);
spanContentMatch.appendChild(document.createTextNode(mainText.substr(matchMainOffset)));
const spanCity = document.createElement('span');
spanCity.appendChild(document.createTextNode(secondaryText));
item.appendChild(spanIcon);
item.appendChild(spanContentMatch);
item.appendChild(spanCity);
item.addEventListener('click', () => {
this.getPlaceDetails(placeId);
});
return item;
}
getPlaceDetails(placeId) {
this.ngxAutocomplaceService.getPlaceDetails(placeId).then((result) => {
// this.inputElement.value = result.formatted_address;
// this.inputElement.blur();
this.selectedPlace.emit(result);
});
}
blurEvent() {
setTimeout(() => {
if (this.resultPacContainer) {
this.removePacItems();
}
}, 250);
}
inputEvent(_e) {
if (this.inputElement && this.inputElement.value) {
this.ngxAutocomplaceService.getPredictions(this.inputElement.value, this.options).then((results) => {
this.removePacItems();
if (results) {
if (!this.hideResultDropdown) {
this.results = results;
this.createPacContainer(this.inputElement, results);
}
this.predictions.emit(results);
}
});
}
else {
this.removePacItems();
}
}
keydownEvent(e) {
var _a, _b;
if (this.handleEnterKeydown) {
if (e.key === 'Enter' || e.keyCode === 13) {
if (this.results && this.results.length > 0) {
this.getPlaceDetails(this.results[this.downArrowIndex > -1 ? this.downArrowIndex : 0].place_id);
this.removePacItems();
}
}
}
if (e.keyCode === 40) {
this.downArrowIndex++;
if (this.downArrowIndex > 0) {
(_a = document.querySelectorAll('.pac-item')[this.downArrowIndex - 1]) === null || _a === void 0 ? void 0 : _a.classList.remove('pac-item-selected');
}
(_b = document.querySelectorAll('.pac-item')[this.downArrowIndex]) === null || _b === void 0 ? void 0 : _b.classList.add('pac-item-selected');
}
}
removePacItems() {
if (this.resultPacContainer) {
this.resultPacContainer.remove();
this.resultPacContainer = null;
}
this.downArrowIndex = -1;
;
}
ngOnDestroy() {
this.inputElement.removeEventListener('blur', () => {
this.blurEvent();
});
this.inputSubscription.unsubscribe();
this.inputElement.removeEventListener('keydown', (e) => {
this.keydownEvent(e);
});
}
}
NgxAutocomPlaceDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngxAutocomPlace]'
},] }
];
NgxAutocomPlaceDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: NgxAutocomPlaceService }
];
NgxAutocomPlaceDirective.propDecorators = {
selectedPlace: [{ type: Output }],
predictions: [{ type: Output }],
options: [{ type: Input }],
handleEnterKeydown: [{ type: Input }],
hideResultDropdown: [{ type: Input }],
debounceTime: [{ type: Input }]
};
class NgxAutocomPlaceModule {
}
NgxAutocomPlaceModule.decorators = [
{ type: NgModule, args: [{
imports: [],
declarations: [NgxAutocomPlaceDirective],
exports: [NgxAutocomPlaceDirective],
providers: [NgxAutocomPlaceService]
},] }
];
/*
* Public API Surface of ngx-autocom-place
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxAutocomPlaceDirective, NgxAutocomPlaceModule, NgxAutocomPlaceService as ɵa };
//# sourceMappingURL=ngx-autocom-place.js.map