diff --git a/draftlogs/7963_add.md b/draftlogs/7963_add.md new file mode 100644 index 00000000000..e8450e18b47 --- /dev/null +++ b/draftlogs/7963_add.md @@ -0,0 +1 @@ +- Add an opt-in modebar button for downloading Plotly figures as JSON [[#7963](https://github.com/plotly/plotly.js/pull/7963)] diff --git a/src/components/modebar/buttons.js b/src/components/modebar/buttons.js index 267d109d5c9..3be005b944f 100644 --- a/src/components/modebar/buttons.js +++ b/src/components/modebar/buttons.js @@ -68,6 +68,18 @@ modeBarButtons.toImage = { } }; +modeBarButtons.downloadJson = { + name: 'downloadJson', + title: function(gd) { return _(gd, 'Download plot as JSON'); }, + icon: Icons.disk, + click: function(gd) { + Registry.call('downloadImage', gd, {format: 'full-json'}) + .catch(function() { + Lib.notifier(_(gd, 'Sorry, there was a problem downloading your JSON file!'), 'long', gd); + }); + } +}; + modeBarButtons.sendChartToCloud = { name: 'sendChartToCloud', title: function(gd) { return _(gd, 'Share with Plotly Cloud'); }, diff --git a/src/components/modebar/constants.js b/src/components/modebar/constants.js index 788cbb5ae4e..caee7c3a274 100644 --- a/src/components/modebar/constants.js +++ b/src/components/modebar/constants.js @@ -18,7 +18,7 @@ var backButtons = [ 'hovercompare', 'togglehover', 'togglespikelines' -].concat(DRAW_MODES); +].concat(DRAW_MODES, ['downloadJson']); var foreButtons = []; var addToForeButtons = function(b) { diff --git a/src/components/modebar/manage.js b/src/components/modebar/manage.js index f00a046c486..a561f570b80 100644 --- a/src/components/modebar/manage.js +++ b/src/components/modebar/manage.js @@ -258,6 +258,8 @@ function getButtonGroups(gd) { enableHover('hoverClosestGeo'); enableHover('hoverClosest3d'); enableHover('hoverClosestPie'); + } else if(b === 'downloadjson') { + newList.push(modeBarButtons.downloadJson); } } else newList.push(b); } diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js index 55237deb55c..33c008a36f4 100644 --- a/src/plot_api/plot_config.js +++ b/src/plot_api/plot_config.js @@ -303,7 +303,8 @@ var configAttributes = { 'To enable predefined modebar buttons e.g. shape drawing, hover and spikelines,', 'simply provide their string name(s). This could include:', '*v1hovermode*, *hoverclosest*, *hovercompare*, *togglehover*, *togglespikelines*,', - '*drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect* and *eraseshape*.', + '*drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect*, *eraseshape*', + 'and *downloadJson*.', 'Please note that these predefined buttons will only be shown if they are compatible', 'with all trace types used in a graph.' ].join(' ') diff --git a/test/jasmine/tests/modebar_test.js b/test/jasmine/tests/modebar_test.js index e3c3fb919ed..2b2cc4dd8ce 100644 --- a/test/jasmine/tests/modebar_test.js +++ b/test/jasmine/tests/modebar_test.js @@ -1102,6 +1102,27 @@ describe('ModeBar', function() { }); }); + describe('downloadJson handler', function() { + beforeEach(function() { + spyOn(Registry, 'call').and.callFake(function() { + return Promise.resolve(); + }); + gd = createGraphDiv(); + }); + + it('should request a full JSON download', function(done) { + Plotly.newPlot(gd, {data: [], layout: {}, config: { + modeBarButtonsToAdd: ['downloadJson'] + }}) + .then(function() { + selectButton(gd._fullLayout._modeBar, 'downloadJson').click(); + expect(Registry.call) + .toHaveBeenCalledWith('downloadImage', gd, {format: 'full-json'}); + }) + .then(done, done.fail); + }); + }); + describe('cartesian handlers', function() { beforeEach(function(done) { var mockData = [{ diff --git a/test/plot-schema.json b/test/plot-schema.json index 78614b86693..738bad5408b 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -255,7 +255,7 @@ "valType": "any" }, "modeBarButtonsToAdd": { - "description": "Add mode bar button using config objects See ./components/modebar/buttons.js for list of arguments. To enable predefined modebar buttons e.g. shape drawing, hover and spikelines, simply provide their string name(s). This could include: *v1hovermode*, *hoverclosest*, *hovercompare*, *togglehover*, *togglespikelines*, *drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect* and *eraseshape*. Please note that these predefined buttons will only be shown if they are compatible with all trace types used in a graph.", + "description": "Add mode bar button using config objects See ./components/modebar/buttons.js for list of arguments. To enable predefined modebar buttons e.g. shape drawing, hover and spikelines, simply provide their string name(s). This could include: *v1hovermode*, *hoverclosest*, *hovercompare*, *togglehover*, *togglespikelines*, *drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect*, *eraseshape* and *downloadJson*. Please note that these predefined buttons will only be shown if they are compatible with all trace types used in a graph.", "dflt": [], "valType": "any" }, @@ -4606,7 +4606,7 @@ }, "add": { "arrayOk": true, - "description": "Determines which predefined modebar buttons to add. Please note that these buttons will only be shown if they are compatible with all trace types used in a graph. Similar to `config.modeBarButtonsToAdd` option. This may include *v1hovermode*, *hoverclosest*, *hovercompare*, *togglehover*, *togglespikelines*, *drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect*, *eraseshape*.", + "description": "Determines which predefined modebar buttons to add. Please note that these buttons will only be shown if they are compatible with all trace types used in a graph. Similar to `config.modeBarButtonsToAdd` option. This may include *v1hovermode*, *hoverclosest*, *hovercompare*, *togglehover*, *togglespikelines*, *drawline*, *drawopenpath*, *drawclosedpath*, *drawcircle*, *drawrect*, *eraseshape*, *downloadJson*.", "dflt": "", "editType": "modebar", "valType": "string"