Permalink
Newer
100644
229 lines (197 sloc)
6.6 KB
1
L.Control.RevealOSM = L.Control.extend({
2
includes: L.Mixin.Events,
3
4
options: {
5
position: 'topleft',
6
apiUrl: 'http://overpass-api.de/api/interpreter?data=',
7
queryTemplate: '[out:json];node(around:{radius},{lat},{lng})[name];out body qt 1;',
11
},
12
13
onAdd: function (map) {
14
this._map = map;
15
this.popup = this.getPopup();
16
var className = 'leaflet-control-reveal-osm',
17
container = this._container = L.DomUtil.create('div', className);
18
var link = L.DomUtil.create('a', "", container);
19
link.href = '#';
20
link.title = this.getHelpText();
21
var tooltip = this._tootip = L.DomUtil.create('span', '', container);
22
tooltip.innerHTML = this.getHelpText();
23
L.DomEvent
24
.on(link, "click", this.toggle, this)
25
.on(link, "click", L.DomEvent.stop);
26
return container;
27
},
28
29
toggle: function () {
30
if (L.DomUtil.hasClass(this._map._container, "reveal-osm")) {
31
this.deactivate();
32
}
33
else {
34
this.activate();
35
}
36
},
37
38
activate: function () {
39
this._map.on('click', this._onClick, this);
40
this._map.on("preclick", this._preventCallOnClickToClose, this);
41
L.DomUtil.addClass(this._map._container, "reveal-osm");
42
},
43
44
deactivate: function () {
45
this._map.off('click', this._onClick, this);
46
this._map.off("preclick", this._preventCallOnClickToClose, this);
47
L.DomUtil.removeClass(this._map._container, "reveal-osm");
49
},
50
51
_preventCallOnClickToClose: function (e) {
52
if (e.target._popup == this.popup) {
53
this._abortNextClick = true;
54
}
55
},
56
57
getPopup: function () {
58
return L.popup();
59
},
60
61
isAllowedKey: function (key) {
62
for(var i=0, l=this.options.excludeKeys.length; i<l; i++) {
63
if (key.match(this.options.excludeKeys[i])) {
64
return false;
65
}
66
}
67
return true;
68
},
69
70
formatContent: function (element) {
71
var content = "",
72
title = this.formatTitle(element);
73
for (var tag in element.tags) {
77
content = title + '<ul>' + content + '</ul>';
78
content = '<div class="reveal-osm-popup">' + content + '</div>';
79
return content;
80
},
81
82
formatTitle: function (element) {
83
var title;
84
if (element.tags.name) {
85
title = "<h4>" + element.tags.name + "</h4>";
86
}
87
return title;
88
},
89
90
translateKey: function (element, key) {
91
return this.options.translateKeys[key] || key;
92
},
93
94
cleanKey: function (element, key) {
95
return key.replace(':', ' ').replace('_', ' ');
96
},
97
99
var value = element.tags[key];
100
key = this.translateKey(element, key);
101
key = this.cleanKey(element, key);
102
return '<li><strong>' + key + "</strong> " + this.formatValue(element, key, value) + "</li>";
106
if (value.match(/^http(s)?\:\/\//)) {
107
value = '<a href="' + value + '">' + value + '</a>';
108
}
109
return value;
110
},
111
112
getUrl: function (query) {
113
return this.options.apiUrl + encodeURIComponent(query);
114
},
115
116
getQueryTemplate: function () {
117
return this.options.queryTemplate;
118
},
119
120
getQuery: function () {
121
var lat = this._latlng.lat,
122
lng = this._latlng.lng,
123
kwargs = {lat:lat, lng:lng, radius: this.getRadius()};
124
return L.Util.template(this.getQueryTemplate(), kwargs);
125
},
126
127
getRadius: function () {
128
return this.options.radius || 100 - (5 * this._map.getZoom());
129
},
130
131
getHelpText: function () {
132
return this.options.helpText;
133
},
134
135
_onClick: function (e) {
136
this._latlng = e.latlng;
137
if (this._abortNextClick) {
138
this._abortNextClick = false;
139
return;
140
}
141
this.onClick(e);
142
},
143
144
onClick: function (e) {
145
var query = this.getQuery(),
146
url = this.getUrl(query);
147
this._requestAPI(url);
148
},
149
150
error: function (msg) {
151
if (this.options.errorCallback) {
152
this.options.errorCallback(msg);
153
}
154
else {
155
console.error(msg);
156
}
157
},
158
159
_requestAPI: function (uri, options) {
160
var self = this;
161
162
var xhr = new XMLHttpRequest();
163
xhr.open("GET", uri, true);
164
165
xhr.onload = function(e) {
167
if (this.status == 200) {
168
var data;
169
try {
170
data = JSON.parse(this.response);
171
}
172
catch (err) {
173
self.error(err);
174
}
175
self.handleResponse(data);
176
}
177
else {
178
self.error("Problem in the response");
179
}
180
};
181
183
xhr.send();
184
},
185
186
openPopup: function (latlng, content) {
187
this.popup
188
.setLatLng(latlng)
189
.setContent(content)
190
.openOn(this._map);
191
},
192
193
handleResponse: function (data) {
194
if (this.options.debug) {
195
console.log(data);
196
}
197
if (data.elements.length) {
198
var element = data.elements[0];
199
if (element.type === "node") {
200
this.handleNode(element);
201
}
202
else if (element.type === "way") {
203
this.handleWay(element);
204
}
205
}
206
},
207
208
handleNode: function (element) {
209
var latlng = L.latLng(element.lat, element.lon);
210
var content = this.formatContent(element);
211
this.openPopup(latlng, content);
212
},
213
214
handleWay: function (element) {
215
var content = this.formatContent(element);
216
// No nodes nor latlng in way data, so use click latlng for now
217
// Another option is to request nodes by adding recurse on request
218
// but it's heavier, and avoid limiting results...
219
this.openPopup(this._latlng, content);
220
}
221
222
});
223
224
L.Map.addInitHook(function () {
225
if (this.options.revealOSMControl) {
226
var options = this.options.revealOSMControlOptions || {};
227
this.revealOSMControl = (new L.Control.RevealOSM(options)).addTo(this);
228
}
229
});