Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ The plugin supports many different data providers:
- [ArcGIS](https://developers.arcgis.com/features/geocoding/)
- [Azure Maps Geocoding](https://www.microsoft.com/en-us/maps/azure/location-services/geocoding)

Multiple data providers can be combined by using the AggregatingGeocoder.

The plugin can easily be extended to support other providers. Current extensions:

- [DAWA Geocoder](https://github.com/kjoller/leaflet-control-geocoder-dawa/tree/new) - support for Danish Address Web API by [Niels Kjøller Hansen](https://github.com/kjoller)
Expand Down
39 changes: 39 additions & 0 deletions spec/aggregating-geocoder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { describe, expect, it, vi } from 'vitest';
import { AggregatingGeocoder, AgregatorOptions } from '../src/geocoders/aggregating-geocoder';
import { LatLngLiteral } from 'leaflet';

describe('L.Control.Geocoder.AggregatingGeocoder', () => {
it('geocde returns empty when no geocoders', async () => {
const options: AgregatorOptions = {
geocoders: []
}
const geocoder = new AggregatingGeocoder(options);

const results = await geocoder.geocode('foo');
expect(results).toEqual([]);
});

it('suggest returns empty when no geocoders', async () => {
const options: AgregatorOptions = {
geocoders: []
}
const geocoder = new AggregatingGeocoder(options);

const results = await geocoder.suggest('foo');
expect(results).toEqual([]);
});

it('reverse returns emtpy when no geocoders', async () => {
const options: AgregatorOptions = {
geocoders: []
}
const geocoder = new AggregatingGeocoder(options);

const loc: LatLngLiteral = {
lat: 0,
lng: 0
};
const results = await geocoder.reverse(loc, 1);
expect(results).toEqual([]);
});
});
65 changes: 65 additions & 0 deletions src/geocoders/aggregating-geocoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as L from 'leaflet';
import { LatLngLiteral } from 'leaflet';
import { IGeocoder, GeocodingContext, GeocodingResult } from './api';

export interface AgregatorOptions {
geocoders: IGeocoder[];
}

/**
* Implementation of a geocoder that takes other geocoders and aggregates their results together.
**/
export class AggregatingGeocoder implements IGeocoder {
options: AgregatorOptions = {
geocoders: []
}

constructor(options?: Partial<AgregatorOptions>) {
L.Util.setOptions(this, options)
}

private async combineResults(queries: Array<Promise<GeocodingResult[]>>): Promise<GeocodingResult[]> {
const queryResults: Array<GeocodingResult[]> = await Promise.all(queries);
const results: Array<GeocodingResult> = [];
for(const r of queryResults) {
results.push(...r);
}
return results;
}

geocode(query: string, context?: GeocodingContext): Promise<GeocodingResult[]> {
const queries: Promise<GeocodingResult[]>[] = [];
for(const geocoder of this.options.geocoders) {
queries.push(geocoder.geocode(query, context));
}
return this.combineResults(queries);
}

suggest?(query: string, context?: GeocodingContext): Promise<GeocodingResult[]> {
const queries: Promise<GeocodingResult[]>[] = [];
for(const geocoder of this.options.geocoders) {
if (geocoder.suggest) {
queries.push(geocoder.suggest(query, context));
}
}
return this.combineResults(queries);
}

reverse?(location: LatLngLiteral, scale: number): Promise<GeocodingResult[]> {
const queries: Promise<GeocodingResult[]>[] = [];
for(const geocoder of this.options.geocoders) {
if (geocoder.reverse) {
queries.push(geocoder.reverse(location, scale));
}
}
return this.combineResults(queries);
}
}

/**
* [Class factory method](https://leafletjs.com/reference.html#class-class-factories) for {@link AggregatingGeocoder}
* @param options the services to aggregate together.
*/
export function aggregatingGeocoder(options: Partial<AgregatorOptions>) {
return new AggregatingGeocoder(options);
}
1 change: 1 addition & 0 deletions src/geocoders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export * from './opencage';
export * from './pelias';
export * from './photon';
export * from './what3words';
export * from './aggregating-geocoder';