Skip to content
Permalink
 
 
Cannot retrieve contributors at this time
L.Control.RevealOSM = L.Control.extend({
includes: L.Mixin.Events,
options: {
position: 'topleft',
apiUrl: 'http://overpass-api.de/api/interpreter?data=',
queryTemplate: '[out:json];node(around:{radius},{lat},{lng})[name];out body qt 1;',
helpText: "Click on names to get more infos",
excludeKeys: [/source/, /^ref\:/ ], //
translateKeys: {}
},
onAdd: function (map) {
this._map = map;
this.popup = this.getPopup();
var className = 'leaflet-control-reveal-osm',
container = this._container = L.DomUtil.create('div', className);
var link = L.DomUtil.create('a', "", container);
link.href = '#';
link.title = this.getHelpText();
var tooltip = this._tootip = L.DomUtil.create('span', '', container);
tooltip.innerHTML = this.getHelpText();
L.DomEvent
.on(link, "click", this.toggle, this)
.on(link, "click", L.DomEvent.stop);
return container;
},
toggle: function () {
if (L.DomUtil.hasClass(this._map._container, "reveal-osm")) {
this.deactivate();
}
else {
this.activate();
}
},
activate: function () {
this._map.on('click', this._onClick, this);
this._map.on("preclick", this._preventCallOnClickToClose, this);
L.DomUtil.addClass(this._map._container, "reveal-osm");
},
deactivate: function () {
this._map.off('click', this._onClick, this);
this._map.off("preclick", this._preventCallOnClickToClose, this);
L.DomUtil.removeClass(this._map._container, "reveal-osm");
L.DomUtil.removeClass(this._map._container, "loading");
},
_preventCallOnClickToClose: function (e) {
if (e.target._popup == this.popup) {
this._abortNextClick = true;
}
},
getPopup: function () {
return L.popup();
},
isAllowedKey: function (key) {
for(var i=0, l=this.options.excludeKeys.length; i<l; i++) {
if (key.match(this.options.excludeKeys[i])) {
return false;
}
}
return true;
},
formatContent: function (element) {
var content = "",
title = this.formatTitle(element);
for (var tag in element.tags) {
if (!this.isAllowedKey(tag)) { continue;}
content += this.formatKey(element, tag);
}
content = title + '<ul>' + content + '</ul>';
content = '<div class="reveal-osm-popup">' + content + '</div>';
return content;
},
formatTitle: function (element) {
var title;
if (element.tags.name) {
title = "<h4>" + element.tags.name + "</h4>";
}
return title;
},
translateKey: function (element, key) {
return this.options.translateKeys[key] || key;
},
cleanKey: function (element, key) {
return key.replace(':', ' ').replace('_', ' ');
},
formatKey: function (element, key) {
var value = element.tags[key];
key = this.translateKey(element, key);
key = this.cleanKey(element, key);
return '<li><strong>' + key + "</strong> " + this.formatValue(element, key, value) + "</li>";
},
formatValue: function (element, key, value) {
if (value.match(/^http(s)?\:\/\//)) {
value = '<a href="' + value + '">' + value + '</a>';
}
return value;
},
getUrl: function (query) {
return this.options.apiUrl + encodeURIComponent(query);
},
getQueryTemplate: function () {
return this.options.queryTemplate;
},
getQuery: function () {
var lat = this._latlng.lat,
lng = this._latlng.lng,
kwargs = {lat:lat, lng:lng, radius: this.getRadius()};
return L.Util.template(this.getQueryTemplate(), kwargs);
},
getRadius: function () {
return this.options.radius || 100 - (5 * this._map.getZoom());
},
getHelpText: function () {
return this.options.helpText;
},
_onClick: function (e) {
this._latlng = e.latlng;
if (this._abortNextClick) {
this._abortNextClick = false;
return;
}
this.onClick(e);
},
onClick: function (e) {
var query = this.getQuery(),
url = this.getUrl(query);
this._requestAPI(url);
},
error: function (msg) {
if (this.options.errorCallback) {
this.options.errorCallback(msg);
}
else {
console.error(msg);
}
},
_requestAPI: function (uri, options) {
var self = this;
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.onload = function(e) {
L.DomUtil.removeClass(self._map._container, "loading");
if (this.status == 200) {
var data;
try {
data = JSON.parse(this.response);
}
catch (err) {
self.error(err);
}
self.handleResponse(data);
}
else {
self.error("Problem in the response");
}
};
L.DomUtil.addClass(this._map._container, "loading");
xhr.send();
},
openPopup: function (latlng, content) {
this.popup
.setLatLng(latlng)
.setContent(content)
.openOn(this._map);
},
handleResponse: function (data) {
if (this.options.debug) {
console.log(data);
}
if (data.elements.length) {
var element = data.elements[0];
if (element.type === "node") {
this.handleNode(element);
}
else if (element.type === "way") {
this.handleWay(element);
}
}
},
handleNode: function (element) {
var latlng = L.latLng(element.lat, element.lon);
var content = this.formatContent(element);
this.openPopup(latlng, content);
},
handleWay: function (element) {
var content = this.formatContent(element);
// No nodes nor latlng in way data, so use click latlng for now
// Another option is to request nodes by adding recurse on request
// but it's heavier, and avoid limiting results...
this.openPopup(this._latlng, content);
}
});
L.Map.addInitHook(function () {
if (this.options.revealOSMControl) {
var options = this.options.revealOSMControlOptions || {};
this.revealOSMControl = (new L.Control.RevealOSM(options)).addTo(this);
}
});