Skip to content

Commit f3df6f0

Browse files
committed
Close #1359
Add an include statement, that will allow users to override specific methods at Leaflet level. This allows users to customize the "createTile" method using a JsCode object.
1 parent b97053b commit f3df6f0

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

folium/elements.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ class IncludeStatement(MacroElement):
155155

156156
_template = Template(
157157
"""
158-
L.{{ this.class_name }}.include(
158+
{{ this.leaflet_class_name }}.include(
159159
{{ this.options | tojavascript }}
160160
)
161161
"""
162162
)
163163

164-
def __init__(self, class_name: str, **kwargs):
164+
def __init__(self, leaflet_class_name: str, **kwargs):
165165
super().__init__()
166-
self.class_name = class_name
166+
self.leaflet_class_name = leaflet_class_name
167167
self.options = kwargs
168168

169169
def render(self, *args, **kwargs):

folium/map.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,26 @@ def include(cls, **kwargs):
4848
def includes(cls):
4949
return cls._includes[cls]
5050

51+
@property
52+
def leaflet_class_name(self):
53+
# TODO: I did not check all Folium classes to see if
54+
# this holds up. This breaks at least for CustomIcon.
55+
return f"L.{self._name}"
56+
5157
def render(self, **kwargs):
5258
figure = self.get_root()
5359
assert isinstance(
5460
figure, Figure
5561
), "You cannot render this Element if it is not in a Figure."
5662
if self.includes:
57-
stmt = IncludeStatement(self._name, **self.includes)
63+
stmt = IncludeStatement(self.leaflet_class_name, **self.includes)
64+
# A bit weird. I tried adding IncludeStatement directly to both
65+
# figure and script, but failed. So we render this ourself.
5866
figure.script.add_child(
5967
Element(stmt._template.render(this=stmt, kwargs=self.includes)),
68+
# make sure each class include gets rendered only once
69+
name=self._name + "_includes",
70+
# make sure this renders before the element itself
6071
index=-1,
6172
)
6273
super().render(**kwargs)

tests/test_map.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import pytest
1111

1212
from folium import GeoJson, Map, TileLayer
13-
from folium.map import CustomPane, Icon, LayerControl, Marker, Popup
13+
from folium.map import Class, CustomPane, Icon, LayerControl, Marker, Popup
1414
from folium.utilities import JsCode, normalize
1515

1616
tmpl = """
@@ -173,11 +173,11 @@ def test_include():
173173
tiles=tiles,
174174
)
175175
rendered = m.get_root().render()
176+
Class._includes.clear()
176177
expected = """
177178
L.TileLayer.include({
178179
"createTile":
179180
function(coords, done) {
180-
console.log("creating tile");
181181
const url = this.getTileUrl(coords);
182182
const img = document.createElement('img');
183183
fetch(url, {
@@ -193,10 +193,32 @@ def test_include():
193193
},
194194
})
195195
"""
196+
print(expected)
197+
print("-----")
198+
print(rendered)
196199

197200
assert normalize(expected) in normalize(rendered)
198201

199202

203+
def test_include_once():
204+
abc = "MY BEAUTIFUL SENTINEL"
205+
TileLayer.include(abc=abc)
206+
tiles = TileLayer(
207+
tiles="OpenStreetMap",
208+
)
209+
m = Map(
210+
tiles=tiles,
211+
)
212+
TileLayer(
213+
tiles="OpenStreetMap",
214+
).add_to(m)
215+
216+
rendered = m.get_root().render()
217+
Class._includes.clear()
218+
219+
assert rendered.count(abc) == 1, "Includes should happen only once per class"
220+
221+
200222
def test_popup_backticks():
201223
m = Map()
202224
popup = Popup("back`tick`tick").add_to(m)

0 commit comments

Comments
 (0)