Files
2024-09-29 01:46:07 -04:00

140 lines
3.9 KiB
Python

from typing import List, Tuple
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."""
default_js: List[Tuple[str, str]] = []
default_css: List[Tuple[str, str]] = []
def render(self, **kwargs) -> None:
figure = self.get_root()
assert isinstance(
figure, Figure
), "You cannot render this Element if it is not in a Figure."
for name, url in self.default_js:
figure.header.add_child(JavascriptLink(url), name=name)
for name, url in self.default_css:
figure.header.add_child(CssLink(url), name=name)
super().render(**kwargs)
def add_css_link(self, name: str, url: str):
"""Add or update css resource link."""
self._add_link(name, url, self.default_css)
def add_js_link(self, name: str, url: str):
"""Add or update JS resource link."""
self._add_link(name, url, self.default_js)
def _add_link(self, name: str, url: str, default_list: List[Tuple[str, str]]):
"""Modify a css or js link.
If `name` does not exist, the link will be appended
"""
for i, pair in enumerate(default_list):
if pair[0] == name:
default_list[i] = (name, url)
break
else:
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."""
_template = Template(
"""
{% macro script(this, kwargs) %}
{{ this.element_name }}.addTo({{ this.element_parent_name }});
{% endmacro %}
"""
)
def __init__(self, element_name: str, element_parent_name: str):
super().__init__()
self.element_name = element_name
self.element_parent_name = element_parent_name