@abi-software/flatmap-viewer 2.2.8 → 2.2.10-devel
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/controls.js +186 -7
- package/src/flatmap-viewer.js +25 -9
- package/src/interactions.js +66 -55
- package/src/layers.js +163 -143
- package/src/main.js +24 -17
- package/src/search.js +4 -1
- package/src/styling.js +5 -5
- package/static/flatmap-viewer.css +31 -1
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.2.
|
|
41
|
+
* ``npm install @abi-software/flatmap-viewer@2.2.9``
|
|
42
42
|
|
|
43
43
|
Documentation
|
|
44
44
|
-------------
|
package/package.json
CHANGED
package/src/controls.js
CHANGED
|
@@ -26,6 +26,20 @@ import * as pathways from './pathways.js';
|
|
|
26
26
|
|
|
27
27
|
//==============================================================================
|
|
28
28
|
|
|
29
|
+
// Make sure colour string is in `#rrggbb` form.
|
|
30
|
+
// Based on https://stackoverflow.com/a/47355187
|
|
31
|
+
|
|
32
|
+
function standardise_color(str){
|
|
33
|
+
const canvas = document.createElement("canvas");
|
|
34
|
+
const ctx = canvas.getContext("2d");
|
|
35
|
+
ctx.fillStyle = str;
|
|
36
|
+
const colour = ctx.fillStyle;
|
|
37
|
+
canvas.remove()
|
|
38
|
+
return colour;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//==============================================================================
|
|
42
|
+
|
|
29
43
|
export class NavigationControl
|
|
30
44
|
{
|
|
31
45
|
constructor(flatmap)
|
|
@@ -102,9 +116,9 @@ export class PathControl
|
|
|
102
116
|
this._legend.className = 'flatmap-nerve-grid';
|
|
103
117
|
|
|
104
118
|
const innerHTML = [];
|
|
105
|
-
innerHTML.push(`<label for="path-all-paths">ALL PATHS:</label><input id="path-all-paths" type="checkbox" checked
|
|
119
|
+
innerHTML.push(`<label for="path-all-paths">ALL PATHS:</label><div class="nerve-line"></div><input id="path-all-paths" type="checkbox" checked/>`);
|
|
106
120
|
for (const path of pathways.PATH_TYPES) {
|
|
107
|
-
innerHTML.push(`<label for="path-${path.type}">${path.label}</label><input id="path-${path.type}" type="checkbox" checked
|
|
121
|
+
innerHTML.push(`<label for="path-${path.type}">${path.label}</label><div class="nerve-line nerve-${path.type}"></div><input id="path-${path.type}" type="checkbox" checked/>`);
|
|
108
122
|
}
|
|
109
123
|
this._legend.innerHTML = innerHTML.join('\n');
|
|
110
124
|
this.__checkedCount = pathways.PATH_TYPES.length;
|
|
@@ -112,10 +126,10 @@ export class PathControl
|
|
|
112
126
|
|
|
113
127
|
this._button = document.createElement('button');
|
|
114
128
|
this._button.id = 'nerve-key-button';
|
|
115
|
-
this._button.className = 'control-button';
|
|
129
|
+
this._button.className = 'control-button text-button';
|
|
116
130
|
this._button.setAttribute('type', 'button');
|
|
117
131
|
this._button.setAttribute('aria-label', 'Nerve paths legend');
|
|
118
|
-
this._button.setAttribute('
|
|
132
|
+
this._button.setAttribute('control-visible', 'false');
|
|
119
133
|
this._button.textContent = 'PATHS';
|
|
120
134
|
this._button.title = 'Show/hide neuron paths';
|
|
121
135
|
this._container.appendChild(this._button);
|
|
@@ -135,13 +149,13 @@ export class PathControl
|
|
|
135
149
|
//=============
|
|
136
150
|
{
|
|
137
151
|
if (event.target.id === 'nerve-key-button') {
|
|
138
|
-
if (this._button.getAttribute('
|
|
152
|
+
if (this._button.getAttribute('control-visible') === 'false') {
|
|
139
153
|
this._container.appendChild(this._legend);
|
|
140
|
-
this._button.setAttribute('
|
|
154
|
+
this._button.setAttribute('control-visible', 'true');
|
|
141
155
|
this._legend.focus();
|
|
142
156
|
} else {
|
|
143
157
|
this._legend = this._container.removeChild(this._legend);
|
|
144
|
-
this._button.setAttribute('
|
|
158
|
+
this._button.setAttribute('control-visible', 'false');
|
|
145
159
|
}
|
|
146
160
|
} else if (event.target.tagName === 'INPUT') {
|
|
147
161
|
if (event.target.id === 'path-all-paths') {
|
|
@@ -186,3 +200,168 @@ export class PathControl
|
|
|
186
200
|
}
|
|
187
201
|
|
|
188
202
|
//==============================================================================
|
|
203
|
+
|
|
204
|
+
export class LayerControl
|
|
205
|
+
{
|
|
206
|
+
constructor(flatmap, layerManager)
|
|
207
|
+
{
|
|
208
|
+
this.__flatmap = flatmap;
|
|
209
|
+
this.__manager = layerManager;
|
|
210
|
+
this.__map = undefined;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getDefaultPosition()
|
|
214
|
+
//==================
|
|
215
|
+
{
|
|
216
|
+
return 'top-right';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
onAdd(map)
|
|
220
|
+
//========
|
|
221
|
+
{
|
|
222
|
+
this.__map = map;
|
|
223
|
+
this.__container = document.createElement('div');
|
|
224
|
+
this.__container.className = 'maplibregl-ctrl';
|
|
225
|
+
this.__container.id = 'flatmap-layer-control';
|
|
226
|
+
|
|
227
|
+
this.__layers = document.createElement('div');
|
|
228
|
+
this.__layers.id = 'layer-control-text';
|
|
229
|
+
this.__layers.className = 'flatmap-layer-grid';
|
|
230
|
+
|
|
231
|
+
const innerHTML = [];
|
|
232
|
+
innerHTML.push(`<label for="layer-all-layers">ALL LAYERS:</label><input id="layer-all-layers" type="checkbox" checked/>`);
|
|
233
|
+
for (const layer of this.__manager.layers) {
|
|
234
|
+
innerHTML.push(`<label for="layer-${layer.id}">${layer.description}</label><input id="layer-${layer.id}" type="checkbox" checked/>`);
|
|
235
|
+
}
|
|
236
|
+
this.__layers.innerHTML = innerHTML.join('\n');
|
|
237
|
+
|
|
238
|
+
this.__layersCount = this.__manager.layers.length;
|
|
239
|
+
this.__checkedCount = this.__layersCount;
|
|
240
|
+
this.__halfCount = Math.trunc(this.__checkedCount/2);
|
|
241
|
+
|
|
242
|
+
this.__button = document.createElement('button');
|
|
243
|
+
this.__button.id = 'map-layers-button';
|
|
244
|
+
this.__button.className = 'control-button text-button';
|
|
245
|
+
this.__button.setAttribute('type', 'button');
|
|
246
|
+
this.__button.setAttribute('aria-label', 'Show/hide map layers');
|
|
247
|
+
this.__button.setAttribute('control-visible', 'false');
|
|
248
|
+
this.__button.textContent = 'LAYERS';
|
|
249
|
+
this.__button.title = 'Show/hide map layers';
|
|
250
|
+
this.__container.appendChild(this.__button);
|
|
251
|
+
|
|
252
|
+
this.__container.addEventListener('click', this.onClick_.bind(this));
|
|
253
|
+
return this.__container;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
onRemove()
|
|
257
|
+
//========
|
|
258
|
+
{
|
|
259
|
+
this.__container.parentNode.removeChild(this.__container);
|
|
260
|
+
this.__map = undefined;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
onClick_(event)
|
|
264
|
+
//=============
|
|
265
|
+
{
|
|
266
|
+
if (event.target.id === 'map-layers-button') {
|
|
267
|
+
if (this.__button.getAttribute('control-visible') === 'false') {
|
|
268
|
+
this.__container.appendChild(this.__layers);
|
|
269
|
+
this.__button.setAttribute('control-visible', 'true');
|
|
270
|
+
this.__layers.focus();
|
|
271
|
+
} else {
|
|
272
|
+
this.__layers = this.__container.removeChild(this.__layers);
|
|
273
|
+
this.__button.setAttribute('control-visible', 'false');
|
|
274
|
+
}
|
|
275
|
+
} else if (event.target.tagName === 'INPUT') {
|
|
276
|
+
if (event.target.id === 'layer-all-layers') {
|
|
277
|
+
if (event.target.indeterminate) {
|
|
278
|
+
event.target.checked = (this.__checkedCount >= this.__halfCount);
|
|
279
|
+
event.target.indeterminate = false;
|
|
280
|
+
}
|
|
281
|
+
if (event.target.checked) {
|
|
282
|
+
this.__checkedCount = this.__layersCount;
|
|
283
|
+
} else {
|
|
284
|
+
this.__checkedCount = 0;
|
|
285
|
+
}
|
|
286
|
+
for (const layer of this.__manager.layers) {
|
|
287
|
+
const layerCheckbox = document.getElementById(`layer-${layer.id}`);
|
|
288
|
+
if (layerCheckbox) {
|
|
289
|
+
layerCheckbox.checked = event.target.checked;
|
|
290
|
+
this.__manager.activate(layer.id, event.target.checked);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
} else if (event.target.id.startsWith('layer-')) {
|
|
294
|
+
const layerId = event.target.id.substring(6);
|
|
295
|
+
this.__manager.activate(layerId, event.target.checked);
|
|
296
|
+
if (event.target.checked) {
|
|
297
|
+
this.__checkedCount += 1;
|
|
298
|
+
} else {
|
|
299
|
+
this.__checkedCount -= 1;
|
|
300
|
+
}
|
|
301
|
+
const allLayersCheckbox = document.getElementById('layer-all-layers');
|
|
302
|
+
if (this.__checkedCount === 0) {
|
|
303
|
+
allLayersCheckbox.checked = false;
|
|
304
|
+
allLayersCheckbox.indeterminate = false;
|
|
305
|
+
} else if (this.__checkedCount === this.__layersCount) {
|
|
306
|
+
allLayersCheckbox.checked = true;
|
|
307
|
+
allLayersCheckbox.indeterminate = false;
|
|
308
|
+
} else {
|
|
309
|
+
allLayersCheckbox.indeterminate = true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
event.stopPropagation();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
//==============================================================================
|
|
318
|
+
|
|
319
|
+
export class BackgroundControl
|
|
320
|
+
{
|
|
321
|
+
constructor(flatmap)
|
|
322
|
+
{
|
|
323
|
+
this.__flatmap = flatmap;
|
|
324
|
+
this.__map = undefined;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
getDefaultPosition()
|
|
328
|
+
//==================
|
|
329
|
+
{
|
|
330
|
+
return 'top-right';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
onAdd(map)
|
|
334
|
+
//========
|
|
335
|
+
{
|
|
336
|
+
this.__map = map;
|
|
337
|
+
this.__container = document.createElement('div');
|
|
338
|
+
this.__container.className = 'maplibregl-ctrl';
|
|
339
|
+
this.__colourDiv = document.createElement('div');
|
|
340
|
+
this.__colourDiv.setAttribute('aria-label', 'Change background colour');
|
|
341
|
+
this.__colourDiv.title = 'Change background colour';
|
|
342
|
+
const background = standardise_color(this.__flatmap.getBackgroundColour());
|
|
343
|
+
this.__colourDiv.innerHTML = `<input type="color" id="colourPicker" value="${background}">`;
|
|
344
|
+
this.__container.appendChild(this.__colourDiv);
|
|
345
|
+
this.__colourDiv.addEventListener('input', this.__updateColour.bind(this), false);
|
|
346
|
+
this.__colourDiv.addEventListener('change', this.__updateColour.bind(this), false);
|
|
347
|
+
return this.__container;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
onRemove()
|
|
351
|
+
//========
|
|
352
|
+
{
|
|
353
|
+
this.__container.parentNode.removeChild(this.__container);
|
|
354
|
+
this.__map = undefined;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
__updateColour(event)
|
|
358
|
+
//===================
|
|
359
|
+
{
|
|
360
|
+
const colour = event.target.value;
|
|
361
|
+
this.__flatmap.setBackgroundColour(colour);
|
|
362
|
+
this.__flatmap.controlEvent('change', 'background', colour)
|
|
363
|
+
event.stopPropagation();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
//==============================================================================
|
package/src/flatmap-viewer.js
CHANGED
|
@@ -621,12 +621,6 @@ class FlatMap
|
|
|
621
621
|
this._map.resize();
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
mapLayerId(name)
|
|
625
|
-
//==============
|
|
626
|
-
{
|
|
627
|
-
return `${this.uniqueId}/${name}`;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
624
|
getIdentifier()
|
|
631
625
|
//=============
|
|
632
626
|
{
|
|
@@ -872,6 +866,23 @@ class FlatMap
|
|
|
872
866
|
});
|
|
873
867
|
}
|
|
874
868
|
|
|
869
|
+
/**
|
|
870
|
+
* Generate a callback as a result of some event in a control.
|
|
871
|
+
*
|
|
872
|
+
* @param {string} eventType The event type
|
|
873
|
+
* @param {string} control The name of the control
|
|
874
|
+
* @param {string} value The value of the control
|
|
875
|
+
*/
|
|
876
|
+
controlEvent(eventType, control, value)
|
|
877
|
+
//=====================================
|
|
878
|
+
{
|
|
879
|
+
this.callback(eventType, {
|
|
880
|
+
type: 'control',
|
|
881
|
+
control: control,
|
|
882
|
+
value: value
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
|
|
875
886
|
/**
|
|
876
887
|
* Generate callbacks as a result of panning/zooming the map.
|
|
877
888
|
*
|
|
@@ -1211,6 +1222,12 @@ export class MapManager
|
|
|
1211
1222
|
mapOptions['pathControls'] = true;
|
|
1212
1223
|
}
|
|
1213
1224
|
|
|
1225
|
+
// Default is to show layer controls
|
|
1226
|
+
|
|
1227
|
+
if (!('layerControl' in mapOptions)) {
|
|
1228
|
+
mapOptions['layerControl'] = true;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1214
1231
|
// Mapmaker's changed the name of the field to indicate that indicates if
|
|
1215
1232
|
// there are raster layers
|
|
1216
1233
|
if (!('image-layers' in mapIndex) && ('image_layer' in mapIndex)) {
|
|
@@ -1285,9 +1302,8 @@ export class MapManager
|
|
|
1285
1302
|
outline: true
|
|
1286
1303
|
};
|
|
1287
1304
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
} else if ('style' in mapIndex) {
|
|
1305
|
+
mapOptions.layerOptions.authoring = ('authoring' in mapIndex) ? mapIndex.authoring : false;
|
|
1306
|
+
if ('style' in mapIndex) {
|
|
1291
1307
|
mapOptions.layerOptions.style = mapIndex.style;
|
|
1292
1308
|
} else {
|
|
1293
1309
|
mapOptions.layerOptions.style = 'flatmap';
|
package/src/interactions.js
CHANGED
|
@@ -38,10 +38,11 @@ import {displayedProperties} from './info.js';
|
|
|
38
38
|
import {InfoControl} from './info.js';
|
|
39
39
|
import {LayerManager} from './layers.js';
|
|
40
40
|
import {PATHWAYS_LAYER, Pathways} from './pathways.js';
|
|
41
|
-
import {PathControl} from './controls.js';
|
|
41
|
+
import {BackgroundControl, LayerControl, PathControl} from './controls.js';
|
|
42
42
|
import {SearchControl} from './search.js';
|
|
43
43
|
import {VECTOR_TILES_SOURCE} from './styling.js';
|
|
44
44
|
|
|
45
|
+
import * as pathways from './pathways.js';
|
|
45
46
|
import * as utils from './utils.js';
|
|
46
47
|
|
|
47
48
|
//==============================================================================
|
|
@@ -144,20 +145,32 @@ export class UserInteractions
|
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
// Add and manage our layers
|
|
149
|
+
|
|
150
|
+
this._layerManager = new LayerManager(flatmap);
|
|
151
|
+
|
|
152
|
+
// Control background colour (NB. this depends on having map layers created)
|
|
153
|
+
|
|
154
|
+
if (flatmap.options.backgroundControl) {
|
|
155
|
+
this._map.addControl(new BackgroundControl(flatmap));
|
|
156
|
+
}
|
|
157
|
+
|
|
147
158
|
// Neural pathways which are either controlled externally
|
|
148
159
|
// or by our local controls
|
|
149
160
|
|
|
150
161
|
this._pathways = new Pathways(flatmap);
|
|
151
162
|
|
|
152
|
-
|
|
153
|
-
// Add controls to manage our pathways
|
|
163
|
+
// Add a control to manage our pathways
|
|
154
164
|
|
|
165
|
+
if (flatmap.options.pathControls) {
|
|
155
166
|
this._map.addControl(new PathControl(flatmap));
|
|
156
167
|
}
|
|
157
168
|
|
|
158
|
-
//
|
|
169
|
+
// Add a control to manage our layers
|
|
159
170
|
|
|
160
|
-
|
|
171
|
+
if (flatmap.options.layerControl) {
|
|
172
|
+
this._map.addControl(new LayerControl(flatmap, this._layerManager));
|
|
173
|
+
}
|
|
161
174
|
|
|
162
175
|
// Flag features that have annotations
|
|
163
176
|
// Also flag those features that are models of something
|
|
@@ -649,17 +662,17 @@ export class UserInteractions
|
|
|
649
662
|
if (('label' in properties || 'hyperlink' in properties)
|
|
650
663
|
&& (forceLabel || !('tooltip' in properties) || properties.tooltip)
|
|
651
664
|
&& !('labelled' in properties)) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
tooltip = (label.substr(0, 1).toUpperCase() + label.substr(1)).replaceAll("\n", "<br/>");
|
|
656
|
-
} else {
|
|
657
|
-
tooltip = properties.hyperlink
|
|
658
|
-
}
|
|
665
|
+
const label = ('label' in properties) ? (properties.label.substr(0, 1).toUpperCase()
|
|
666
|
+
+ properties.label.substr(1)).replaceAll("\n", "<br/>")
|
|
667
|
+
: '';
|
|
659
668
|
if ('hyperlink' in properties) {
|
|
660
|
-
|
|
669
|
+
if (label === '') {
|
|
670
|
+
return `<div class='flatmap-feature-label'><a href='{properties.hyperlink}'>${properties.hyperlink}</a></div>`;
|
|
671
|
+
} else {
|
|
672
|
+
return `<div class='flatmap-feature-label'><a href='{properties.hyperlink}'>${properties.hyperlink}</a><br/>${label}</div>`;
|
|
673
|
+
}
|
|
661
674
|
} else {
|
|
662
|
-
return `<div class='flatmap-feature-label'>${
|
|
675
|
+
return `<div class='flatmap-feature-label'>${label}</div>`;
|
|
663
676
|
}
|
|
664
677
|
}
|
|
665
678
|
return '';
|
|
@@ -842,31 +855,34 @@ export class UserInteractions
|
|
|
842
855
|
selectionEvent_(event, feature)
|
|
843
856
|
//=============================
|
|
844
857
|
{
|
|
845
|
-
const multipleSelect = event.ctrlKey || event.metaKey;
|
|
846
|
-
if (!multipleSelect) {
|
|
847
|
-
this.__unselectFeatures();
|
|
848
|
-
}
|
|
849
858
|
if (feature !== undefined) {
|
|
850
|
-
const
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
859
|
+
const clickedFeatureId = feature.id;
|
|
860
|
+
const dim = !('properties' in feature
|
|
861
|
+
&& 'kind' in feature.properties
|
|
862
|
+
&& ['cell-type', 'scaffold', 'tissue'].indexOf(feature.properties.kind) >= 0);
|
|
863
|
+
if (!(event.ctrlKey || event.metaKey)) {
|
|
864
|
+
let selecting = true;
|
|
865
|
+
for (const featureId of this._selectedFeatureIds.keys()) {
|
|
866
|
+
if (featureId === clickedFeatureId) {
|
|
867
|
+
selecting = false;
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
this.__unselectFeatures();
|
|
872
|
+
if (selecting) {
|
|
873
|
+
for (const feature of this._activeFeatures) {
|
|
874
|
+
this.selectFeature_(feature.id, dim);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
} else {
|
|
878
|
+
const clickedSelected = this.featureSelected_(clickedFeatureId);
|
|
855
879
|
for (const feature of this._activeFeatures) {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
this.selectFeature_(featureId);
|
|
880
|
+
if (clickedSelected) {
|
|
881
|
+
this.unselectFeature_(feature.id);
|
|
859
882
|
} else {
|
|
860
|
-
this.
|
|
883
|
+
this.selectFeature_(feature.id, dim);
|
|
861
884
|
}
|
|
862
885
|
}
|
|
863
|
-
} else if (selecting) {
|
|
864
|
-
const dim = !('properties' in feature
|
|
865
|
-
&& 'kind' in feature.properties
|
|
866
|
-
&& ['cell-type', 'scaffold', 'tissue'].indexOf(feature.properties.kind) >= 0);
|
|
867
|
-
this.selectFeature_(featureId, dim);
|
|
868
|
-
} else {
|
|
869
|
-
this.unselectFeature_(featureId);
|
|
870
886
|
}
|
|
871
887
|
}
|
|
872
888
|
}
|
|
@@ -875,24 +891,14 @@ export class UserInteractions
|
|
|
875
891
|
//================
|
|
876
892
|
{
|
|
877
893
|
this.clearActiveMarker_();
|
|
878
|
-
const clickedFeatures = this._map.queryRenderedFeatures(event.point)
|
|
879
|
-
.filter(feature => this.__enabledFeature(feature));
|
|
894
|
+
const clickedFeatures = this._map.queryRenderedFeatures(event.point);
|
|
880
895
|
if (clickedFeatures.length == 0){
|
|
896
|
+
this.__unselectFeatures();
|
|
881
897
|
return;
|
|
882
898
|
}
|
|
883
899
|
const clickedFeature = clickedFeatures[0];
|
|
884
900
|
const originalEvent = event.originalEvent;
|
|
885
|
-
|
|
886
|
-
this.selectionEvent_(originalEvent, clickedFeature);
|
|
887
|
-
} else if (this._activeFeatures.length > 1) {
|
|
888
|
-
const multipleSelect = originalEvent.ctrlKey || originalEvent.metaKey;
|
|
889
|
-
if (!multipleSelect) {
|
|
890
|
-
this.__unselectFeatures();
|
|
891
|
-
}
|
|
892
|
-
for (const feature of this._activeFeatures) {
|
|
893
|
-
this.selectFeature_(feature.id);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
901
|
+
this.selectionEvent_(originalEvent, clickedFeature);
|
|
896
902
|
if (this._modal) {
|
|
897
903
|
// Remove tooltip, reset active features, etc
|
|
898
904
|
this.__resetFeatureDisplay();
|
|
@@ -976,18 +982,23 @@ export class UserInteractions
|
|
|
976
982
|
//===============================
|
|
977
983
|
{
|
|
978
984
|
// Disable/enable all paths except those with `pathTypes`
|
|
979
|
-
|
|
980
|
-
this.enablePathFeatures_(!enable, this._pathways.allFeatureIds());
|
|
981
|
-
|
|
982
985
|
if (Array.isArray(pathTypes)) {
|
|
983
|
-
for (const pathType of
|
|
984
|
-
|
|
986
|
+
for (const pathType of pathways.PATH_TYPES) {
|
|
987
|
+
if (pathTypes.indexOf(pathType.type) >= 0) {
|
|
988
|
+
this.enablePath(pathType.type, enable)
|
|
989
|
+
} else {
|
|
990
|
+
this.enablePath(pathType.type, !enable)
|
|
991
|
+
}
|
|
985
992
|
}
|
|
986
993
|
} else {
|
|
987
|
-
|
|
994
|
+
for (const pathType of pathways.PATH_TYPES) {
|
|
995
|
+
if (pathType.type === pathTypes) {
|
|
996
|
+
this.enablePath(pathType.type, enable)
|
|
997
|
+
} else {
|
|
998
|
+
this.enablePath(pathType.type, !enable)
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
988
1001
|
}
|
|
989
|
-
|
|
990
|
-
this._disabledPathFeatures = true;
|
|
991
1002
|
}
|
|
992
1003
|
|
|
993
1004
|
pathwaysFeatureIds(externalIds)
|
package/src/layers.js
CHANGED
|
@@ -28,113 +28,174 @@ import * as style from './styling.js';
|
|
|
28
28
|
import * as utils from './utils.js';
|
|
29
29
|
|
|
30
30
|
const FEATURES_LAYER = 'features'
|
|
31
|
+
const RASTER_LAYERS_NAME = 'Background image layer'
|
|
31
32
|
|
|
32
33
|
//==============================================================================
|
|
33
34
|
|
|
34
|
-
class
|
|
35
|
+
class MapStylingLayers
|
|
35
36
|
{
|
|
36
|
-
constructor(flatmap,
|
|
37
|
+
constructor(flatmap, layerId)
|
|
37
38
|
{
|
|
38
39
|
this.__map = flatmap.map;
|
|
40
|
+
this.__id = layerId;
|
|
41
|
+
this.__layers = [];
|
|
42
|
+
this.__active = true;
|
|
43
|
+
this.__layerOptions = flatmap.options.layerOptions;
|
|
39
44
|
this.__separateLayers = flatmap.options.separateLayers;
|
|
40
|
-
|
|
41
|
-
this.__rasterLayers = [];
|
|
42
|
-
this.__styleLayers = [];
|
|
45
|
+
}
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
get id()
|
|
48
|
+
//======
|
|
49
|
+
{
|
|
50
|
+
return this.__id;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get active()
|
|
54
|
+
//==========
|
|
55
|
+
{
|
|
56
|
+
return this.__active;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addLayer(styleLayer, options)
|
|
60
|
+
//==========================
|
|
61
|
+
{
|
|
62
|
+
this.__map.addLayer(styleLayer.style(options));
|
|
63
|
+
this.__layers.push(styleLayer);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
__showLayer(layer, visible=true)
|
|
67
|
+
//===============================
|
|
68
|
+
{
|
|
69
|
+
this.__map.setLayoutProperty(layer.id, 'visibility', visible ? 'visible' : 'none');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
activate(enable=true)
|
|
73
|
+
//===================
|
|
74
|
+
{
|
|
75
|
+
for (const layer of this.__layers) {
|
|
76
|
+
this.__showLayer(layer, enable);
|
|
77
|
+
}
|
|
78
|
+
this.__active = enable;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
vectorSourceId(sourceLayer)
|
|
82
|
+
//=========================
|
|
83
|
+
{
|
|
84
|
+
return this.__separateLayers ? `${this.__id}_${sourceLayer}`
|
|
85
|
+
: sourceLayer;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//==============================================================================
|
|
90
|
+
|
|
91
|
+
class MapFeatureLayers extends MapStylingLayers
|
|
92
|
+
{
|
|
93
|
+
constructor(flatmap, layer)
|
|
94
|
+
{
|
|
95
|
+
super(flatmap, layer.id);
|
|
45
96
|
const vectorTileSource = this.__map.getSource('vector-tiles');
|
|
46
97
|
const haveVectorLayers = (typeof vectorTileSource !== 'undefined');
|
|
47
|
-
|
|
48
|
-
? `${this.__id}_${FEATURES_LAYER}`
|
|
49
|
-
: FEATURES_LAYER;
|
|
50
|
-
const vectorFeatures = haveVectorLayers
|
|
51
|
-
&& vectorTileSource.vectorLayerIds.indexOf(featuresVectorLayerId) >= 0;
|
|
52
|
-
if (background_layers) {
|
|
53
|
-
if (vectorFeatures) {
|
|
54
|
-
this.__addStyleLayer(style.BodyLayer, layerOptions);
|
|
55
|
-
}
|
|
56
|
-
if (flatmap.details['image-layers']) {
|
|
57
|
-
for (const raster_layer_id of layer['image-layers']) {
|
|
58
|
-
this.__addRasterLayer(raster_layer_id, layerOptions);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
98
|
+
|
|
62
99
|
// if no image layers then make feature borders (and lines?) more visible...??
|
|
63
100
|
if (haveVectorLayers) {
|
|
101
|
+
const featuresVectorSource = this.vectorSourceId(FEATURES_LAYER);
|
|
102
|
+
const vectorFeatures = vectorTileSource.vectorLayerIds
|
|
103
|
+
.indexOf(featuresVectorSource) >= 0;
|
|
64
104
|
if (vectorFeatures) {
|
|
65
|
-
this.__addStyleLayer(style.FeatureFillLayer
|
|
66
|
-
this.__addStyleLayer(style.FeatureDashLineLayer
|
|
67
|
-
this.__addStyleLayer(style.FeatureLineLayer
|
|
68
|
-
this.__addStyleLayer(style.FeatureBorderLayer
|
|
105
|
+
this.__addStyleLayer(style.FeatureFillLayer);
|
|
106
|
+
this.__addStyleLayer(style.FeatureDashLineLayer);
|
|
107
|
+
this.__addStyleLayer(style.FeatureLineLayer);
|
|
108
|
+
this.__addStyleLayer(style.FeatureBorderLayer);
|
|
69
109
|
}
|
|
70
|
-
this.__addPathwayStyleLayers(
|
|
110
|
+
this.__addPathwayStyleLayers(this.__layerOptions);
|
|
71
111
|
if (vectorFeatures) {
|
|
72
|
-
this.__addStyleLayer(style.FeatureLargeSymbolLayer
|
|
112
|
+
this.__addStyleLayer(style.FeatureLargeSymbolLayer);
|
|
73
113
|
if (!flatmap.options.tooltips) {
|
|
74
|
-
this.__addStyleLayer(style.FeatureSmallSymbolLayer
|
|
114
|
+
this.__addStyleLayer(style.FeatureSmallSymbolLayer);
|
|
75
115
|
}
|
|
76
116
|
}
|
|
77
117
|
}
|
|
78
118
|
|
|
79
119
|
// Make sure our colour options are set properly, in particular raster layer visibility
|
|
80
120
|
|
|
81
|
-
this.setColour(
|
|
121
|
+
this.setColour(this.__layerOptions);
|
|
82
122
|
}
|
|
83
123
|
|
|
84
|
-
|
|
85
|
-
|
|
124
|
+
__addStyleLayer(styleClass, sourceLayer=FEATURES_LAYER)
|
|
125
|
+
//=====================================================
|
|
86
126
|
{
|
|
87
|
-
|
|
127
|
+
const styleLayer = new styleClass(`${this.__id}_${sourceLayer}`,
|
|
128
|
+
this.vectorSourceId(sourceLayer));
|
|
129
|
+
this.__map.addLayer(styleLayer.style(this.__layerOptions));
|
|
130
|
+
this.__layers.push(styleLayer);
|
|
88
131
|
}
|
|
89
132
|
|
|
90
|
-
|
|
91
|
-
|
|
133
|
+
__addPathwayStyleLayers()
|
|
134
|
+
//=======================
|
|
92
135
|
{
|
|
93
|
-
const
|
|
94
|
-
this.__map.
|
|
95
|
-
|
|
136
|
+
const pathwaysVectorSource = this.vectorSourceId(PATHWAYS_LAYER);
|
|
137
|
+
if (this.__map.getSource('vector-tiles')
|
|
138
|
+
.vectorLayerIds
|
|
139
|
+
.indexOf(pathwaysVectorSource) >= 0) {
|
|
140
|
+
this.__addStyleLayer(style.PathLineLayer, PATHWAYS_LAYER);
|
|
141
|
+
this.__addStyleLayer(style.PathDashlineLayer, PATHWAYS_LAYER);
|
|
142
|
+
this.__addStyleLayer(style.NervePolygonBorder, PATHWAYS_LAYER);
|
|
143
|
+
this.__addStyleLayer(style.NervePolygonFill, PATHWAYS_LAYER);
|
|
144
|
+
this.__addStyleLayer(style.FeatureNerveLayer, PATHWAYS_LAYER);
|
|
145
|
+
}
|
|
96
146
|
}
|
|
97
147
|
|
|
98
|
-
|
|
99
|
-
|
|
148
|
+
setColour(options)
|
|
149
|
+
//================
|
|
100
150
|
{
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.indexOf(pathwaysVectorLayerId) >= 0) {
|
|
107
|
-
this.__addStyleLayer(style.PathLineLayer, options, PATHWAYS_LAYER);
|
|
108
|
-
this.__addStyleLayer(style.PathDashlineLayer, options, PATHWAYS_LAYER);
|
|
109
|
-
this.__addStyleLayer(style.NervePolygonBorder, options, PATHWAYS_LAYER);
|
|
110
|
-
this.__addStyleLayer(style.NervePolygonFill, options, PATHWAYS_LAYER);
|
|
111
|
-
this.__addStyleLayer(style.FeatureNerveLayer, options, PATHWAYS_LAYER);
|
|
151
|
+
for (const layer of this.__layers) {
|
|
152
|
+
const paintStyle = layer.paintStyle(options, true);
|
|
153
|
+
for (const [property, value] of Object.entries(paintStyle)) {
|
|
154
|
+
this.__map.setPaintProperty(layer.id, property, value, {validate: false});
|
|
155
|
+
}
|
|
112
156
|
}
|
|
113
157
|
}
|
|
158
|
+
}
|
|
114
159
|
|
|
115
|
-
|
|
116
|
-
|
|
160
|
+
//==============================================================================
|
|
161
|
+
|
|
162
|
+
class MapRasterLayers extends MapStylingLayers
|
|
163
|
+
{
|
|
164
|
+
constructor(flatmap, bodyLayerId=null)
|
|
117
165
|
{
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
166
|
+
super(flatmap, 'background-image-layer');
|
|
167
|
+
if (bodyLayerId !== null) {
|
|
168
|
+
const layerId = `${bodyLayerId}_${FEATURES_LAYER}`;
|
|
169
|
+
const source = flatmap.options.separateLayers ? layerId : FEATURES_LAYER;
|
|
170
|
+
const styleLayer = new style.BodyLayer(layerId, source);
|
|
171
|
+
this.__map.addLayer(styleLayer.style(this.__layerOptions));
|
|
172
|
+
this.__layers.push(styleLayer);
|
|
173
|
+
}
|
|
174
|
+
// Make sure our colour options are set properly, in particular raster layer visibility
|
|
175
|
+
this.setColour(this.__layerOptions);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
addLayer(layer)
|
|
179
|
+
//=============
|
|
180
|
+
{
|
|
181
|
+
for (const layer_id of layer['image-layers']) {
|
|
182
|
+
const rasterLayer = new style.RasterLayer(layer_id);
|
|
183
|
+
this.__map.addLayer(rasterLayer.style(this.__layerOptions));
|
|
184
|
+
this.__layers.push(rasterLayer);
|
|
185
|
+
}
|
|
186
|
+
// Make sure our colour options are set properly, in particular raster layer visibility
|
|
187
|
+
this.setColour(this.__layerOptions);
|
|
123
188
|
}
|
|
124
189
|
|
|
125
190
|
setColour(options)
|
|
126
191
|
//================
|
|
127
192
|
{
|
|
128
193
|
const coloured = !('colour' in options) || options.colour;
|
|
129
|
-
for (const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const paintStyle = styleLayer.paintStyle(options, true);
|
|
135
|
-
for (const [property, value] of Object.entries(paintStyle)) {
|
|
136
|
-
this.__map.setPaintProperty(styleLayer.id, property, value, {validate: false});
|
|
137
|
-
}
|
|
194
|
+
for (const layer of this.__layers) {
|
|
195
|
+
// Check active status when resetting to visible....
|
|
196
|
+
this.__map.setLayoutProperty(layer.id, 'visibility',
|
|
197
|
+
(coloured && this.active) ? 'visible' : 'none',
|
|
198
|
+
{validate: false});
|
|
138
199
|
}
|
|
139
200
|
}
|
|
140
201
|
}
|
|
@@ -143,89 +204,73 @@ class MapFeatureLayer
|
|
|
143
204
|
|
|
144
205
|
export class LayerManager
|
|
145
206
|
{
|
|
146
|
-
constructor(flatmap
|
|
207
|
+
constructor(flatmap)
|
|
147
208
|
{
|
|
148
209
|
this.__flatmap = flatmap;
|
|
149
210
|
this.__map = flatmap.map;
|
|
150
211
|
this.__layers = new Map;
|
|
151
212
|
this.__mapLayers = new Map;
|
|
152
|
-
this.__activeLayers = [];
|
|
153
|
-
this.__activeLayerNames = [];
|
|
154
|
-
this.__rasterLayers = [];
|
|
155
213
|
const layerOptions = flatmap.options.layerOptions;
|
|
156
|
-
const fcDiagram = ('style' in layerOptions && layerOptions.style == 'fcdiagram');
|
|
157
214
|
const backgroundLayer = new style.BackgroundLayer();
|
|
158
|
-
if (
|
|
159
|
-
this.__map.addLayer(backgroundLayer.style('black', 1));
|
|
160
|
-
}
|
|
161
|
-
else if ('background' in flatmap.options) {
|
|
215
|
+
if ('background' in flatmap.options) {
|
|
162
216
|
this.__map.addLayer(backgroundLayer.style(flatmap.options.background));
|
|
163
217
|
} else {
|
|
164
218
|
this.__map.addLayer(backgroundLayer.style('white'));
|
|
165
219
|
}
|
|
220
|
+
|
|
166
221
|
// Add the map's layers
|
|
167
|
-
if (
|
|
222
|
+
if (flatmap.details['image-layers']) {
|
|
223
|
+
// Image layers are below all feature layers
|
|
224
|
+
|
|
225
|
+
const bodyLayer = flatmap.layers[0];
|
|
226
|
+
|
|
227
|
+
const rasterLayers = new MapRasterLayers(this.__flatmap, bodyLayer.id); // body layer if not FC??
|
|
228
|
+
|
|
168
229
|
for (const layer of flatmap.layers) {
|
|
169
|
-
|
|
170
|
-
const rasterLayer = new style.RasterLayer(raster_layer_id);
|
|
171
|
-
this.__map.addLayer(rasterLayer.style(layerOptions));
|
|
172
|
-
this.__rasterLayers.push(rasterLayer);
|
|
173
|
-
}
|
|
230
|
+
rasterLayers.addLayer(layer);
|
|
174
231
|
}
|
|
232
|
+
this.__layers.set(RASTER_LAYERS_NAME, {
|
|
233
|
+
id: RASTER_LAYERS_NAME,
|
|
234
|
+
description: RASTER_LAYERS_NAME
|
|
235
|
+
});
|
|
236
|
+
this.__mapLayers.set(RASTER_LAYERS_NAME, rasterLayers);
|
|
175
237
|
}
|
|
176
238
|
for (const layer of flatmap.layers) {
|
|
177
|
-
|
|
239
|
+
this.__addFeatureLayer(layer);
|
|
178
240
|
}
|
|
179
241
|
}
|
|
180
242
|
|
|
181
243
|
get activeLayerNames()
|
|
182
244
|
//====================
|
|
183
245
|
{
|
|
184
|
-
|
|
246
|
+
const activeNames = [];
|
|
247
|
+
for (const mapLayer of this.__mapLayers.values()) {
|
|
248
|
+
if (mapLayer.active) {
|
|
249
|
+
activeNames.push(mapLayer.id);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return activeNames;
|
|
185
253
|
}
|
|
186
254
|
|
|
187
|
-
|
|
188
|
-
|
|
255
|
+
__addFeatureLayer(layer)
|
|
256
|
+
//======================
|
|
189
257
|
{
|
|
190
|
-
this.
|
|
191
|
-
|
|
192
|
-
const layers = new MapFeatureLayer(this.__flatmap, layer, background_layers);
|
|
193
|
-
const layerId = this.__flatmap.mapLayerId(layer.id);
|
|
194
|
-
this.__layers.set(layerId, layers);
|
|
258
|
+
this.__layers.set(layer.id, layer);
|
|
259
|
+
this.__mapLayers.set(layer.id, new MapFeatureLayers(this.__flatmap, layer));
|
|
195
260
|
}
|
|
196
261
|
|
|
197
262
|
get layers()
|
|
198
263
|
//==========
|
|
199
264
|
{
|
|
200
|
-
return this.__layers;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
activate(layerId)
|
|
204
|
-
//===============
|
|
205
|
-
{
|
|
206
|
-
const layer = this.__layers.get(layerId);
|
|
207
|
-
if (layer !== undefined) {
|
|
208
|
-
layer.activate();
|
|
209
|
-
if (this.__activeLayers.indexOf(layer) < 0) {
|
|
210
|
-
this.__activeLayers.push(layer);
|
|
211
|
-
this.__activeLayerNames.push(layer.id);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
265
|
+
return Array.from(this.__layers.values());
|
|
214
266
|
}
|
|
215
267
|
|
|
216
|
-
|
|
217
|
-
|
|
268
|
+
activate(layerId, enable=true)
|
|
269
|
+
//============================
|
|
218
270
|
{
|
|
219
|
-
const
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
const index = this.__activeLayers.indexOf(layer);
|
|
223
|
-
if (index >= 0) {
|
|
224
|
-
delete this.__activeLayers[index];
|
|
225
|
-
this.__activeLayers.splice(index, 1);
|
|
226
|
-
delete this.__activeLayerNames[index];
|
|
227
|
-
this.__activeLayerNames.splice(index, 1);
|
|
228
|
-
}
|
|
271
|
+
const mapLayer = this.__mapLayers.get(layerId);
|
|
272
|
+
if (mapLayer !== undefined) {
|
|
273
|
+
mapLayer.activate(enable);
|
|
229
274
|
}
|
|
230
275
|
}
|
|
231
276
|
|
|
@@ -233,35 +278,10 @@ export class LayerManager
|
|
|
233
278
|
//=====================
|
|
234
279
|
{
|
|
235
280
|
options = utils.setDefaultOptions(options, {colour: true, outline: true});
|
|
236
|
-
for (const
|
|
237
|
-
|
|
281
|
+
for (const mapLayer of this.__mapLayers.values()) {
|
|
282
|
+
mapLayer.setColour(options)
|
|
238
283
|
}
|
|
239
284
|
}
|
|
240
|
-
|
|
241
|
-
makeUppermost(layerId)
|
|
242
|
-
//====================
|
|
243
|
-
{
|
|
244
|
-
// position before top layer
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
makeLowest(layerId)
|
|
248
|
-
//=================
|
|
249
|
-
{
|
|
250
|
-
// position after bottom layer (before == undefined)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
lower(layerId)
|
|
255
|
-
//============
|
|
256
|
-
{
|
|
257
|
-
// position before second layer underneath...
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
raise(layerId)
|
|
261
|
-
//============
|
|
262
|
-
{
|
|
263
|
-
// position before layer above...
|
|
264
|
-
}
|
|
265
285
|
}
|
|
266
286
|
|
|
267
287
|
//==============================================================================
|
package/src/main.js
CHANGED
|
@@ -27,7 +27,7 @@ export { MapManager };
|
|
|
27
27
|
|
|
28
28
|
//==============================================================================
|
|
29
29
|
|
|
30
|
-
export async function standaloneViewer(map_endpoint=null,
|
|
30
|
+
export async function standaloneViewer(map_endpoint=null, options={})
|
|
31
31
|
{
|
|
32
32
|
const requestUrl = new URL(window.location.href);
|
|
33
33
|
if (map_endpoint == null) {
|
|
@@ -52,6 +52,18 @@ export async function standaloneViewer(map_endpoint=null, map_options={})
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
let currentMap = null;
|
|
55
|
+
let defaultBackground = 'black';
|
|
56
|
+
|
|
57
|
+
const mapOptions = Object.assign({
|
|
58
|
+
tooltips: true,
|
|
59
|
+
background: defaultBackground,
|
|
60
|
+
backgroundControl: true,
|
|
61
|
+
debug: false,
|
|
62
|
+
minimap: false,
|
|
63
|
+
searchable: true,
|
|
64
|
+
featureInfo: true,
|
|
65
|
+
showPosition: false
|
|
66
|
+
}, options);
|
|
55
67
|
|
|
56
68
|
function loadMap(id, taxon, sex)
|
|
57
69
|
//==============================
|
|
@@ -71,20 +83,15 @@ export async function standaloneViewer(map_endpoint=null, map_options={})
|
|
|
71
83
|
}
|
|
72
84
|
requestUrl.searchParams.delete('id');
|
|
73
85
|
}
|
|
86
|
+
|
|
87
|
+
// Update address bar URL to current map
|
|
74
88
|
window.history.pushState('data', document.title, requestUrl);
|
|
75
89
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
navigationControl: 'top-right',
|
|
82
|
-
searchable: true,
|
|
83
|
-
featureInfo: true,
|
|
84
|
-
showPosition: false
|
|
85
|
-
}, map_options);
|
|
86
|
-
|
|
87
|
-
mapManager.loadMap(id, 'map-canvas', (...args) => console.log(...args), options)
|
|
90
|
+
mapManager.loadMap(id, 'map-canvas', (eventType, ...args) => {
|
|
91
|
+
if (args[0].type === 'control' && args[0].control === 'background') {
|
|
92
|
+
mapOptions.background = args[0].value;
|
|
93
|
+
}
|
|
94
|
+
}, mapOptions)
|
|
88
95
|
.then(map => {
|
|
89
96
|
map.addMarker('UBERON:0000948'); // Heart
|
|
90
97
|
map.addMarker('UBERON:0002048'); // Lung
|
|
@@ -129,7 +136,7 @@ export async function standaloneViewer(map_endpoint=null, map_options={})
|
|
|
129
136
|
let mapId = null;
|
|
130
137
|
let mapTaxon = null;
|
|
131
138
|
let mapSex = null;
|
|
132
|
-
const
|
|
139
|
+
const mapList = [];
|
|
133
140
|
for (const [name, map] of sortedMaps.entries()) {
|
|
134
141
|
const text = [ name, map.created ];
|
|
135
142
|
let selected = '';
|
|
@@ -145,12 +152,12 @@ export async function standaloneViewer(map_endpoint=null, map_options={})
|
|
|
145
152
|
mapSex = viewMapSex;
|
|
146
153
|
selected = 'selected';
|
|
147
154
|
}
|
|
148
|
-
|
|
155
|
+
mapList.push(`<option value="${id}" ${selected}>${text.join(' -- ')}</option>`);
|
|
149
156
|
}
|
|
150
|
-
|
|
157
|
+
mapList.splice(0, 0, '<option value="">Select flatmap...</option>');
|
|
151
158
|
|
|
152
159
|
const selector = document.getElementById('map-selector');
|
|
153
|
-
selector.innerHTML =
|
|
160
|
+
selector.innerHTML = mapList.join('');
|
|
154
161
|
selector.onchange = (e) => {
|
|
155
162
|
if (e.target.value !== '') {
|
|
156
163
|
loadMap(e.target.value);
|
package/src/search.js
CHANGED
|
@@ -158,7 +158,10 @@ export class SearchIndex
|
|
|
158
158
|
|
|
159
159
|
addTerm_(featureId, text)
|
|
160
160
|
//=======================
|
|
161
|
-
{
|
|
161
|
+
{
|
|
162
|
+
text = text.replace(new RegExp('<br/>', 'g'), ' ')
|
|
163
|
+
.replace('\n', ' ');
|
|
164
|
+
if (text) {
|
|
162
165
|
this._searchEngine.add({
|
|
163
166
|
id: this._featureIds.length,
|
|
164
167
|
text: text
|
package/src/styling.js
CHANGED
|
@@ -226,8 +226,7 @@ export class FeatureBorderLayer extends VectorStyleLayer
|
|
|
226
226
|
'type': 'line',
|
|
227
227
|
'filter': [
|
|
228
228
|
'all',
|
|
229
|
-
['==', '$type', 'Polygon']
|
|
230
|
-
['has', 'id']
|
|
229
|
+
['==', '$type', 'Polygon']
|
|
231
230
|
],
|
|
232
231
|
'paint': this.paintStyle(options)
|
|
233
232
|
};
|
|
@@ -268,7 +267,7 @@ export class FeatureLineLayer extends VectorStyleLayer
|
|
|
268
267
|
['boolean', ['feature-state', 'active'], false], coloured ? '#888' : '#CCC',
|
|
269
268
|
['==', ['get', 'type'], 'network'], '#AFA202',
|
|
270
269
|
['has', 'centreline'], '#888',
|
|
271
|
-
|
|
270
|
+
options.authoring ? '#C44' : '#444'
|
|
272
271
|
],
|
|
273
272
|
'line-opacity': [
|
|
274
273
|
'case',
|
|
@@ -284,7 +283,7 @@ export class FeatureLineLayer extends VectorStyleLayer
|
|
|
284
283
|
['==', ['get', 'type'], 'network'], 1.2,
|
|
285
284
|
['boolean', ['feature-state', 'selected'], false], 1.2,
|
|
286
285
|
['boolean', ['feature-state', 'active'], false], 1.2,
|
|
287
|
-
|
|
286
|
+
options.authoring ? 0.7 : 0.5
|
|
288
287
|
], [
|
|
289
288
|
'interpolate',
|
|
290
289
|
['exponential', 2],
|
|
@@ -357,6 +356,7 @@ export class PathLineLayer extends VectorStyleLayer
|
|
|
357
356
|
const paintStyle = {
|
|
358
357
|
'line-color': [
|
|
359
358
|
'case',
|
|
359
|
+
['boolean', ['feature-state', 'selected'], false], '#0F0',
|
|
360
360
|
['boolean', ['feature-state', 'hidden'], false], '#CCC',
|
|
361
361
|
['==', ['get', 'type'], 'bezier'], 'red',
|
|
362
362
|
['==', ['get', 'kind'], 'error'], '#FFFE0E',
|
|
@@ -683,7 +683,7 @@ export class BackgroundLayer
|
|
|
683
683
|
return this.__id;
|
|
684
684
|
}
|
|
685
685
|
|
|
686
|
-
style(backgroundColour, opacity=0
|
|
686
|
+
style(backgroundColour, opacity=1.0)
|
|
687
687
|
{
|
|
688
688
|
return {
|
|
689
689
|
'id': this.__id,
|
|
@@ -51,6 +51,10 @@ li.flatmap-contextmenu-item:hover {
|
|
|
51
51
|
margin-top: 2px;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
.text-button {
|
|
55
|
+
width: 64px;
|
|
56
|
+
}
|
|
57
|
+
|
|
54
58
|
/* Search box */
|
|
55
59
|
|
|
56
60
|
#search-control-input {
|
|
@@ -176,7 +180,7 @@ li.flatmap-contextmenu-item:hover {
|
|
|
176
180
|
.flatmap-nerve-grid {
|
|
177
181
|
margin-top: 10px;
|
|
178
182
|
display: grid;
|
|
179
|
-
grid-template-columns: 3fr 0.
|
|
183
|
+
grid-template-columns: 3fr 0.8fr 0.2fr;
|
|
180
184
|
column-gap: 10px;
|
|
181
185
|
row-gap: 0.2em;
|
|
182
186
|
width: 300px;
|
|
@@ -226,6 +230,32 @@ label[for=path-all-paths] {
|
|
|
226
230
|
background: repeating-linear-gradient(to right,#EA3423 0,#EA3423 6px,transparent 6px,transparent 9px)
|
|
227
231
|
}
|
|
228
232
|
|
|
233
|
+
/* Layer control */
|
|
234
|
+
|
|
235
|
+
#flatmap-layer-control {
|
|
236
|
+
text-align: right;
|
|
237
|
+
}
|
|
238
|
+
.flatmap-layer-grid {
|
|
239
|
+
margin-top: 10px;
|
|
240
|
+
display: grid;
|
|
241
|
+
grid-template-columns: 3.8fr 0.2fr;
|
|
242
|
+
column-gap: 10px;
|
|
243
|
+
row-gap: 0.2em;
|
|
244
|
+
width: 300px;
|
|
245
|
+
font-size: 10pt;
|
|
246
|
+
cursor: pointer;
|
|
247
|
+
text-align: left;
|
|
248
|
+
background: white;
|
|
249
|
+
border: 1px solid gray;
|
|
250
|
+
padding: 4px;
|
|
251
|
+
opacity: 0.8;
|
|
252
|
+
}
|
|
253
|
+
.flatmap-layer-grid input {
|
|
254
|
+
height: 1.1em;
|
|
255
|
+
}
|
|
256
|
+
label[for=layer-all-layers] {
|
|
257
|
+
font-weight: bold;
|
|
258
|
+
}
|
|
229
259
|
|
|
230
260
|
/* Markers */
|
|
231
261
|
|