Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f0ff634

Browse files
committed
Basic fixes for making number-named frames work better
1 parent 2dbdf07 commit f0ff634

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

src/plot_api/plot_api.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,18 +2416,18 @@ Plotly.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) {
24162416
type: 'object',
24172417
data: setTransitionConfig(Lib.extendFlat({}, frameOrGroupNameOrFrameList))
24182418
});
2419-
} else if(allFrames || typeof frameOrGroupNameOrFrameList === 'string') {
2419+
} else if(allFrames || ['string', 'number'].indexOf(typeof frameOrGroupNameOrFrameList) !== -1) {
24202420
// In this case, null or undefined has been passed so that we want to
24212421
// animate *all* currently defined frames
24222422
for(i = 0; i < trans._frames.length; i++) {
24232423
frame = trans._frames[i];
24242424

24252425
if(!frame) continue;
24262426

2427-
if(allFrames || frame.group === frameOrGroupNameOrFrameList) {
2427+
if(allFrames || String(frame.group) === String(frameOrGroupNameOrFrameList)) {
24282428
frameList.push({
24292429
type: 'byname',
2430-
name: frame.name,
2430+
name: String(frame.name),
24312431
data: setTransitionConfig({name: frame.name})
24322432
});
24332433
}
@@ -2528,6 +2528,8 @@ Plotly.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) {
25282528
Plotly.addFrames = function(gd, frameList, indices) {
25292529
gd = helpers.getGraphDiv(gd);
25302530

2531+
var hasBeenWarnedAboutNumericNames = false;
2532+
25312533
if(frameList === null || frameList === undefined) {
25322534
return Promise.resolve();
25332535
}
@@ -2558,6 +2560,13 @@ Plotly.addFrames = function(gd, frameList, indices) {
25582560

25592561
var insertions = [];
25602562
for(i = frameList.length - 1; i >= 0; i--) {
2563+
var name = (_hash[frameList[i].name] || {}).name;
2564+
var newName = frameList[i].name;
2565+
2566+
if (name && newName && typeof newName === 'number' && _hash[name]) {
2567+
Lib.warn('addFrames: overwriting frame "' + _hash[name].name + '" with a frame whose name of type "number" also equates to "' + name + '". This is valid but may potentially lead to unexpected behavior since all plotly.js frame names are stored internally as strings.');
2568+
}
2569+
25612570
insertions.push({
25622571
frame: Plots.supplyFrameDefaults(frameList[i]),
25632572
index: (indices && indices[i] !== undefined && indices[i] !== null) ? indices[i] : bigIndex + i
@@ -2578,6 +2587,12 @@ Plotly.addFrames = function(gd, frameList, indices) {
25782587
for(i = insertions.length - 1; i >= 0; i--) {
25792588
frame = insertions[i].frame;
25802589

2590+
if (typeof frame.name === 'number') {
2591+
Lib.warn('Warning: addFrames accepts frames with numeric names, but the numbers are' +
2592+
'implicitly cast to strings');
2593+
2594+
}
2595+
25812596
if(!frame.name) {
25822597
// Repeatedly assign a default name, incrementing the counter each time until
25832598
// we get a name that's not in the hashed lookup table:

src/plots/command.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ exports.computeAPICommandBindings = function(gd, method, args) {
301301
function computeAnimateBindings(gd, args) {
302302
// We'll assume that the only relevant modification an animation
303303
// makes that's meaningfully tracked is the frame:
304-
if(Array.isArray(args[0]) && args[0].length === 1 && typeof args[0][0] === 'string') {
305-
return [{type: 'layout', prop: '_currentFrame', value: args[0][0]}];
304+
if(Array.isArray(args[0]) && args[0].length === 1 && ['string', 'number'].indexOf(typeof args[0][0]) !== -1) {
305+
return [{type: 'layout', prop: '_currentFrame', value: args[0][0].toString()}];
306306
} else {
307307
return [];
308308
}

src/plots/plots.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,17 @@ plots.computeFrame = function(gd, frameName) {
14781478
var frameLookup = gd._transitionData._frameHash;
14791479
var i, traceIndices, traceIndex, destIndex;
14801480

1481-
var framePtr = frameLookup[frameName];
1481+
// Null or undefined will fail on .toString(). We'll allow numbers since we
1482+
// make it clear frames must be given string names, but we'll allow numbers
1483+
// here since they're otherwise fine for looking up frames as long as they're
1484+
// properly cast to strings. We really just want to ensure here that this
1485+
// 1) doesn't fail, and
1486+
// 2) doens't give an incorrect answer (which String(frameName) would)
1487+
if (!frameName) {
1488+
throw new Error('computeFrame must be given a string frame name')
1489+
}
1490+
1491+
var framePtr = frameLookup[frameName.toString()];
14821492

14831493
// Return false if the name is invalid:
14841494
if(!framePtr) {
@@ -1489,7 +1499,7 @@ plots.computeFrame = function(gd, frameName) {
14891499
var frameNameStack = [framePtr.name];
14901500

14911501
// Follow frame pointers:
1492-
while((framePtr = frameLookup[framePtr.baseframe])) {
1502+
while(framePtr.baseframe && (framePtr = frameLookup[framePtr.baseframe.toString()])) {
14931503
// Avoid infinite loops:
14941504
if(frameNameStack.indexOf(framePtr.name) !== -1) break;
14951505

test/jasmine/tests/frame_api_test.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var Plotly = require('@lib/index');
2+
var Lib = require('@src/lib');
23

34
var createGraphDiv = require('../assets/create_graph_div');
45
var destroyGraphDiv = require('../assets/destroy_graph_div');
@@ -73,13 +74,41 @@ describe('Test frame api', function() {
7374
});
7475

7576
it('creates multiple unnamed frames in series', function(done) {
76-
Plotly.addFrames(gd, [{}]).then(
77-
Plotly.addFrames(gd, [{}])
78-
).then(function() {
77+
Plotly.addFrames(gd, [{}]).then(function () {
78+
return Plotly.addFrames(gd, [{}])
79+
}).then(function() {
7980
expect(f).toEqual([{name: 'frame 0'}, {name: 'frame 1'}]);
8081
}).catch(fail).then(done);
8182
});
8283

84+
it('casts number names to strings on insertion', function (done) {
85+
Plotly.addFrames(gd, [{name: 2}]).then(function () {
86+
expect(f).toEqual([{name: '2'}]);
87+
}).catch(fail).then(done);
88+
});
89+
90+
it('updates frames referenced by number', function (done) {
91+
Plotly.addFrames(gd, [{name: 2}]).then(function () {
92+
return Plotly.addFrames(gd, [{name: 2, layout: {foo: 'bar'}}]);
93+
}).then(function () {
94+
expect(f).toEqual([{name: '2', layout: {foo: 'bar'}}]);
95+
}).catch(fail).then(done);
96+
});
97+
98+
it('issues a warning if a number-named frame would overwrite a frame', function (done) {
99+
var warnings = [];
100+
spyOn(Lib, 'warn').and.callFake(function (msg){
101+
warnings.push(msg);
102+
});
103+
104+
Plotly.addFrames(gd, [{name: 2}]).then(function () {
105+
return Plotly.addFrames(gd, [{name: 2, layout: {foo: 'bar'}}]);
106+
}).then(function () {
107+
expect(warnings.length).toEqual(1);
108+
expect(warnings[0]).toMatch(/overwriting/);
109+
}).catch(fail).then(done);
110+
});
111+
83112
it('avoids name collisions', function(done) {
84113
Plotly.addFrames(gd, [{name: 'frame 0'}, {name: 'frame 2'}]).then(function() {
85114
expect(f).toEqual([{name: 'frame 0'}, {name: 'frame 2'}]);

0 commit comments

Comments
 (0)