bh 6.9.1 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/app/javascript/bh/combobox/menu.js +1 -1
- data/app/javascript/bh/map_controller.js +32 -11
- data/lib/bh/version.rb +1 -1
- data/public/bh/js/bh.js +15 -15
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 323e18fad01eb3fdc146019166fdec96ecc7455a12b2ce170525ee07d5083c47
|
|
4
|
+
data.tar.gz: c6050641e6910669ef9b645b55cae1141f94370e9a3167ddd93937c4f28274eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 901c770b2d53376cd82a3ccf7f0e09c3499f26415d3f10dc896488b483b344cfd6cef5d3eed869174337945338c3b79fc6c38e36f5ce02273d5ba6caad06a35a
|
|
7
|
+
data.tar.gz: 15f84dd6790385a89d6d8ca6b9fcceab7168ce0c8dcae1a63cc24e749c282a782d18f118f86a0e1fc85ee4ca94c2ec8d4d4634110abba83b839eca32f7da14bc
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,24 @@ For more information about changelogs, check
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## 6.10.0 - 2026-09-26
|
|
12
|
+
|
|
13
|
+
* [FEATURE] A pin or an area on a map leads where its row does
|
|
14
|
+
|
|
15
|
+
The map controller takes a point as `[lat, lng, href, title]` and a place as
|
|
16
|
+
`[id, href, title]`. A pin with an `href` is clickable, shows its `title` on hover, and a
|
|
17
|
+
click follows it through Turbo; an area filled on a boundary layer is followed the same
|
|
18
|
+
way. A bare `[lat, lng]` or a bare place ID still draws a pin that leads nowhere.
|
|
19
|
+
|
|
20
|
+
## 6.9.2 - 2026-09-20
|
|
21
|
+
|
|
22
|
+
* [FIX] A small select's combobox is small too
|
|
23
|
+
|
|
24
|
+
The button that stands in for a `<select>` took the compact size from `form-select-sm`
|
|
25
|
+
alone, so a select wearing `form-control-sm` — which is what a filter beside a search
|
|
26
|
+
box wears — was replaced by a full-height one. It stood two pixels taller than the trail
|
|
27
|
+
beside it, which is what set the height of every row it sat in.
|
|
28
|
+
|
|
11
29
|
## 6.9.1 - 2026-09-20
|
|
12
30
|
|
|
13
31
|
* [FIX] A combobox's search box carries an id
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// The toggle takes the select's size and its error, and is labelled the way the select was.
|
|
6
6
|
export function menuFor(select, controller) {
|
|
7
7
|
const toggle = element('button', 'form-control combobox-toggle', { type: 'button' })
|
|
8
|
-
if (
|
|
8
|
+
if (['form-select-sm', 'form-control-sm'].some(size => select.classList.contains(size))) { toggle.classList.add('form-control-sm') }
|
|
9
9
|
if (select.classList.contains('is-invalid')) { toggle.classList.add('is-invalid') }
|
|
10
10
|
toggle.dataset.bsToggle = 'combobox'
|
|
11
11
|
toggle.dataset.bsSearch = 'true'
|
|
@@ -6,6 +6,11 @@ import { load } from './map/loader.js'
|
|
|
6
6
|
// none, a pin at the place; a row keeping coordinates is a pin there and then, with
|
|
7
7
|
// nothing to look up. The key and the map are the host's, read from its credentials; the
|
|
8
8
|
// rows are the page's, and the map is fitted round whatever it drew.
|
|
9
|
+
//
|
|
10
|
+
// A row may carry where it leads and what it is called: a point as `[lat, lng, href, title]`,
|
|
11
|
+
// a place as `[id, href, title]`, where a bare place ID or a bare `[lat, lng]` leads nowhere.
|
|
12
|
+
// A pin or an area with somewhere to lead is clicked through to it, the way the row's own
|
|
13
|
+
// link in the table is.
|
|
9
14
|
export default class extends Controller {
|
|
10
15
|
static values = { key: String, id: String, boundary: String, places: Array, points: Array }
|
|
11
16
|
|
|
@@ -30,7 +35,8 @@ export default class extends Controller {
|
|
|
30
35
|
async place(map, bounds) {
|
|
31
36
|
if (this.placesValue.length === 0) return
|
|
32
37
|
const { Place } = await google.maps.importLibrary('places')
|
|
33
|
-
const
|
|
38
|
+
const rows = this.placesValue.map(row => [].concat(row))
|
|
39
|
+
const places = rows.map(([id, href, title]) => ({ place: new Place({ id }), href, title }))
|
|
34
40
|
|
|
35
41
|
if (this.hasBoundaryValue) return this.fill(map, bounds, places)
|
|
36
42
|
return this.pin(map, bounds, places)
|
|
@@ -38,13 +44,19 @@ export default class extends Controller {
|
|
|
38
44
|
|
|
39
45
|
// The layer styles every boundary Google knows at that level, and a function saying
|
|
40
46
|
// which of them are ours is what fills them in. The bounds are the places' viewports.
|
|
47
|
+
// An area with somewhere to lead is followed there when clicked.
|
|
41
48
|
async fill(map, bounds, places) {
|
|
42
|
-
const
|
|
43
|
-
map.getFeatureLayer(this.boundaryValue)
|
|
44
|
-
|
|
49
|
+
const hrefs = new Map(places.map(({ place, href }) => [place.id, href]))
|
|
50
|
+
const layer = map.getFeatureLayer(this.boundaryValue)
|
|
51
|
+
layer.style = ({ feature }) => {
|
|
52
|
+
if (hrefs.has(feature.placeId)) return FILLED
|
|
45
53
|
}
|
|
54
|
+
layer.addListener('click', ({ features }) => {
|
|
55
|
+
const href = features.map(feature => hrefs.get(feature.placeId)).find(Boolean)
|
|
56
|
+
if (href) visit(href)
|
|
57
|
+
})
|
|
46
58
|
|
|
47
|
-
await Promise.all(places.map(place =>
|
|
59
|
+
await Promise.all(places.map(({ place }) =>
|
|
48
60
|
fetched(place, 'viewport').then(() => { if (place.viewport) bounds.union(place.viewport) })
|
|
49
61
|
))
|
|
50
62
|
}
|
|
@@ -52,8 +64,8 @@ export default class extends Controller {
|
|
|
52
64
|
async pin(map, bounds, places) {
|
|
53
65
|
const drop = await this.dropper(map, bounds)
|
|
54
66
|
|
|
55
|
-
await Promise.all(places.map(place =>
|
|
56
|
-
fetched(place, 'location').then(() => { if (place.location) drop(place.location) })
|
|
67
|
+
await Promise.all(places.map(({ place, href, title }) =>
|
|
68
|
+
fetched(place, 'location').then(() => { if (place.location) drop(place.location, href, title) })
|
|
57
69
|
))
|
|
58
70
|
}
|
|
59
71
|
|
|
@@ -62,20 +74,29 @@ export default class extends Controller {
|
|
|
62
74
|
if (this.pointsValue.length === 0) return
|
|
63
75
|
const drop = await this.dropper(map, bounds)
|
|
64
76
|
|
|
65
|
-
for (const [lat, lng] of this.pointsValue) drop({ lat, lng })
|
|
77
|
+
for (const [lat, lng, href, title] of this.pointsValue) drop({ lat, lng }, href, title)
|
|
66
78
|
}
|
|
67
79
|
|
|
68
|
-
// One marker at a position, and the bounds widened to hold it.
|
|
80
|
+
// One marker at a position, and the bounds widened to hold it. A marker with somewhere to
|
|
81
|
+
// lead is clickable, names what it leads to on hover, and is followed there when clicked.
|
|
69
82
|
async dropper(map, bounds) {
|
|
70
83
|
const { AdvancedMarkerElement } = await google.maps.importLibrary('marker')
|
|
71
84
|
|
|
72
|
-
return (position) => {
|
|
73
|
-
new AdvancedMarkerElement({ map, position })
|
|
85
|
+
return (position, href, title) => {
|
|
86
|
+
const marker = new AdvancedMarkerElement({ map, position, title, gmpClickable: Boolean(href) })
|
|
87
|
+
if (href) marker.addEventListener('gmp-click', () => visit(href))
|
|
74
88
|
bounds.extend(position)
|
|
75
89
|
}
|
|
76
90
|
}
|
|
77
91
|
}
|
|
78
92
|
|
|
93
|
+
// Through Turbo where the page has it, so the table's frame and scroll behave as a click on
|
|
94
|
+
// the row's own link would; a plain navigation otherwise.
|
|
95
|
+
function visit(href) {
|
|
96
|
+
if (window.Turbo) window.Turbo.visit(href)
|
|
97
|
+
else window.location.assign(href)
|
|
98
|
+
}
|
|
99
|
+
|
|
79
100
|
// A place that cannot be fetched — an ID Google no longer knows — is left off the map
|
|
80
101
|
// rather than taking the rest of the page's rows with it.
|
|
81
102
|
function fetched(place, field) {
|
data/lib/bh/version.rb
CHANGED