'use strict'; var parcoords = require('./parcoords'); var prepareRegl = require('../../lib/prepare_regl'); var isVisible = require('./helpers').isVisible; var reglPrecompiled = {}; function newIndex(visibleIndices, orig, dim) { var origIndex = orig.indexOf(dim); var currentIndex = visibleIndices.indexOf(origIndex); if(currentIndex === -1) { // invisible dimensions initially go to the end currentIndex += orig.length; } return currentIndex; } function sorter(visibleIndices, orig) { return function sorter(d1, d2) { return ( newIndex(visibleIndices, orig, d1) - newIndex(visibleIndices, orig, d2) ); }; } var exports = module.exports = function plot(gd, cdModule) { var fullLayout = gd._fullLayout; var success = prepareRegl(gd, [], reglPrecompiled); if(!success) return; var currentDims = {}; var initialDims = {}; var fullIndices = {}; var inputIndices = {}; var size = fullLayout._size; cdModule.forEach(function(d, i) { var trace = d[0].trace; fullIndices[i] = trace.index; var iIn = inputIndices[i] = trace._fullInput.index; currentDims[i] = gd.data[iIn].dimensions; initialDims[i] = gd.data[iIn].dimensions.slice(); }); var filterChanged = function(i, initialDimIndex, newRanges) { // Have updated `constraintrange` data on `gd.data` and raise `Plotly.restyle` event // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call var dim = initialDims[i][initialDimIndex]; var newConstraints = newRanges.map(function(r) { return r.slice(); }); // Store constraint range in preGUI // This one doesn't work if it's stored in pieces in _storeDirectGUIEdit // because it's an array of variable dimensionality. So store the whole // thing at once manually. var aStr = 'dimensions[' + initialDimIndex + '].constraintrange'; var preGUI = fullLayout._tracePreGUI[gd._fullData[fullIndices[i]]._fullInput.uid]; if(preGUI[aStr] === undefined) { var initialVal = dim.constraintrange; preGUI[aStr] = initialVal || null; } var fullDimension = gd._fullData[fullIndices[i]].dimensions[initialDimIndex]; if(!newConstraints.length) { delete dim.constraintrange; delete fullDimension.constraintrange; newConstraints = null; } else { if(newConstraints.length === 1) newConstraints = newConstraints[0]; dim.constraintrange = newConstraints; fullDimension.constraintrange = newConstraints.slice(); // wrap in another array for restyle event data newConstraints = [newConstraints]; } var restyleData = {}; restyleData[aStr] = newConstraints; gd.emit('plotly_restyle', [restyleData, [inputIndices[i]]]); }; var hover = function(eventData) { gd.emit('plotly_hover', eventData); }; var unhover = function(eventData) { gd.emit('plotly_unhover', eventData); }; var axesMoved = function(i, visibleIndices) { // Have updated order data on `gd.data` and raise `Plotly.restyle` event // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call // drag&drop sorting of the visible dimensions var orig = sorter(visibleIndices, initialDims[i].filter(isVisible)); currentDims[i].sort(orig); // invisible dimensions are not interpreted in the context of drag&drop sorting as an invisible dimension // cannot be dragged; they're interspersed into their original positions by this subsequent merging step initialDims[i].filter(function(d) {return !isVisible(d);}) .sort(function(d) { // subsequent splicing to be done left to right, otherwise indices may be incorrect return initialDims[i].indexOf(d); }) .forEach(function(d) { currentDims[i].splice(currentDims[i].indexOf(d), 1); // remove from the end currentDims[i].splice(initialDims[i].indexOf(d), 0, d); // insert at original index }); // TODO: we can't really store this part of the interaction state // directly as below, since it incudes data arrays. If we want to // persist column order we may have to do something special for this // case to just store the order itself. // Registry.call('_storeDirectGUIEdit', // gd.data[inputIndices[i]], // fullLayout._tracePreGUI[gd._fullData[fullIndices[i]]._fullInput.uid], // {dimensions: currentDims[i]} // ); gd.emit('plotly_restyle', [{dimensions: [currentDims[i]]}, [inputIndices[i]]]); }; parcoords( gd, cdModule, { // layout width: size.w, height: size.h, margin: { t: size.t, r: size.r, b: size.b, l: size.l } }, { // callbacks filterChanged: filterChanged, hover: hover, unhover: unhover, axesMoved: axesMoved } ); }; exports.reglPrecompiled = reglPrecompiled;