Skip to content

Commit 08d6736

Browse files
committed
several improvements to responsive charts
- move cleanup code into Plots.purge - attach responsive handlers synchronously earlier in the drawing sequence - honors Plotly.react - add several tests
1 parent cb37565 commit 08d6736

File tree

5 files changed

+107
-21
lines changed

5 files changed

+107
-21
lines changed

src/lib/clear_responsive.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright 2012-2018, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
/**
12+
* Clear responsive handlers (if any).
13+
*
14+
* @param {DOM node or object} gd : graph div object
15+
*/
16+
module.exports = function clearResponsive(gd) {
17+
if(gd._responsiveChartHandler) {
18+
window.removeEventListener('resize', gd._responsiveChartHandler);
19+
delete gd._responsiveChartHandler;
20+
}
21+
};

src/lib/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ lib.clearThrottle = throttleModule.clear;
118118

119119
lib.getGraphDiv = require('./get_graph_div');
120120

121+
lib.clearResponsive = require('./clear_responsive');
122+
121123
lib.makeTraceGroups = require('./make_trace_groups');
122124

123125
lib._ = require('./localize');

src/plot_api/plot_api.js

+12-14
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ exports.plot = function(gd, data, layout, config) {
191191
gd.calcdata[i][0].trace = gd._fullData[i];
192192
}
193193

194+
// make the figure responsive
195+
if(gd._context.responsive && !gd._responsiveChartHandler) {
196+
// Keep a reference to the resize handler to purge it down the road
197+
gd._responsiveChartHandler = function() {Plots.resize(gd);};
198+
199+
// Listen to window resize
200+
window.addEventListener('resize', gd._responsiveChartHandler);
201+
}
202+
194203
/*
195204
* start async-friendly code - now we're actually drawing things
196205
*/
@@ -385,15 +394,6 @@ function emitAfterPlot(gd) {
385394
fullLayout._redrawFromAutoMarginCount--;
386395
} else {
387396
gd.emit('plotly_afterplot');
388-
389-
// make the figure responsive
390-
if(gd._context.responsive && !gd._responsiveChartHandler) {
391-
// Keep a reference to the resize handler to purge it down the road
392-
gd._responsiveChartHandler = function() {Plots.resize(gd);};
393-
394-
// Listen to window resize
395-
window.addEventListener('resize', gd._responsiveChartHandler);
396-
}
397397
}
398398
}
399399

@@ -2243,6 +2243,9 @@ exports.react = function(gd, data, layout, config) {
22432243
gd._context = undefined;
22442244
setPlotContext(gd, config);
22452245
configChanged = diffConfig(oldConfig, gd._context);
2246+
2247+
// remove responsive handler
2248+
Lib.clearResponsive(gd);
22462249
}
22472250

22482251
gd.data = data || [];
@@ -3164,11 +3167,6 @@ exports.purge = function purge(gd) {
31643167
var fullData = gd._fullData || [];
31653168
var calcdata = gd.calcdata || [];
31663169

3167-
// remove responsive handler
3168-
if(gd._responsiveChartHandler) {
3169-
window.removeEventListener('resize', gd._responsiveChartHandler);
3170-
}
3171-
31723170
// remove gl contexts
31733171
Plots.cleanPlot([], {}, fullData, fullLayout, calcdata);
31743172

src/plots/plots.js

+3
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,9 @@ plots.purge = function(gd) {
15361536
// remove any planned throttles
15371537
Lib.clearThrottle();
15381538

1539+
// remove responsive handler
1540+
Lib.clearResponsive(gd);
1541+
15391542
// data and layout
15401543
delete gd.data;
15411544
delete gd.layout;

test/jasmine/tests/config_test.js

+69-7
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,12 @@ describe('config argument', function() {
533533

534534
describe('responsive figure', function() {
535535
var gd;
536+
var startWidth = 960, startHeight = 400;
537+
var newWidth = 400, newHeight = 700;
536538
var data = [{x: [1, 2, 3, 4], y: [5, 10, 2, 8]}];
537539

538540
beforeEach(function() {
539-
viewport.reset();
541+
viewport.set(startWidth, startHeight);
540542
gd = createGraphDiv();
541543

542544
// Make the graph fill the parent
@@ -546,10 +548,27 @@ describe('config argument', function() {
546548

547549
afterEach(function() {
548550
destroyGraphDiv();
549-
// Reset window size
550551
viewport.reset();
551552
});
552553

554+
function testResponsive(promise) {
555+
return promise
556+
.then(function() {
557+
checkLayoutSize(startWidth, startHeight);
558+
})
559+
// Resize viewport
560+
.then(function() {
561+
viewport.set(newWidth, newHeight);
562+
})
563+
// Wait for resize to happen (Plotly.resize has a 100ms timeout)
564+
.then(delay(200))
565+
// Check final figure size
566+
.then(function() {
567+
checkLayoutSize(newWidth, newHeight);
568+
})
569+
.catch(failTest);
570+
}
571+
553572
function checkLayoutSize(width, height) {
554573
expect(gd._fullLayout.width).toBe(width);
555574
expect(gd._fullLayout.height).toBe(height);
@@ -560,17 +579,60 @@ describe('config argument', function() {
560579
}
561580

562581
it('should resize when the viewport width/height changes', function(done) {
563-
var newWidth = 400, newHeight = 700;
564-
Plotly.newPlot(gd, data, {}, {responsive: true})
582+
var promise = Plotly.plot(gd, data, {}, {responsive: true});
583+
584+
testResponsive(promise)
585+
.then(done);
586+
});
587+
588+
it('should still be responsive if the plot is redrawn', function(done) {
589+
var promise = Plotly.plot(gd, data, {}, {responsive: true})
590+
.then(function() {
591+
Plotly.restyle(gd, 'y[0]', data[0].y[0] * 2);
592+
});
593+
594+
testResponsive(promise)
595+
.then(done);
596+
});
597+
598+
it('should still be responsive if the plot is purged and replotted', function(done) {
599+
var promise = Plotly.plot(gd, data, {}, {responsive: true})
600+
.then(function() {
601+
Plotly.newPlot(gd, data, {}, {responsive: true});
602+
});
603+
604+
testResponsive(promise)
605+
.then(done);
606+
});
607+
608+
it('should become responsive if configured to be so by Plotly.react', function(done) {
609+
var promise = Plotly.plot(gd, data, {}, {responsive: false})
610+
.then(function() {
611+
Plotly.react(gd, data, {}, {responsive: true});
612+
});
613+
614+
testResponsive(promise)
615+
.then(done);
616+
});
617+
618+
it('should stop being responsive if configured to be so by Plotly.react', function(done) {
619+
Plotly.plot(gd, data, {}, {responsive: true})
620+
// Check initial size
621+
.then(function() {
622+
checkLayoutSize(startWidth, startHeight);
623+
})
624+
// Turn off responsiveness
625+
.then(function() {
626+
Plotly.react(gd, data, {}, {responsive: false});
627+
})
565628
// Resize viewport
566629
.then(function() {
567630
viewport.set(newWidth, newHeight);
568631
})
569-
// Wait for resize to happen (Plotly.resize has a 100ms timeout)
570632
.then(delay(200))
571-
// Check final figure size
633+
// Check final figure size hasn't changed
572634
.then(function() {
573-
checkLayoutSize(newWidth, newHeight);
635+
checkLayoutSize(startWidth, startHeight);
574636
})
575637
.catch(failTest)
576638
.then(done);

0 commit comments

Comments
 (0)