Skip to content

Commit

Permalink
Override css and js links (python-visualization#1898)
Browse files Browse the repository at this point in the history
* Re: python-visualization#1519 Override css and js links

Add a method to the JSCSSMixin that allows users
to override a specific link to css or js. Unfortunately
this still requires users to know the name of the
of the link, which will require looking at the code
or introspection.

* Update to also add links when not already present

Also added a method to bulk add several links in one call.

* Updated after review comments

* Update folium/elements.py

Co-authored-by: Frank Anema <[email protected]>

* Add documentation on overriding css and js links

---------

Co-authored-by: Frank Anema <[email protected]>
  • Loading branch information
hansthen and Conengmo authored Apr 4, 2024
1 parent aa13026 commit 5c2f3d1
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/advanced_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ Advanced guide
advanced_guide/custom_tiles
advanced_guide/piechart_icons
advanced_guide/polygons_from_list_of_points
advanced_guide/customize_javascript_and_css
79 changes: 79 additions & 0 deletions docs/advanced_guide/customize_javascript_and_css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Customizing javascript or css resources

```{code-cell} ipython3
---
nbsphinx: hidden
---
import folium
```

## Adding javascript or css resources
Many leaflet resources require loading of custom css or javascript modules. This is handled in the `folium.elements.JSCSSMixin` class. Anything that inherits from this class can load custom resources.

You can use the methods `add_js_link` and `add_css_link` to ensure these resources are loaded into the map.

### Example 1: overriding the locations from where resources are loaded
One use case is to override the locations from where resources are loaded. This can be useful if you have to use a private CDN for your javascript and css resources, or if you want to use a different version.

```{code-cell}
m = folium.Map()
m.add_css_link(
"bootstrap_css",
"https://example.com/bootstrap/400.5.0/css/bootstrap.min.css"
)
```


### Example 2: loading additional javascript
A second use case is to load library modules that you can then use inside JsCode blocks. Continuing from the Realtime ISS example, see :doc:Realtime <user_guide/plugins/realtime>, we can modify this so that it uses the dayjs library to format the current date.

```{code-cell} ipython3
from folium.utilities import JsCode
from folium.plugins import Realtime
m = folium.Map()
on_each_feature = JsCode("""
function(f, l) {
l.bindPopup(function() {
return '<h5>' + dayjs.unix(f.properties.timestamp).format() + '</h5>';
});
}
""")
source = JsCode("""
function(responseHandler, errorHandler) {
var url = 'https://api.wheretheiss.at/v1/satellites/25544';
fetch(url)
.then((response) => {
return response.json().then((data) => {
var { id, timestamp, longitude, latitude } = data;
return {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [longitude, latitude]
},
'properties': {
'id': id,
'timestamp': timestamp
}
}]
};
})
})
.then(responseHandler)
.catch(errorHandler);
}
""")
rt = Realtime(source,
on_each_feature=on_each_feature,
interval=1000)
rt.add_js_link("dayjs", "https://cdn.jsdelivr.net/npm/[email protected]/dayjs.min.js")
rt.add_to(m)
m
```
21 changes: 21 additions & 0 deletions folium/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@ def render(self, **kwargs) -> None:

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 ElementAddToElement(MacroElement):
"""Abstract class to add an element to another element."""
Expand Down

0 comments on commit 5c2f3d1

Please sign in to comment.