Skip to content

Conversation

@hansthen
Copy link
Collaborator

@hansthen hansthen commented Apr 6, 2025

@Conengmo

This is a new, smaller implementation of the Control class I implemented earlier. For this PR I focused only on the user's ability to load a new control in user space, without having to write a new plugin. It is not difficult to write a plugin, but it does require knowledge of Jinja. Also, there is quite some boilerplate code involved.

With this Control clas I was able to implement the minimap and ruler plugins, using just a few lines of code.

import folium import streamlit as st from folium import Control, TileLayer from streamlit_folium import st_folium st.set_page_config( page_title="minimap", layout="wide" ) m = folium.Map( location=[39.949610, -75.150282], zoom_start=5, zoom_control=False ) tiles = TileLayer( tiles="OpenStreetMap", show=False, control=False, ) tiles.add_to(m) minimap = Control("MiniMap", tiles) minimap.add_js_link( "minimap_js", "https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.js" ) minimap.add_css_link( "minimap_css", "https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.css" ) minimap.add_to(m) ruler = Control("Ruler", tiles) ruler.add_js_link( "ruler_js", "https://cdn.rawgit.com/gokertanrisever/leaflet-ruler/master/src/leaflet-ruler.js", ) ruler.add_css_link( "ruler_css", "https://cdn.rawgit.com/gokertanrisever/leaflet-ruler/master/src/leaflet-ruler.css", ) ruler.add_to(m) st_folium(m, width=1600, height=600) 
@hansthen hansthen requested a review from Conengmo April 6, 2025 19:39
@hansthen hansthen changed the title Add leaflet control Allow users to add new Control classes without implementing a plugin Apr 18, 2025
@hansthen
Copy link
Collaborator Author

hansthen commented Apr 18, 2025

Closes #1992

This was linked to issues Apr 18, 2025
@hansthen hansthen requested a review from ocefpaf April 19, 2025 05:30
@hansthen
Copy link
Collaborator Author

@ocefpaf can you have a look?

control: str
The javascript class name of the control to be rendered.
position: str
One of "bottomright", "bottomleft", "topright", "topleft"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One problem that we have in folium templates are the silent erros when passing keywords to it. For example, if someone types bottonright instead of bottomright, it will take user a while to figure out what is wrong.

Maybe we should check for this 4 valid kw? I know this doesn't solve it for all templates, but in this case it may be small enough that it is worth it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean as a static typing check or as an assert?

Copy link
Member

@ocefpaf ocefpaf Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid assert use outside of tests.

I'm old school but here is what I would do:

  1. make position a kw argument, not an arg;
  2. Sanitize it with a position.lower() to validate names copied from leaflet JS docs;
  3. Check if the sanitized positions is in a valid list with those 4 names and raise a ValueError if not.

What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we have been inconsistent in banning assert :-)

@hansthen hansthen requested a review from ocefpaf April 22, 2025 13:14

if position is not None:
position = position.lower() # type: ignore
if position not in (args := get_args(TypePosition)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I was a Fortran programmer in my early days, type checking is not my forte. (Heck, I moved to Python to get away from this ;-p)

My crude review tells me that this is equivalent to what I described in my review comment, right? If so, merge away!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote my first program for money in RPG :-) which is a fairly obscure language almost as old as Fortran. Whitespace is significant to a fault.

 C* PARAMETER LIST C *ENTRY PLIST C PARM DATEIN 80 C* PROGRAM START C DATEIN DIV 100 DATEIN C MVR DAY 20 C DATEIN DIV 100 DATEIN C MVR MONTH 20 C Z-ADDDATEIN YEAR 40 C* SHOW RESULTS C YEAR DSPLY C MONTH DSPLY C DAY DSPLY C SETON LR C* EXECUTION EXAMPLE C* CALL SEPDATE PARM(X'019960531F') 

I added one more test.

@hansthen hansthen merged commit c1210ce into python-visualization:main Apr 22, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants