Skip to content

Commit 2d87e1b

Browse files
Onclick (#35)
* oncilck draft * take off unused importes * Update Playwright Snapshots * Update Playwright Snapshots * Update output path for documentation widget bundle * updated .gitignore * Update Playwright Snapshots --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 9a8d04e commit 2d87e1b

10 files changed

+80
-19
lines changed

.gitignore

+2-6
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ instance/
6262
# Sphinx documentation
6363
docs/_build/
6464
docs/_static/
65-
docs/_static/embed-bundle.js
66-
docs/_static/embed-bundle.js.map
6765
docs/build
6866
docs/output
6967
docs/jupyter_execute
@@ -133,6 +131,8 @@ ehthumbs.db
133131
# Folder config file
134132
Desktop.ini
135133
.config.ini
134+
.env.ini
135+
136136

137137
# Recycle Bin used on file shares
138138
$RECYCLE.BIN/
@@ -167,9 +167,5 @@ ipyopenlayers/nbextension
167167

168168

169169
.yarn
170-
.vscode/
171-
172170
#jupyter lite
173171
.jupyterlite.doit.db
174-
lite_build_output/dist
175-
lite_build_output/.jupyterlite.doit.db

examples/GeojsonLayer.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@
466466
"name": "python",
467467
"nbconvert_exporter": "python",
468468
"pygments_lexer": "ipython3",
469-
"version": "3.9.19"
469+
"version": "3.12.4"
470470
}
471471
},
472472
"nbformat": 4,

examples/RasterLayer.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
"name": "python",
111111
"nbconvert_exporter": "python",
112112
"pygments_lexer": "ipython3",
113-
"version": "3.9.19"
113+
"version": "3.12.4"
114114
}
115115
},
116116
"nbformat": 4,

examples/map.ipynb

+43-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
{
1212
"cell_type": "code",
13-
"execution_count": 1,
13+
"execution_count": 7,
1414
"id": "94284d6e",
1515
"metadata": {
1616
"vscode": {
@@ -21,15 +21,15 @@
2121
{
2222
"data": {
2323
"application/vnd.jupyter.widget-view+json": {
24-
"model_id": "cf72e462ac2847b586c82d5738e01598",
24+
"model_id": "2fe473c94493460082701df614ff2268",
2525
"version_major": 2,
2626
"version_minor": 0
2727
},
2828
"text/plain": [
29-
"Map(center=[0.0, 0.0], layers=[RasterTileLayer()])"
29+
"Map(center=[0.0, 0.0], zoom=2.0)"
3030
]
3131
},
32-
"execution_count": 1,
32+
"execution_count": 7,
3333
"metadata": {},
3434
"output_type": "execute_result"
3535
}
@@ -38,6 +38,10 @@
3838
"from ipyopenlayers import (\n",
3939
" Map, RasterTileLayer\n",
4040
")\n",
41+
"import configparser\n",
42+
"import requests\n",
43+
"import unicodedata\n",
44+
"\n",
4145
"m = Map(center=[0.0, 0.0], zoom=2)\n",
4246
"layer= RasterTileLayer()\n",
4347
"m.add_layer(layer)\n",
@@ -46,11 +50,43 @@
4650
},
4751
{
4852
"cell_type": "code",
49-
"execution_count": null,
53+
"execution_count": 8,
5054
"id": "6ecd0ff6-93f3-4cd8-bc0a-8520aab07a84",
5155
"metadata": {},
5256
"outputs": [],
53-
"source": []
57+
"source": [
58+
"config = configparser.ConfigParser()\n",
59+
"config.read('../.env.ini')\n",
60+
"api_key = config['DEFAULT']['api_key']"
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": 9,
66+
"id": "c2a997b5-3f80-4e9c-8956-5dba704f7eae",
67+
"metadata": {},
68+
"outputs": [],
69+
"source": [
70+
"def get_country_from_coordinates_geoapify(**kwargs):\n",
71+
" lon = kwargs.get('lon')\n",
72+
" lat = kwargs.get('lat')\n",
73+
" url = f\"https://api.geoapify.com/v1/geocode/reverse?lat={lat}&lon={lon}&apiKey={api_key}\"\n",
74+
" \n",
75+
" response = requests.get(url)\n",
76+
" data = response.json()\n",
77+
" \n",
78+
" features = data.get('features', [])\n",
79+
" if features:\n",
80+
" first_feature = features[0]\n",
81+
" properties = first_feature.get('properties', {})\n",
82+
" country = properties.get('country', None)\n",
83+
" normalized_name = country.split(' ')[0]\n",
84+
" normalized_name = unicodedata.normalize('NFKD', normalized_name)\n",
85+
" normalized_name = normalized_name.encode('ASCII', 'ignore').decode('utf-8')\n",
86+
" print(f\"Country: {normalized_name}\")\n",
87+
"\n",
88+
"m.on_click(get_country_from_coordinates_geoapify)"
89+
]
5490
}
5591
],
5692
"metadata": {
@@ -69,7 +105,7 @@
69105
"name": "python",
70106
"nbconvert_exporter": "python",
71107
"pygments_lexer": "ipython3",
72-
"version": "3.9.19"
108+
"version": "3.12.4"
73109
}
74110
},
75111
"nbformat": 4,

ipyopenlayers/openlayers.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright (c) QuantStack.
55
# Distributed under the terms of the Modified BSD License.
66

7-
from ipywidgets import DOMWidget, Widget, widget_serialization
7+
from ipywidgets import DOMWidget, Widget, widget_serialization, CallbackDispatcher
88
from traitlets import Unicode, List, Instance, CFloat, Bool, Dict, Int, Float
99
from ._frontend import module_name, module_version
1010

@@ -43,7 +43,7 @@ class TileLayer(Layer):
4343
Additional format options for the tile source.
4444
"""
4545

46-
url = Unicode('').tag(sync=True)
46+
url = Unicode('https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png').tag(sync=True)
4747
attribution = Unicode("").tag(sync=True)
4848
opacity = Float(1.0, min=0.0, max=1.0).tag(sync=True)
4949
visible = Bool(True).tag(sync=True)
@@ -263,6 +263,8 @@ class Map(DOMWidget):
263263
layers = List(Instance(Layer)).tag(sync=True, **widget_serialization)
264264
overlays=List(Instance(BaseOverlay)).tag(sync=True, **widget_serialization)
265265
controls=List(Instance(BaseControl)).tag(sync=True, **widget_serialization)
266+
_click_callbacks = Instance(CallbackDispatcher, ())
267+
266268

267269

268270

@@ -277,6 +279,7 @@ def __init__(self, center=None, zoom=None, **kwargs):
277279
The initial zoom level of the map.
278280
"""
279281
super().__init__(**kwargs)
282+
self.on_msg(self._handle_mouse_events)
280283
if center is not None:
281284
self.center = center
282285
if zoom is not None:
@@ -351,4 +354,19 @@ def clear_layers(self):
351354
"""Remove all layers from the map.
352355
353356
"""
354-
self.layers = []
357+
self.layers = []
358+
359+
def _handle_mouse_events(self, _, content, buffers):
360+
"""Handle mouse events and trigger click callbacks.
361+
"""
362+
event_type = content.get("type", "")
363+
if event_type == "click":
364+
self._click_callbacks(**content)
365+
366+
def on_click(self, callback, remove=False):
367+
"""Add a click event listener.
368+
"""
369+
self._click_callbacks.register_callback(callback, remove=remove)
370+
371+
372+

src/widget.ts

+11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { BaseOverlayModel, BaseOverlayView } from './baseoverlay';
1212
import { BaseControlModel, BaseControlView } from './basecontrol';
1313
import { ViewObjectEventTypes } from 'ol/View';
1414
import TileLayer from 'ol/layer/Tile';
15+
import MapBrowserEvent from 'ol/MapBrowserEvent';
1516
import { Map } from 'ol';
1617
import View from 'ol/View';
1718
import 'ol/ol.css';
@@ -122,6 +123,10 @@ export class MapView extends DOMWidgetView {
122123
],
123124
});
124125

126+
this.map.on('click', (event: MapBrowserEvent<MouseEvent>) => {
127+
this.handleMapClick(event);
128+
});
129+
125130
this.map.getView().on('change:center', () => {
126131
this.model.set('center', this.map.getView().getCenter());
127132
this.model.save_changes();
@@ -143,6 +148,12 @@ export class MapView extends DOMWidgetView {
143148
this.model.on('change:zoom', this.zoomChanged, this);
144149
this.model.on('change:center', this.centerChanged, this);
145150
}
151+
152+
handleMapClick(event: MapBrowserEvent<MouseEvent>) {
153+
const coordinate = event.coordinate;
154+
const [lon, lat] = coordinate;
155+
this.send({ type: 'click', lon, lat });
156+
}
146157
layersChanged() {
147158
const layers = this.model.get('layers') as LayerModel[];
148159
this.layerViews.update(layers);
Loading

webpack.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ module.exports = [
7575
entry: './src/index.ts',
7676
output: {
7777
filename: 'embed-bundle.js',
78-
path: path.resolve(__dirname, 'docs', 'source', '_static'),
78+
path: path.resolve(__dirname, 'docs', '_static'),
7979
library: 'ipyopenlayers',
8080
libraryTarget: 'amd',
8181
},

0 commit comments

Comments
 (0)