Skip to content

Commit d128a77

Browse files
committed
Merge branch 'master' into null-frames
Conflicts: test/jasmine/tests/animate_test.js
2 parents eb090db + 62b33d3 commit d128a77

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

src/plot_api/plot_api.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,7 +2258,6 @@ Plotly.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) {
22582258
frameOpts: frameOpts,
22592259
transitionOpts: transitionOpts,
22602260
};
2261-
22622261
if(i === frameList.length - 1) {
22632262
// The last frame in this .animate call stores the promise resolve
22642263
// and reject callbacks. This is how we ensure that the animation
@@ -2412,14 +2411,15 @@ Plotly.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) {
24122411
} else if(isFrameArray) {
24132412
for(i = 0; i < frameOrGroupNameOrFrameList.length; i++) {
24142413
var frameOrName = frameOrGroupNameOrFrameList[i];
2415-
if(typeof frameOrName === 'string') {
2414+
if(['number', 'string'].indexOf(typeof frameOrName) !== -1) {
2415+
frameOrName = String(frameOrName);
24162416
// In this case, there's an array and this frame is a string name:
24172417
frameList.push({
24182418
type: 'byname',
24192419
name: frameOrName,
24202420
data: setTransitionConfig({name: frameOrName})
24212421
});
2422-
} else {
2422+
} else if(Lib.isPlainObject(frameOrName)) {
24232423
frameList.push({
24242424
type: 'object',
24252425
data: setTransitionConfig(Lib.extendFlat({}, frameOrName))

src/plots/plots.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,9 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts)
17981798
}
17991799

18001800
function completeTransition(callback) {
1801+
// Fail-safe against purged plot:
1802+
if(!gd._transitionData) return;
1803+
18011804
flushCallbacks(gd._transitionData._interruptCallbacks);
18021805

18031806
return Promise.resolve().then(function() {
@@ -1815,6 +1818,9 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts)
18151818
}
18161819

18171820
function interruptPreviousTransitions() {
1821+
// Fail-safe against purged plot:
1822+
if(!gd._transitionData) return;
1823+
18181824
// If a transition is interrupted, set this to false. At the moment, the only thing that would
18191825
// interrupt a transition is another transition, so that it will momentarily be set to true
18201826
// again, but this determines whether autorange or dragbox work, so it's for the sake of

test/jasmine/tests/animate_test.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ describe('Test animate API', function() {
8888

8989
mockCopy = Lib.extendDeep({}, mock);
9090

91+
// ------------------------------------------------------------
92+
// NB: TRANSITION IS FAKED
93+
//
94+
// This means that you should not expect `.animate` to actually
95+
// modify the plot in any way in the tests below. For tests
96+
// involvingnon-faked transitions, see the bottom of this file.
97+
// ------------------------------------------------------------
98+
9199
spyOn(Plots, 'transition').and.callFake(function() {
92100
// Transition's fake behavior is just to delay by the duration
93101
// and resolve:
@@ -580,7 +588,7 @@ describe('Test animate API', function() {
580588
});
581589
});
582590

583-
describe('null frames', function() {
591+
describe('Animate API details', function() {
584592
'use strict';
585593

586594
var gd, mockCopy;
@@ -600,12 +608,38 @@ describe('null frames', function() {
600608
destroyGraphDiv();
601609
});
602610

603-
it('should not break everything', function(done) {
611+
it('null frames should not break everything', function(done) {
604612
gd._transitionData._frames.push(null);
605613

606614
Plotly.animate(gd, null, {
607615
frame: {duration: 0},
608616
transition: {duration: 0}
609617
}).catch(fail).then(done);
610618
});
619+
620+
it('does not fail if strings are not used', function(done) {
621+
Plotly.addFrames(gd, [{name: 8, data: [{x: [8, 7, 6]}]}]).then(function() {
622+
// Verify it was added as a string name:
623+
expect(gd._transitionData._frameHash['8']).not.toBeUndefined();
624+
625+
// Transition using a number:
626+
return Plotly.animate(gd, [8], {transition: {duration: 0}, frame: {duration: 0}});
627+
}).then(function() {
628+
// Confirm the result:
629+
expect(gd.data[0].x).toEqual([8, 7, 6]);
630+
}).catch(fail).then(done);
631+
});
632+
633+
it('ignores null and undefined frames', function(done) {
634+
var cnt = 0;
635+
gd.on('plotly_animatingframe', function() {cnt++;});
636+
637+
Plotly.animate(gd, ['frame0', null, undefined], {transition: {duration: 0}, frame: {duration: 0}}).then(function() {
638+
// Check only one animating was fired:
639+
expect(cnt).toEqual(1);
640+
641+
// Check unused frames did not affect the current frame:
642+
expect(gd._fullLayout._currentFrame).toEqual('frame0');
643+
}).catch(fail).then(done);
644+
});
611645
});

test/jasmine/tests/frame_api_test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ describe('Test frame api', function() {
6060
}).catch(fail).then(done);
6161
});
6262

63+
it('casts names to strings', function(done) {
64+
Plotly.addFrames(gd, [{name: 5}]).then(function() {
65+
expect(Object.keys(h)).toEqual(['5']);
66+
}).catch(fail).then(done);
67+
});
68+
6369
it('creates multiple unnamed frames at the same time', function(done) {
6470
Plotly.addFrames(gd, [{}, {}]).then(function() {
6571
expect(f).toEqual([{name: 'frame 0'}, {name: 'frame 1'}]);

0 commit comments

Comments
 (0)