@abi-software/flatmap-viewer 2.3.0-b.2 → 2.3.2-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.
- package/README.rst +1 -1
- package/package.json +1 -1
- package/src/annotation.js +137 -17
- package/src/controls/controls.js +133 -229
- package/src/controls/info.js +2 -0
- package/src/controls/paths.js +143 -0
- package/src/controls/systems.js +18 -9
- package/src/flatmap-viewer.js +14 -25
- package/src/interactions.js +150 -165
- package/src/layers.js +2 -2
- package/src/pathways.js +110 -93
- package/src/styling.js +71 -48
- package/src/systems.js +54 -31
- package/src/utils.js +18 -0
- package/static/css/flatmap-viewer.css +12 -0
- package/src/controls/newcontrols.js +0 -617
- package/src/editor.js +0 -198
package/README.rst
CHANGED
|
@@ -38,7 +38,7 @@ The map server endpoint is specified as ``MAP_ENDPOINT`` in ``src/main.js``. It
|
|
|
38
38
|
Package Installation
|
|
39
39
|
====================
|
|
40
40
|
|
|
41
|
-
* ``npm install @abi-software/flatmap-viewer@2.3.
|
|
41
|
+
* ``npm install @abi-software/flatmap-viewer@2.3.2-b.1``
|
|
42
42
|
|
|
43
43
|
Documentation
|
|
44
44
|
-------------
|
package/package.json
CHANGED
package/src/annotation.js
CHANGED
|
@@ -82,9 +82,10 @@ function stopSpinner(panel)
|
|
|
82
82
|
|
|
83
83
|
export class Annotator
|
|
84
84
|
{
|
|
85
|
-
constructor(flatmap)
|
|
85
|
+
constructor(flatmap, ui)
|
|
86
86
|
{
|
|
87
87
|
this.__flatmap = flatmap;
|
|
88
|
+
this.__ui = ui;
|
|
88
89
|
this.__haveAnnotation = false;
|
|
89
90
|
this.__user = undefined;
|
|
90
91
|
this.__savedStatusMessage = '';
|
|
@@ -444,20 +445,134 @@ export class Annotator
|
|
|
444
445
|
});
|
|
445
446
|
}
|
|
446
447
|
|
|
447
|
-
|
|
448
|
-
|
|
448
|
+
__chooseFeatureProperties(features, callback)
|
|
449
|
+
//===========================================
|
|
450
|
+
{
|
|
451
|
+
this.__ui.selectFeature(features[0].id);
|
|
452
|
+
|
|
453
|
+
// Feature chooser is only for multiple selections
|
|
454
|
+
if (features.length === 1
|
|
455
|
+
|| features[0].properties['cd-class'] !== 'celldl:Connection'
|
|
456
|
+
|| (features.length === 2
|
|
457
|
+
&& features[1].properties['cd-class'] !== 'celldl:Connection')) {
|
|
458
|
+
callback(features[0].properties);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
const featureList = [];
|
|
462
|
+
const featureProperties = new Map();
|
|
463
|
+
const featureSeen = new Set();
|
|
464
|
+
let selected = 'selected'; // Select the first entry
|
|
465
|
+
for (const feature of features) {
|
|
466
|
+
if (feature.properties['cd-class'] !== 'celldl:Connection'
|
|
467
|
+
|| feature.properties['id'] == undefined
|
|
468
|
+
|| featureSeen.has(feature.properties['id'])) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const mapFeature = this.__ui.mapFeature(feature.id);
|
|
472
|
+
const annotated = (mapFeature !== undefined)
|
|
473
|
+
? this.__ui._map.getFeatureState(mapFeature)['annotated']
|
|
474
|
+
: false;
|
|
475
|
+
let label = '';
|
|
476
|
+
if (feature.properties.models) {
|
|
477
|
+
label = ` -- ${feature.properties.label.split('\n')[0]} (${feature.properties.models})`;
|
|
478
|
+
}
|
|
479
|
+
featureList.push(`<option value="${feature.id}" ${selected}>${annotated ? '*' : ' '} ${feature.properties.id} -- ${feature.properties.kind}${label}</option>`);
|
|
480
|
+
featureProperties.set(+feature.id, feature.properties);
|
|
481
|
+
featureSeen.add(feature.properties['id']);
|
|
482
|
+
selected = '';
|
|
483
|
+
}
|
|
484
|
+
if (featureList.length == 0) {
|
|
485
|
+
callback(undefined);
|
|
486
|
+
return;
|
|
487
|
+
} else if (featureList.length == 1) {
|
|
488
|
+
callback(featureProperties.values().next().value);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const panelContent = `
|
|
492
|
+
<div id="annotation-feature-selection">
|
|
493
|
+
<div>
|
|
494
|
+
<label for="annotation-feature-selector">Select feature:</label>
|
|
495
|
+
<select id="annotation-feature-selector" size="${Math.min(featureList.length, 7)}">
|
|
496
|
+
${featureList.join('\n')}
|
|
497
|
+
</select>
|
|
498
|
+
</div>
|
|
499
|
+
<div id="annotation-feature-buttons">
|
|
500
|
+
<input id="annotation-feature-cancel" type="button" value="Cancel"/>
|
|
501
|
+
<input id="annotation-feature-annotate" type="button" value="Annotate"/>
|
|
502
|
+
</div>
|
|
503
|
+
</div>`;
|
|
504
|
+
this.__panel = jsPanel.create({
|
|
505
|
+
theme: 'light',
|
|
506
|
+
border: '2px solid #080',
|
|
507
|
+
borderRadius: '.5rem',
|
|
508
|
+
panelSize: 'auto auto',
|
|
509
|
+
position: 'left-top',
|
|
510
|
+
content: panelContent,
|
|
511
|
+
data: features[0].properties,
|
|
512
|
+
closeOnEscape: true,
|
|
513
|
+
closeOnBackdrop: false,
|
|
514
|
+
headerTitle: 'Select feature to annotate',
|
|
515
|
+
headerControls: 'closeonly xs',
|
|
516
|
+
callback: ((panel) => {
|
|
517
|
+
const selector = document.getElementById('annotation-feature-selector');
|
|
518
|
+
selector.onchange = (e) => {
|
|
519
|
+
if (e.target.value !== '') {
|
|
520
|
+
this.__ui.unselectFeatures();
|
|
521
|
+
this.__ui.selectFeature(e.target.value);
|
|
522
|
+
this.__panel.options.data = featureProperties.get(+e.target.value);
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
selector.ondblclick = (e) => {
|
|
526
|
+
if (e.target.value !== '') {
|
|
527
|
+
const properties = this.__panel.options.data;
|
|
528
|
+
this.__panel.close();
|
|
529
|
+
callback(properties);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
selector.focus();
|
|
533
|
+
document.getElementById('annotation-feature-cancel')
|
|
534
|
+
.onclick = (e) => {
|
|
535
|
+
this.__panel.close();
|
|
536
|
+
callback(undefined);
|
|
537
|
+
};
|
|
538
|
+
document.getElementById('annotation-feature-annotate')
|
|
539
|
+
.onclick = (e) => {
|
|
540
|
+
const properties = this.__panel.options.data;
|
|
541
|
+
this.__panel.close();
|
|
542
|
+
callback(properties);
|
|
543
|
+
};
|
|
544
|
+
}).bind(this)
|
|
545
|
+
});
|
|
546
|
+
document.addEventListener('jspanelcloseduser', (e) => { callback(undefined) }, false);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
annotate(features, closedCallback)
|
|
550
|
+
//================================
|
|
449
551
|
{
|
|
450
|
-
|
|
552
|
+
// provide a list of features so dialog needs to first provide selection list
|
|
553
|
+
// and highlight current one as user scrolls...
|
|
554
|
+
|
|
555
|
+
this.__chooseFeatureProperties(features, (featureProperties) => {
|
|
556
|
+
if (featureProperties) {
|
|
557
|
+
this.__annotateFeature(featureProperties, closedCallback);
|
|
558
|
+
} else {
|
|
559
|
+
closedCallback();
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
451
563
|
|
|
564
|
+
__annotateFeature(featureProperties, callback)
|
|
565
|
+
//============================================
|
|
566
|
+
{
|
|
567
|
+
this.__currentFeatureId = featureProperties['id'];
|
|
452
568
|
if (this.__currentFeatureId === undefined) {
|
|
453
|
-
|
|
569
|
+
callback();
|
|
454
570
|
return;
|
|
455
571
|
}
|
|
456
|
-
|
|
457
572
|
const panelContent = [];
|
|
458
573
|
panelContent.push('<div id="flatmap-annotation-panel">');
|
|
459
574
|
panelContent.push(' <div id="flatmap-annotation-feature">');
|
|
460
|
-
panelContent.push(...this.__featureHtml(
|
|
575
|
+
panelContent.push(...this.__featureHtml(featureProperties));
|
|
461
576
|
panelContent.push(' </div>');
|
|
462
577
|
panelContent.push(' <form id="flatmap-annotation-form"></form>');
|
|
463
578
|
panelContent.push(' <div id="flatmap-annotation-existing"></div>');
|
|
@@ -517,23 +632,28 @@ export class Annotator
|
|
|
517
632
|
});
|
|
518
633
|
|
|
519
634
|
// should we warn if unsaved changes when closing??
|
|
520
|
-
document.addEventListener('jspanelclosed',
|
|
635
|
+
document.addEventListener('jspanelclosed', callback, false);
|
|
521
636
|
}
|
|
522
637
|
|
|
523
638
|
async annotated_features()
|
|
524
639
|
//========================
|
|
525
640
|
{
|
|
526
641
|
const url = this.__flatmap.makeServerUrl('', 'annotator/');
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
642
|
+
try {
|
|
643
|
+
const response = await fetch(url, {
|
|
644
|
+
headers: {
|
|
645
|
+
"Accept": "application/json; charset=utf-8",
|
|
646
|
+
"Cache-Control": "no-store"
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
if (response.ok) {
|
|
650
|
+
return response.json();
|
|
651
|
+
} else {
|
|
652
|
+
console.error(`Annotated features: ${response.status} ${response.statusText}`);
|
|
653
|
+
return Promise.resolve([]);
|
|
531
654
|
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
return response.json();
|
|
535
|
-
} else {
|
|
536
|
-
console.error(`Annotated features: ${response.status} ${response.statusText}`);
|
|
655
|
+
} catch {
|
|
656
|
+
console.error(`Fetch failed -- is annotator available at ${this.__flatmap._baseUrl} ?`);
|
|
537
657
|
return Promise.resolve([]);
|
|
538
658
|
}
|
|
539
659
|
}
|
package/src/controls/controls.js
CHANGED
|
@@ -32,12 +32,15 @@ function standardise_color(str){
|
|
|
32
32
|
|
|
33
33
|
//==============================================================================
|
|
34
34
|
|
|
35
|
-
export class
|
|
35
|
+
export class Control
|
|
36
36
|
{
|
|
37
|
-
constructor(flatmap)
|
|
37
|
+
constructor(flatmap, id, name)
|
|
38
38
|
{
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
39
|
+
this.__flatmap = flatmap;
|
|
40
|
+
this.__id = id;
|
|
41
|
+
this.__name = name;
|
|
42
|
+
this.__map = undefined;
|
|
43
|
+
this.__prefix = `${this.__id}-`
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
getDefaultPosition()
|
|
@@ -46,48 +49,140 @@ export class NavigationControl
|
|
|
46
49
|
return 'top-right';
|
|
47
50
|
}
|
|
48
51
|
|
|
52
|
+
_addControlDetails()
|
|
53
|
+
//==================
|
|
54
|
+
{
|
|
55
|
+
return {
|
|
56
|
+
enabled: 0,
|
|
57
|
+
total: 0
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
_enableAll(enable)
|
|
62
|
+
//================
|
|
63
|
+
{
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
__setAllCheckedState()
|
|
67
|
+
//====================
|
|
68
|
+
{
|
|
69
|
+
if (this.__checkedCount === 0) {
|
|
70
|
+
this.__allCheckbox.checked = false;
|
|
71
|
+
this.__allCheckbox.indeterminate = false;
|
|
72
|
+
} else if (this.__checkedCount === this.__totalCount) {
|
|
73
|
+
this.__allCheckbox.checked = true;
|
|
74
|
+
this.__allCheckbox.indeterminate = false;
|
|
75
|
+
} else {
|
|
76
|
+
this.__allCheckbox.indeterminate = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_addControlLine(id, name, style=null)
|
|
81
|
+
//===================================
|
|
82
|
+
{
|
|
83
|
+
const label = document.createElement('label');
|
|
84
|
+
label.setAttribute('for', id);
|
|
85
|
+
if (style !== null) {
|
|
86
|
+
label.setAttribute('style', style);
|
|
87
|
+
}
|
|
88
|
+
label.textContent = name;
|
|
89
|
+
this.__control.appendChild(label);
|
|
90
|
+
const input = document.createElement('input');
|
|
91
|
+
input.setAttribute('type', 'checkbox');
|
|
92
|
+
input.id = id;
|
|
93
|
+
this.__control.appendChild(input);
|
|
94
|
+
return input;
|
|
95
|
+
}
|
|
96
|
+
|
|
49
97
|
onAdd(map)
|
|
50
98
|
//========
|
|
51
99
|
{
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
|
|
100
|
+
this.__map = map;
|
|
101
|
+
this.__container = document.createElement('div');
|
|
102
|
+
this.__container.className = 'maplibregl-ctrl flatmap-control';
|
|
103
|
+
this.__control = document.createElement('div');
|
|
104
|
+
this.__control.className = 'flatmap-control-grid';
|
|
105
|
+
|
|
106
|
+
this.__allCheckbox = this._addControlLine(`control-all-${this.__id}`, `ALL ${this.__name.toUpperCase()}:`);
|
|
107
|
+
const controlDetails = this._addControlDetails();
|
|
108
|
+
this.__totalCount = controlDetails.total;
|
|
109
|
+
this.__halfCount = Math.trunc(this.__totalCount/2);
|
|
110
|
+
this.__checkedCount = controlDetails.enabled;
|
|
111
|
+
this.__setAllCheckedState();
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
const innerDetails = this._innerLinesHTML();
|
|
115
|
+
const innerHTML = innerDetails.html;
|
|
116
|
+
innerHTML.splice(0, 0, `<label for="control-all-${this.__id}">ALL ${this.__name.toUpperCase()}:</label><input id="control-all-${this.__id}" type="checkbox"/>`);
|
|
117
|
+
this.__control.innerHTML = innerHTML.join('\n');
|
|
118
|
+
|
|
119
|
+
this.__totalCount = innerHTML.length;
|
|
120
|
+
this.__halfCount = Math.trunc(this.__totalCount/2);
|
|
121
|
+
this.__checkedCount = innerDetails.enabled;
|
|
122
|
+
this.__allCheckbox = document.getElementById(`control-all-${this.__id}`);
|
|
123
|
+
this.__setAllCheckedState();
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
this.__button = document.createElement('button');
|
|
127
|
+
this.__button.id = `flatmap-${this.__id}-button`;
|
|
128
|
+
this.__button.className = 'control-button text-button';
|
|
129
|
+
this.__button.setAttribute('type', 'button');
|
|
130
|
+
this.__button.setAttribute('aria-label', `Show/hide map's ${this.__name}`);
|
|
131
|
+
this.__button.setAttribute('control-visible', 'false');
|
|
132
|
+
this.__button.textContent = this.__name.toUpperCase().substring(0, 6);
|
|
133
|
+
this.__button.title = `Show/hide map's ${this.__name}`;
|
|
134
|
+
this.__container.appendChild(this.__button);
|
|
135
|
+
|
|
136
|
+
this.__container.addEventListener('click', this.onClick_.bind(this));
|
|
137
|
+
return this.__container;
|
|
60
138
|
}
|
|
61
139
|
|
|
62
140
|
onRemove()
|
|
63
141
|
//========
|
|
64
142
|
{
|
|
65
|
-
this.
|
|
66
|
-
this.
|
|
143
|
+
this.__container.parentNode.removeChild(this.__container);
|
|
144
|
+
this.__map = undefined;
|
|
67
145
|
}
|
|
68
146
|
|
|
69
|
-
onClick_(
|
|
70
|
-
|
|
147
|
+
onClick_(event)
|
|
148
|
+
//=============
|
|
71
149
|
{
|
|
72
|
-
if
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
150
|
+
if (event.target.id === `flatmap-${this.__id}-button`) {
|
|
151
|
+
if (this.__button.getAttribute('control-visible') === 'false') {
|
|
152
|
+
this.__container.appendChild(this.__control);
|
|
153
|
+
this.__button.setAttribute('control-visible', 'true');
|
|
154
|
+
this.__control.focus();
|
|
155
|
+
} else {
|
|
156
|
+
this.__control = this.__container.removeChild(this.__control);
|
|
157
|
+
this.__button.setAttribute('control-visible', 'false');
|
|
158
|
+
}
|
|
159
|
+
} else if (event.target.tagName === 'INPUT') {
|
|
160
|
+
if (event.target.id === `control-all-${this.__id}`) {
|
|
161
|
+
if (event.target.indeterminate) {
|
|
162
|
+
event.target.checked = (this.__checkedCount >= this.__halfCount);
|
|
163
|
+
event.target.indeterminate = false;
|
|
164
|
+
}
|
|
165
|
+
this.__checkedCount = event.target.checked ? this.__totalCount : 0;
|
|
166
|
+
this._enableAll(event.target.checked);
|
|
167
|
+
} else if (event.target.id.startsWith(`${this.__id}-`)) {
|
|
168
|
+
this.__enableControl(event.target.id.substring(this.__prefix.length),
|
|
169
|
+
event.target.checked);
|
|
170
|
+
this.__checkedCount += (event.target.checked ? 1 : -1);
|
|
171
|
+
this.__setAllCheckedState();
|
|
172
|
+
}
|
|
78
173
|
}
|
|
174
|
+
event.stopPropagation();
|
|
79
175
|
}
|
|
80
176
|
}
|
|
81
177
|
|
|
82
178
|
//==============================================================================
|
|
83
179
|
|
|
84
|
-
export class
|
|
180
|
+
export class NavigationControl
|
|
85
181
|
{
|
|
86
|
-
constructor(flatmap
|
|
182
|
+
constructor(flatmap)
|
|
87
183
|
{
|
|
88
184
|
this._flatmap = flatmap;
|
|
89
185
|
this._map = undefined;
|
|
90
|
-
this.__pathTypes = pathTypes;
|
|
91
186
|
}
|
|
92
187
|
|
|
93
188
|
getDefaultPosition()
|
|
@@ -101,41 +196,11 @@ export class PathControl
|
|
|
101
196
|
{
|
|
102
197
|
this._map = map;
|
|
103
198
|
this._container = document.createElement('div');
|
|
104
|
-
this._container.className = 'maplibregl-ctrl';
|
|
105
|
-
this._container.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.
|
|
109
|
-
this._legend.className = 'flatmap-nerve-grid';
|
|
110
|
-
|
|
111
|
-
const innerHTML = [];
|
|
112
|
-
innerHTML.push(`<label for="path-all-paths">ALL PATHS:</label><div class="nerve-line"></div><input id="path-all-paths" type="checkbox" checked/>`);
|
|
113
|
-
this.__checkedCount = 0;
|
|
114
|
-
for (const path of this.__pathTypes) {
|
|
115
|
-
const checked = !('enabled' in path) || path.enabled ? 'checked' : '';
|
|
116
|
-
if (checked != '') {
|
|
117
|
-
this.__checkedCount += 1;
|
|
118
|
-
}
|
|
119
|
-
const colour = path.colour || '#440';
|
|
120
|
-
const style = path.dashed ? `background: repeating-linear-gradient(to right,${colour} 0,${colour} 6px,transparent 6px,transparent 9px);`
|
|
121
|
-
: `background: ${colour};`;
|
|
122
|
-
|
|
123
|
-
innerHTML.push(`<label for="path-${path.type}">${path.label}</label><div class="nerve-line" style="${style}"></div><input id="path-${path.type}" type="checkbox" ${checked}/>`);
|
|
124
|
-
}
|
|
125
|
-
this._legend.innerHTML = innerHTML.join('\n');
|
|
126
|
-
this.__halfCount = Math.trunc(this.__pathTypes.length/2);
|
|
127
|
-
|
|
128
|
-
this._button = document.createElement('button');
|
|
129
|
-
this._button.id = 'nerve-key-button';
|
|
130
|
-
this._button.className = 'control-button text-button';
|
|
131
|
-
this._button.setAttribute('type', 'button');
|
|
132
|
-
this._button.setAttribute('aria-label', 'Nerve paths legend');
|
|
133
|
-
this._button.setAttribute('control-visible', 'false');
|
|
134
|
-
this._button.textContent = 'PATHS';
|
|
135
|
-
this._button.title = 'Show/hide neuron paths';
|
|
136
|
-
this._container.appendChild(this._button);
|
|
137
|
-
|
|
138
|
-
this._container.addEventListener('click', this.onClick_.bind(this));
|
|
199
|
+
this._container.className = 'maplibregl-ctrl navigation-group';
|
|
200
|
+
this._container.innerHTML = `<button id="flatmap-zoom-in" class="navigation-zoom-in" type="button" title="Zoom in" aria-label="Zoom in"></button>
|
|
201
|
+
<button id="flatmap-zoom-out" class="navigation-zoom-out" type="button" title="Zoom out" aria-label="Zoom out"></button>
|
|
202
|
+
<button id="flatmap-reset" class="navigation-reset" type="button" title="Reset" aria-label="Reset"></button>`;
|
|
203
|
+
this._container.onclick = this.onClick_.bind(this);
|
|
139
204
|
return this._container;
|
|
140
205
|
}
|
|
141
206
|
|
|
@@ -146,60 +211,16 @@ export class PathControl
|
|
|
146
211
|
this._map = undefined;
|
|
147
212
|
}
|
|
148
213
|
|
|
149
|
-
onClick_(
|
|
150
|
-
|
|
214
|
+
onClick_(e)
|
|
215
|
+
//=========
|
|
151
216
|
{
|
|
152
|
-
if
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
&& this.__checkedCount > 0;
|
|
159
|
-
this._legend.focus();
|
|
160
|
-
} else {
|
|
161
|
-
this._legend = this._container.removeChild(this._legend);
|
|
162
|
-
this._button.setAttribute('control-visible', 'false');
|
|
163
|
-
}
|
|
164
|
-
} else if (event.target.tagName === 'INPUT') {
|
|
165
|
-
if (event.target.id === 'path-all-paths') {
|
|
166
|
-
if (event.target.indeterminate) {
|
|
167
|
-
event.target.checked = (this.__checkedCount >= this.__halfCount);
|
|
168
|
-
event.target.indeterminate = false;
|
|
169
|
-
}
|
|
170
|
-
if (event.target.checked) {
|
|
171
|
-
this.__checkedCount = this.__pathTypes.length;
|
|
172
|
-
} else {
|
|
173
|
-
this.__checkedCount = 0;
|
|
174
|
-
}
|
|
175
|
-
for (const path of this.__pathTypes) {
|
|
176
|
-
const pathCheckbox = document.getElementById(`path-${path.type}`);
|
|
177
|
-
if (pathCheckbox) {
|
|
178
|
-
pathCheckbox.checked = event.target.checked;
|
|
179
|
-
this._flatmap.enablePath(path.type, event.target.checked);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
} else if (event.target.id.startsWith('path-')) {
|
|
183
|
-
const pathType = event.target.id.substring(5);
|
|
184
|
-
this._flatmap.enablePath(pathType, event.target.checked);
|
|
185
|
-
if (event.target.checked) {
|
|
186
|
-
this.__checkedCount += 1;
|
|
187
|
-
} else {
|
|
188
|
-
this.__checkedCount -= 1;
|
|
189
|
-
}
|
|
190
|
-
const allPathsCheckbox = document.getElementById('path-all-paths');
|
|
191
|
-
if (this.__checkedCount === 0) {
|
|
192
|
-
allPathsCheckbox.checked = false;
|
|
193
|
-
allPathsCheckbox.indeterminate = false;
|
|
194
|
-
} else if (this.__checkedCount === this.__pathTypes.length) {
|
|
195
|
-
allPathsCheckbox.checked = true;
|
|
196
|
-
allPathsCheckbox.indeterminate = false;
|
|
197
|
-
} else {
|
|
198
|
-
allPathsCheckbox.indeterminate = true;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
217
|
+
if (e.target.id === 'flatmap-zoom-in') {
|
|
218
|
+
this._flatmap.zoomIn();
|
|
219
|
+
} else if (e.target.id === 'flatmap-zoom-out') {
|
|
220
|
+
this._flatmap.zoomOut();
|
|
221
|
+
} else if (e.target.id === 'flatmap-reset') {
|
|
222
|
+
this._flatmap.resetMap();
|
|
201
223
|
}
|
|
202
|
-
event.stopPropagation();
|
|
203
224
|
}
|
|
204
225
|
}
|
|
205
226
|
|
|
@@ -317,123 +338,6 @@ export class LayerControl
|
|
|
317
338
|
|
|
318
339
|
//==============================================================================
|
|
319
340
|
|
|
320
|
-
export class Control
|
|
321
|
-
{
|
|
322
|
-
constructor(flatmap, id, name)
|
|
323
|
-
{
|
|
324
|
-
this.__flatmap = flatmap;
|
|
325
|
-
this.__id = id;
|
|
326
|
-
this.__name = name;
|
|
327
|
-
this.__map = undefined;
|
|
328
|
-
this.__prefix = `${this.__id}-`
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
getDefaultPosition()
|
|
332
|
-
//==================
|
|
333
|
-
{
|
|
334
|
-
return 'top-right';
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
__innerLinesHTML()
|
|
338
|
-
//================
|
|
339
|
-
{
|
|
340
|
-
return [];
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
__enableAll(enable)
|
|
344
|
-
//=================
|
|
345
|
-
{
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
onAdd(map)
|
|
350
|
-
//========
|
|
351
|
-
{
|
|
352
|
-
this.__map = map;
|
|
353
|
-
this.__container = document.createElement('div');
|
|
354
|
-
this.__container.className = 'maplibregl-ctrl flatmap-control';
|
|
355
|
-
this.__control = document.createElement('div');
|
|
356
|
-
this.__control.className = 'flatmap-control-grid';
|
|
357
|
-
|
|
358
|
-
const innerHTML = this.__innerLinesHTML();
|
|
359
|
-
this.__totalCount = innerHTML.length;
|
|
360
|
-
innerHTML.splice(0, 0, `<label for="control-all-${this.__id}">ALL ${this.__name.toUpperCase()}:</label><input id="control-all-${this.__id}" type="checkbox" checked/>`);
|
|
361
|
-
this.__control.innerHTML = innerHTML.join('\n');
|
|
362
|
-
|
|
363
|
-
this.__checkedCount = this.__totalCount;
|
|
364
|
-
this.__halfCount = Math.trunc(this.__checkedCount/2);
|
|
365
|
-
|
|
366
|
-
this.__button = document.createElement('button');
|
|
367
|
-
this.__button.id = `flatmap-${this.__id}-button`;
|
|
368
|
-
this.__button.className = 'control-button text-button';
|
|
369
|
-
this.__button.setAttribute('type', 'button');
|
|
370
|
-
this.__button.setAttribute('aria-label', `Show/hide map's ${this.__name}`);
|
|
371
|
-
this.__button.setAttribute('control-visible', 'false');
|
|
372
|
-
this.__button.textContent = this.__name.toUpperCase().substring(0, 6);
|
|
373
|
-
this.__button.title = `Show/hide map's ${this.__name}`;
|
|
374
|
-
this.__container.appendChild(this.__button);
|
|
375
|
-
|
|
376
|
-
this.__container.addEventListener('click', this.onClick_.bind(this));
|
|
377
|
-
return this.__container;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
onRemove()
|
|
381
|
-
//========
|
|
382
|
-
{
|
|
383
|
-
this.__container.parentNode.removeChild(this.__container);
|
|
384
|
-
this.__map = undefined;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
onClick_(event)
|
|
388
|
-
//=============
|
|
389
|
-
{
|
|
390
|
-
if (event.target.id === `flatmap-${this.__id}-button`) {
|
|
391
|
-
if (this.__button.getAttribute('control-visible') === 'false') {
|
|
392
|
-
this.__container.appendChild(this.__control);
|
|
393
|
-
this.__button.setAttribute('control-visible', 'true');
|
|
394
|
-
this.__control.focus();
|
|
395
|
-
} else {
|
|
396
|
-
this.__control = this.__container.removeChild(this.__control);
|
|
397
|
-
this.__button.setAttribute('control-visible', 'false');
|
|
398
|
-
}
|
|
399
|
-
} else if (event.target.tagName === 'INPUT') {
|
|
400
|
-
if (event.target.id === `control-all-${this.__id}`) {
|
|
401
|
-
if (event.target.indeterminate) {
|
|
402
|
-
event.target.checked = (this.__checkedCount >= this.__halfCount);
|
|
403
|
-
event.target.indeterminate = false;
|
|
404
|
-
}
|
|
405
|
-
if (event.target.checked) {
|
|
406
|
-
this.__checkedCount = this.__totalCount;
|
|
407
|
-
} else {
|
|
408
|
-
this.__checkedCount = 0;
|
|
409
|
-
}
|
|
410
|
-
this.__enableAll(event.target.checked);
|
|
411
|
-
} else if (event.target.id.startsWith(`${this.__id}-`)) {
|
|
412
|
-
this.__enableControl(event.target.id.substring(this.__prefix.length),
|
|
413
|
-
event.target.checked);
|
|
414
|
-
if (event.target.checked) {
|
|
415
|
-
this.__checkedCount += 1;
|
|
416
|
-
} else {
|
|
417
|
-
this.__checkedCount -= 1;
|
|
418
|
-
}
|
|
419
|
-
const allCheckbox = document.getElementById(`control-all-${this.__id}`);
|
|
420
|
-
if (this.__checkedCount === 0) {
|
|
421
|
-
allCheckbox.checked = false;
|
|
422
|
-
allCheckbox.indeterminate = false;
|
|
423
|
-
} else if (this.__checkedCount === this.__totalCount) {
|
|
424
|
-
allCheckbox.checked = true;
|
|
425
|
-
allCheckbox.indeterminate = false;
|
|
426
|
-
} else {
|
|
427
|
-
allCheckbox.indeterminate = true;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
event.stopPropagation();
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
//==============================================================================
|
|
436
|
-
|
|
437
341
|
const SCKAN_STATES = [
|
|
438
342
|
{
|
|
439
343
|
'id': 'VALID',
|