Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Utilities
---------------------

.. autoclass:: folium.utilities.JsCode
.. autoclass:: folium.elements.EventHandler


Plugins
Expand Down
76 changes: 76 additions & 0 deletions folium/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from branca.element import CssLink, Element, Figure, JavascriptLink, MacroElement
from jinja2 import Template

from folium.utilities import JsCode


class JSCSSMixin(Element):
"""Render links to external Javascript and CSS resources."""
Expand Down Expand Up @@ -46,6 +48,80 @@ def _add_link(self, name: str, url: str, default_list: List[Tuple[str, str]]):
default_list.append((name, url))


class EventHandler(MacroElement):
'''
Add javascript event handlers.

Examples
--------
>>> import folium
>>> from folium.utilities import JsCode
>>>
>>> m = folium.Map()
>>>
>>> geo_json_data = {
... "type": "FeatureCollection",
... "features": [
... {
... "type": "Feature",
... "geometry": {
... "type": "Polygon",
... "coordinates": [
... [
... [100.0, 0.0],
... [101.0, 0.0],
... [101.0, 1.0],
... [100.0, 1.0],
... [100.0, 0.0],
... ]
... ],
... },
... "properties": {"prop1": {"title": "Somewhere on Sumatra"}},
... }
... ],
... }
>>>
>>> g = folium.GeoJson(geo_json_data).add_to(m)
>>>
>>> highlight = JsCode(
... """
... function highlight(e) {
... e.target.original_color = e.layer.options.color;
... e.target.setStyle({ color: "green" });
... }
... """
... )
>>>
>>> reset = JsCode(
... """
... function reset(e) {
... e.target.setStyle({ color: e.target.original_color });
... }
... """
... )
>>>
>>> g.add_child(EventHandler("mouseover", highlight))
>>> g.add_child(EventHandler("mouseout", reset))
'''

_template = Template(
"""
{% macro script(this, kwargs) %}
{{ this._parent.get_name()}}.on(
{{ this.event|tojson}},
{{ this.handler.js_code }}
);
{% endmacro %}
"""
)

def __init__(self, event: str, handler: JsCode):
super().__init__()
self._name = "EventHandler"
self.event = event
self.handler = handler


class ElementAddToElement(MacroElement):
"""Abstract class to add an element to another element."""

Expand Down
19 changes: 19 additions & 0 deletions tests/test_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

import folium
from folium import Choropleth, ClickForMarker, GeoJson, Map, Popup
from folium.elements import EventHandler
from folium.utilities import JsCode


@pytest.fixture
Expand Down Expand Up @@ -283,6 +285,23 @@ def test_geojson_empty_features_with_styling():
m.get_root().render()


def test_geojson_event_handler():
"""Test that event handlers are properly generated"""
m = Map()
data = {"type": "FeatureCollection", "features": []}
geojson = GeoJson(data, style_function=lambda x: {}).add_to(m)
fn = JsCode(
"""
function f(e) {
console.log("only for testing")
}
"""
)
geojson.add_child(EventHandler("mouseover", fn))
rendered = m.get_root().render()
assert fn.js_code in rendered


def test_geometry_collection_get_bounds():
"""Assert #1599 is fixed"""
geojson_data = {
Expand Down