1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | 2x 2x 2x 7x 2x 48x 48x 94x 11x 11x 83x 36x 36x 47x 48x 2x 2x 2x 4x 4x 4x 4x 4x 4x 2x 2x 4x 4x 4x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | 'use strict'; 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) { 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') }; } function _processOptionsToParams(params, options){ //language (language_region, ex: `ru_RU`, `uk_UA`) Iif (options.language) { params.lang = options.language; } //results count (default 10) Iif (options.results) { params.results = options.results; } //skip count (default 0) Iif (options.skip) { params.skip = options.skip; } //Type of toponym (only for reverse geocoding) //could be `house`, `street`, `metro`, `district`, `locality` Iif (options.kind) { params.kind = options.kind; } //BBox (ex: `[[lat: 1.0, lng:2.0],[lat: 1.1, lng:2.2]]`) Iif (options.bbox) { if (options.bbox.length === 2){ params.kind = options.bbox[0].lng + ',' + options.bbox[0].lat; params.kind = params.kind + '~'; params.kind = params.kind + options.bbox[1].lng + ',' + options.bbox[1].lat; } } //Limit search in bbox (1) or not limit (0) Iif (options.rspn) { params.rspn = options.rspn; } } // 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) { Iif (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; |