'use strict'; var overrideAll = require('../../plot_api/edit_types').overrideAll; var getModuleCalcData = require('../../plots/get_data').getModuleCalcData; var plot = require('./plot'); var fxAttrs = require('../../components/fx/layout_attributes'); var setCursor = require('../../lib/setcursor'); var dragElement = require('../../components/dragelement'); var prepSelect = require('../../components/selections').prepSelect; var Lib = require('../../lib'); var Registry = require('../../registry'); var SANKEY = 'sankey'; exports.name = SANKEY; exports.baseLayoutAttrOverrides = overrideAll({ hoverlabel: fxAttrs.hoverlabel }, 'plot', 'nested'); exports.plot = function(gd) { var calcData = getModuleCalcData(gd.calcdata, SANKEY)[0]; plot(gd, calcData); exports.updateFx(gd); }; exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { var hadPlot = (oldFullLayout._has && oldFullLayout._has(SANKEY)); var hasPlot = (newFullLayout._has && newFullLayout._has(SANKEY)); if(hadPlot && !hasPlot) { oldFullLayout._paperdiv.selectAll('.sankey').remove(); oldFullLayout._paperdiv.selectAll('.bgsankey').remove(); } }; exports.updateFx = function(gd) { for(var i = 0; i < gd._fullData.length; i++) { subplotUpdateFx(gd, i); } }; function subplotUpdateFx(gd, index) { var trace = gd._fullData[index]; var fullLayout = gd._fullLayout; var dragMode = fullLayout.dragmode; var cursor = fullLayout.dragmode === 'pan' ? 'move' : 'crosshair'; var bgRect = trace._bgRect; if(!bgRect) return; if(dragMode === 'pan' || dragMode === 'zoom') return; setCursor(bgRect, cursor); var xaxis = { _id: 'x', c2p: Lib.identity, _offset: trace._sankey.translateX, _length: trace._sankey.width }; var yaxis = { _id: 'y', c2p: Lib.identity, _offset: trace._sankey.translateY, _length: trace._sankey.height }; // Note: dragOptions is needed to be declared for all dragmodes because // it's the object that holds persistent selection state. var dragOptions = { gd: gd, element: bgRect.node(), plotinfo: { id: index, xaxis: xaxis, yaxis: yaxis, fillRangeItems: Lib.noop }, subplot: index, // create mock x/y axes for hover routine xaxes: [xaxis], yaxes: [yaxis], doneFnCompleted: function(selection) { var traceNow = gd._fullData[index]; var newGroups; var oldGroups = traceNow.node.groups.slice(); var newGroup = []; function findNode(pt) { var nodes = traceNow._sankey.graph.nodes; for(var i = 0; i < nodes.length; i++) { if(nodes[i].pointNumber === pt) return nodes[i]; } } for(var j = 0; j < selection.length; j++) { var node = findNode(selection[j].pointNumber); if(!node) continue; // If the node represents a group if(node.group) { // Add all its children to the current selection for(var k = 0; k < node.childrenNodes.length; k++) { newGroup.push(node.childrenNodes[k].pointNumber); } // Flag group for removal from existing list of groups oldGroups[node.pointNumber - traceNow.node._count] = false; } else { newGroup.push(node.pointNumber); } } newGroups = oldGroups .filter(Boolean) .concat([newGroup]); Registry.call('_guiRestyle', gd, { 'node.groups': [ newGroups ] }, index); } }; dragOptions.prepFn = function(e, startX, startY) { prepSelect(e, startX, startY, dragOptions, dragMode); }; dragElement.init(dragOptions); }