node-geocoder
Version:
Node Geocoder, node geocoding library, supports google maps, mapquest, open street map, tom tom, promise
117 lines (116 loc) • 3.86 kB
JavaScript
var util = require('util');
var AbstractGeocoder = require('./abstractgeocoder');
/**
* Constructor
* @param <object> httpAdapter Http Adapter
* @param <object> options Options (language, clientId, apiKey)
*/
var YandexGeocoder = function YandexGeocoder(httpAdapter, options) {
this.options = ['apiKey'];
YandexGeocoder.super_.call(this, httpAdapter, options);
};
util.inherits(YandexGeocoder, AbstractGeocoder);
function _findKey(result, wantedKey) {
var val = null;
Object.keys(result).every(function (key) {
if (key === wantedKey) {
val = result[key];
return false;
}
if (typeof result[key] === 'object') {
val = _findKey(result[key], wantedKey);
return val === null ? true : false;
}
return true;
});
return val;
}
function _formatResult(result) {
var position = result.GeoObject.Point.pos.split(' ');
result = result.GeoObject.metaDataProperty.GeocoderMetaData.AddressDetails;
return {
'latitude': parseFloat(position[1]),
'longitude': parseFloat(position[0]),
'city': _findKey(result, 'LocalityName'),
'state': _findKey(result, 'AdministrativeAreaName'),
'streetName': _findKey(result, 'ThoroughfareName'),
'streetNumber': _findKey(result, 'PremiseNumber'),
'countryCode': _findKey(result, 'CountryNameCode'),
'country': _findKey(result, 'CountryName'),
'formattedAddress': _findKey(result, 'AddressLine')
};
}
function _processOptionsToParams(params, options) {
//language (language_region, ex: `ru_RU`, `uk_UA`)
if (options.language) {
params.lang = options.language;
}
//results count (default 10)
if (options.results) {
params.results = options.results;
}
//skip count (default 0)
if (options.skip) {
params.skip = options.skip;
}
//Type of toponym (only for reverse geocoding)
//could be `house`, `street`, `metro`, `district`, `locality`
if (options.kind) {
params.kind = options.kind;
}
//BBox (ex: `[[lat: 1.0, lng:2.0],[lat: 1.1, lng:2.2]]`)
if (options.bbox) {
if (options.bbox.length === 2) {
params.bbox = options.bbox[0].lng + ',' + options.bbox[0].lat;
params.bbox = params.bbox + '~';
params.bbox = params.bbox + options.bbox[1].lng + ',' + options.bbox[1].lat;
}
}
//Limit search in bbox (1) or not limit (0)
if (options.rspn) {
params.rspn = options.rspn;
}
if (options.apiKey) {
params.apikey = options.apiKey;
}
}
// Yandex geocoding API endpoint
YandexGeocoder.prototype._endpoint = 'https://geocode-maps.yandex.ru/1.x/';
/**
* Geocode
* @param <string> value Value to geocode (Address)
* @param <function> callback Callback method
*/
YandexGeocoder.prototype._geocode = function (value, callback) {
var params = {
geocode: value,
format: 'json'
};
_processOptionsToParams(params, this.options);
this.httpAdapter.get(this._endpoint, params, function (err, result) {
if (err) {
return callback(err);
}
else {
var results = [];
result.response.GeoObjectCollection.featureMember.forEach(function (geopoint) {
results.push(_formatResult(geopoint));
});
results.raw = result;
callback(false, results);
}
});
};
/**
* Reverse geocoding
* @param {lat:<number>,lon:<number>} lat: Latitude, lon: Longitude
* @param <function> callback Callback method
*/
YandexGeocoder.prototype._reverse = function (query, callback) {
var lat = query.lat;
var lng = query.lon;
var value = lng + ',' + lat;
this._geocode(value, callback);
};
module.exports = YandexGeocoder;
;