/**
* @module nyc/OsmGeocoder
*/
import Geocoder from './Geocoder'
import proj4 from 'proj4'
/**
* @desc A class for geocoding
* @public
*/
class OsmGeocoder extends Geocoder {
/**
* @desc Create an instance of Geocoder
* @public
* @constructor
* @param {Object<string, Object>} options Constructor options
*/
constructor(options) {
super()
this.countryCodes = options?.countryCodes?.join() || 'us'
this.viewbox = options?.viewbox?.join() || ''
this.projection = options?.projection || 'EPSG:3857'
this.url = `https://nominatim.openstreetmap.org/search.php?format=geocodejson&dedupe=1&countrycodes=${this.countryCodes}&viewbox=${this.viewbox}`
}
/**
* @private
* @method
* @param {Array<number>} coordinate Coordinate
* @return {Array<number>} Reprojected coordinate
*/
project(coordinate) {
if (coordinate && this.projection !== 'EPSG:4326') {
return proj4('EPSG:4326', this.projection, coordinate)
}
return coordinate
}
/**
* @private
* @method
* @param {Object} feature feature
* @return {Locator.Result} Locator result
*/
parse(feature) {
return {
type: 'geocoded',
coordinate: this.project(feature.geometry.coordinates),
data: feature,
name: feature.properties.geocoding.label
}
}
/**
* @desc Search for a location
* @public
* @method
* @param {string} input Input
* @returns {Promise<Object>} The result of the search request
*/
search(input) {
input = input.replace(/"/g, '').replace(/'/g, '').replace(/&/g, ' and ')
return new Promise((resolve, reject) => {
fetch(`${this.url}&q=${encodeURIComponent(input)}`).then(response => {
response.json().then(result => {
const features = result.features
if (features.length === 0) {
const nothing = {
type: 'ambiguous',
input: result.geocoding.query,
possible: []
}
resolve(nothing)
this.trigger('ambiguous', nothing)
} else {
const location = this.parse(features[0])
resolve(location)
this.trigger('geocoded', location)
}
})
})
})
}
}
export default OsmGeocoder