Skip to content

Commit 5c295cc

Browse files
author
Stefan Kuethe
committed
Support mustache templates
1 parent 92830d6 commit 5c295cc

File tree

24 files changed

+430
-95
lines changed

24 files changed

+430
-95
lines changed

examples/standalone/circles.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@
3030

3131
gdf = ol.GeoDataFrame.from_features(features, crs=Projection.MERCATOR)
3232
m = gdf.ol.explore(style=style, controls=[ol.controls.ZoomSliderControl()])
33-
m.add_tooltip(None)
33+
# m.add_default_tooltip()
34+
m.add_tooltip("{{ name }}: {{ pop_max }}")
3435
m.save(preview=True)

examples/standalone/polygons.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
countries = ol.WebGLVectorLayer(source=ol.VectorSource(url=url))
77

88
m = ol.Map(layers=[BasemapLayer.carto(), countries])
9-
m.add_tooltip("name")
9+
m.add_tooltip("{{ name }}")
1010
# m.add_tooltip()
1111
m.add_control(ol.controls.ZoomSliderControl())
1212
m.add_control(ol.controls.InfoBox(

notebooks/layers/Untitled.ipynb

Lines changed: 306 additions & 14 deletions
Large diffs are not rendered by default.

src/openlayers/__future__/elements.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from ..models.view import View as ViewModel
22

3-
class View(object):
3+
4+
class View(object):
45
def __init__(self, center: tuple[float, float], **kwargs) -> None:
56
self._model = ViewModel(**(locals() | kwargs))
67

src/openlayers/anywidget.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import traitlets
77
from anywidget import AnyWidget
88

9-
from .models.controls import ControlT, LayerT
109
from .map import Map
10+
from .models.controls import ControlT, LayerT
1111
from .models.view import View
1212

1313

src/openlayers/basemaps.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from .models.layers import TileLayer
88
from .models.sources import OSM, ImageTileSource
99

10-
1110
# light_all,
1211
# dark_all,
1312
# light_nolabels,

src/openlayers/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from pydantic import BaseModel, ConfigDict
77

8-
from .styles import default_style, FlatStyle
8+
from .styles import FlatStyle, default_style
99

1010
"""
1111
DEFAULT_STYLE = {

src/openlayers/controls.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@
88
ZoomSliderControl,
99
)
1010

11-
__all__ = ["FullScreenControl", "InfoBox", "OverviewMapControl", "ScaleLineControl", "ZoomSliderControl"]
11+
__all__ = [
12+
"FullScreenControl",
13+
"InfoBox",
14+
"OverviewMapControl",
15+
"ScaleLineControl",
16+
"ZoomSliderControl",
17+
]

src/openlayers/express.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
class SimpleLayer(object): ...
22

3+
34
class GeoJSONLayer(object): ...
45

6+
57
class TileLayer(object): ...
68

9+
710
class OSMBaseLayer(object): ...

src/openlayers/geopandas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ def explore(
3131
# Create geojson source
3232
feature_collection = gdf_to_geojson(self._gdf)
3333
source = VectorSource(geojson=feature_collection)
34-
34+
3535
# Create layer
3636
layer_class = WebGLVectorLayer if webgl else VectorLayer
3737
layer = layer_class(id=layer_id, style=style, source=source)
38-
38+
3939
# Initialize map instance add add components
4040
m = MapWidget(**kwargs)
4141
m.add_layer(layer)

src/openlayers/js/openlayers.standalone.js

Lines changed: 63 additions & 54 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/openlayers/layers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
WebGLVectorLayer,
88
)
99

10-
__all__ = ["TileLayer", "VectorLayer","WebGLTileLayer", "WebGLVectorLayer"]
10+
__all__ = ["TileLayer", "VectorLayer", "WebGLTileLayer", "WebGLVectorLayer"]

src/openlayers/map.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .models.view import View
1313
from .styles import FlatStyle
1414

15+
1516
class Map(object):
1617
def __init__(
1718
self,
@@ -60,8 +61,11 @@ def add_control(self, control: ControlT | dict) -> None:
6061
def remove_control(self, control_id: str) -> None:
6162
self.add_call("removeControl", control_id)
6263

63-
def add_tooltip(self, prop: str | None = None) -> None:
64-
self.add_call("addTooltip", prop)
64+
def add_default_tooltip(self) -> None:
65+
self.add_tooltip()
66+
67+
def add_tooltip(self, template: str | None = None) -> None:
68+
self.add_call("addTooltip", template)
6569

6670
def set_layer_style(self, layer_id: str, style: dict | FlatStyle) -> None:
6771
if isinstance(style, FlatStyle):

src/openlayers/models/controls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .layers import LayerT, TileLayer
1010
from .sources import OSM
1111

12+
1213
# -- Base control
1314
class Control(OLBaseModel):
1415
id: str = Field(default_factory=lambda x: str(uuid4()))

src/openlayers/models/layers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
from pydantic import Field, field_validator
77

8+
from ..styles import FlatStyle, default_style
89
from .core import OLBaseModel
910
from .sources import SourceT
10-
from ..styles import FlatStyle, default_style
1111

1212

1313
# --- Base layer

src/openlayers/models/map_options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
class MapOptions(BaseModel):
11-
view: View | None = View() # Field(View(), serialization_alias="viewOptions")
11+
view: View | None = View() # Field(View(), serialization_alias="viewOptions")
1212
controls: list[dict | ControlT] | None = None
1313
layers: list[dict | LayerT] | None = None
1414

src/openlayers/models/view.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ..abstracts import MyBaseModel
44
from .core import OLBaseModel
55

6+
67
class Projection(object):
78
MERCATOR = "EPSG:4326"
89
WEB_MERCATOR = "EPSG:3857"
@@ -11,13 +12,15 @@ class Projection(object):
1112
def from_epsg(code: int) -> str:
1213
return f"EPSG:{code}"
1314

15+
1416
class ViewOptions(MyBaseModel):
1517
center: tuple[float, float] | None = (0, 0)
1618
zoom: float | None = 0
1719
projection: str | None = Projection.WEB_MERCATOR
1820
min_zoom: int | float | None = None
1921
max_zoom: int | float | None = None
2022

23+
2124
class View(OLBaseModel):
2225
center: tuple[float, float] | None = (0, 0)
2326
zoom: float | None = 0

src/openlayers/sources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from .models.sources import (
22
OSM,
33
GeoTIFFSource,
4+
ImageTileSource,
45
Source,
56
SourceT,
67
VectorSource,
7-
ImageTileSource,
88
)
99

1010
__all__ = ["OSM", "GeoTIFFSource", "VectorSource"]

src/openlayers/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import base64
22
from pathlib import Path
33

4+
45
def create_icon_src_from_file(filename: str) -> bytes:
56
with open(filename, "rb") as f:
6-
encoded_image = base64.b64encode(f.read()).decode('utf-8')
7+
encoded_image = base64.b64encode(f.read()).decode("utf-8")
78

89
image_type = Path(filename).suffix.replace(".", "")
910
return f"data:image/{image_type};base64," + encoded_image

src/openlayers/view.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from.models.view import View, Projection
2-
1+
from .models.view import Projection, View
2+
33
__all__ = ["Projection", "View"]

srcjs/ipywidget-ts/map.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export default class MapWidget {
197197
}
198198

199199
// ...
200-
addTooltip(prop: string | null): void {
201-
addTooltip2(this._map, prop);
200+
addTooltip(template: string | null): void {
201+
addTooltip2(this._map, template);
202202
}
203203
}

srcjs/ipywidget-ts/tooltip2.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { Map } from "ol";
55
import type { FeatureLike } from "ol/Feature";
66
import type { Pixel } from "ol/pixel";
77

8+
import mustache from "mustache";
9+
810
import { getFeatureProperties } from "./utils";
911

1012
/*
@@ -42,15 +44,15 @@ info.style.left = "50%";
4244
info.style.visibility = "hidden";
4345
info.style.pointerEvents = "none";
4446

45-
function renderFeatureProperties(feature: FeatureLike, prop: string | null): string {
46-
if (prop)
47-
return feature.get(prop);
48-
47+
function renderFeatureProperties(feature: FeatureLike, template: string | null): string {
4948
const properties = getFeatureProperties(feature);
49+
if (template)
50+
return mustache.render(template, properties);
51+
5052
return Object.keys(properties).map((key) => `${key}: ${properties[key]}`).join("</br>");
5153
}
5254

53-
function addTooltip2(map: Map, prop: string | null): void {
55+
function addTooltip2(map: Map, template: string | null): void {
5456
info.id = "ol-tooltip";
5557
map.getTargetElement().appendChild(info);
5658
console.log("tooltip element added", info);
@@ -69,7 +71,7 @@ function addTooltip2(map: Map, prop: string | null): void {
6971
info.style.top = pixel[1] + 'px';
7072
if (feature !== currentFeature) {
7173
info.style.visibility = 'visible';
72-
info.innerHTML = renderFeatureProperties(feature, prop);
74+
info.innerHTML = renderFeatureProperties(feature, template);
7375
}
7476
} else {
7577
info.style.visibility = 'hidden';

srcjs/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

srcjs/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
},
1717
"devDependencies": {
1818
"@anywidget/types": "^0.2.0",
19+
"@types/mustache": "^4.2.5",
1920
"esbuild": "^0.25.2",
2021
"prettier": "^3.5.3",
2122
"typescript": "^5.8.3",
2223
"vite": "^6.2.4"
2324
},
2425
"dependencies": {
26+
"mustache": "^4.2.0",
2527
"ol": "latest"
2628
}
27-
}
29+
}

0 commit comments

Comments
 (0)