@abi-software/flatmap-viewer 2.3.0-b.1 → 2.3.1-b.1

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.
@@ -34,14 +34,16 @@ import polylabel from 'polylabel';
34
34
  //==============================================================================
35
35
 
36
36
  import {Annotator} from './annotation';
37
- import {displayedProperties, InfoControl} from './info';
38
37
  import {LayerManager} from './layers';
39
38
  import {PATHWAYS_LAYER, Pathways} from './pathways';
39
+ import {COLOUR_ERROR, VECTOR_TILES_SOURCE} from './styling';
40
+ import {SystemsManager} from './systems';
41
+
42
+ import {displayedProperties, InfoControl} from './controls/info';
40
43
  import {BackgroundControl, LayerControl, NerveControl,
41
- PathControl, SCKANControl} from './controls';
42
- import {SearchControl} from './search';
43
- import {VECTOR_TILES_SOURCE} from './styling';
44
- import {SystemsControl, SystemsManager} from './systems';
44
+ PathControl, SCKANControl} from './controls/controls';
45
+ import {SearchControl} from './controls/search';
46
+ import {SystemsControl} from './controls/systems';
45
47
 
46
48
  import * as pathways from './pathways';
47
49
  import * as utils from './utils';
@@ -102,8 +104,6 @@ export class UserInteractions
102
104
  this._infoControl = null;
103
105
  this._tooltip = null;
104
106
 
105
- this._disabledPathFeatures = false;
106
-
107
107
  this._inQuery = false;
108
108
  this._modal = false;
109
109
 
@@ -144,25 +144,16 @@ export class UserInteractions
144
144
  }
145
145
  }
146
146
 
147
- this.__featureIdToMapId = new Map();
148
- this.__setupAnnotation();
147
+ // Add annotation capability
148
+ if (flatmap.options.annotator) {
149
+ this.__setupAnnotation();
150
+ } else {
151
+ this.__annotator = null;
152
+ }
149
153
 
150
154
  // Note features that are FC systems
151
155
 
152
- this.__systems = new Map();
153
- for (const [id, ann] of this._flatmap.annotations) {
154
- if (ann['fc-class'] === 'fc-class:System') {
155
- if (this.__systems.has(ann.name)) {
156
- this.__systems.get(ann.name).featureIds.push(ann.featureId)
157
- } else {
158
- this.__systems.set(ann.name, {
159
- id: ann.name.replaceAll(' ', '_'),
160
- colour: ann.colour,
161
- featureIds: [ ann.featureId ]
162
- });
163
- }
164
- }
165
- }
156
+ this.__systemsManager = new SystemsManager(this._flatmap, this);
166
157
 
167
158
  // Add various controls when running standalone
168
159
 
@@ -191,7 +182,7 @@ export class UserInteractions
191
182
 
192
183
  // SCKAN path and SYSTEMS controls for FC maps
193
184
  if (flatmap.options.style === 'functional') {
194
- this._map.addControl(new SystemsControl(flatmap, this.__systems));
185
+ this._map.addControl(new SystemsControl(flatmap, this.__systemsManager.systems));
195
186
  this._map.addControl(new SCKANControl(flatmap, flatmap.options.layerOptions));
196
187
  }
197
188
  }
@@ -254,14 +245,14 @@ export class UserInteractions
254
245
  {
255
246
  // Add annotation capability
256
247
 
257
- this.__annotator = new Annotator(this._flatmap);
248
+ this.__annotator = new Annotator(this._flatmap, this);
258
249
  const annotated_features = await this.__annotator.annotated_features();
259
250
 
260
251
  // Flag features that have annotations
261
-
252
+ this.__featureIdToMapId = new Map();
262
253
  for (const [mapId, ann] of this._flatmap.annotations) {
263
254
  this.__featureIdToMapId.set(ann.id, mapId);
264
- const feature = this.mapFeature_(mapId);
255
+ const feature = this.mapFeature(mapId);
265
256
  if (feature !== undefined) {
266
257
  this._map.setFeatureState(feature, { 'map-annotation': true });
267
258
  if (annotated_features.indexOf(ann.id) >= 0) {
@@ -274,11 +265,13 @@ export class UserInteractions
274
265
  setFeatureAnnotated(featureId)
275
266
  //============================
276
267
  {
277
- // featureId v's geoJSON id
278
- const mapId = this.__featureIdToMapId.get(featureId);
279
- const feature = this.mapFeature_(mapId);
280
- if (feature !== undefined) {
281
- this._map.setFeatureState(feature, { 'annotated': true });
268
+ if (this.__annotator) {
269
+ // featureId v's geoJSON id
270
+ const mapId = this.__featureIdToMapId.get(featureId);
271
+ const feature = this.mapFeature(mapId);
272
+ if (feature !== undefined) {
273
+ this._map.setFeatureState(feature, { 'annotated': true });
274
+ }
282
275
  }
283
276
  }
284
277
 
@@ -304,34 +297,35 @@ export class UserInteractions
304
297
  getSystems()
305
298
  //==========
306
299
  {
307
- const systems = [];
308
- for (const system of this.__systems.values()) {
309
- systems.push({
310
- name: system.name,
311
- colour: system.colour,
312
- });
313
- }
314
- return systems;
300
+ return this.__systemsManager.systems;
315
301
  }
316
302
 
317
303
  enableSystem(systemName, enable=true)
318
304
  //===================================
319
305
  {
320
- if (this.__systems.has(systemName)) {
321
- for (const featureId of this.__systems.get(systemName).featureIds) {
322
- this.__enableFeatureWithChildren(featureId, enable);
306
+ this.__systemsManager.enable(systemName, enable);
307
+ }
308
+
309
+ enableFeatureWithChildren(featureId, enable=true)
310
+ //===============================================
311
+ {
312
+ const feature = this.mapFeature(featureId);
313
+ if (feature !== undefined) {
314
+ this.enableFeature(feature, enable);
315
+ for (const childFeatureId of feature.children) {
316
+ this.enableFeatureWithChildren(childFeatureId, enable);
323
317
  }
324
318
  }
325
319
  }
326
320
 
327
- __enableFeatureWithChildren(featureId, enable=true)
328
- //=================================================
321
+ __enableFeatureWithParents(featureId, enable=true)
322
+ //================================================
329
323
  {
330
- const feature = this.mapFeature_(featureId);
324
+ const feature = this.mapFeature(featureId);
331
325
  if (feature !== undefined) {
332
- this.__enableFeature(feature, enable);
333
- for (const childFeatureId of feature.children) {
334
- this.__enableFeatureWithChildren(childFeatureId, enable);
326
+ this.enableFeature(feature, enable);
327
+ for (const childFeatureId of feature.parents) {
328
+ this.__enableFeatureWithParents(childFeatureId, enable);
335
329
  }
336
330
  }
337
331
  }
@@ -348,8 +342,8 @@ export class UserInteractions
348
342
  }
349
343
  }
350
344
 
351
- __enableFeature(feature, enable=true)
352
- //===================================
345
+ enableFeature(feature, enable=true)
346
+ //=================================
353
347
  {
354
348
  if (feature !== undefined) {
355
349
  if (enable) {
@@ -361,8 +355,16 @@ export class UserInteractions
361
355
  }
362
356
  }
363
357
 
364
- mapFeature_(featureId)
365
- //====================
358
+ __featureEnabled(feature)
359
+ //=======================
360
+ {
361
+ const state = this._map.getFeatureState(feature);
362
+ return (state !== undefined
363
+ && (!('hidden' in state) || !state.hidden));
364
+ }
365
+
366
+ mapFeature(featureId)
367
+ //===================
366
368
  {
367
369
  const ann = this._flatmap.annotation(featureId);
368
370
  if (ann !== undefined) {
@@ -384,8 +386,8 @@ export class UserInteractions
384
386
  return this._selectedFeatureIds.has(+featureId);
385
387
  }
386
388
 
387
- selectFeature_(featureId, dim=true)
388
- //=================================
389
+ selectFeature(featureId, dim=true)
390
+ //================================
389
391
  {
390
392
  featureId = +featureId; // Ensure numeric
391
393
  if (this._selectedFeatureIds.size === 0) {
@@ -394,7 +396,7 @@ export class UserInteractions
394
396
  if (this._selectedFeatureIds.has(featureId)) {
395
397
  this._selectedFeatureIds.set(featureId, this._selectedFeatureIds.get(featureId) + 1);
396
398
  } else {
397
- const feature = this.mapFeature_(featureId);
399
+ const feature = this.mapFeature(featureId);
398
400
  if (feature !== undefined) {
399
401
  this._map.setFeatureState(feature, { 'selected': true });
400
402
  this._selectedFeatureIds.set(featureId, 1);
@@ -402,8 +404,8 @@ export class UserInteractions
402
404
  }
403
405
  }
404
406
 
405
- unselectFeature_(featureId)
406
- //=========================
407
+ unselectFeature(featureId)
408
+ //========================
407
409
  {
408
410
  featureId = +featureId; // Ensure numeric
409
411
  if (this._selectedFeatureIds.has(featureId)) {
@@ -411,7 +413,7 @@ export class UserInteractions
411
413
  if (references > 1) {
412
414
  this._selectedFeatureIds.set(featureId, references - 1);
413
415
  } else {
414
- const feature = this.mapFeature_(featureId);
416
+ const feature = this.mapFeature(featureId);
415
417
  if (feature !== undefined) {
416
418
  this._map.removeFeatureState(feature, 'selected');
417
419
  this._selectedFeatureIds.delete(+featureId);
@@ -423,11 +425,11 @@ export class UserInteractions
423
425
  }
424
426
  }
425
427
 
426
- __unselectFeatures()
427
- //==================
428
+ unselectFeatures()
429
+ //================
428
430
  {
429
431
  for (const featureId of this._selectedFeatureIds.keys()) {
430
- const feature = this.mapFeature_(featureId);
432
+ const feature = this.mapFeature(featureId);
431
433
  if (feature !== undefined) {
432
434
  this._map.removeFeatureState(feature, 'selected');
433
435
  }
@@ -437,7 +439,7 @@ export class UserInteractions
437
439
  }
438
440
 
439
441
  __activateFeature(feature)
440
- //=======================
442
+ //========================
441
443
  {
442
444
  if (feature !== undefined) {
443
445
  this._map.setFeatureState(feature, { active: true });
@@ -457,7 +459,7 @@ export class UserInteractions
457
459
  //==========================
458
460
  {
459
461
  featureId = +featureId; // Ensure numeric
460
- this.__activateFeature(this.mapFeature_(featureId));
462
+ this.__activateFeature(this.mapFeature(featureId));
461
463
  }
462
464
 
463
465
  unhighlightFeatures_()
@@ -503,16 +505,15 @@ export class UserInteractions
503
505
  //=====
504
506
  {
505
507
  this.__clearModal();
506
- this.clearActiveMarker_();
507
- this.__unselectFeatures();
508
- this.enablePathFeatures_(true, this._pathways.allFeatureIds());
509
- this._disabledPathFeatures = false;
508
+ this.__clearActiveMarker();
509
+ this.unselectFeatures();
510
+ this.__enablePathFeatures(this._pathways.allFeatureIds(), true);
510
511
  }
511
512
 
512
513
  clearSearchResults(reset=true)
513
514
  //============================
514
515
  {
515
- this.__unselectFeatures();
516
+ this.unselectFeatures();
516
517
  }
517
518
 
518
519
  /**
@@ -548,14 +549,14 @@ export class UserInteractions
548
549
  //========================
549
550
  {
550
551
  if (featureIds.length) {
551
- this.__unselectFeatures();
552
+ this.unselectFeatures();
552
553
  for (const featureId of featureIds) {
553
554
  const annotation = this._flatmap.annotation(featureId);
554
555
  if (annotation) {
555
- this.selectFeature_(featureId);
556
+ this.selectFeature(featureId);
556
557
  if ('type' in annotation && annotation.type.startsWith('line')) {
557
558
  for (const pathFeatureId of this._pathways.lineFeatureIds([featureId])) {
558
- this.selectFeature_(pathFeatureId);
559
+ this.selectFeature(pathFeatureId);
559
560
  }
560
561
  }
561
562
  }
@@ -592,7 +593,7 @@ export class UserInteractions
592
593
  const highlight = (options.highlight === true);
593
594
  if (featureIds.length) {
594
595
  this.unhighlightFeatures_();
595
- if (select) this.__unselectFeatures();
596
+ if (select) this.unselectFeatures();
596
597
  let bbox = null;
597
598
  if (options.noZoomIn) {
598
599
  const bounds = this._map.getBounds().toArray();
@@ -602,7 +603,7 @@ export class UserInteractions
602
603
  const annotation = this._flatmap.annotation(featureId);
603
604
  if (annotation) {
604
605
  if (select) {
605
- this.selectFeature_(featureId);
606
+ this.selectFeature(featureId);
606
607
  } else if (highlight) {
607
608
  this.highlightFeature_(featureId);
608
609
  }
@@ -610,7 +611,7 @@ export class UserInteractions
610
611
  if ('type' in annotation && annotation.type.startsWith('line')) {
611
612
  for (const pathFeatureId of this._pathways.lineFeatureIds([featureId])) {
612
613
  if (select) {
613
- this.selectFeature_(pathFeatureId);
614
+ this.selectFeature(pathFeatureId);
614
615
  } else if (highlight) {
615
616
  this.highlightFeature_(pathFeatureId);
616
617
  }
@@ -643,8 +644,8 @@ export class UserInteractions
643
644
 
644
645
  // Highlight the feature
645
646
 
646
- this.__unselectFeatures();
647
- this.selectFeature_(featureId);
647
+ this.unselectFeatures();
648
+ this.selectFeature(featureId);
648
649
 
649
650
  // Find the pop-up's postion
650
651
 
@@ -679,7 +680,7 @@ export class UserInteractions
679
680
  //============
680
681
  {
681
682
  this.__clearModal();
682
- this.__unselectFeatures();
683
+ this.unselectFeatures();
683
684
  }
684
685
 
685
686
  removeTooltip_()
@@ -789,7 +790,7 @@ export class UserInteractions
789
790
 
790
791
  // Get all the features at the current point
791
792
  const features = this._map.queryRenderedFeatures(event.point)
792
- .filter(feature => this.__enabledFeature(feature));
793
+ .filter(feature => this.__featureEnabled(feature));
793
794
  if (features.length === 0) {
794
795
  this._lastFeatureMouseEntered = null;
795
796
  this._lastFeatureModelsMouse = null;
@@ -833,7 +834,7 @@ export class UserInteractions
833
834
  const lineIds = new Set(lineFeatures.map(f => f.properties.featureId));
834
835
  for (const featureId of this._pathways.lineFeatureIds(lineIds)) {
835
836
  if (+featureId !== lineFeatureId) {
836
- this.__activateFeature(this.mapFeature_(featureId));
837
+ this.__activateFeature(this.mapFeature(featureId));
837
838
  }
838
839
  }
839
840
  }
@@ -935,42 +936,43 @@ export class UserInteractions
935
936
  break;
936
937
  }
937
938
  }
938
- this.__unselectFeatures();
939
+ this.unselectFeatures();
939
940
  if (selecting) {
940
941
  for (const feature of this._activeFeatures) {
941
- this.selectFeature_(feature.id, dim);
942
+ this.selectFeature(feature.id, dim);
942
943
  }
943
944
  }
944
945
  } else {
945
946
  const clickedSelected = this.featureSelected_(clickedFeatureId);
946
947
  for (const feature of this._activeFeatures) {
947
948
  if (clickedSelected) {
948
- this.unselectFeature_(feature.id);
949
+ this.unselectFeature(feature.id);
949
950
  } else {
950
- this.selectFeature_(feature.id, dim);
951
+ this.selectFeature(feature.id, dim);
951
952
  }
952
953
  }
953
954
  }
954
955
  }
955
956
  }
956
957
 
957
- __annotationEvent(feature)
958
- //========================
958
+ __annotationEvent(features)
959
+ //=========================
959
960
  {
961
+ if (!this.__annotator) {
962
+ return;
963
+ }
964
+
960
965
  event.preventDefault();
961
966
 
962
967
  // Remove any tooltip
963
968
  this.removeTooltip_();
964
969
 
965
- // Select the feature
966
- this.selectFeature_(feature.id);
967
-
968
970
  // Don't respond to mouse events while the dialog is open
969
971
  this.setModal_();
970
972
 
971
973
  // The annotation dialog...
972
- this.__annotator.annotate(feature, e => {
973
- this.__unselectFeatures();
974
+ this.__annotator.annotate(features, () => {
975
+ this.unselectFeatures();
974
976
  this.__clearModal();
975
977
  });
976
978
  }
@@ -982,25 +984,25 @@ export class UserInteractions
982
984
  return;
983
985
  }
984
986
 
985
- this.clearActiveMarker_();
987
+ this.__clearActiveMarker();
986
988
  const clickedFeatures = this._map.queryRenderedFeatures(event.point)
987
- .filter(feature => this.__enabledFeature(feature));
989
+ .filter(feature => this.__featureEnabled(feature));
988
990
  if (clickedFeatures.length == 0){
989
- this.__unselectFeatures();
991
+ this.unselectFeatures();
990
992
  return;
991
993
  }
992
- const clickedFeature = clickedFeatures[0];
993
994
  const originalEvent = event.originalEvent;
994
995
  if (originalEvent.altKey) {
995
- this.__annotationEvent(clickedFeature);
996
+ this.__annotationEvent(clickedFeatures);
996
997
  return;
997
998
  }
998
999
 
1000
+ const clickedFeature = clickedFeatures[0];
999
1001
  this.selectionEvent_(originalEvent, clickedFeature);
1000
1002
  if (this._modal) {
1001
1003
  // Remove tooltip, reset active features, etc
1002
1004
  this.__resetFeatureDisplay();
1003
- this.__unselectFeatures();
1005
+ this.unselectFeatures();
1004
1006
  this.__clearModal();
1005
1007
  } else if (clickedFeature !== undefined) {
1006
1008
  this.__lastClickLngLat = event.lngLat;
@@ -1016,64 +1018,28 @@ export class UserInteractions
1016
1018
  {
1017
1019
  if ('nerveId' in feature.properties) {
1018
1020
  for (const featureId of this._pathways.nerveFeatureIds(feature.properties.nerveId)) {
1019
- this.__activateFeature(this.mapFeature_(featureId));
1021
+ this.__activateFeature(this.mapFeature(featureId));
1020
1022
  }
1021
1023
  }
1022
1024
  if ('nodeId' in feature.properties) {
1023
1025
  for (const featureId of this._pathways.nodeFeatureIds(feature.properties.nodeId)) {
1024
- this.__activateFeature(this.mapFeature_(featureId));
1026
+ this.__activateFeature(this.mapFeature(featureId));
1025
1027
  }
1026
1028
  }
1027
1029
  }
1028
1030
 
1029
- __enabledFeature(feature)
1030
- //=======================
1031
- {
1032
- const state = this._map.getFeatureState(feature);
1033
- return (state !== undefined
1034
- && (!('hidden' in state) || !state.hidden));
1035
- }
1036
-
1037
- enablePaths_(enable, event)
1038
- //=========================
1039
- {
1040
- const nodeId = event.target.getAttribute('featureId');
1041
- this.enablePathFeatures_(enable, this._pathways.pathFeatureIds(nodeId));
1042
- this.__clearModal();
1043
- }
1044
-
1045
- enablePathFeatures_(enable, featureIds)
1046
- //=====================================
1031
+ __enablePathFeatures(featureIds, enable)
1032
+ //======================================
1047
1033
  {
1048
1034
  for (const featureId of featureIds) {
1049
- const feature = this.mapFeature_(featureId);
1050
- if (feature !== undefined) {
1051
- if (enable) {
1052
- this._map.removeFeatureState(feature, 'hidden');
1053
- } else {
1054
- this._map.setFeatureState(feature, { 'hidden': true });
1055
- this._disabledPathFeatures = true;
1056
- }
1057
- }
1058
- }
1059
- }
1060
-
1061
- togglePaths()
1062
- //===========
1063
- {
1064
- console.log('Depracated API function called: togglePaths()')
1065
- if (this._disabledPathFeatures){
1066
- this.enablePathFeatures_(true, this._pathways.allFeatureIds());
1067
- this._disabledPathFeatures = false;
1068
- } else {
1069
- this.enablePathFeatures_(false, this._pathways.allFeatureIds());
1035
+ this.enableFeature(this.mapFeature(featureId), enable);
1070
1036
  }
1071
1037
  }
1072
1038
 
1073
1039
  enablePath(pathType, enable=true)
1074
1040
  //===============================
1075
1041
  {
1076
- this.enablePathFeatures_(enable, this._pathways.typeFeatureIds(pathType));
1042
+ this.__enablePathFeatures(this._pathways.typeFeatureIds(pathType), enable);
1077
1043
  }
1078
1044
 
1079
1045
  pathwaysFeatureIds(externalIds)
@@ -1257,7 +1223,7 @@ export class UserInteractions
1257
1223
  const markerId = this.__markerIdByMarker.get(marker);
1258
1224
  const annotation = this.__annotationByMarkerId.get(markerId);
1259
1225
  // The marker's feature
1260
- const feature = this.mapFeature_(annotation.featureId);
1226
+ const feature = this.mapFeature(annotation.featureId);
1261
1227
  if (feature !== undefined) {
1262
1228
  if (event.type === 'mouseenter') {
1263
1229
  // Highlight on mouse enter
@@ -1278,7 +1244,7 @@ export class UserInteractions
1278
1244
  event.stopPropagation();
1279
1245
  }
1280
1246
 
1281
- clearActiveMarker_()
1247
+ __clearActiveMarker()
1282
1248
  //==================
1283
1249
  {
1284
1250
  if (this.__activeMarker !== null) {
@@ -1292,7 +1258,7 @@ export class UserInteractions
1292
1258
  {
1293
1259
  const marker = this.__activeMarker;
1294
1260
  if (markerId !== this.__markerIdByMarker.get(marker)) {
1295
- this.clearActiveMarker_();
1261
+ this.__clearActiveMarker();
1296
1262
  return false;
1297
1263
  }
1298
1264
 
@@ -1311,7 +1277,7 @@ export class UserInteractions
1311
1277
  element.innerHTML = content;
1312
1278
  }
1313
1279
 
1314
- element.addEventListener('click', e => this.clearActiveMarker_());
1280
+ element.addEventListener('click', e => this.__clearActiveMarker());
1315
1281
 
1316
1282
  this._tooltip = new maplibre.Popup({
1317
1283
  closeButton: false,
package/src/main.js CHANGED
@@ -60,7 +60,8 @@ export async function standaloneViewer(map_endpoint=null, options={})
60
60
  debug: false,
61
61
  minimap: false,
62
62
  showPosition: false,
63
- standalone: true
63
+ standalone: true,
64
+ annotator: true
64
65
  }, options);
65
66
 
66
67
  function loadMap(id, taxon, sex)
package/src/pathways.js CHANGED
@@ -37,8 +37,8 @@ const PATH_TYPES = [
37
37
  { type: "symp-pre", label: "Sympathetic pre-ganglionic", colour: "#EA3423"},
38
38
  { type: "symp-post", label: "Sympathetic post-ganglionic", colour: "#EA3423", dashed: true},
39
39
  { type: "other", label: "Other neuron type", colour: "#888"},
40
- { type: "arterial", label: "Arterial blood vessel", colour: "#F00"},
41
- { type: "venous", label: "Venous blood vessel", colour: "#2F6EBA"},
40
+ { type: "arterial", label: "Arterial blood vessel", colour: "#F00", enabled: false},
41
+ { type: "venous", label: "Venous blood vessel", colour: "#2F6EBA", enabled: false},
42
42
  { type: "centreline", label: "Nerve centrelines", colour: "#CCC", enabled: false},
43
43
  { type: "error", label: "Paths with errors or warnings", colour: "#FF0"}
44
44
  ];
package/src/search.js CHANGED
@@ -36,99 +36,6 @@ export const indexedProperties = [
36
36
 
37
37
  //==============================================================================
38
38
 
39
- export class SearchControl
40
- {
41
- constructor(flatmap)
42
- {
43
- this.__flatmap = flatmap;
44
- }
45
-
46
- onAdd(map)
47
- //========
48
- {
49
- this._map = map;
50
- this._container = document.createElement('div');
51
- this._container.className = 'maplibregl-ctrl search-control';
52
-
53
- this._input = document.createElement('input');
54
- this._input.id = 'search-control-input';
55
- this._input.setAttribute('type', 'search');
56
- this._input.setAttribute('visible', 'false');
57
- this._input.setAttribute('placeholder', 'Search...');
58
-
59
- this._button = document.createElement('button');
60
- this._button.id = 'search-control-button';
61
- this._button.className = 'control-button';
62
- this._button.title = 'Search flatmap';
63
- this._button.setAttribute('type', 'button');
64
- this._button.setAttribute('aria-label', 'Search flatmap');
65
- // https://iconmonstr.com/magnifier-6-svg/
66
- this._button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" id="search-control-icon" viewBox="0 0 24 24">
67
- <path d="M21.172 24l-7.387-7.387c-1.388.874-3.024 1.387-4.785 1.387-4.971 0-9-4.029-9-9s4.029-9 9-9 9 4.029 9 9c0 1.761-.514 3.398-1.387 4.785l7.387 7.387-2.828 2.828zm-12.172-8c3.859 0 7-3.14 7-7s-3.141-7-7-7-7 3.14-7 7 3.141 7 7 7z"/>
68
- </svg>`;
69
- this._container.appendChild(this._button);
70
-
71
- this._container.onclick = this.onClick_.bind(this);
72
- return this._container;
73
- }
74
-
75
- getDefaultPosition()
76
- //==================
77
- {
78
- return 'top-right';
79
- }
80
-
81
- onRemove()
82
- //========
83
- {
84
- this._container.parentNode.removeChild(this._container);
85
- this._map = undefined;
86
- }
87
-
88
- searchMap_(search=true)
89
- //=====================
90
- {
91
- this._input = this._container.removeChild(this._input);
92
- this._input.setAttribute('visible', 'false');
93
- const text = this._input.value;
94
- if (search && text !== '') {
95
- const results = this.__flatmap.search(text);
96
- this.__flatmap.showSearchResults(results);
97
- }
98
- }
99
-
100
- onKeyDown_(e)
101
- //===========
102
- {
103
- if (e.key === 'Enter') {
104
- this.searchMap_();
105
- } else if (e.key === 'Escape') {
106
- this.searchMap_(false);
107
- }
108
- }
109
-
110
- onClick_(e)
111
- //=========
112
- {
113
- const targetId = ('rangeTarget' in e) ? e.rangeTarget.id : e.target.id; // FF has rangeTarget
114
- if (['search-control-button', 'search-control-icon'].includes(targetId)) {
115
- if (this._input.getAttribute('visible') === 'false') {
116
- this._container.appendChild(this._input);
117
- this._container.appendChild(this._button);
118
- this._input.setAttribute('visible', 'true');
119
- this._input.onkeydown = this.onKeyDown_.bind(this);
120
- this._input.value = '';
121
- this.__flatmap.clearSearchResults();
122
- this._input.focus();
123
- } else {
124
- this.searchMap_();
125
- }
126
- }
127
- }
128
- }
129
-
130
- //==============================================================================
131
-
132
39
  export class SearchIndex
133
40
  {
134
41
  constructor()