Skip to content

Commit 3f6e647

Browse files
committed
mapbox: allow access token to be set per map
- use token in gd._context if not present in fullLayout - make sure map is removed + re-created if access token changes -
1 parent 85a8e7d commit 3f6e647

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

src/plots/mapbox/index.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,21 @@ exports.layoutAttributes = require('./layout_attributes');
4747
exports.supplyLayoutDefaults = require('./layout_defaults');
4848

4949
exports.plot = function plotMapbox(gd) {
50-
51-
if(!gd._context.mapboxAccessToken) {
52-
throw new Error(constants.noAccessTokenErrorMsg);
53-
}
54-
else {
55-
mapboxgl.accessToken = gd._context.mapboxAccessToken;
56-
}
57-
5850
var fullLayout = gd._fullLayout,
5951
calcData = gd.calcdata,
6052
mapboxIds = Plots.getSubplotIds(fullLayout, 'mapbox');
6153

54+
var accessToken = findAccessToken(gd, mapboxIds);
55+
mapboxgl.accessToken = accessToken;
56+
6257
for(var i = 0; i < mapboxIds.length; i++) {
6358
var id = mapboxIds[i],
6459
subplotCalcData = getSubplotCalcData(calcData, id),
65-
mapbox = fullLayout[id]._subplot;
60+
opts = fullLayout[id],
61+
mapbox = opts._subplot;
62+
63+
// copy access token to fullLayout (to handle the context case)
64+
opts.accesstoken = accessToken;
6665

6766
if(!mapbox) {
6867
mapbox = createMapbox({
@@ -131,3 +130,27 @@ function getSubplotCalcData(calcData, id) {
131130

132131
return subplotCalcData;
133132
}
133+
134+
function findAccessToken(gd, mapboxIds) {
135+
var fullLayout = gd._fullLayout,
136+
context = gd._context;
137+
138+
// first look for access token in context
139+
var accessToken = context.mapboxAccessToken;
140+
141+
// allow mapbox layout options to override it
142+
for(var i = 0; i < mapboxIds.length; i++) {
143+
var opts = fullLayout[mapboxIds[i]];
144+
145+
if(opts.accesstoken) {
146+
accessToken = opts.accesstoken;
147+
break;
148+
}
149+
}
150+
151+
if(!accessToken) {
152+
throw new Error(constants.noAccessTokenErrorMsg);
153+
}
154+
155+
return accessToken;
156+
}

src/plots/mapbox/layout_attributes.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ module.exports = {
4545
}
4646
},
4747

48+
accesstoken: {
49+
valType: 'string',
50+
noBlank: true,
51+
strict: true,
52+
role: 'info',
53+
description: [
54+
'Sets the mapbox access token to be set or as a configuration option',
55+
'under `mapboxAccessToken`.'
56+
].join(' ')
57+
},
4858
style: {
4959
valType: 'string',
5060
values: ['basic', 'streets', 'outdoors', 'light', 'dark', 'satellite', 'satellite-streets'],
@@ -55,6 +65,7 @@ module.exports = {
5565
'Either input the defaults Mapbox names or the URL to a custom style.'
5666
].join(' ')
5767
},
68+
5869
center: {
5970
lon: {
6071
valType: 'number',

src/plots/mapbox/layout_defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
2525
};
2626

2727
function handleDefaults(containerIn, containerOut, coerce) {
28+
coerce('accesstoken');
2829
coerce('style');
2930
coerce('center.lon');
3031
coerce('center.lat');

src/plots/mapbox/mapbox.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function Mapbox(opts) {
4040

4141
// state variables used to infer how and what to update
4242
this.map = null;
43+
this.accessToken = null;
4344
this.styleUrl = null;
4445
this.traceHash = {};
4546
this.layerList = [];
@@ -57,7 +58,16 @@ proto.plot = function(calcData, fullLayout, promises) {
5758
var self = this;
5859

5960
// feed in new mapbox options
60-
self.opts = fullLayout[this.id];
61+
var opts = self.opts = fullLayout[this.id];
62+
63+
// remove map and create a new map if access token has change
64+
if(self.map && (opts.accesstoken !== self.accessToken)) {
65+
self.map.remove();
66+
self.map = null;
67+
self.styleUrl = null;
68+
self.traceHash = [];
69+
self.layerList = {};
70+
}
6171

6272
var promise;
6373

@@ -83,6 +93,9 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
8393
// mapbox doesn't have a way to get the current style URL; do it ourselves
8494
var styleUrl = self.styleUrl = convertStyleUrl(opts.style);
8595

96+
// store access token associated with this map
97+
self.accessToken = opts.accesstoken;
98+
8699
var map = self.map = new mapboxgl.Map({
87100
container: self.div,
88101

@@ -334,7 +347,7 @@ proto.updateLayers = function() {
334347
};
335348

336349
proto.destroy = function() {
337-
this.map.remove();
350+
if(this.map) this.map.remove();
338351
this.container.removeChild(this.div);
339352
};
340353

test/jasmine/tests/mapbox_test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ describe('mapbox credentials', function() {
188188
mapboxAccessToken: dummyToken
189189
}).catch(function(err) {
190190
expect(err).toEqual(new Error(constants.mapOnErrorMsg));
191+
}).then(done);
192+
});
193+
194+
it('should use access token in mapbox layout options if present', function(done) {
195+
Plotly.plot(gd, [{
196+
type: 'scattermapbox',
197+
lon: [10, 20, 30],
198+
lat: [10, 20, 30]
199+
}], {
200+
mapbox: {
201+
accesstoken: MAPBOX_ACCESS_TOKEN
202+
}
203+
}, {
204+
mapboxAccessToken: dummyToken
205+
}).then(function() {
206+
expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN);
191207
done();
192208
});
193209
});
@@ -476,6 +492,22 @@ describe('mapbox plots', function() {
476492
});
477493
});
478494

495+
it('should be able to update the access token', function(done) {
496+
var promise = Plotly.relayout(gd, 'mapbox.accesstoken', 'wont-work');
497+
498+
promise.catch(function(err) {
499+
expect(gd._fullLayout.mapbox.accesstoken).toEqual('wont-work');
500+
expect(err).toEqual(new Error(constants.mapOnErrorMsg));
501+
});
502+
503+
promise.then(function() {
504+
return Plotly.relayout(gd, 'mapbox.accesstoken', MAPBOX_ACCESS_TOKEN);
505+
}).then(function() {
506+
expect(gd._fullLayout.mapbox.accesstoken).toEqual(MAPBOX_ACCESS_TOKEN);
507+
}).then(done);
508+
});
509+
510+
479511
it('should be able to update traces', function(done) {
480512
function assertDataPts(lengths) {
481513
var lines = getGeoJsonData(gd, 'lines'),

0 commit comments

Comments
 (0)