geocoder
Version:
node wrapper around google's geocoder api
157 lines (130 loc) • 4.44 kB
JavaScript
// xml2js is optional because only needed for geonames support
var xml2js = require("xml2js");
var request = require("request");
var _ = require('underscore');
exports.geocode = function ( providerOpts, loc, cbk, opts ) {
var options = _.extend({q: loc, flags: "J", appid:providerOpts.appid||"[yourappidhere]" }, opts || {});
request({
uri:"http://where.yahooapis.com/geocode",
qs:options
}, function(err,resp,body) {
if (err) return cbk(err);
var result;
try {
result = JSON.parse(body);
} catch (err) {
cbk(err);
return;
}
cbk(null,result);
});
};
// yahoo placefinder api http://developer.yahoo.com/geo/placefinder/guide/
exports.reverseGeocode = function ( providerOpts, lat, lng, cbk, opts ) {
var options = _.extend({q: lat+", "+lng, gflags:"R", flags: "J", appid:providerOpts.appid||"[yourappidhere]" }, opts || {});
request({
uri:"http://where.yahooapis.com/geocode",
qs:options
}, function(err,resp,body) {
// console.log("[GEOCODER Yahoo API] uri:", "http://where.yahooapis.com/geocode");
// console.log("[GEOCODER Yahoo API] options:", JSON.stringify(options));
// console.log("[GEOCODER Yahoo API] body:", body);
if (err) return cbk(err);
var result;
try {
result = JSON.parse(body);
} catch (err) {
cbk(err);
return;
}
// Transform yahoo' structure into something that looks like Google's JSON outpu
// https://developers.google.com/maps/documentation/geocoding/#JSON
var googlejson = {
"status":"OK",
"results":[
{
"address_components":[],
"formatted_address":"",
"geometry":{
"location":{
"lat":lat,
"lng":lng
}
}
}
]
};
if (result.ResultSet.Error !== "0" && result.ResultSet.Error !== 0) {
console.log("[GEOCODER Yahoo API] ERROR", result.Error, result.ErrorMessage);
return cbk(result.ResultSet.ErrorMessage);
}
var a = null;
// Yahoo seems to change its response format "randomly". So, sometimes, it there is only one result,
// it will be in ResultSet.Result, and sometimes, in ResultSet.Results[0]
if (undefined !== result.ResultSet.Result) {
a = result.ResultSet.Result;
}
else if (result.ResultSet.Results && result.ResultSet.Results.length) {
a = result.ResultSet.Results[0];
}
if (!a) {
return cbk("Error getting results from Yahoo API");
}
if (a.house)
googlejson.results[0].address_components.push({
"long_name":a.house,
"short_name":a.house,
"types":["street_number"]
});
if (a.street)
googlejson.results[0].address_components.push({
"long_name":a.street,
"short_name":a.street,
"types":["route"]
});
if (a.city)
googlejson.results[0].address_components.push({
"long_name":a.city,
"short_name":a.city,
"types":["locality", "political"]
});
if (a.state)
googlejson.results[0].address_components.push({
"long_name":a.state,
"short_name":a.statecode || a.state,
"types":[ "administrative_area_level_1", "political" ]
});
if (a.county)
googlejson.results[0].address_components.push({
"long_name":a.county,
"short_name":a.countycode || a.county,
"types":[ "administrative_area_level_2", "political" ]
});
if (a.country)
googlejson.results[0].address_components.push({
"long_name":a.country,
"short_name":a.countrycode,
"types":[ "country" ]
});
if (a.postal)
googlejson.results[0].address_components.push({
"long_name":a.postal,
"short_name":a.postal,
"types":[ "postal_code" ]
});
if (a.latitude)
googlejson.results[0].geometry.location = {
"lat":parseFloat(a.latitude),
"lng":parseFloat(a.longitude)
};
// Make a formatted address as well as we can
var formatted = [];
if (a.line1) formatted.push(a.line1);
if (a.line2) formatted.push(a.line2);
if (a.line3) formatted.push(a.line3);
if (a.line4) formatted.push(a.line4);
googlejson.results[0].formatted_address = formatted.join(", ");
// console.log("[GEOCODER Yahoo API], calling callback w/", JSON.stringify(googlejson));
cbk(null, googlejson);
});
};