diff --git a/src/traces/sunburst/fx.js b/src/traces/sunburst/fx.js index 5efae33736f..fd043c13c73 100644 --- a/src/traces/sunburst/fx.js +++ b/src/traces/sunburst/fx.js @@ -217,27 +217,33 @@ module.exports = function attachFxHandlers(sliceTop, entry, gd, cd, opts) { var fullLayoutNow = gd._fullLayout; var traceNow = gd._fullData[trace.index]; - var clickVal = Events.triggerHandler(gd, 'plotly_' + trace.type + 'click', { + var noTransition = isSunburst && (helpers.isHierarchyRoot(pt) || helpers.isLeaf(pt)); + + var id = helpers.getPtId(pt); + var nextEntry = helpers.isEntry(pt) ? + helpers.findEntryWithChild(hierarchy, id) : + helpers.findEntryWithLevel(hierarchy, id); + var nextLevel = helpers.getPtId(nextEntry); + + var typeClickEvtData = { points: [makeEventData(pt, traceNow, opts.eventDataKeys)], event: d3.event - }); + }; + if(!noTransition) typeClickEvtData.nextLevel = nextLevel; - // 'regular' click event when sunburst/treemap click is disabled or when - // clicking on leaves or the hierarchy root - if( - clickVal === false || - isSunburst && ( - helpers.isHierarchyRoot(pt) || - helpers.isLeaf(pt) - ) - ) { - if(fullLayoutNow.hovermode) { - gd._hoverdata = [makeEventData(pt, traceNow, opts.eventDataKeys)]; - Fx.click(gd, d3.event); - } - return; + var clickVal = Events.triggerHandler(gd, 'plotly_' + trace.type + 'click', typeClickEvtData); + + if(clickVal !== false && fullLayoutNow.hovermode) { + gd._hoverdata = [makeEventData(pt, traceNow, opts.eventDataKeys)]; + Fx.click(gd, d3.event); } + // if click does not trigger a transition, we're done! + if(noTransition) return; + + // if custom handler returns false, we're done! + if(clickVal === false) return; + // skip if triggered from dragging a nearby cartesian subplot if(gd._dragging) return; @@ -251,13 +257,8 @@ module.exports = function attachFxHandlers(sliceTop, entry, gd, cd, opts) { level: traceNow.level }); - var id = helpers.getPtId(pt); - var nextEntry = helpers.isEntry(pt) ? - helpers.findEntryWithChild(hierarchy, id) : - helpers.findEntryWithLevel(hierarchy, id); - var frame = { - data: [{level: helpers.getPtId(nextEntry)}], + data: [{level: nextLevel}], traces: [trace.index] }; diff --git a/test/jasmine/tests/sunburst_test.js b/test/jasmine/tests/sunburst_test.js index b46033f7dbb..3d2727dceeb 100644 --- a/test/jasmine/tests/sunburst_test.js +++ b/test/jasmine/tests/sunburst_test.js @@ -811,11 +811,16 @@ describe('Test sunburst clicks:', function() { if(trackers.sunburstclick.length === 1) { expect(trackers.sunburstclick[0].event).toBeDefined(); expect(trackers.sunburstclick[0].points[0].label).toBe('Seth'); + expect(trackers.sunburstclick[0].nextLevel).toBe('Seth'); } else { fail('incorrect plotly_sunburstclick triggering'); } - if(trackers.click.length) { + if(trackers.click.length === 1) { + expect(trackers.click[0].event).toBeDefined(); + expect(trackers.click[0].points[0].label).toBe('Seth'); + expect(trackers.click[0].nextLevel).not.toBeDefined(); + } else { fail('incorrect plotly_click triggering'); } @@ -888,16 +893,6 @@ describe('Test sunburst clicks:', function() { it('should not trigger animation when graph is transitioning', function(done) { var mock = Lib.extendDeep({}, require('@mocks/sunburst_first.json')); - // should be same before and after 2nd click - function _assertCommon(msg) { - if(trackers.click.length) { - fail('incorrect plotly_click triggering - ' + msg); - } - if(trackers.animating.length !== 1) { - fail('incorrect plotly_animating triggering - ' + msg); - } - } - Plotly.plot(gd, mock) .then(setupListeners()) .then(click(gd, 2)) @@ -907,27 +902,49 @@ describe('Test sunburst clicks:', function() { if(trackers.sunburstclick.length === 1) { expect(trackers.sunburstclick[0].event).toBeDefined(msg); expect(trackers.sunburstclick[0].points[0].label).toBe('Seth', msg); + expect(trackers.sunburstclick[0].nextLevel).toBe('Seth', msg); } else { fail('incorrect plotly_sunburstclick triggering - ' + msg); } - _assertCommon(msg); + if(trackers.click.length === 1) { + expect(trackers.click[0].event).toBeDefined(msg); + expect(trackers.click[0].points[0].label).toBe('Seth', msg); + expect(trackers.click[0].nextLevel).not.toBeDefined(msg); + } else { + fail('incorrect plotly_click triggering - ' + msg); + } + + if(trackers.animating.length !== 1) { + fail('incorrect plotly_animating triggering - ' + msg); + } }) .then(click(gd, 4)) .then(function() { var msg = 'after 2nd click'; - // should trigger plotly_sunburstclick twice, but not additional - // plotly_click nor plotly_animating + // should trigger plotly_sunburstclick and plotly_click twice, + // but not plotly_animating if(trackers.sunburstclick.length === 2) { expect(trackers.sunburstclick[0].event).toBeDefined(msg); expect(trackers.sunburstclick[0].points[0].label).toBe('Awan', msg); + expect(trackers.sunburstclick[0].nextLevel).toBe('Awan', msg); } else { fail('incorrect plotly_sunburstclick triggering - ' + msg); } - _assertCommon(msg); + if(trackers.click.length === 2) { + expect(trackers.click[0].event).toBeDefined(msg); + expect(trackers.click[0].points[0].label).toBe('Awan', msg); + expect(trackers.click[0].nextLevel).not.toBeDefined(msg); + } else { + fail('incorrect plotly_click triggering - ' + msg); + } + + if(trackers.animating.length !== 1) { + fail('incorrect plotly_animating triggering - ' + msg); + } }) .catch(failTest) .then(done); @@ -947,10 +964,7 @@ describe('Test sunburst clicks:', function() { fail('incorrect plotly_sunburstclick triggering'); } - if(trackers.click.length === 1) { - expect(trackers.click[0].event).toBeDefined(); - expect(trackers.click[0].points[0].label).toBe('Seth'); - } else { + if(trackers.click.length !== 0) { fail('incorrect plotly_click triggering'); } diff --git a/test/jasmine/tests/treemap_test.js b/test/jasmine/tests/treemap_test.js index 96d89755d31..4e4357333dc 100644 --- a/test/jasmine/tests/treemap_test.js +++ b/test/jasmine/tests/treemap_test.js @@ -1042,11 +1042,16 @@ describe('Test treemap clicks:', function() { if(trackers.treemapclick.length === 1) { expect(trackers.treemapclick[0].event).toBeDefined(); expect(trackers.treemapclick[0].points[0].label).toBe('Seth'); + expect(trackers.treemapclick[0].nextLevel).toBe('Seth'); } else { fail('incorrect plotly_treemapclick triggering'); } - if(trackers.click.length) { + if(trackers.click.length === 1) { + expect(trackers.click[0].event).toBeDefined(); + expect(trackers.click[0].points[0].label).toBe('Seth'); + expect(trackers.click[0].nextLevel).not.toBeDefined(); + } else { fail('incorrect plotly_click triggering'); } @@ -1084,16 +1089,6 @@ describe('Test treemap clicks:', function() { it('should not trigger animation when graph is transitioning', function(done) { var mock = Lib.extendDeep({}, require('@mocks/treemap_first.json')); - // should be same before and after 2nd click - function _assertCommon(msg) { - if(trackers.click.length) { - fail('incorrect plotly_click triggering - ' + msg); - } - if(trackers.animating.length !== 1) { - fail('incorrect plotly_animating triggering - ' + msg); - } - } - Plotly.plot(gd, mock) .then(setupListeners()) .then(click(gd, 2)) @@ -1103,27 +1098,50 @@ describe('Test treemap clicks:', function() { if(trackers.treemapclick.length === 1) { expect(trackers.treemapclick[0].event).toBeDefined(msg); expect(trackers.treemapclick[0].points[0].label).toBe('Seth', msg); + expect(trackers.treemapclick[0].nextLevel).toBe('Seth', msg); } else { fail('incorrect plotly_treemapclick triggering - ' + msg); } - _assertCommon(msg); + if(trackers.click.length === 1) { + expect(trackers.click[0].event).toBeDefined(msg); + expect(trackers.click[0].points[0].label).toBe('Seth', msg); + expect(trackers.click[0].nextLevel).not.toBeDefined(msg); + } else { + fail('incorrect plotly_click triggering - ' + msg); + } + + if(trackers.animating.length !== 1) { + fail('incorrect plotly_animating triggering - ' + msg); + } }) .then(click(gd, 4)) .then(function() { var msg = 'after 2nd click'; - // should trigger plotly_treemapclick twice, but not additional - // plotly_click nor plotly_animating + // should trigger plotly_treemapclick and plotly_click twice, + // but not plotly_animating if(trackers.treemapclick.length === 2) { expect(trackers.treemapclick[0].event).toBeDefined(msg); expect(trackers.treemapclick[0].points[0].label).toBe('Awan', msg); + expect(trackers.treemapclick[0].nextLevel).toBe('Awan', msg); } else { fail('incorrect plotly_treemapclick triggering - ' + msg); } - _assertCommon(msg); + if(trackers.click.length === 2) { + expect(trackers.click[0].event).toBeDefined(msg); + expect(trackers.click[0].points[0].label).toBe('Awan', msg); + expect(trackers.click[0].nextLevel).not.toBeDefined(msg); + } else { + fail('incorrect plotly_click triggering - ' + msg); + } + + + if(trackers.animating.length !== 1) { + fail('incorrect plotly_animating triggering - ' + msg); + } }) .catch(failTest) .then(done); @@ -1143,10 +1161,7 @@ describe('Test treemap clicks:', function() { fail('incorrect plotly_treemapclick triggering'); } - if(trackers.click.length === 1) { - expect(trackers.click[0].event).toBeDefined(); - expect(trackers.click[0].points[0].label).toBe('Seth'); - } else { + if(trackers.click.length !== 0) { fail('incorrect plotly_click triggering'); }