Skip to content

Commit 70a01c0

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fix-test-issues
2 parents 6343237 + d9e1e9a commit 70a01c0

File tree

4 files changed

+66
-17
lines changed

4 files changed

+66
-17
lines changed

folium/plugins/draw.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55

66

77
class Draw(JSCSSMixin, MacroElement):
8-
"""
8+
'''
99
Vector drawing and editing plugin for Leaflet.
1010
1111
Parameters
1212
----------
1313
export : bool, default False
1414
Add a small button that exports the drawn shapes as a geojson file.
15+
feature_group : FeatureGroup, optional
16+
The FeatureGroup object that will hold the editable figures. This can
17+
be used to initialize the Draw plugin with predefined Layer objects.
1518
filename : string, default 'data.geojson'
1619
Name of geojson file
1720
position : {'topleft', 'toprigth', 'bottomleft', 'bottomright'}
@@ -25,22 +28,35 @@ class Draw(JSCSSMixin, MacroElement):
2528
edit_options : dict, optional
2629
The options used to configure the edit toolbar. See
2730
https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html#editpolyoptions
31+
on : dict, optional
32+
Event handlers to attach to the created layer. Pass a mapping from the
33+
names of the events to their `JsCode` handlers.
2834
2935
Examples
3036
--------
3137
>>> m = folium.Map()
3238
>>> Draw(
3339
... export=True,
3440
... filename="my_data.geojson",
41+
... show_geometry_on_click=False,
3542
... position="topleft",
3643
... draw_options={"polyline": {"allowIntersection": False}},
3744
... edit_options={"poly": {"allowIntersection": False}},
45+
... on={
46+
... "click": JsCode(
47+
... """
48+
... function(event) {
49+
... alert(JSON.stringify(this.toGeoJSON()));
50+
... }
51+
... """
52+
... )
53+
... },
3854
... ).add_to(m)
3955
4056
For more info please check
4157
https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html
4258
43-
"""
59+
'''
4460

4561
_template = Template(
4662
"""
@@ -50,10 +66,17 @@ class Draw(JSCSSMixin, MacroElement):
5066
draw: {{ this.draw_options|tojson }},
5167
edit: {{ this.edit_options|tojson }},
5268
}
53-
// FeatureGroup is to store editable layers.
54-
var drawnItems_{{ this.get_name() }} = new L.featureGroup().addTo(
55-
{{ this._parent.get_name() }}
56-
);
69+
{%- if this.feature_group %}
70+
var drawnItems_{{ this.get_name() }} =
71+
{{ this.feature_group.get_name() }};
72+
{%- else %}
73+
// FeatureGroup is to store editable layers.
74+
var drawnItems_{{ this.get_name() }} =
75+
new L.featureGroup().addTo(
76+
{{ this._parent.get_name() }}
77+
);
78+
{%- endif %}
79+
5780
options.edit.featureGroup = drawnItems_{{ this.get_name() }};
5881
var {{ this.get_name() }} = new L.Control.Draw(
5982
options
@@ -68,11 +91,19 @@ class Draw(JSCSSMixin, MacroElement):
6891
console.log(coords);
6992
});
7093
{%- endif %}
94+
95+
{%- for event, handler in this.on.items() %}
96+
layer.on(
97+
"{{event}}",
98+
{{handler}}
99+
);
100+
{%- endfor %}
71101
drawnItems_{{ this.get_name() }}.addLayer(layer);
72-
});
102+
});
73103
{{ this._parent.get_name() }}.on('draw:created', function(e) {
74104
drawnItems_{{ this.get_name() }}.addLayer(e.layer);
75105
});
106+
76107
{% if this.export %}
77108
document.getElementById('export').onclick = function(e) {
78109
var data = drawnItems_{{ this.get_name() }}.toGeoJSON();
@@ -106,20 +137,24 @@ class Draw(JSCSSMixin, MacroElement):
106137
def __init__(
107138
self,
108139
export=False,
140+
feature_group=None,
109141
filename="data.geojson",
110142
position="topleft",
111143
show_geometry_on_click=True,
112144
draw_options=None,
113145
edit_options=None,
146+
on=None,
114147
):
115148
super().__init__()
116149
self._name = "DrawControl"
117150
self.export = export
151+
self.feature_group = feature_group
118152
self.filename = filename
119153
self.position = position
120154
self.show_geometry_on_click = show_geometry_on_click
121155
self.draw_options = draw_options or {}
122156
self.edit_options = edit_options or {}
157+
self.on = on or {}
123158

124159
def render(self, **kwargs):
125160
super().render(**kwargs)

folium/plugins/heat_map_withtime.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class HeatMapWithTime(JSCSSMixin, Layer):
8686
speedStep: {{this.speed_step}},
8787
styleNS: "{{this.style_NS}}",
8888
timeSlider: {{this.time_slider}},
89-
timeSliderDrapUpdate: {{this.time_slider_drap_update}},
89+
timeSliderDragUpdate: {{this.time_slider_drag_update}},
9090
timeSteps: {{this.index_steps}}
9191
})
9292
.addTo({{this._parent.get_name()}});
@@ -199,7 +199,7 @@ def __init__(
199199
self.time_slider = "true"
200200
self.play_button = "true"
201201
self.play_reverse_button = "true"
202-
self.time_slider_drap_update = "false"
202+
self.time_slider_drag_update = "false"
203203
self.style_NS = "leaflet-control-timecontrol"
204204

205205
def render(self, **kwargs):

folium/plugins/time_slider_choropleth.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class TimeSliderChoropleth(JSCSSMixin, Layer):
1919
styledict: dict
2020
A dictionary where the keys are the geojson feature ids and the values are
2121
dicts of `{time: style_options_dict}`
22+
date_options: str, default "ddd MMM DD YYYY"
23+
A format string to render the currently active time in the control.
2224
highlight: bool, default False
2325
Whether to show a visual effect on mouse hover and click.
2426
name : string, default None
@@ -44,6 +46,11 @@ class TimeSliderChoropleth(JSCSSMixin, Layer):
4446
let styledict = {{ this.styledict|tojson }};
4547
let current_timestamp = timestamps[{{ this.init_timestamp }}];
4648
49+
function formatDate(date) {
50+
var newdate = new moment(date);
51+
return newdate.format({{this.date_format|tojson}});
52+
}
53+
4754
let slider_body = d3.select("body").insert("div", "div.folium-map")
4855
.attr("id", "slider_{{ this.get_name() }}");
4956
$("#slider_{{ this.get_name() }}").hide();
@@ -64,7 +71,7 @@ class TimeSliderChoropleth(JSCSSMixin, Layer):
6471
.attr("step", "1")
6572
.style('align', 'center');
6673
67-
let datestring = new Date(parseInt(current_timestamp)*1000).toDateString();
74+
let datestring = formatDate(parseInt(current_timestamp)*1000);
6875
d3.select("#slider_{{ this.get_name() }} > output").text(datestring);
6976
7077
let fill_map = function(){
@@ -84,7 +91,7 @@ class TimeSliderChoropleth(JSCSSMixin, Layer):
8491
8592
d3.select("#slider_{{ this.get_name() }} > input").on("input", function() {
8693
current_timestamp = timestamps[this.value];
87-
var datestring = new Date(parseInt(current_timestamp)*1000).toDateString();
94+
let datestring = formatDate(parseInt(current_timestamp)*1000);
8895
d3.select("#slider_{{ this.get_name() }} > output").text(datestring);
8996
fill_map();
9097
});
@@ -155,12 +162,19 @@ class TimeSliderChoropleth(JSCSSMixin, Layer):
155162
"""
156163
)
157164

158-
default_js = [("d3v4", "https://d3js.org/d3.v4.min.js")]
165+
default_js = [
166+
("d3v4", "https://d3js.org/d3.v4.min.js"),
167+
(
168+
"moment",
169+
"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js",
170+
),
171+
]
159172

160173
def __init__(
161174
self,
162175
data,
163176
styledict,
177+
date_options: str = "ddd MMM DD YYYY",
164178
highlight: bool = False,
165179
name=None,
166180
overlay=True,
@@ -173,21 +187,21 @@ def __init__(
173187
):
174188
super().__init__(name=name, overlay=overlay, control=control, show=show)
175189
self.data = GeoJson.process_data(GeoJson({}), data)
190+
self.date_format = date_options
176191
self.highlight = highlight
177192

178193
self.stroke_opacity = stroke_opacity
179194
self.stroke_width = stroke_width
180195
self.stroke_color = stroke_color
181196

182197
if not isinstance(styledict, dict):
183-
raise ValueError(
184-
f"styledict must be a dictionary, got {styledict!r}"
185-
) # noqa
198+
raise ValueError(f"styledict must be a dictionary, got {styledict!r}")
199+
186200
for val in styledict.values():
187201
if not isinstance(val, dict):
188202
raise ValueError(
189203
f"Each item in styledict must be a dictionary, got {val!r}"
190-
) # noqa
204+
)
191205

192206
# Make set of timestamps.
193207
timestamps_set = set()

tests/plugins/test_heat_map_withtime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_heat_map_with_time():
5959
speedStep: {{this.speed_step}},
6060
styleNS: "{{this.style_NS}}",
6161
timeSlider: {{this.time_slider}},
62-
timeSliderDrapUpdate: {{this.time_slider_drap_update}},
62+
timeSliderDragUpdate: {{this.time_slider_drag_update}},
6363
timeSteps: {{this.index_steps}}
6464
})
6565
.addTo({{this._parent.get_name()}});

0 commit comments

Comments
 (0)