Skip to content

Commit e466354

Browse files
authored
Merge pull request #759 from ocefpaf/leaflet-search_plugin
Leaflet search plugin
2 parents 60f3a89 + 72fd048 commit e466354

File tree

7 files changed

+293
-30
lines changed

7 files changed

+293
-30
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
0.6.0
22
~~~~~
33

4+
- Added leaflet-search plugin (ghandic #759)
45
- Improved Vector Layers docs, notebooks, and optional arguments (ocefpaf #731)
56
- Implemented `export=False/True` option to the Draw plugin layer for saving
67
GeoJSON files (ocefpaf #727)

examples/Features.ipynb

Lines changed: 20 additions & 30 deletions
Large diffs are not rendered by default.

examples/data/search_bars_rome.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"type": "FeatureCollection", "generator": "overpass-turbo", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", "timestamp": "2015-08-08T19:03:02Z", "features": [{"type": "Feature", "id": "node/500129236", "properties": {"@id": "node/500129236", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "5", "addr:postcode": "00184", "addr:street": "Piazza della Madonna dei Monti", "amenity": "bar", "name": "la Bottega del caffe'"}, "geometry": {"type": "Point", "coordinates": [12.4910927, 41.8950196]}}, {"type": "Feature", "id": "node/560446888", "properties": {"@id": "node/560446888", "amenity": "bar", "name": "Marani"}, "geometry": {"type": "Point", "coordinates": [12.5132952, 41.8970607]}}, {"type": "Feature", "id": "node/574326909", "properties": {"@id": "node/574326909", "amenity": "bar", "name": "Il Faraone"}, "geometry": {"type": "Point", "coordinates": [12.4910603, 41.8948257]}}, {"type": "Feature", "id": "node/1213332726", "properties": {"@id": "node/1213332726", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "139", "addr:postcode": "00185", "addr:street": "Via Principe Amedeo", "amenity": "bar", "name": "Snackbar Eugenio", "operator": "Marchetti Eugenio", "phone": "+39 06 4466154"}, "geometry": {"type": "Point", "coordinates": [12.5031364, 41.8970108]}}, {"type": "Feature", "id": "node/1660369493", "properties": {"@id": "node/1660369493", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "27", "addr:street": "Via San Martino della Battaglia", "amenity": "bar", "name": "Pretorius Cafe'", "operator": "Cesarina Utilia", "phone": "+39 06 490077", "ref:vatin": "IT09397401002"}, "geometry": {"type": "Point", "coordinates": [12.5051946, 41.905864]}}, {"type": "Feature", "id": "node/1660404822", "properties": {"@id": "node/1660404822", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "9", "addr:street": "Via Clementina", "amenity": "bar", "cuisine": "regional", "name": "Casa Clementina", "operator": "Flexy Soc.Coop Arl.", "phone": "+39 06 48913254", "ref:vatin": "IT09253451000", "restaurant:type": "enoteca"}, "geometry": {"type": "Point", "coordinates": [12.492714, 41.8959687]}}, {"type": "Feature", "id": "node/1926196463", "properties": {"@id": "node/1926196463", "amenity": "bar", "name": "Twins"}, "geometry": {"type": "Point", "coordinates": [12.5009894, 41.8999812]}}, {"type": "Feature", "id": "node/2092013187", "properties": {"@id": "node/2092013187", "addr:housenumber": "12", "addr:street": "Via di San Giovanni in Laterano", "amenity": "bar", "name": "My Bar", "operator": "Anfiteatro S.r.l.", "phone": "+39 06 7004425", "ref:vatin": "IT067475410008"}, "geometry": {"type": "Point", "coordinates": [12.4946166, 41.8898973]}}, {"type": "Feature", "id": "node/2128214065", "properties": {"@id": "node/2128214065", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "106", "addr:postcode": "00184", "addr:street": "Via di San Giovanni in Laterano", "amenity": "bar", "cuisine": "italian", "name": "San Clemente", "source": "GPS", "website": "http://www.iclementini.it/"}, "geometry": {"type": "Point", "coordinates": [12.4979123, 41.8889233]}}, {"type": "Feature", "id": "node/2244964954", "properties": {"@id": "node/2244964954", "addr:housenumber": "40", "addr:street": "Via Palestro", "amenity": "bar", "contact:phone": "+39 06 49382682", "contact:website": "http://the-yellow.com/", "name": "The Yellow Bar", "payment:bitcoin": "yes"}, "geometry": {"type": "Point", "coordinates": [12.5045633, 41.9048511]}}, {"type": "Feature", "id": "node/2361780469", "properties": {"@id": "node/2361780469", "addr:city": "Roma", "addr:housenumber": "72/73", "addr:street": "Via Urbana", "amenity": "bar", "name": "Er Caffettiere", "operator": "Sa.Pe. SNC di Spartaco Pelle & C.", "phone": "+39 320 4168532", "ref:vatin": "IT09487221005", "restaurant:type:it": "bar;tavola_calda"}, "geometry": {"type": "Point", "coordinates": [12.4929144, 41.8949856]}}, {"type": "Feature", "id": "node/3217327590", "properties": {"@id": "node/3217327590", "addr:city": "Roma", "addr:housenumber": "65", "addr:street": "Via dei Cerchi", "amenity": "bar", "name": "0,75", "opening_hours": "Mo-Su 11:00-02:00", "phone": "+39 066875706"}, "geometry": {"type": "Point", "coordinates": [12.4839357, 41.8879519]}}, {"type": "Feature", "id": "node/3320437843", "properties": {"@id": "node/3320437843", "addr:housenumber": "26", "addr:street": "Via Capo d'Africa", "amenity": "bar", "name": "La Follia", "operator": "Dolce Calabria SAS di Morello Alessandra & C.", "phone": "+39 06 45477438", "ref:vatin": "IT11279721002", "restaurant:type:it": "wine_bar", "shop": "pastry"}, "geometry": {"type": "Point", "coordinates": [12.4952573, 41.8888415]}}, {"type": "Feature", "id": "node/3403821230", "properties": {"@id": "node/3403821230", "amenity": "bar", "name": "Snack bar peter bar"}, "geometry": {"type": "Point", "coordinates": [12.4978786, 41.9001486]}}, {"type": "Feature", "id": "node/3485963126", "properties": {"@id": "node/3485963126", "addr:housename": "Roma Termini", "addr:housenumber": "25", "addr:street": "Via Marsala", "amenity": "bar", "brand": "Chef Express", "building:level": "0", "name": "Buffet Roma Termini", "operator": "Chef Express S.p.A.", "ref:vatin": "IT00876120213"}, "geometry": {"type": "Point", "coordinates": [12.5023541, 41.9016306]}}, {"type": "Feature", "id": "node/3551307620", "properties": {"@id": "node/3551307620", "addr:housenumber": "30-34", "addr:street": "Via Ludovisi", "amenity": "bar", "name": "Bar Ludovisi", "operator": "Doppio Zero Srl.", "phone": "+39 06 42016014", "ref:vatin": "IT11344331001"}, "geometry": {"type": "Point", "coordinates": [12.4887487, 41.9069283]}}, {"type": "Feature", "id": "node/3578353919", "properties": {"@id": "node/3578353919", "addr:city": "Roma", "addr:country": "IT", "addr:housenumber": "36/37", "addr:postcode": "00185", "addr:street": "Via Merulana", "amenity": "bar", "name": "Il Pasticciaccio", "operator": "Angelo Blu s.r.l.", "phone": "+39 06 4826928", "ref:vatin": "IT09547101007"}, "geometry": {"type": "Point", "coordinates": [12.5005788, 41.8948307]}}, {"type": "Feature", "id": "node/3607603463", "properties": {"@id": "node/3607603463", "addr:city": "Roma", "addr:housenumber": "22", "addr:postcode": "00185", "addr:street": "Via Tiburtina", "amenity": "bar", "name": "Buddha Bar"}, "geometry": {"type": "Point", "coordinates": [12.5121332, 41.8971197]}}]}

examples/data/search_states.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

examples/plugin-Search.ipynb

Lines changed: 172 additions & 0 deletions
Large diffs are not rendered by default.

folium/plugins/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from folium.plugins.time_slider_choropleth import TimeSliderChoropleth
2626
from folium.plugins.timestamped_geo_json import TimestampedGeoJson
2727
from folium.plugins.timestamped_wmstilelayer import TimestampedWmsTileLayers
28+
from folium.plugins.search import Search
2829

2930
__all__ = [
3031
'BoatMarker',
@@ -42,4 +43,5 @@
4243
'TimeSliderChoropleth',
4344
'TimestampedGeoJson',
4445
'TimestampedWmsTileLayers',
46+
'Search',
4547
]

folium/plugins/search.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import (absolute_import, division, print_function)
4+
5+
from branca.element import CssLink, Figure, JavascriptLink, MacroElement
6+
7+
from jinja2 import Template
8+
9+
10+
class Search(MacroElement):
11+
"""
12+
Adds a search tool to your map.
13+
14+
Parameters
15+
----------
16+
data: str/JSON
17+
GeoJSON strings
18+
search_zoom: int
19+
zoom level when searching features, default 12
20+
search_label: str
21+
label to index the search, default 'name'
22+
geom_type: str
23+
geometry type, default 'Point'
24+
position: str
25+
Change the position of the search bar, can be:
26+
'topleft', 'topright', 'bottomright' or 'bottomleft',
27+
default 'topleft'
28+
29+
See https://github.com/stefanocudini/leaflet-search for more information.
30+
31+
"""
32+
def __init__(self, data, search_zoom=12, search_label='name', geom_type='Point', position='topleft'):
33+
super(Search, self).__init__()
34+
self.position = position
35+
self.data = data
36+
self.search_label = search_label
37+
self.search_zoom = search_zoom
38+
self.geom_type = geom_type
39+
40+
self._template = Template("""
41+
{% macro script(this, kwargs) %}
42+
43+
var {{this.get_name()}} = new L.GeoJSON({{this.data}});
44+
45+
{{this._parent.get_name()}}.addLayer({{this.get_name()}});
46+
47+
var searchControl = new L.Control.Search({
48+
layer: {{this.get_name()}},
49+
propertyName: '{{this.search_label}}',
50+
{% if this.geom_type == 'Point' %}
51+
initial: false,
52+
zoom: {{this.search_zoom}},
53+
position:'{{this.position}}',
54+
hideMarkerOnCollapse: true
55+
{% endif %}
56+
{% if this.geom_type == 'Polygon' %}
57+
marker: false,
58+
moveToLocation: function(latlng, title, map) {
59+
var zoom = {{this._parent.get_name()}}.getBoundsZoom(latlng.layer.getBounds());
60+
{{this._parent.get_name()}}.setView(latlng, zoom); // access the zoom
61+
}
62+
{% endif %}
63+
});
64+
searchControl.on('search:locationfound', function(e) {
65+
66+
e.layer.setStyle({fillColor: '#3f0', color: '#0f0'});
67+
if(e.layer._popup)
68+
e.layer.openPopup();
69+
70+
}).on('search:collapsed', function(e) {
71+
72+
{{this.get_name()}}.eachLayer(function(layer) { //restore feature color
73+
{{this.get_name()}}.resetStyle(layer);
74+
});
75+
});
76+
{{this._parent.get_name()}}.addControl( searchControl );
77+
78+
{% endmacro %}
79+
""") # noqa
80+
81+
def render(self, **kwargs):
82+
super(Search, self).render()
83+
84+
figure = self.get_root()
85+
assert isinstance(figure, Figure), ('You cannot render this Element '
86+
'if it is not in a Figure.')
87+
88+
figure.header.add_child(
89+
JavascriptLink('https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet-search.min.js'), # noqa
90+
name='Leaflet.Search.js'
91+
)
92+
93+
figure.header.add_child(
94+
CssLink('https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet-search.min.css'), # noqa
95+
name='Leaflet.Search.css'
96+
)

0 commit comments

Comments
 (0)