python-visualization / folium

Python Data. Leaflet.js Maps.
https://python-visualization.github.io/folium/
MIT License
6.91k stars 2.22k forks source link

How to open the popup automatically when a search is found for a GeoJson layer? #1286

Open RenchengDong opened 4 years ago

RenchengDong commented 4 years ago

Please add a code sample or a nbviewer link, copy-pastable if possible

# Your code here
import folium
import branca
import geopandas
from folium.plugins import Search

print(folium.__version__)

states = geopandas.read_file(
    'https://rawcdn.githack.com/PublicaMundi/MappingAPI/master/data/geojson/us-states.json',
    driver='GeoJSON'
)

min, max = states['density'].quantile([0.05,0.95]).apply(lambda x: round(x, 2))

colormap = branca.colormap.LinearColormap(
    colors=['#f2f0f7','#cbc9e2','#9e9ac8','#756bb1','#54278f'],
    index=states['density'].quantile([0.2,0.4,0.6,0.8]),
    vmin=min,
    vmax=max
)

colormap.caption="Population Density in the United States"

m = folium.Map(location=[38,-97], zoom_start=4)

style_function = lambda x: {
    'fillColor': colormap(x['properties']['density']),
    'color': 'black',
    'weight':2,
    'fillOpacity':0.5
}

stategeo = folium.GeoJson(
    states,
    name='US States',
    style_function=style_function,
    popup=folium.GeoJsonPopup(
        fields=['name', 'density'],
        aliases=['State', 'Density'], 
        localize=True
    )
).add_to(m)

statesearch = Search(
    layer=stategeo,
    geom_type='Polygon',
    placeholder='Search for a US State',
    collapsed=False,
    search_label='name'
).add_to(m)

folium.LayerControl().add_to(m)
colormap.add_to(m)

m

Problem description

I was trying to make the popup open automatically when a search is found in a GeoJson layer. My code is modified from an example code "plugin-Search.ipynb". I am using the "master" version of folium on the github. Right now, my code cannot open the popup when a search is found. I checked the source code "search.py" in "plugins" folder. The code is:

{{this.layer.get_name()}}searchControl.on('search:locationfound', function(e) { {{this.layer.get_name()}}.setStyle(function(feature){ return feature.properties.style }) {% if this.options %} e.layer.setStyle({{ this.options|tojson }}); {% endif %} if(e.layer._popup) e.layer.openPopup(); })

I think the code should open popup if location is found but it did not.

I manually added console.log(e.layer._popup) in front of if(e.layer._popup) in the html file. When I searched one state on the web page, the console outputs "undefined" for e.layer._popup. It's confusing to me.

Expected Output

I expect to open the popup automatically when a search is found like this leaflet search example https://labs.easyblog.it/maps/leaflet-search/examples/geojson-layer.html.

Output of folium.__version__

0+unknown

Conengmo commented 1 year ago

This one was tricky. It seems to be because of the way we bind popups on GeoJson. We do these after the GeoJson object is created, using bindPopup. In the search plugin example they use the onEachFeature argument instead. If I use that to bind popups as well I can get it working correctly.

I don't know if we'll be able to fix this. We might change the rendering of GeoJson and GeoJsonPopup to use onEachFeature, but it's a bigger change and I'm not sure if it's worth it.