@abi-software/flatmap-viewer 2.7.2 → 2.7.3-a.2
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.
- package/dist/assets/index.css +1 -0
- package/dist/index.js +80577 -0
- package/dist/lib/index.d.ts +4 -0
- package/package.json +10 -7
- package/lib/index.ts +0 -10
- package/src/contextmenu.js +0 -97
- package/src/controls/annotation.js +0 -302
- package/src/controls/controls.js +0 -645
- package/src/controls/flightpaths.js +0 -95
- package/src/controls/info.js +0 -291
- package/src/controls/minimap.js +0 -442
- package/src/controls/paths.js +0 -143
- package/src/controls/search.js +0 -113
- package/src/controls/systems.js +0 -75
- package/src/controls/taxons.js +0 -73
- package/src/flatmap-viewer.js +0 -1789
- package/src/images.js +0 -66
- package/src/interactions.js +0 -1569
- package/src/layers/cluster.js +0 -177
- package/src/layers/filter.js +0 -310
- package/src/layers/flightpaths.js +0 -383
- package/src/layers/index.js +0 -478
- package/src/layers/styling.js +0 -1077
- package/src/main.js +0 -272
- package/src/mapserver.js +0 -64
- package/src/mathjax.js +0 -100
- package/src/pathways.js +0 -427
- package/src/search.js +0 -137
- package/src/systems.js +0 -146
- package/src/utils.js +0 -152
- package/static/css/flatmap-viewer.css +0 -238
- package/static/icons/favicon.ico +0 -0
- package/static/images/active.png +0 -0
- package/static/images/inactive.png +0 -0
- package/static/images/reset-map-active.png +0 -0
- package/static/images/reset-map-button.png +0 -0
- package/static/images/rounded-background.png +0 -0
- package/static/images/zoom-in-active.png +0 -0
- package/static/images/zoom-in-button.png +0 -0
- package/static/images/zoom-out-active.png +0 -0
- package/static/images/zoom-out-button.png +0 -0
- package/thirdParty/maplibre-gl-svg/CHANGELOG.md +0 -13
- package/thirdParty/maplibre-gl-svg/LICENSE +0 -21
- package/thirdParty/maplibre-gl-svg/LICENSE.md +0 -21
- package/thirdParty/maplibre-gl-svg/README.md +0 -24
- package/thirdParty/maplibre-gl-svg/assets/Add custom SVG template to template manager.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/All built-in SVG templates as HTML markers.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/All built-in SVG templates as symbols.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/Fill polygon with built-in SVG template.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/HTML Marker with Custom SVG Template.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/HTML Marker with built-in SVG template.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/Line layer with built-in SVG template.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/Load SVG from URL.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/SVG template options.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/Smiley_face_changed.svg +0 -37
- package/thirdParty/maplibre-gl-svg/assets/Symbol layer with built-in SVG template.jpg +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/arrow-up-thin.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/arrow-up.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/car.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/checker-rotated.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/checker.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/circles-spaced.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/circles.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/diagonal-lines-down.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/diagonal-lines-up.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/diagonal-stripes-down.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/diagonal-stripes-up.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/dots.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/flag-triangle.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/flag.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/grid-lines.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/hexagon-rounded-thick.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/hexagon-rounded.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/hexagon-thick.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/hexagon.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-arrow.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-ball-pin.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-circle.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-flat.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-square-cluster.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-square-rounded-cluster.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-square-rounded.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-square.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker-thick.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/marker.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/pin-round.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/pin.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/rotated-grid-lines.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/rotated-grid-stripes.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/rounded-square-thick.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/rounded-square.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/triangle-arrow-left.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/triangle-arrow-up.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/triangle-thick.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/triangle.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/x-fill.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/zig-zag-vertical.png +0 -0
- package/thirdParty/maplibre-gl-svg/assets/image-templates/zig-zag.png +0 -0
- package/thirdParty/maplibre-gl-svg/build/build.js +0 -210
- package/thirdParty/maplibre-gl-svg/dist/maplibre-gl-svg.js +0 -339
- package/thirdParty/maplibre-gl-svg/dist/maplibre-gl-svg.min.js +0 -4
- package/thirdParty/maplibre-gl-svg/docs/docs.md +0 -375
- package/thirdParty/maplibre-gl-svg/examples/Add custom SVG template to template manager.html +0 -101
- package/thirdParty/maplibre-gl-svg/examples/All built-in SVG templates as HTML markers.html +0 -82
- package/thirdParty/maplibre-gl-svg/examples/All built-in SVG templates as symbols.html +0 -124
- package/thirdParty/maplibre-gl-svg/examples/Fill polygon with built-in SVG template.html +0 -94
- package/thirdParty/maplibre-gl-svg/examples/HTML Marker with Custom SVG Template.html +0 -86
- package/thirdParty/maplibre-gl-svg/examples/HTML Marker with built-in SVG template.html +0 -83
- package/thirdParty/maplibre-gl-svg/examples/Line layer with built-in SVG template.html +0 -129
- package/thirdParty/maplibre-gl-svg/examples/Load SVG from URL.html +0 -96
- package/thirdParty/maplibre-gl-svg/examples/SVG template options.html +0 -264
- package/thirdParty/maplibre-gl-svg/examples/Symbol layer with built-in SVG template.html +0 -93
- package/thirdParty/maplibre-gl-svg/index.html +0 -151
- package/thirdParty/maplibre-gl-svg/package-lock.json +0 -5882
- package/thirdParty/maplibre-gl-svg/package.json +0 -49
- package/thirdParty/maplibre-gl-svg/src/SvgManager.ts +0 -186
- package/thirdParty/maplibre-gl-svg/src/SvgTemplateManager.ts +0 -144
- package/thirdParty/maplibre-gl-svg/src/index.ts +0 -4
- package/thirdParty/maplibre-gl-svg/tsconfig.json +0 -31
- package/thirdParty/maplibre-gl-svg/typings/index.d.ts +0 -111
package/src/layers/cluster.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/******************************************************************************
|
|
2
|
-
|
|
3
|
-
Flatmap viewer and annotation tool
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2019 - 2023 David Brooks
|
|
6
|
-
|
|
7
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
-
you may not use this file except in compliance with the License.
|
|
9
|
-
You may obtain a copy of the License at
|
|
10
|
-
|
|
11
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
|
|
13
|
-
Unless required by applicable law or agreed to in writing, software
|
|
14
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
See the License for the specific language governing permissions and
|
|
17
|
-
limitations under the License.
|
|
18
|
-
|
|
19
|
-
******************************************************************************/
|
|
20
|
-
|
|
21
|
-
import {SvgManager, SvgTemplateManager} from '../../thirdParty/maplibre-gl-svg/src'
|
|
22
|
-
|
|
23
|
-
//==============================================================================
|
|
24
|
-
|
|
25
|
-
const markerLargeCircle = `<svg xmlns="http://www.w3.org/2000/svg" width="calc(28 * {scale})" height="calc(39 * {scale})" viewBox="-1 -1 27 42">
|
|
26
|
-
<ellipse style="fill: rgb(0, 0, 0); fill-opacity: 0.2;" cx="12" cy="36" rx="8" ry="4"/>
|
|
27
|
-
<path d="M12.25.25a12.254 12.254 0 0 0-12 12.494c0 6.444 6.488 12.109 11.059 22.564.549 1.256 1.333 1.256 1.882 0
|
|
28
|
-
C17.762 24.853 24.25 19.186 24.25 12.744A12.254 12.254 0 0 0 12.25.25Z"
|
|
29
|
-
style="fill:{color};stroke:{secondaryColor};stroke-width:1"/>
|
|
30
|
-
<circle cx="12.5" cy="12.5" r="9" fill="{secondaryColor}"/>
|
|
31
|
-
<text x="12" y="17.5" style="font-size:14px;fill:#000;text-anchor:middle">{text}</text>
|
|
32
|
-
</svg>`
|
|
33
|
-
|
|
34
|
-
const markerSmallCircle = `<svg xmlns="http://www.w3.org/2000/svg" width="calc(28 * {scale})" height="calc(39 * {scale})" viewBox="-1 -1 27 42">
|
|
35
|
-
<ellipse style="fill: rgb(0, 0, 0); fill-opacity: 0.2;" cx="12" cy="36" rx="8" ry="4"/>
|
|
36
|
-
<path d="M12.25.25a12.254 12.254 0 0 0-12 12.494c0 6.444 6.488 12.109 11.059 22.564.549 1.256 1.333 1.256 1.882 0
|
|
37
|
-
C17.762 24.853 24.25 19.186 24.25 12.744A12.254 12.254 0 0 0 12.25.25Z"
|
|
38
|
-
style="fill:{color};stroke:{secondaryColor};stroke-width:1"/>
|
|
39
|
-
<circle cx="12.5" cy="12.5" r="5" fill="{secondaryColor}"/>
|
|
40
|
-
</svg>`
|
|
41
|
-
|
|
42
|
-
//==============================================================================
|
|
43
|
-
|
|
44
|
-
export async function loadClusterIcons(map)
|
|
45
|
-
{
|
|
46
|
-
SvgTemplateManager.addTemplate('marker-large-circle', markerLargeCircle, false)
|
|
47
|
-
SvgTemplateManager.addTemplate('marker-small-circle', markerSmallCircle, false)
|
|
48
|
-
|
|
49
|
-
const svgManager = new SvgManager(map)
|
|
50
|
-
await svgManager.createFromTemplate('clustered-marker', 'marker-large-circle', '#EE5900', '#fff')
|
|
51
|
-
await svgManager.createFromTemplate('unclustered-marker', 'marker-small-circle', '#005974', '#fff')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
//==============================================================================
|
|
55
|
-
|
|
56
|
-
export class ClusteredMarkerLayer
|
|
57
|
-
{
|
|
58
|
-
#flatmap
|
|
59
|
-
#map
|
|
60
|
-
#points = {
|
|
61
|
-
type: 'FeatureCollection',
|
|
62
|
-
features: []
|
|
63
|
-
}
|
|
64
|
-
#ui
|
|
65
|
-
|
|
66
|
-
constructor(flatmap, ui)
|
|
67
|
-
{
|
|
68
|
-
this.#flatmap = flatmap
|
|
69
|
-
this.#ui = ui
|
|
70
|
-
this.#map = flatmap.map
|
|
71
|
-
|
|
72
|
-
this.#map.addSource('markers', {
|
|
73
|
-
type: 'geojson',
|
|
74
|
-
data: this.#points,
|
|
75
|
-
cluster: true, // Adds the ``point_count`` property to source data
|
|
76
|
-
clusterMaxZoom: 9, // Max zoom to cluster points on
|
|
77
|
-
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
this.#map.addLayer({
|
|
81
|
-
id: 'clustered-markers',
|
|
82
|
-
type: 'symbol',
|
|
83
|
-
source: 'markers',
|
|
84
|
-
filter: ['has', 'point_count'],
|
|
85
|
-
'layout': {
|
|
86
|
-
'icon-image': 'clustered-marker',
|
|
87
|
-
'icon-allow-overlap': true,
|
|
88
|
-
'icon-ignore-placement': true,
|
|
89
|
-
'icon-offset': [0, -17],
|
|
90
|
-
'icon-size': 0.8,
|
|
91
|
-
'text-field': '{point_count_abbreviated}',
|
|
92
|
-
'text-size': 10,
|
|
93
|
-
'text-offset': [0, -1.93]
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
this.#map.addLayer({
|
|
98
|
-
id: 'single-points',
|
|
99
|
-
type: 'symbol',
|
|
100
|
-
source: 'markers',
|
|
101
|
-
filter: ['!', ['has', 'point_count']],
|
|
102
|
-
'layout': {
|
|
103
|
-
'icon-image': 'unclustered-marker',
|
|
104
|
-
'icon-allow-overlap': true,
|
|
105
|
-
'icon-ignore-placement': true,
|
|
106
|
-
'icon-offset': [0, -17],
|
|
107
|
-
'icon-size': 0.6
|
|
108
|
-
}
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
// inspect a cluster on click
|
|
112
|
-
this.#map.on('click', 'clustered-markers', async (e) => {
|
|
113
|
-
const features = this.#map.queryRenderedFeatures(e.point, {
|
|
114
|
-
layers: ['clustered-markers']
|
|
115
|
-
})
|
|
116
|
-
const clusterId = features[0].properties.cluster_id
|
|
117
|
-
const zoom = await this.#map.getSource('markers').getClusterExpansionZoom(clusterId)
|
|
118
|
-
this.#map.easeTo({
|
|
119
|
-
center: features[0].geometry.coordinates,
|
|
120
|
-
zoom
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
this.#map.on('click', 'single-points', this.singleMarkerEvent.bind(this))
|
|
125
|
-
this.#map.on('mouseenter', 'single-points', this.singleMarkerEvent.bind(this))
|
|
126
|
-
this.#map.on('mousemove', 'single-points', this.singleMarkerEvent.bind(this))
|
|
127
|
-
|
|
128
|
-
this.#map.on('mouseenter', 'clustered-markers', () => {
|
|
129
|
-
this.#map.getCanvas().style.cursor = 'pointer'
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
this.#map.on('mouseleave', 'clustered-markers', () => {
|
|
133
|
-
this.#map.getCanvas().style.cursor = ''
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
singleMarkerEvent(event)
|
|
138
|
-
//======================
|
|
139
|
-
{
|
|
140
|
-
const features = this.#map.queryRenderedFeatures(event.point, {
|
|
141
|
-
layers: ['single-points']
|
|
142
|
-
})
|
|
143
|
-
for (const feature of features) {
|
|
144
|
-
const properties = feature.properties
|
|
145
|
-
const position = properties.markerPosition.slice(1, -1).split(',').map(p => +p)
|
|
146
|
-
this.#ui.markerEvent_(event, feature.id, position, properties.models, properties)
|
|
147
|
-
}
|
|
148
|
-
event.originalEvent.stopPropagation()
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
addMarker(id, position, properties={})
|
|
152
|
-
//====================================
|
|
153
|
-
{
|
|
154
|
-
this.#points.features.push({
|
|
155
|
-
type: 'Feature',
|
|
156
|
-
id,
|
|
157
|
-
properties,
|
|
158
|
-
geometry: {
|
|
159
|
-
type: 'Point',
|
|
160
|
-
coordinates: position
|
|
161
|
-
}
|
|
162
|
-
})
|
|
163
|
-
this.#map.getSource('markers')
|
|
164
|
-
.setData(this.#points)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
clearMarkers()
|
|
168
|
-
//============
|
|
169
|
-
{
|
|
170
|
-
this.#points.features = []
|
|
171
|
-
this.#map.getSource('markers')
|
|
172
|
-
.setData(this.#points)
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
//==============================================================================
|
|
177
|
-
|
package/src/layers/filter.js
DELETED
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
/******************************************************************************
|
|
2
|
-
|
|
3
|
-
Flatmap viewer and annotation tool
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2019 - 2024 David Brooks
|
|
6
|
-
|
|
7
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
-
you may not use this file except in compliance with the License.
|
|
9
|
-
You may obtain a copy of the License at
|
|
10
|
-
|
|
11
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
|
|
13
|
-
Unless required by applicable law or agreed to in writing, software
|
|
14
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
See the License for the specific language governing permissions and
|
|
17
|
-
limitations under the License.
|
|
18
|
-
|
|
19
|
-
******************************************************************************/
|
|
20
|
-
|
|
21
|
-
import Set from 'core-js-pure/actual/set'
|
|
22
|
-
|
|
23
|
-
//==============================================================================
|
|
24
|
-
|
|
25
|
-
export class PropertiesFilter
|
|
26
|
-
{
|
|
27
|
-
#filter
|
|
28
|
-
|
|
29
|
-
constructor(filter=true)
|
|
30
|
-
//======================
|
|
31
|
-
{
|
|
32
|
-
if (filter.constructor !== Object) { // We allow boolean values
|
|
33
|
-
this.#filter = filter
|
|
34
|
-
} else {
|
|
35
|
-
this.#filter = Object.assign({}, filter)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
clear()
|
|
40
|
-
//=====
|
|
41
|
-
{
|
|
42
|
-
if (this.#filter !== true) {
|
|
43
|
-
this.#filter = true
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
expand(filter)
|
|
48
|
-
//============
|
|
49
|
-
{
|
|
50
|
-
if (this.#filter === false) {
|
|
51
|
-
this.#filter = filter
|
|
52
|
-
} else if (this.#filter !== true) {
|
|
53
|
-
const copiedFilter = Object.assign({}, filter)
|
|
54
|
-
this.#filter = { "OR": [this.#filter, copiedFilter] }
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
invert()
|
|
59
|
-
//======
|
|
60
|
-
{
|
|
61
|
-
if (this.#filter === false) {
|
|
62
|
-
this.#filter = true
|
|
63
|
-
} else if (this.#filter === true) {
|
|
64
|
-
this.#filter = false
|
|
65
|
-
} else {
|
|
66
|
-
const copiedFilter = Object.assign({}, filter)
|
|
67
|
-
this.#filter = { "NOT": copiedFilter }
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
getFilter()
|
|
72
|
-
//=========
|
|
73
|
-
{
|
|
74
|
-
return this.#filter
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
makeStyleFilter()
|
|
78
|
-
//===============
|
|
79
|
-
{
|
|
80
|
-
return this.#makeStyleFilter(this.#filter)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
match(properties)
|
|
84
|
-
//===============
|
|
85
|
-
{
|
|
86
|
-
return this.#match(properties, this.#filter)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
narrow(filter)
|
|
90
|
-
//============
|
|
91
|
-
{
|
|
92
|
-
if (this.#filter === true) {
|
|
93
|
-
this.#filter = filter
|
|
94
|
-
} else if (this.#filter !== false) {
|
|
95
|
-
const copiedFilter = Object.assign({}, filter)
|
|
96
|
-
this.#filter = { "AND": [this.#filter, copiedFilter] }
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
setFilter(filter)
|
|
101
|
-
//===============
|
|
102
|
-
{
|
|
103
|
-
if (filter.constructor !== Object) {
|
|
104
|
-
this.#filter = filter
|
|
105
|
-
} else {
|
|
106
|
-
this.#filter = Object.assign({}, filter)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
#makeStyleFilter(filter)
|
|
111
|
-
//======================
|
|
112
|
-
{
|
|
113
|
-
if (filter.constructor !== Object) {
|
|
114
|
-
return !!filter
|
|
115
|
-
}
|
|
116
|
-
const styleFilter = []
|
|
117
|
-
for (const [key, expr] of Object.entries(filter)) {
|
|
118
|
-
if (key === 'AND' || key === 'OR') {
|
|
119
|
-
if (Array.isArray(expr) && expr.length >= 2) {
|
|
120
|
-
styleFilter.push((key === 'AND') ? 'all' : 'any',
|
|
121
|
-
...expr.map(e => this.#makeStyleFilter(e)))
|
|
122
|
-
} else {
|
|
123
|
-
console.warn(`makeFilter: Invalid ${key} operands: ${expr}`)
|
|
124
|
-
}
|
|
125
|
-
} else if (key === 'HAS') {
|
|
126
|
-
styleFilter.push('has', expr)
|
|
127
|
-
} else if (key === 'NOT') {
|
|
128
|
-
const filterExpr = this.#makeStyleFilter(expr)
|
|
129
|
-
if (Array.isArray(filterExpr)) {
|
|
130
|
-
if (filterExpr.length === 2 && ['has', '!has'].includes(filterExpr[0])) {
|
|
131
|
-
if (filterExpr[0] === 'has') {
|
|
132
|
-
styleFilter.push('!has', filterExpr[1])
|
|
133
|
-
} else {
|
|
134
|
-
styleFilter.push('has', filterExpr[1])
|
|
135
|
-
}
|
|
136
|
-
} else if (filterExpr.length === 3 && ['==', '!='].includes(filterExpr[0])) {
|
|
137
|
-
if (filterExpr[0] === '==') {
|
|
138
|
-
styleFilter.push('!=', filterExpr[1], filterExpr[2])
|
|
139
|
-
} else {
|
|
140
|
-
styleFilter.push('==', filterExpr[1], filterExpr[2])
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
styleFilter.push('!', filterExpr)
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
styleFilter.push(!filterExpr)
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
if (Array.isArray(expr)) {
|
|
150
|
-
styleFilter.push('any', ...expr.map(e => ['==', key, e]))
|
|
151
|
-
} else {
|
|
152
|
-
styleFilter.push('==', key, expr)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return styleFilter
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
#match(properties, filter)
|
|
160
|
-
//========================
|
|
161
|
-
{
|
|
162
|
-
if (filter.constructor !== Object) {
|
|
163
|
-
return !!filter
|
|
164
|
-
}
|
|
165
|
-
for (const [key, expr] of Object.entries(filter)) {
|
|
166
|
-
let matched = true
|
|
167
|
-
if (key === 'AND' || key === 'OR') {
|
|
168
|
-
if (Array.isArray(expr) && expr.length >= 2) {
|
|
169
|
-
const matches = expr.map(e => this.#match(properties, e))
|
|
170
|
-
matched = (key === 'AND') ? matches.reduce((result, match) => result && match, true)
|
|
171
|
-
: matches.reduce((result, match) => result || match, false)
|
|
172
|
-
} else {
|
|
173
|
-
console.warn(`makeFilter: Invalid ${key} operands: ${expr}`)
|
|
174
|
-
}
|
|
175
|
-
} else if (key === 'HAS') {
|
|
176
|
-
matched = (expr in properties)
|
|
177
|
-
} else if (key === 'NOT') {
|
|
178
|
-
matched = !this.#match(properties, expr)
|
|
179
|
-
} else if (key in properties) {
|
|
180
|
-
const value = properties[key]
|
|
181
|
-
if (Array.isArray(value)) {
|
|
182
|
-
if (Array.isArray(expr)) {
|
|
183
|
-
matched = !(new Set(value).isDisjointFrom(new Set(expr)))
|
|
184
|
-
} else {
|
|
185
|
-
matched = value.includes(expr)
|
|
186
|
-
}
|
|
187
|
-
} else if (Array.isArray(expr)) {
|
|
188
|
-
matched = expr.includes(value)
|
|
189
|
-
} else {
|
|
190
|
-
matched = (value === expr)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
if (!matched) {
|
|
194
|
-
return false
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return true
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//==============================================================================
|
|
202
|
-
|
|
203
|
-
const testProperties = {
|
|
204
|
-
prop: 1,
|
|
205
|
-
prop1: 5,
|
|
206
|
-
prop2: 11,
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function testFilter(filter)
|
|
210
|
-
//=========================
|
|
211
|
-
{
|
|
212
|
-
const featureFilter = new PropertiesFilter(filter)
|
|
213
|
-
console.log(filter, '--->', featureFilter.makeStyleFilter(), featureFilter.match(testProperties))
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function testFilters()
|
|
217
|
-
//====================
|
|
218
|
-
{
|
|
219
|
-
/*
|
|
220
|
-
{ HAS: 'prop' } ---> [ 'has', 'prop' ]
|
|
221
|
-
{ prop: 1 } ---> [ '==', 'prop', 1 ]
|
|
222
|
-
{ NOT: { prop: 1 } } ---> [ '!=', 'prop', 1 ]
|
|
223
|
-
{ NOT: { prop: [ 1, 2 ] } } ---> [ '!', [ 'any', [ '==', 'prop', 1 ], [ '==', 'prop', 2 ] ] ]
|
|
224
|
-
{ OR: [ { prop1: 10 }, { prop2: 11 } ] } ---> [ 'any', [ '==', 'prop1', 10 ], [ '==', 'prop2', 11 ] ]
|
|
225
|
-
{ AND: [ { prop1: 10 }, { prop2: 11 } ] } ---> [ 'all', [ '==', 'prop1', 10 ], [ '==', 'prop2', 11 ] ]
|
|
226
|
-
{ OR: [ { AND: [Array] }, { AND: [Array] } ] } ---> [
|
|
227
|
-
'any',
|
|
228
|
-
[ 'all', [ '!=', 'prop1', 10 ], [ '==', 'prop2', 11 ] ],
|
|
229
|
-
[ 'all', [ '==', 'prop3', 10 ], [ '==', 'prop4', 11 ] ]
|
|
230
|
-
]
|
|
231
|
-
{ NOT: { OR: [ [Object], [Object] ] } } ---> [
|
|
232
|
-
'!',
|
|
233
|
-
[ 'any', [ 'all', [Array], [Array] ], [ 'all', [Array], [Array] ] ]
|
|
234
|
-
]
|
|
235
|
-
*/
|
|
236
|
-
|
|
237
|
-
console.log('test properties', testProperties)
|
|
238
|
-
|
|
239
|
-
testFilter({
|
|
240
|
-
"HAS": "prop"
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
testFilter({
|
|
244
|
-
"prop": 1
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
testFilter({
|
|
248
|
-
"NOT": {
|
|
249
|
-
"prop": 1
|
|
250
|
-
}
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
testFilter({
|
|
254
|
-
"prop": [1, 2]
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
testFilter({
|
|
258
|
-
"NOT": {
|
|
259
|
-
"prop": [1, 2]
|
|
260
|
-
}
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
testFilter({
|
|
264
|
-
"OR": [
|
|
265
|
-
{"prop1": 10},
|
|
266
|
-
{"prop2": 11}
|
|
267
|
-
]
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
testFilter({
|
|
271
|
-
"AND": [
|
|
272
|
-
{"prop1": 10},
|
|
273
|
-
{"prop2": 11}
|
|
274
|
-
]
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
testFilter({
|
|
278
|
-
"OR": [{
|
|
279
|
-
"AND": [
|
|
280
|
-
{ "NOT": {"prop1": 10}},
|
|
281
|
-
{"prop2": 11}
|
|
282
|
-
]}, {
|
|
283
|
-
"AND": [
|
|
284
|
-
{"prop3": 10},
|
|
285
|
-
{"prop4": 11}
|
|
286
|
-
]}
|
|
287
|
-
]
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
testFilter({
|
|
291
|
-
"NOT": {
|
|
292
|
-
"OR": [{
|
|
293
|
-
"AND": [
|
|
294
|
-
{"prop1": 10},
|
|
295
|
-
{"prop2": 11}
|
|
296
|
-
]}, {
|
|
297
|
-
"AND": [
|
|
298
|
-
{"prop3": 10},
|
|
299
|
-
{"prop4": 11}
|
|
300
|
-
]}
|
|
301
|
-
]
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
//==============================================================================
|
|
307
|
-
|
|
308
|
-
//testFilters()
|
|
309
|
-
|
|
310
|
-
//==============================================================================
|