From cb375656a4811d2cec7f3b8e664e7caa6a8a8c7d Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 5 Sep 2018 13:45:23 -0400 Subject: [PATCH 1/7] add responsive option to config `responsive: true` will trigger Plotly.resize whenver the window is resized --- package-lock.json | 38 +++++++++++++++++++++++++ package.json | 1 + src/plot_api/plot_api.js | 14 +++++++++ src/plot_api/plot_config.js | 3 ++ test/jasmine/.eslintrc | 3 ++ test/jasmine/karma.conf.js | 2 +- test/jasmine/tests/config_test.js | 47 +++++++++++++++++++++++++++++++ 7 files changed, 107 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2ec7d9ec2bf..8b17ba63fc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -124,6 +124,28 @@ "d3-interpolate": "1" } }, + "@types/bluebird": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.24.tgz", + "integrity": "sha512-YeQoDpq4Lm8ppSBqAnAeF/xy1cYp/dMTif2JFcvmAbETMRlvKHT2iLcWu+WyYiJO3b3Ivokwo7EQca/xfLVJmg==", + "dev": true + }, + "@types/karma": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@types/karma/-/karma-1.7.6.tgz", + "integrity": "sha512-VLyBOU0SmMjGTUpuZvPOzoR0GIKMGcYueGz803V55lbkI4oGsLG03rYP43kJowh9vNNkVERrDYYoFoTbMftzFw==", + "dev": true, + "requires": { + "@types/bluebird": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz", + "integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==", + "dev": true + }, "JSONStream": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.4.tgz", @@ -6187,6 +6209,12 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "jsonschema": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", + "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6308,6 +6336,16 @@ "colors": ">=1.0" } }, + "karma-viewport": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/karma-viewport/-/karma-viewport-1.0.2.tgz", + "integrity": "sha512-rvzY9UTVXHPt9QRwawyh1D50qzqtxRsoPe5svgOY5kvV7eigv8e5dcW3RSmPZ6m/3Hx+QwJEMY+kLhCmamKJ6A==", + "dev": true, + "requires": { + "@types/karma": "^1.7.3", + "jsonschema": "^1.1.1" + } + }, "kdbush": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-1.0.1.tgz", diff --git a/package.json b/package.json index 4a966f70a1a..e0f42fb32e0 100644 --- a/package.json +++ b/package.json @@ -142,6 +142,7 @@ "karma-jasmine-spec-tags": "^1.0.1", "karma-spec-reporter": "0.0.32", "karma-verbose-reporter": "0.0.6", + "karma-viewport": "^1.0.2", "madge": "^3.2.0", "minify-stream": "^1.2.0", "minimist": "^1.2.0", diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 9804f2d50ff..020430869c1 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -385,6 +385,15 @@ function emitAfterPlot(gd) { fullLayout._redrawFromAutoMarginCount--; } else { gd.emit('plotly_afterplot'); + + // make the figure responsive + if(gd._context.responsive && !gd._responsiveChartHandler) { + // Keep a reference to the resize handler to purge it down the road + gd._responsiveChartHandler = function() {Plots.resize(gd);}; + + // Listen to window resize + window.addEventListener('resize', gd._responsiveChartHandler); + } } } @@ -3155,6 +3164,11 @@ exports.purge = function purge(gd) { var fullData = gd._fullData || []; var calcdata = gd.calcdata || []; + // remove responsive handler + if(gd._responsiveChartHandler) { + window.removeEventListener('resize', gd._responsiveChartHandler); + } + // remove gl contexts Plots.cleanPlot([], {}, fullData, fullLayout, calcdata); diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js index 596f0bf43c3..574b618e0a7 100644 --- a/src/plot_api/plot_config.js +++ b/src/plot_api/plot_config.js @@ -57,6 +57,9 @@ module.exports = { */ autosizable: false, + // responsive: determines whether to change the layout size when window is resized + responsive: false, + // set the length of the undo/redo queue queueLength: 0, diff --git a/test/jasmine/.eslintrc b/test/jasmine/.eslintrc index d177999d069..d57cd856c99 100644 --- a/test/jasmine/.eslintrc +++ b/test/jasmine/.eslintrc @@ -3,5 +3,8 @@ "env": { "browser": true, "jasmine": true + }, + "globals": { + "viewport": true } } diff --git a/test/jasmine/karma.conf.js b/test/jasmine/karma.conf.js index c46ac22b472..66bce39e73c 100644 --- a/test/jasmine/karma.conf.js +++ b/test/jasmine/karma.conf.js @@ -137,7 +137,7 @@ func.defaultConfig = { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['jasmine', 'jasmine-spec-tags', 'browserify'], + frameworks: ['jasmine', 'jasmine-spec-tags', 'browserify', 'viewport'], // list of files / patterns to load in the browser // diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index 041aa96ae82..56a5e28e969 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -6,6 +6,7 @@ var destroyGraphDiv = require('../assets/destroy_graph_div'); var click = require('../assets/click'); var mouseEvent = require('../assets/mouse_event'); var failTest = require('../assets/fail_test'); +var delay = require('../assets/delay'); describe('config argument', function() { @@ -529,4 +530,50 @@ describe('config argument', function() { }); }); }); + + describe('responsive figure', function() { + var gd; + var data = [{x: [1, 2, 3, 4], y: [5, 10, 2, 8]}]; + + beforeEach(function() { + viewport.reset(); + gd = createGraphDiv(); + + // Make the graph fill the parent + gd.style.width = '100%'; + gd.style.height = '100%'; + }); + + afterEach(function() { + destroyGraphDiv(); + // Reset window size + viewport.reset(); + }); + + function checkLayoutSize(width, height) { + expect(gd._fullLayout.width).toBe(width); + expect(gd._fullLayout.height).toBe(height); + + var svg = document.getElementsByClassName('main-svg')[0]; + expect(+svg.getAttribute('width')).toBe(width); + expect(+svg.getAttribute('height')).toBe(height); + } + + it('should resize when the viewport width/height changes', function(done) { + var newWidth = 400, newHeight = 700; + Plotly.newPlot(gd, data, {}, {responsive: true}) + // Resize viewport + .then(function() { + viewport.set(newWidth, newHeight); + }) + // Wait for resize to happen (Plotly.resize has a 100ms timeout) + .then(delay(200)) + // Check final figure size + .then(function() { + checkLayoutSize(newWidth, newHeight); + }) + .catch(failTest) + .then(done); + }); + }); }); From 069b0e257509637bea08001d4d480fcc80a458c9 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 5 Sep 2018 14:02:30 -0400 Subject: [PATCH 2/7] fix typo in comment --- test/jasmine/tests/config_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index 56a5e28e969..65d4aed6a87 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -566,7 +566,7 @@ describe('config argument', function() { .then(function() { viewport.set(newWidth, newHeight); }) - // Wait for resize to happen (Plotly.resize has a 100ms timeout) + // Wait for resize to happen (Plotly.Plots.resize has a 100ms timeout) .then(delay(200)) // Check final figure size .then(function() { From 08d67366b8024597702c7af437773c2dd5045f42 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 5 Sep 2018 17:15:55 -0400 Subject: [PATCH 3/7] 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 --- src/lib/clear_responsive.js | 21 +++++++++ src/lib/index.js | 2 + src/plot_api/plot_api.js | 26 +++++------ src/plots/plots.js | 3 ++ test/jasmine/tests/config_test.js | 76 ++++++++++++++++++++++++++++--- 5 files changed, 107 insertions(+), 21 deletions(-) create mode 100644 src/lib/clear_responsive.js diff --git a/src/lib/clear_responsive.js b/src/lib/clear_responsive.js new file mode 100644 index 00000000000..1fbfb7848f1 --- /dev/null +++ b/src/lib/clear_responsive.js @@ -0,0 +1,21 @@ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Clear responsive handlers (if any). + * + * @param {DOM node or object} gd : graph div object + */ +module.exports = function clearResponsive(gd) { + if(gd._responsiveChartHandler) { + window.removeEventListener('resize', gd._responsiveChartHandler); + delete gd._responsiveChartHandler; + } +}; diff --git a/src/lib/index.js b/src/lib/index.js index cd9f7e2ad6b..10839689e54 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -118,6 +118,8 @@ lib.clearThrottle = throttleModule.clear; lib.getGraphDiv = require('./get_graph_div'); +lib.clearResponsive = require('./clear_responsive'); + lib.makeTraceGroups = require('./make_trace_groups'); lib._ = require('./localize'); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 020430869c1..4b724aa57c1 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -191,6 +191,15 @@ exports.plot = function(gd, data, layout, config) { gd.calcdata[i][0].trace = gd._fullData[i]; } + // make the figure responsive + if(gd._context.responsive && !gd._responsiveChartHandler) { + // Keep a reference to the resize handler to purge it down the road + gd._responsiveChartHandler = function() {Plots.resize(gd);}; + + // Listen to window resize + window.addEventListener('resize', gd._responsiveChartHandler); + } + /* * start async-friendly code - now we're actually drawing things */ @@ -385,15 +394,6 @@ function emitAfterPlot(gd) { fullLayout._redrawFromAutoMarginCount--; } else { gd.emit('plotly_afterplot'); - - // make the figure responsive - if(gd._context.responsive && !gd._responsiveChartHandler) { - // Keep a reference to the resize handler to purge it down the road - gd._responsiveChartHandler = function() {Plots.resize(gd);}; - - // Listen to window resize - window.addEventListener('resize', gd._responsiveChartHandler); - } } } @@ -2243,6 +2243,9 @@ exports.react = function(gd, data, layout, config) { gd._context = undefined; setPlotContext(gd, config); configChanged = diffConfig(oldConfig, gd._context); + + // remove responsive handler + Lib.clearResponsive(gd); } gd.data = data || []; @@ -3164,11 +3167,6 @@ exports.purge = function purge(gd) { var fullData = gd._fullData || []; var calcdata = gd.calcdata || []; - // remove responsive handler - if(gd._responsiveChartHandler) { - window.removeEventListener('resize', gd._responsiveChartHandler); - } - // remove gl contexts Plots.cleanPlot([], {}, fullData, fullLayout, calcdata); diff --git a/src/plots/plots.js b/src/plots/plots.js index 908289fa72c..2ec8811a917 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1536,6 +1536,9 @@ plots.purge = function(gd) { // remove any planned throttles Lib.clearThrottle(); + // remove responsive handler + Lib.clearResponsive(gd); + // data and layout delete gd.data; delete gd.layout; diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index 56a5e28e969..54e46cfb3d7 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -533,10 +533,12 @@ describe('config argument', function() { describe('responsive figure', function() { var gd; + var startWidth = 960, startHeight = 400; + var newWidth = 400, newHeight = 700; var data = [{x: [1, 2, 3, 4], y: [5, 10, 2, 8]}]; beforeEach(function() { - viewport.reset(); + viewport.set(startWidth, startHeight); gd = createGraphDiv(); // Make the graph fill the parent @@ -546,10 +548,27 @@ describe('config argument', function() { afterEach(function() { destroyGraphDiv(); - // Reset window size viewport.reset(); }); + function testResponsive(promise) { + return promise + .then(function() { + checkLayoutSize(startWidth, startHeight); + }) + // Resize viewport + .then(function() { + viewport.set(newWidth, newHeight); + }) + // Wait for resize to happen (Plotly.resize has a 100ms timeout) + .then(delay(200)) + // Check final figure size + .then(function() { + checkLayoutSize(newWidth, newHeight); + }) + .catch(failTest); + } + function checkLayoutSize(width, height) { expect(gd._fullLayout.width).toBe(width); expect(gd._fullLayout.height).toBe(height); @@ -560,17 +579,60 @@ describe('config argument', function() { } it('should resize when the viewport width/height changes', function(done) { - var newWidth = 400, newHeight = 700; - Plotly.newPlot(gd, data, {}, {responsive: true}) + var promise = Plotly.plot(gd, data, {}, {responsive: true}); + + testResponsive(promise) + .then(done); + }); + + it('should still be responsive if the plot is redrawn', function(done) { + var promise = Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() { + Plotly.restyle(gd, 'y[0]', data[0].y[0] * 2); + }); + + testResponsive(promise) + .then(done); + }); + + it('should still be responsive if the plot is purged and replotted', function(done) { + var promise = Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() { + Plotly.newPlot(gd, data, {}, {responsive: true}); + }); + + testResponsive(promise) + .then(done); + }); + + it('should become responsive if configured to be so by Plotly.react', function(done) { + var promise = Plotly.plot(gd, data, {}, {responsive: false}) + .then(function() { + Plotly.react(gd, data, {}, {responsive: true}); + }); + + testResponsive(promise) + .then(done); + }); + + it('should stop being responsive if configured to be so by Plotly.react', function(done) { + Plotly.plot(gd, data, {}, {responsive: true}) + // Check initial size + .then(function() { + checkLayoutSize(startWidth, startHeight); + }) + // Turn off responsiveness + .then(function() { + Plotly.react(gd, data, {}, {responsive: false}); + }) // Resize viewport .then(function() { viewport.set(newWidth, newHeight); }) - // Wait for resize to happen (Plotly.resize has a 100ms timeout) .then(delay(200)) - // Check final figure size + // Check final figure size hasn't changed .then(function() { - checkLayoutSize(newWidth, newHeight); + checkLayoutSize(startWidth, startHeight); }) .catch(failTest) .then(done); From d82447a714571c9b4566f2f87da6d0e9aa984bb5 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 6 Sep 2018 16:09:46 -0400 Subject: [PATCH 4/7] improve tests for responsive charts --- test/jasmine/tests/config_test.js | 99 ++++++++++++++----------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index ac15ed1c7cf..6f9a409a3e9 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -551,24 +551,6 @@ describe('config argument', function() { viewport.reset(); }); - function testResponsive(promise) { - return promise - .then(function() { - checkLayoutSize(startWidth, startHeight); - }) - // Resize viewport - .then(function() { - viewport.set(newWidth, newHeight); - }) - // Wait for resize to happen (Plotly.resize has an internal timeout) - .then(delay(200)) - // Check final figure size - .then(function() { - checkLayoutSize(newWidth, newHeight); - }) - .catch(failTest); - } - function checkLayoutSize(width, height) { expect(gd._fullLayout.width).toBe(width); expect(gd._fullLayout.height).toBe(height); @@ -578,63 +560,74 @@ describe('config argument', function() { expect(+svg.getAttribute('height')).toBe(height); } - it('should resize when the viewport width/height changes', function(done) { - var promise = Plotly.plot(gd, data, {}, {responsive: true}); + function testResponsive() { + checkLayoutSize(startWidth, startHeight); + viewport.set(newWidth, newHeight); + + return Promise.resolve() + .then(delay(200)) + .then(function() { + checkLayoutSize(newWidth, newHeight); + }) + .catch(failTest); + } - testResponsive(promise) + it('should resize when the viewport width/height changes', function(done) { + Plotly.plot(gd, data, {}, {responsive: true}) + .then(testResponsive) .then(done); }); - it('should still be responsive if the plot is redrawn', function(done) { - var promise = Plotly.plot(gd, data, {}, {responsive: true}) - .then(function() { - Plotly.restyle(gd, 'y[0]', data[0].y[0] * 2); - }); - - testResponsive(promise) + it('should still be responsive if the plot is edited', function(done) { + Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) + .then(testResponsive) .then(done); }); it('should still be responsive if the plot is purged and replotted', function(done) { - var promise = Plotly.plot(gd, data, {}, {responsive: true}) - .then(function() { - Plotly.newPlot(gd, data, {}, {responsive: true}); - }); - - testResponsive(promise) + Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() {return Plotly.newPlot(gd, data, {}, {responsive: true});}) + .then(testResponsive) .then(done); }); - it('should become responsive if configured to be so by Plotly.react', function(done) { - var promise = Plotly.plot(gd, data, {}, {responsive: false}) + it('should only have one resize handler when plotted more than once', function(done) { + var cntWindowResize = 0; + window.addEventListener('resize', function() {cntWindowResize++;}); + spyOn(Plotly.Plots, 'resize').and.callThrough(); + + Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) + .then(function() {viewport.set(newWidth, newHeight);}) + .then(delay(200)) .then(function() { - Plotly.react(gd, data, {}, {responsive: true}); - }); + expect(cntWindowResize).toBe(1); + expect(Plotly.Plots.resize.calls.count()).toBe(4); + }) + .catch(failTest) + .then(done); + }); - testResponsive(promise) + it('should become responsive if configured as such via Plotly.react', function(done) { + Plotly.plot(gd, data, {}, {responsive: false}) + .then(function() {return Plotly.react(gd, data, {}, {responsive: true});}) + .then(testResponsive) .then(done); }); - it('should stop being responsive if configured to be so by Plotly.react', function(done) { + it('should stop being responsive if configured as such via Plotly.react', function(done) { Plotly.plot(gd, data, {}, {responsive: true}) // Check initial size - .then(function() { - checkLayoutSize(startWidth, startHeight); - }) + .then(function() {checkLayoutSize(startWidth, startHeight);}) // Turn off responsiveness - .then(function() { - Plotly.react(gd, data, {}, {responsive: false}); - }) + .then(function() {return Plotly.react(gd, data, {}, {responsive: false});}) // Resize viewport - .then(function() { - viewport.set(newWidth, newHeight); - }) + .then(function() {viewport.set(newWidth, newHeight);}) // Wait for resize to happen (Plotly.resize has an internal timeout) .then(delay(200)) - // Check final figure size hasn't changed - .then(function() { - checkLayoutSize(startWidth, startHeight); - }) + // Check that final figure's size hasn't changed + .then(function() {checkLayoutSize(startWidth, startHeight);}) .catch(failTest) .then(done); }); From 62145e9f2e66dcec9c73653649d921ca03e1df9c Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 6 Sep 2018 17:50:22 -0400 Subject: [PATCH 5/7] fix test to check responsive charts only have one resize handler --- test/jasmine/tests/config_test.js | 35 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index 6f9a409a3e9..d7011dceaf0 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -572,6 +572,24 @@ describe('config argument', function() { .catch(failTest); } + it('should only have one resize handler when plotted more than once', function(done) { + var cntWindowResize = 0; + window.addEventListener('resize', function() {cntWindowResize++;}); + spyOn(Plotly.Plots, 'resize').and.callThrough(); + + Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) + .then(function() {viewport.set(newWidth, newHeight);}) + .then(delay(200)) + // .then(function() {viewport.set(newWidth, 2 * newHeight);}).then(delay(200)) + .then(function() { + expect(cntWindowResize).toBe(1); + expect(Plotly.Plots.resize.calls.count()).toBe(1); + }) + .catch(failTest) + .then(done); + }); + it('should resize when the viewport width/height changes', function(done) { Plotly.plot(gd, data, {}, {responsive: true}) .then(testResponsive) @@ -592,23 +610,6 @@ describe('config argument', function() { .then(done); }); - it('should only have one resize handler when plotted more than once', function(done) { - var cntWindowResize = 0; - window.addEventListener('resize', function() {cntWindowResize++;}); - spyOn(Plotly.Plots, 'resize').and.callThrough(); - - Plotly.plot(gd, data, {}, {responsive: true}) - .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) - .then(function() {viewport.set(newWidth, newHeight);}) - .then(delay(200)) - .then(function() { - expect(cntWindowResize).toBe(1); - expect(Plotly.Plots.resize.calls.count()).toBe(4); - }) - .catch(failTest) - .then(done); - }); - it('should become responsive if configured as such via Plotly.react', function(done) { Plotly.plot(gd, data, {}, {responsive: false}) .then(function() {return Plotly.react(gd, data, {}, {responsive: true});}) From ec9ffa1e70468b74fcc35b2d6f6e96c8ef647d14 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 6 Sep 2018 18:09:21 -0400 Subject: [PATCH 6/7] properly purge plots after each test --- test/jasmine/tests/config_test.js | 37 ++++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index d7011dceaf0..3b360d93dc5 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -547,6 +547,7 @@ describe('config argument', function() { }); afterEach(function() { + Plotly.purge(gd); // Needed to remove all event listeners destroyGraphDiv(); viewport.reset(); }); @@ -572,24 +573,6 @@ describe('config argument', function() { .catch(failTest); } - it('should only have one resize handler when plotted more than once', function(done) { - var cntWindowResize = 0; - window.addEventListener('resize', function() {cntWindowResize++;}); - spyOn(Plotly.Plots, 'resize').and.callThrough(); - - Plotly.plot(gd, data, {}, {responsive: true}) - .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) - .then(function() {viewport.set(newWidth, newHeight);}) - .then(delay(200)) - // .then(function() {viewport.set(newWidth, 2 * newHeight);}).then(delay(200)) - .then(function() { - expect(cntWindowResize).toBe(1); - expect(Plotly.Plots.resize.calls.count()).toBe(1); - }) - .catch(failTest) - .then(done); - }); - it('should resize when the viewport width/height changes', function(done) { Plotly.plot(gd, data, {}, {responsive: true}) .then(testResponsive) @@ -610,6 +593,24 @@ describe('config argument', function() { .then(done); }); + it('should only have one resize handler when plotted more than once', function(done) { + var cntWindowResize = 0; + window.addEventListener('resize', function() {cntWindowResize++;}); + spyOn(Plotly.Plots, 'resize').and.callThrough(); + + Plotly.plot(gd, data, {}, {responsive: true}) + .then(function() {return Plotly.restyle(gd, 'y[0]', data[0].y[0] + 2);}) + .then(function() {viewport.set(newWidth, newHeight);}) + .then(delay(200)) + // .then(function() {viewport.set(newWidth, 2 * newHeight);}).then(delay(200)) + .then(function() { + expect(cntWindowResize).toBe(1); + expect(Plotly.Plots.resize.calls.count()).toBe(1); + }) + .catch(failTest) + .then(done); + }); + it('should become responsive if configured as such via Plotly.react', function(done) { Plotly.plot(gd, data, {}, {responsive: false}) .then(function() {return Plotly.react(gd, data, {}, {responsive: true});}) From 1262172e6b0f5e6a215636e438b3e68557004903 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Fri, 7 Sep 2018 10:00:54 -0400 Subject: [PATCH 7/7] clear responsive handlers in `Plotly.plot` if needed --- src/plot_api/plot_api.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 4b724aa57c1..cd899de782c 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -192,12 +192,16 @@ exports.plot = function(gd, data, layout, config) { } // make the figure responsive - if(gd._context.responsive && !gd._responsiveChartHandler) { - // Keep a reference to the resize handler to purge it down the road - gd._responsiveChartHandler = function() {Plots.resize(gd);}; + if(gd._context.responsive) { + if(!gd._responsiveChartHandler) { + // Keep a reference to the resize handler to purge it down the road + gd._responsiveChartHandler = function() {Plots.resize(gd);}; - // Listen to window resize - window.addEventListener('resize', gd._responsiveChartHandler); + // Listen to window resize + window.addEventListener('resize', gd._responsiveChartHandler); + } + } else { + Lib.clearResponsive(gd); } /* @@ -2243,9 +2247,6 @@ exports.react = function(gd, data, layout, config) { gd._context = undefined; setPlotContext(gd, config); configChanged = diffConfig(oldConfig, gd._context); - - // remove responsive handler - Lib.clearResponsive(gd); } gd.data = data || [];