740 lines
20 KiB
JavaScript
740 lines
20 KiB
JavaScript
|
(function (factory) {
|
||
|
// Packaging/modules magic dance
|
||
|
var L;
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
// AMD
|
||
|
define(['leaflet'], factory);
|
||
|
} else if (typeof module !== 'undefined') {
|
||
|
// Node/CommonJS
|
||
|
L = require('leaflet');
|
||
|
module.exports = factory(L);
|
||
|
} else {
|
||
|
// Browser globals
|
||
|
if (typeof window.L === 'undefined')
|
||
|
throw 'Leaflet must be loaded first';
|
||
|
factory(window.L);
|
||
|
}
|
||
|
}(function (L) {
|
||
|
'use strict';
|
||
|
L.Control.Geocoder = L.Control.extend({
|
||
|
options: {
|
||
|
showResultIcons: false,
|
||
|
collapsed: true,
|
||
|
expand: 'click',
|
||
|
position: 'topright',
|
||
|
placeholder: 'Search...',
|
||
|
errorMessage: 'Nothing found.'
|
||
|
},
|
||
|
|
||
|
_callbackId: 0,
|
||
|
|
||
|
initialize: function (options) {
|
||
|
L.Util.setOptions(this, options);
|
||
|
if (!this.options.geocoder) {
|
||
|
this.options.geocoder = new L.Control.Geocoder.Nominatim();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onAdd: function (map) {
|
||
|
var className = 'leaflet-control-geocoder',
|
||
|
container = L.DomUtil.create('div', className),
|
||
|
icon = L.DomUtil.create('div', 'leaflet-control-geocoder-icon', container),
|
||
|
form = this._form = L.DomUtil.create('form', className + '-form', container),
|
||
|
input;
|
||
|
|
||
|
this._map = map;
|
||
|
this._container = container;
|
||
|
input = this._input = L.DomUtil.create('input');
|
||
|
input.type = 'text';
|
||
|
input.placeholder = this.options.placeholder;
|
||
|
|
||
|
L.DomEvent.addListener(input, 'keydown', this._keydown, this);
|
||
|
//L.DomEvent.addListener(input, 'onpaste', this._clearResults, this);
|
||
|
//L.DomEvent.addListener(input, 'oninput', this._clearResults, this);
|
||
|
|
||
|
this._errorElement = document.createElement('div');
|
||
|
this._errorElement.className = className + '-form-no-error';
|
||
|
this._errorElement.innerHTML = this.options.errorMessage;
|
||
|
|
||
|
this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-geocoder-alternatives-minimized');
|
||
|
|
||
|
form.appendChild(input);
|
||
|
form.appendChild(this._errorElement);
|
||
|
container.appendChild(this._alts);
|
||
|
|
||
|
L.DomEvent.addListener(form, 'submit', this._geocode, this);
|
||
|
|
||
|
if (this.options.collapsed) {
|
||
|
if (this.options.expand === 'click') {
|
||
|
L.DomEvent.addListener(icon, 'click', function(e) {
|
||
|
// TODO: touch
|
||
|
if (e.button === 0 && e.detail !== 2) {
|
||
|
this._toggle();
|
||
|
}
|
||
|
}, this);
|
||
|
} else {
|
||
|
L.DomEvent.addListener(icon, 'mouseover', this._expand, this);
|
||
|
L.DomEvent.addListener(icon, 'mouseout', this._collapse, this);
|
||
|
this._map.on('movestart', this._collapse, this);
|
||
|
}
|
||
|
} else {
|
||
|
this._expand();
|
||
|
}
|
||
|
|
||
|
L.DomEvent.disableClickPropagation(container);
|
||
|
|
||
|
return container;
|
||
|
},
|
||
|
|
||
|
_geocodeResult: function (results) {
|
||
|
L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-throbber');
|
||
|
if (results.length === 1) {
|
||
|
this._geocodeResultSelected(results[0]);
|
||
|
} else if (results.length > 0) {
|
||
|
this._alts.innerHTML = '';
|
||
|
this._results = results;
|
||
|
L.DomUtil.removeClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
|
||
|
for (var i = 0; i < results.length; i++) {
|
||
|
this._alts.appendChild(this._createAlt(results[i], i));
|
||
|
}
|
||
|
} else {
|
||
|
L.DomUtil.addClass(this._errorElement, 'leaflet-control-geocoder-error');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
markGeocode: function(result) {
|
||
|
this._map.fitBounds(result.bbox);
|
||
|
|
||
|
if (this._geocodeMarker) {
|
||
|
this._map.removeLayer(this._geocodeMarker);
|
||
|
}
|
||
|
|
||
|
this._geocodeMarker = new L.Marker(result.center)
|
||
|
.bindPopup(result.html || result.name)
|
||
|
.addTo(this._map)
|
||
|
.openPopup();
|
||
|
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
_geocode: function(event) {
|
||
|
L.DomEvent.preventDefault(event);
|
||
|
|
||
|
L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-throbber');
|
||
|
this._clearResults();
|
||
|
this.options.geocoder.geocode(this._input.value, this._geocodeResult, this);
|
||
|
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
_geocodeResultSelected: function(result) {
|
||
|
if (this.options.collapsed) {
|
||
|
this._collapse();
|
||
|
} else {
|
||
|
this._clearResults();
|
||
|
}
|
||
|
this.markGeocode(result);
|
||
|
},
|
||
|
|
||
|
_toggle: function() {
|
||
|
if (this._container.className.indexOf('leaflet-control-geocoder-expanded') >= 0) {
|
||
|
this._collapse();
|
||
|
} else {
|
||
|
this._expand();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_expand: function () {
|
||
|
L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded');
|
||
|
this._input.select();
|
||
|
},
|
||
|
|
||
|
_collapse: function () {
|
||
|
this._container.className = this._container.className.replace(' leaflet-control-geocoder-expanded', '');
|
||
|
L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
|
||
|
L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
|
||
|
},
|
||
|
|
||
|
_clearResults: function () {
|
||
|
L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
|
||
|
this._selection = null;
|
||
|
L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
|
||
|
},
|
||
|
|
||
|
_createAlt: function(result, index) {
|
||
|
var li = document.createElement('li'),
|
||
|
a = L.DomUtil.create('a', '', li),
|
||
|
icon = this.options.showResultIcons && result.icon ? L.DomUtil.create('img', '', a) : null,
|
||
|
text = result.html ? undefined : document.createTextNode(result.name);
|
||
|
|
||
|
if (icon) {
|
||
|
icon.src = result.icon;
|
||
|
}
|
||
|
|
||
|
a.href = '#';
|
||
|
a.setAttribute('data-result-index', index);
|
||
|
|
||
|
if (result.html) {
|
||
|
a.innerHTML = result.html;
|
||
|
} else {
|
||
|
a.appendChild(text);
|
||
|
}
|
||
|
|
||
|
L.DomEvent.addListener(li, 'click', function clickHandler(e) {
|
||
|
L.DomEvent.preventDefault(e);
|
||
|
this._geocodeResultSelected(result);
|
||
|
}, this);
|
||
|
|
||
|
return li;
|
||
|
},
|
||
|
|
||
|
_keydown: function(e) {
|
||
|
var _this = this,
|
||
|
select = function select(dir) {
|
||
|
if (_this._selection) {
|
||
|
L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
|
||
|
_this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
|
||
|
}
|
||
|
if (!_this._selection) {
|
||
|
_this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
|
||
|
}
|
||
|
|
||
|
if (_this._selection) {
|
||
|
L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
switch (e.keyCode) {
|
||
|
// Escape
|
||
|
case 27:
|
||
|
if (this.options.collapsed) {
|
||
|
this._collapse();
|
||
|
}
|
||
|
break;
|
||
|
// Up
|
||
|
case 38:
|
||
|
select(-1);
|
||
|
L.DomEvent.preventDefault(e);
|
||
|
break;
|
||
|
// Up
|
||
|
case 40:
|
||
|
select(1);
|
||
|
L.DomEvent.preventDefault(e);
|
||
|
break;
|
||
|
// Enter
|
||
|
case 13:
|
||
|
if (this._selection) {
|
||
|
var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10);
|
||
|
this._geocodeResultSelected(this._results[index]);
|
||
|
this._clearResults();
|
||
|
L.DomEvent.preventDefault(e);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.geocoder = function(id, options) {
|
||
|
return new L.Control.Geocoder(id, options);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.callbackId = 0;
|
||
|
L.Control.Geocoder.jsonp = function(url, params, callback, context, jsonpParam) {
|
||
|
var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++);
|
||
|
params[jsonpParam || 'callback'] = callbackId;
|
||
|
window[callbackId] = L.Util.bind(callback, context);
|
||
|
var script = document.createElement('script');
|
||
|
script.type = 'text/javascript';
|
||
|
script.src = url + L.Util.getParamString(params);
|
||
|
script.id = callbackId;
|
||
|
document.getElementsByTagName('head')[0].appendChild(script);
|
||
|
};
|
||
|
L.Control.Geocoder.getJSON = function(url, params, callback) {
|
||
|
var xmlHttp = new XMLHttpRequest();
|
||
|
xmlHttp.open( "GET", url + L.Util.getParamString(params), true);
|
||
|
xmlHttp.send(null);
|
||
|
xmlHttp.onreadystatechange = function () {
|
||
|
if (xmlHttp.readyState != 4) return;
|
||
|
if (xmlHttp.status != 200 && req.status != 304) return;
|
||
|
callback(JSON.parse(xmlHttp.response));
|
||
|
};
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.template = function (str, data, htmlEscape) {
|
||
|
return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
|
||
|
var value = data[key];
|
||
|
if (value === undefined) {
|
||
|
value = '';
|
||
|
} else if (typeof value === 'function') {
|
||
|
value = value(data);
|
||
|
}
|
||
|
return L.Control.Geocoder.htmlEscape(value);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Adapted from handlebars.js
|
||
|
// https://github.com/wycats/handlebars.js/
|
||
|
L.Control.Geocoder.htmlEscape = (function() {
|
||
|
var badChars = /[&<>"'`]/g;
|
||
|
var possible = /[&<>"'`]/;
|
||
|
var escape = {
|
||
|
'&': '&',
|
||
|
'<': '<',
|
||
|
'>': '>',
|
||
|
'"': '"',
|
||
|
'\'': ''',
|
||
|
'`': '`'
|
||
|
};
|
||
|
|
||
|
function escapeChar(chr) {
|
||
|
return escape[chr];
|
||
|
}
|
||
|
|
||
|
return function(string) {
|
||
|
if (string == null) {
|
||
|
return '';
|
||
|
} else if (!string) {
|
||
|
return string + '';
|
||
|
}
|
||
|
|
||
|
// Force a string conversion as this will be done by the append regardless and
|
||
|
// the regex test will do this transparently behind the scenes, causing issues if
|
||
|
// an object's to string has escaped characters in it.
|
||
|
string = '' + string;
|
||
|
|
||
|
if (!possible.test(string)) {
|
||
|
return string;
|
||
|
}
|
||
|
return string.replace(badChars, escapeChar);
|
||
|
};
|
||
|
})();
|
||
|
|
||
|
L.Control.Geocoder.Nominatim = L.Class.extend({
|
||
|
options: {
|
||
|
serviceUrl: '//nominatim.openstreetmap.org/',
|
||
|
geocodingQueryParams: {},
|
||
|
reverseQueryParams: {},
|
||
|
htmlTemplate: function(r) {
|
||
|
var a = r.address,
|
||
|
parts = [];
|
||
|
if (a.road || a.building) {
|
||
|
parts.push('{building} {road} {house_number}');
|
||
|
}
|
||
|
|
||
|
if (a.city || a.town || a.village) {
|
||
|
parts.push('<span class="' + (parts.length > 0 ? 'leaflet-control-geocoder-address-detail' : '') +
|
||
|
'">{postcode} {city} {town} {village}</span>');
|
||
|
}
|
||
|
|
||
|
if (a.state || a.country) {
|
||
|
parts.push('<span class="' + (parts.length > 0 ? 'leaflet-control-geocoder-address-context' : '') +
|
||
|
'">{state} {country}</span>');
|
||
|
}
|
||
|
|
||
|
return L.Control.Geocoder.template(parts.join('<br/>'), a, true);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
initialize: function(options) {
|
||
|
L.Util.setOptions(this, options);
|
||
|
},
|
||
|
|
||
|
geocode: function(query, cb, context) {
|
||
|
L.Control.Geocoder.jsonp(this.options.serviceUrl + 'search/', L.extend({
|
||
|
q: query,
|
||
|
limit: 5,
|
||
|
format: 'json',
|
||
|
addressdetails: 1
|
||
|
}, this.options.geocodingQueryParams),
|
||
|
function(data) {
|
||
|
var results = [];
|
||
|
for (var i = data.length - 1; i >= 0; i--) {
|
||
|
var bbox = data[i].boundingbox;
|
||
|
for (var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]);
|
||
|
results[i] = {
|
||
|
icon: data[i].icon,
|
||
|
name: data[i].display_name,
|
||
|
html: this.options.htmlTemplate ?
|
||
|
this.options.htmlTemplate(data[i])
|
||
|
: undefined,
|
||
|
bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]),
|
||
|
center: L.latLng(data[i].lat, data[i].lon),
|
||
|
properties: data[i]
|
||
|
};
|
||
|
}
|
||
|
cb.call(context, results);
|
||
|
}, this, 'json_callback');
|
||
|
},
|
||
|
|
||
|
reverse: function(location, scale, cb, context) {
|
||
|
L.Control.Geocoder.jsonp(this.options.serviceUrl + 'reverse/', L.extend({
|
||
|
lat: location.lat,
|
||
|
lon: location.lng,
|
||
|
zoom: Math.round(Math.log(scale / 256) / Math.log(2)),
|
||
|
addressdetails: 1,
|
||
|
format: 'json'
|
||
|
}, this.options.reverseQueryParams), function(data) {
|
||
|
var result = [],
|
||
|
loc;
|
||
|
|
||
|
if (data && data.lat && data.lon) {
|
||
|
loc = L.latLng(data.lat, data.lon);
|
||
|
result.push({
|
||
|
name: data.display_name,
|
||
|
html: this.options.htmlTemplate ?
|
||
|
this.options.htmlTemplate(data)
|
||
|
: undefined,
|
||
|
center: loc,
|
||
|
bounds: L.latLngBounds(loc, loc),
|
||
|
properties: data
|
||
|
});
|
||
|
}
|
||
|
|
||
|
cb.call(context, result);
|
||
|
}, this, 'json_callback');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.nominatim = function(options) {
|
||
|
return new L.Control.Geocoder.Nominatim(options);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.Bing = L.Class.extend({
|
||
|
initialize: function(key) {
|
||
|
this.key = key;
|
||
|
},
|
||
|
|
||
|
geocode : function (query, cb, context) {
|
||
|
L.Control.Geocoder.jsonp('//dev.virtualearth.net/REST/v1/Locations', {
|
||
|
query: query,
|
||
|
key : this.key
|
||
|
}, function(data) {
|
||
|
var results = [];
|
||
|
for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
|
||
|
var resource = data.resourceSets[0].resources[i],
|
||
|
bbox = resource.bbox;
|
||
|
results[i] = {
|
||
|
name: resource.name,
|
||
|
bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
|
||
|
center: L.latLng(resource.point.coordinates)
|
||
|
};
|
||
|
}
|
||
|
cb.call(context, results);
|
||
|
}, this, 'jsonp');
|
||
|
},
|
||
|
|
||
|
reverse: function(location, scale, cb, context) {
|
||
|
L.Control.Geocoder.jsonp('//dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng, {
|
||
|
key : this.key
|
||
|
}, function(data) {
|
||
|
var results = [];
|
||
|
for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
|
||
|
var resource = data.resourceSets[0].resources[i],
|
||
|
bbox = resource.bbox;
|
||
|
results[i] = {
|
||
|
name: resource.name,
|
||
|
bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
|
||
|
center: L.latLng(resource.point.coordinates)
|
||
|
};
|
||
|
}
|
||
|
cb.call(context, results);
|
||
|
}, this, 'jsonp');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.bing = function(key) {
|
||
|
return new L.Control.Geocoder.Bing(key);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.RaveGeo = L.Class.extend({
|
||
|
options: {
|
||
|
querySuffix: '',
|
||
|
deepSearch: true,
|
||
|
wordBased: false
|
||
|
},
|
||
|
|
||
|
jsonp: function(params, callback, context) {
|
||
|
var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++),
|
||
|
paramParts = [];
|
||
|
params.prepend = callbackId + '(';
|
||
|
params.append = ')';
|
||
|
for (var p in params) {
|
||
|
paramParts.push(p + '=' + escape(params[p]));
|
||
|
}
|
||
|
|
||
|
window[callbackId] = L.Util.bind(callback, context);
|
||
|
var script = document.createElement('script');
|
||
|
script.type = 'text/javascript';
|
||
|
script.src = this._serviceUrl + '?' + paramParts.join('&');
|
||
|
script.id = callbackId;
|
||
|
document.getElementsByTagName('head')[0].appendChild(script);
|
||
|
},
|
||
|
|
||
|
initialize: function(serviceUrl, scheme, options) {
|
||
|
L.Util.setOptions(this, options);
|
||
|
|
||
|
this._serviceUrl = serviceUrl;
|
||
|
this._scheme = scheme;
|
||
|
},
|
||
|
|
||
|
geocode: function(query, cb, context) {
|
||
|
L.Control.Geocoder.jsonp(this._serviceUrl, {
|
||
|
address: query + this.options.querySuffix,
|
||
|
scheme: this._scheme,
|
||
|
outputFormat: 'jsonp',
|
||
|
deepSearch: this.options.deepSearch,
|
||
|
wordBased: this.options.wordBased
|
||
|
}, function(data) {
|
||
|
var results = [];
|
||
|
for (var i = data.length - 1; i >= 0; i--) {
|
||
|
var r = data[i],
|
||
|
c = L.latLng(r.y, r.x);
|
||
|
results[i] = {
|
||
|
name: r.address,
|
||
|
bbox: L.latLngBounds([c]),
|
||
|
center: c
|
||
|
};
|
||
|
}
|
||
|
cb.call(context, results);
|
||
|
}, this);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.raveGeo = function(serviceUrl, scheme, options) {
|
||
|
return new L.Control.Geocoder.RaveGeo(serviceUrl, scheme, options);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.MapQuest = L.Class.extend({
|
||
|
initialize: function(key) {
|
||
|
// MapQuest seems to provide URI encoded API keys,
|
||
|
// so to avoid encoding them twice, we decode them here
|
||
|
this._key = decodeURIComponent(key);
|
||
|
},
|
||
|
|
||
|
_formatName: function() {
|
||
|
var r = [],
|
||
|
i;
|
||
|
for (i = 0; i < arguments.length; i++) {
|
||
|
if (arguments[i]) {
|
||
|
r.push(arguments[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return r.join(', ');
|
||
|
},
|
||
|
|
||
|
geocode: function(query, cb, context) {
|
||
|
L.Control.Geocoder.jsonp('//www.mapquestapi.com/geocoding/v1/address', {
|
||
|
key: this._key,
|
||
|
location: query,
|
||
|
limit: 5,
|
||
|
outFormat: 'json'
|
||
|
}, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng;
|
||
|
if (data.results && data.results[0].locations) {
|
||
|
for (var i = data.results[0].locations.length - 1; i >= 0; i--) {
|
||
|
loc = data.results[0].locations[i];
|
||
|
latLng = L.latLng(loc.latLng);
|
||
|
results[i] = {
|
||
|
name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1),
|
||
|
bbox: L.latLngBounds(latLng, latLng),
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
}, this);
|
||
|
},
|
||
|
|
||
|
reverse: function(location, scale, cb, context) {
|
||
|
L.Control.Geocoder.jsonp('//www.mapquestapi.com/geocoding/v1/reverse', {
|
||
|
key: this._key,
|
||
|
location: location.lat + ',' + location.lng,
|
||
|
outputFormat: 'json'
|
||
|
}, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng;
|
||
|
if (data.results && data.results[0].locations) {
|
||
|
for (var i = data.results[0].locations.length - 1; i >= 0; i--) {
|
||
|
loc = data.results[0].locations[i];
|
||
|
latLng = L.latLng(loc.latLng);
|
||
|
results[i] = {
|
||
|
name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1),
|
||
|
bbox: L.latLngBounds(latLng, latLng),
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
}, this);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.mapQuest = function(key) {
|
||
|
return new L.Control.Geocoder.MapQuest(key);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.Mapbox = L.Class.extend({
|
||
|
options: {
|
||
|
service_url: 'https://api.tiles.mapbox.com/v4/geocode/mapbox.places-v1/'
|
||
|
},
|
||
|
|
||
|
initialize: function(access_token) {
|
||
|
this._access_token = access_token;
|
||
|
},
|
||
|
|
||
|
geocode: function(query, cb, context) {
|
||
|
L.Control.Geocoder.getJSON(this.options.service_url + encodeURIComponent(query) + '.json', {
|
||
|
access_token: this._access_token,
|
||
|
}, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng,
|
||
|
latLngBounds;
|
||
|
if (data.features && data.features.length) {
|
||
|
for (var i = 0; i <= data.features.length - 1; i++) {
|
||
|
loc = data.features[i];
|
||
|
latLng = L.latLng(loc.center.reverse());
|
||
|
if(loc.hasOwnProperty('bbox'))
|
||
|
{
|
||
|
latLngBounds = L.latLngBounds(L.latLng(loc.bbox.slice(0, 2).reverse()), L.latLng(loc.bbox.slice(2, 4).reverse()));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
latLngBounds = L.latLngBounds(latLng, latLng);
|
||
|
}
|
||
|
results[i] = {
|
||
|
name: loc.place_name,
|
||
|
bbox: latLngBounds,
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
suggest: function(query, cb, context) {
|
||
|
return this.geocode(query, cb, context);
|
||
|
},
|
||
|
|
||
|
reverse: function(location, scale, cb, context) {
|
||
|
L.Control.Geocoder.getJSON(this.options.service_url + encodeURIComponent(location.lng) + ',' + encodeURIComponent(location.lat) + '.json', {
|
||
|
access_token: this._access_token,
|
||
|
}, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng,
|
||
|
latLngBounds;
|
||
|
if (data.features && data.features.length) {
|
||
|
for (var i = 0; i <= data.features.length - 1; i++) {
|
||
|
loc = data.features[i];
|
||
|
latLng = L.latLng(loc.center.reverse());
|
||
|
if(loc.hasOwnProperty('bbox'))
|
||
|
{
|
||
|
latLngBounds = L.latLngBounds(L.latLng(loc.bbox.slice(0, 2).reverse()), L.latLng(loc.bbox.slice(2, 4).reverse()));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
latLngBounds = L.latLngBounds(latLng, latLng);
|
||
|
}
|
||
|
results[i] = {
|
||
|
name: loc.place_name,
|
||
|
bbox: latLngBounds,
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.mapbox = function(access_token) {
|
||
|
return new L.Control.Geocoder.Mapbox(access_token);
|
||
|
};
|
||
|
|
||
|
L.Control.Geocoder.Google = L.Class.extend({
|
||
|
options: {
|
||
|
service_url: 'https://maps.googleapis.com/maps/api/geocode/json'
|
||
|
},
|
||
|
|
||
|
initialize: function(key) {
|
||
|
this._key = key;
|
||
|
},
|
||
|
|
||
|
geocode: function(query, cb, context) {
|
||
|
var params = {
|
||
|
address: query,
|
||
|
};
|
||
|
if(this._key && this._key.length)
|
||
|
{
|
||
|
params['key'] = this._key
|
||
|
}
|
||
|
|
||
|
L.Control.Geocoder.getJSON(this.options.service_url, params, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng,
|
||
|
latLngBounds;
|
||
|
if (data.results && data.results.length) {
|
||
|
for (var i = 0; i <= data.results.length - 1; i++) {
|
||
|
loc = data.results[i];
|
||
|
latLng = L.latLng(loc.geometry.location);
|
||
|
latLngBounds = L.latLngBounds(L.latLng(loc.geometry.viewport.northeast), L.latLng(loc.geometry.viewport.southwest));
|
||
|
results[i] = {
|
||
|
name: loc.formatted_address,
|
||
|
bbox: latLngBounds,
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
reverse: function(location, scale, cb, context) {
|
||
|
var params = {
|
||
|
latlng: encodeURIComponent(location.lat) + ',' + encodeURIComponent(location.lng)
|
||
|
};
|
||
|
if(this._key && this._key.length)
|
||
|
{
|
||
|
params['key'] = this._key
|
||
|
}
|
||
|
L.Control.Geocoder.getJSON(this.options.service_url, params, function(data) {
|
||
|
var results = [],
|
||
|
loc,
|
||
|
latLng,
|
||
|
latLngBounds;
|
||
|
if (data.results && data.results.length) {
|
||
|
for (var i = 0; i <= data.results.length - 1; i++) {
|
||
|
loc = data.results[i];
|
||
|
latLng = L.latLng(loc.geometry.location);
|
||
|
latLngBounds = L.latLngBounds(L.latLng(loc.geometry.viewport.northeast), L.latLng(loc.geometry.viewport.southwest));
|
||
|
results[i] = {
|
||
|
name: loc.formatted_address,
|
||
|
bbox: latLngBounds,
|
||
|
center: latLng
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cb.call(context, results);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Control.Geocoder.google = function(key) {
|
||
|
return new L.Control.Geocoder.Google(key);
|
||
|
};
|
||
|
return L.Control.Geocoder;
|
||
|
}));
|