Skip to content

Commit 853a391

Browse files
committed
add mapbox subplot.addLayer convenience wrapper
... to Lib.warn users when *below* is invalid.
1 parent 8a4e8f1 commit 853a391

File tree

6 files changed

+113
-12
lines changed

6 files changed

+113
-12
lines changed

src/plots/mapbox/layers.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ var constants = require('./constants');
1414

1515
function MapboxLayer(subplot, index) {
1616
this.subplot = subplot;
17-
this.map = subplot.map;
1817

1918
this.uid = subplot.uid + '-' + index;
2019
this.index = index;
@@ -72,7 +71,7 @@ proto.needsNewLayer = function(opts) {
7271
};
7372

7473
proto.updateSource = function(opts) {
75-
var map = this.map;
74+
var map = this.subplot.map;
7675

7776
if(map.getSource(this.idSource)) map.removeSource(this.idSource);
7877

@@ -87,14 +86,14 @@ proto.updateSource = function(opts) {
8786
};
8887

8988
proto.updateLayer = function(opts) {
90-
var map = this.map;
89+
var subplot = this.subplot;
9190
var convertedOpts = convertOpts(opts);
9291

9392
var below = this.subplot.belowLookup['layout-' + this.index];
9493
var _below;
9594

9695
if(below === 'traces') {
97-
var mapLayers = this.subplot.getMapLayers();
96+
var mapLayers = subplot.getMapLayers();
9897

9998
// find id of first plotly trace layer
10099
for(var i = 0; i < mapLayers.length; i++) {
@@ -113,7 +112,7 @@ proto.updateLayer = function(opts) {
113112
this.removeLayer();
114113

115114
if(isVisible(opts)) {
116-
map.addLayer({
115+
subplot.addLayer({
117116
id: this.idLayer,
118117
source: this.idSource,
119118
'source-layer': opts.sourcelayer || '',
@@ -138,14 +137,14 @@ proto.updateStyle = function(opts) {
138137
};
139138

140139
proto.removeLayer = function() {
141-
var map = this.map;
140+
var map = this.subplot.map;
142141
if(map.getLayer(this.idLayer)) {
143142
map.removeLayer(this.idLayer);
144143
}
145144
};
146145

147146
proto.dispose = function() {
148-
var map = this.map;
147+
var map = this.subplot.map;
149148
map.removeLayer(this.idLayer);
150149
map.removeSource(this.idSource);
151150
};

src/plots/mapbox/mapbox.js

+30
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,36 @@ proto.getMapLayers = function() {
690690
return this.map.getStyle().layers;
691691
};
692692

693+
// convenience wrapper that first check in 'below' references
694+
// a layer that exist and then add the layer to the map,
695+
proto.addLayer = function(opts, below) {
696+
var map = this.map;
697+
698+
if(typeof below === 'string') {
699+
if(below === '') {
700+
map.addLayer(opts, below);
701+
return;
702+
}
703+
704+
var mapLayers = this.getMapLayers();
705+
for(var i = 0; i < mapLayers.length; i++) {
706+
if(below === mapLayers[i].id) {
707+
map.addLayer(opts, below);
708+
return;
709+
}
710+
}
711+
712+
Lib.warn([
713+
'Trying to add layer with *below* value',
714+
below,
715+
'referencing a layer that does not exist',
716+
'or that does not yet exist.'
717+
].join(' '));
718+
}
719+
720+
map.addLayer(opts);
721+
};
722+
693723
// convenience method to project a [lon, lat] array to pixel coords
694724
proto.project = function(v) {
695725
return this.map.project(new mapboxgl.LngLat(v[0], v[1]));

src/traces/choroplethmapbox/plot.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ proto._addLayers = function(optsAll, below) {
7878
var k = item[0];
7979
var opts = optsAll[k];
8080

81-
subplot.map.addLayer({
81+
subplot.addLayer({
8282
type: k,
8383
id: item[1],
8484
source: sourceId,

src/traces/densitymapbox/plot.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ proto._addLayers = function(optsAll, below) {
6868
var k = item[0];
6969
var opts = optsAll[k];
7070

71-
subplot.map.addLayer({
71+
subplot.addLayer({
7272
type: k,
7373
id: item[1],
7474
source: sourceId,

src/traces/scattermapbox/plot.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ proto.setSourceData = function(k, opts) {
5555
};
5656

5757
proto.addLayer = function(k, opts, below) {
58-
var subplot = this.subplot;
59-
60-
subplot.map.addLayer({
58+
this.subplot.addLayer({
6159
type: k,
6260
id: this.layerIds[k],
6361
source: this.sourceIds[k],

test/jasmine/tests/mapbox_test.js

+74
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,80 @@ describe('@noCI test mapbox trace/layout *below* interactions', function() {
15211521
.catch(failTest)
15221522
.then(done);
15231523
}, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
1524+
1525+
it('@gl should be warn when *below* value does not correspond to a layer on the map', function(done) {
1526+
spyOn(Lib, 'warn');
1527+
1528+
var notGonnaWork = 'not-gonna-work';
1529+
var arg = [
1530+
'Trying to add layer with *below* value',
1531+
notGonnaWork,
1532+
'referencing a layer that does not exist',
1533+
'or that does not yet exist.'
1534+
].join(' ');
1535+
1536+
function _assertFallback(msg, exp) {
1537+
var allArgs = Lib.warn.calls.allArgs();
1538+
1539+
if(allArgs.length === exp.warnCnt) {
1540+
for(var i = 0; i < exp.warnCnt; i++) {
1541+
expect(allArgs[i][0]).toBe(arg, 'Lib.warn call #' + i);
1542+
}
1543+
} else {
1544+
fail('Incorrect number of Lib.warn calls');
1545+
}
1546+
Lib.warn.calls.reset();
1547+
1548+
getLayerIds().slice(20, -1).forEach(function(id) {
1549+
expect(id.indexOf('plotly-')).toBe(0, 'layer ' + id + ' fallback to top of map');
1550+
});
1551+
}
1552+
1553+
Plotly.plot(gd, [{
1554+
type: 'scattermapbox',
1555+
lon: [10, 20, 30],
1556+
lat: [15, 25, 35]
1557+
}, {
1558+
type: 'densitymapbox',
1559+
lon: [10, 20, 30],
1560+
lat: [15, 25, 35],
1561+
z: [1, 20, 5]
1562+
}, {
1563+
type: 'choroplethmapbox',
1564+
geojson: 'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/us-states.json',
1565+
locations: ['AL'],
1566+
z: [10]
1567+
}], {
1568+
mapbox: {
1569+
style: 'basic',
1570+
layers: [{
1571+
sourcetype: 'vector',
1572+
source: 'mapbox://mapbox.mapbox-terrain-v2',
1573+
sourcelayer: 'contour',
1574+
type: 'line'
1575+
}]
1576+
}
1577+
})
1578+
.then(function() {
1579+
expect(Lib.warn).toHaveBeenCalledTimes(0);
1580+
})
1581+
.then(function() { return Plotly.restyle(gd, 'below', notGonnaWork); })
1582+
.then(function() {
1583+
// 7 for 4 scattermapbox + 2 choroplethmapbox + 1 densitymapbox layer
1584+
_assertFallback('not-gonna-work for traces', {warnCnt: 7});
1585+
})
1586+
.then(function() { return Plotly.relayout(gd, 'mapbox.layers[0].below', 'not-gonna-work'); })
1587+
.then(function() {
1588+
// same as last but + layout layer
1589+
_assertFallback('not-gonna-work for traces', {warnCnt: 8});
1590+
})
1591+
.then(function() { return Plotly.update(gd, {below: null}, {'mapbox.layers[0].below': null}); })
1592+
.then(function() {
1593+
expect(Lib.warn).toHaveBeenCalledTimes(0);
1594+
})
1595+
.catch(failTest)
1596+
.then(done);
1597+
}, 8 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
15241598
});
15251599

15261600
describe('@noCI Test mapbox GeoJSON fetching:', function() {

0 commit comments

Comments
 (0)