Giter Club home page Giter Club logo

parcoords-es's People

Contributors

bigfatdog avatar dchopson avatar joshhjacobson avatar timelyportfolio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

parcoords-es's Issues

scale api allows user to specify a customized scale

Per @ joshhjacobson 's feature request in issue #16

pc.scale allowed the user to specify the type of scale to use for the axis (log, linear, ordinal, custom). Perhaps pc.scale(input, [lower, upper], scale)? Maybe this is too much?

Clicking the column titles hides data?

I've noticed that a single click on one of the column titles causes the entire chart to render with no data. Am I missing something or is this a bug?

If this is a bug, any pointers as to where it might be located, might be able to look at fixing it. I've noticed it on the slickgrid-hidex-axis.html page.

NoData

Manually reorder axis

Is it possible to restore a manually saved order?

I am saving the value of .getOrderedDimensionKeys() in localStorage.
I tried to use something like .reorder({ 1: -1, 355: 999999999, 21: -9, 778: 999 }), .reorder(["355", "21", "778", "1"]), .dimensions({ 355: 999999999, 21: -9, 778: 999, 1: -1 }) and .dimensions(["355", "21", "778", "1"]) with calling .render().updateAxes() after each try, but nothing seems to reorder them.

In an example I managed to reorder them with the first variant but only with great differences of numbers and for manual inputs.

Is any of the function mentioned above supposed to work?
If yes, which one and how? Thank you in advice!

Use of selected() function

Hi,

I'm trying to use pc.selected() to return all data within brush extents ("1d-axes"). For example,

var pc = ParCoords()("#example")
  .data([
    [0,-0,0,0,0,1],
    [1,-1,1,2,1,1],
    [2,-2,4,4,0.5,1],
    [3,-3,9,6,0.33,1],
    [4,-4,16,8,0.25,1]
  ])
  .alpha(0.4)
  .render()
  .shadows()
  .reorderable()
  .brushMode("1D-axes");  // enable brushing
  .on("brushend", function(brushed) {

    console.log(pc.selected());

  });

However, I get a "TypeError: pc.selected is not a function"

Am I using this function correctly? If not, how else could I obtain all data within the brush extents as an array? Apologies if the solution is obvious, I'm still new to Javascript. Thanks!

Flipped axes have empty brushes

When an axis is upside down, regardless of whether it was flipped by double-clicking the title or with pc.flipAxes, brushing on that axis causes all polylines to disappear. However, if the axis is flipped back to its normal orientation, brushing works as expected. Interestingly, there is no console error...

Here is a quick screencast to illustrate the issue:
flip_broken

bundleDimension requires sylvester

Hi there,

I'd really like to be able to use pc.bundleDimension() without having to include sylvester.js in my html header. The vector function in this library is used for computeCentroids and returns Uncaught ReferenceError: $V is not defined at computeCentroids when sylvester.js is not included in the script.

The good news is there is a somewhat new library sylvester-es6 which should be compatible with parcoords-es and would be a quick fix.

I'd be happy to submit a pull request if you're ok with the dependency. Let me know.

Two parcoords instances are linked

@joshhjacobson mentioned a bug in #14 's follow up:

Another strange thing happens when working with two ParCoords variables:

       var pc1 = ParCoords()("#plot01")
            .alpha(0.4)
        var pc2 = ParCoords()("#plot02")
            .alpha(0.4)

        // load csv file and create the chart
        d3.csv('data/cars.csv').then(function(data) {
            pc1
                .data(data)
                .hideAxis(["name"])
                .composite("darker")
                .render()
                .shadows()
                .reorderable()
                .brushMode("1D-axes")  // enable brushing
                .on("brushend", function(){
                  console.log(pc1.selected());
                  console.log(pc2.selected());
                });

            pc2
                .data(data)
                .hideAxis(["name"])
                .composite("darker")
                .render()
                .shadows()
                .reorderable()
                .brushMode("1D-axes")  // enable brushing
                .on("brushend", function(){
                  console.log(pc1.selected());
                  console.log(pc2.selected());
                });
        });

        d3.select('#brushReset').on('click', function () {
            pc1.brushReset();
            pc2.brushReset();

        });

The two plots seem to be linked, in that console.log(pc1.selected()) and console.log(pc2.selected()) always return the same data even when brushes are different between plots. Could this be because of the way I'm loading the data?

Interestingly, you must also click the brushReset button twice in order for both plots to refresh.

Click-axis-to-reset-brush does not work with multi brush?

The multi brush feature works nicely, but in that mode it seems we can no longer click on the axis to clear the brushes.

In single-brush mode, it click-to-reset still works fine.

This can be seen in the included demo for multi-brushes.

feature request: allow user to set individual line types

Hi again,

In the same way that a user can specify pc.color() with the argument being either a single color or a function, I think it would be useful if they could also specify line type. Canvas has the lineWidth property and setLineDash() method. Using these tools in conjunction, the user could specify many different line types. It could look something like this:

pc.lineType(width = 2, dash = [5, 15])

or

pc.lineType(function)

For charts with lots of lines this could get messy, but for more simple charts I think this could be very powerful. What are your thoughts? Would this be straightforward to implement?

Best,
Josh

Left-most axis label cut off

Hi again,

I believe this is a minor formatting bug as it did not happen in the original parallel-coordinates examples. For longer axis labels, the left-most text is cut off at the edge of the chart's canvas layer. Below is a screen shot of the example in basic.html where the economy (mpg) variable is cut off.

image

Just thought I'd bring this to your attention.

Best,
Josh

compute_real_centroids return empty array

calling compute_real_centroids(row) returns nothing for me.
Tried data.map((row) => compute_real_centroids(row)) and just return an empty array for each row.

What am I doing wrong?

brush arguments for external visibility

@BigFatDog, as I thought more about this the commit comments d95b853#r29660382 probably are not the best way to discuss new features :). Promoting this to a new issue will give us a better opportunity to discuss and track.

this call works perfectly internally within parallel-coordinates. I struggle though with determining externally which brush we are working with on('brushstart', ...) and on('brushend', ...). This example (with a modified old parallel-coordinates) demonstrates the objective. Would it cause any problems to change

events.call('brushstart', pc, config.brushed);

to

events.call('brushstart', pc, config.brushed, arguments);

which leverages https://github.com/d3/d3-brush/blob/master/src/brush.js#L286?? If we do this, then the second argument to pc.on('brushend', function(a, args) {} will be the arguments which contain dimension. I am happy to submit a pull if you agree this is worthwhile.

ParCoords.dimensions() yscale not working?

Changing the scale with .dimension(dimension) is not working for me.

Setting a custom scale with yscale has been removed from the dimensions object in the axis-config example as well.

NPM install issue

Hi @BigFatDog
Thank you one more time for porting this to ES6.
For some reason when installing from NPM, module name is not parcoords-es, but parcoord-es,
so npm install parcoord-es --save works, while npm install parcoords-es --save doesn't.

Multi brush demo in d3 V4 ?

Firstly great work on parallel coordinates with updates on much needed D3 V4.

I have found a sample parallel coordinate with numerical and string axis in D3 V4 like this
http://plnkr.co/edit/dCNuBsaDNBwr7CrAJUBe?p=preview

I am looking to have multiple brush feature on an axis in that example ,something like this http://bl.ocks.org/bollwyvl/8463137 .

So do you have a demo example of multi brush in d3 V4, that may have both numerical and string axis and multi brush enabled on every axis?

Thanks for your time

How to make brushExtent() work with ordinal data?

Hey @BigFatDog, Thanks for developing this awesome library.

I am wondering if you could implement the change in brushExtent() to load data from ordinal scales. Currently, it fails because to my understanding you expect scaled and inverted values for input.

It may be a good idea to get raw selection inputs and make it work on ordinal scale as well.

outside filters with brushes

Summary

Often in integrated applications with parallel coordinates, I need the ability to filter the parallel coordinates from outside with other controls, such as HTML inputs or supplementary visualizations. Here is a very minimal example demonstrating the concept with a modified version of the original parallel-coordinates. Would you be interested in a pull request targeting this functionality?

image

Proof of Concept

As I mentioned, for the previous example, I modified the original parallel-coordinates to add outsideFilters to the API as shown in timelyportfolio/parallel-coordinates@40fa0dc. This poc only targeted categorical/discrete filtering, but ideally I envision robust filtering that would cover all data types.

Thoughts

In all the brush modes, we have something like this before determining what is selected.

...
  // Resolves broken examples for now. They expect to get the full dataset back from empty brushes
  if (actives.length === 0) return config.data;
...
  return config.data.filter(d => {
    switch (brushGroup.predicate) {
      case 'AND':
        return actives.every(function(p, dimension) {
          return within[config.dimensions[p].type](d, p, dimension);
        });
      case 'OR':
        return actives.some(function(p, dimension) {
          return within[config.dimensions[p].type](d, p, dimension);
        });
      default:
        throw new Error('Unknown brush predicate ' + config.brushPredicate);
    }
  });

We could filter config.data here first and then perform the selected logic to the filtered config.data.

  // Resolves broken examples for now. They expect to get the full dataset back from empty brushes
  if (actives.length === 0) return config.data;
...
  //  apply outside filters
  //    assuming we have created an appropriate filter function
  let filteredData = filter(config.data);
...
  return filteredData.filter(d => {
    switch (brushGroup.predicate) {
      case 'AND':
        return actives.every(function(p, dimension) {
          return within[config.dimensions[p].type](d, p, dimension);
        });
      case 'OR':
        return actives.some(function(p, dimension) {
          return within[config.dimensions[p].type](d, p, dimension);
        });
      default:
        throw new Error('Unknown brush predicate ' + config.brushPredicate);
    }
  });

Potential Helper Dependency

I discovered search.js that might help with the API for filtering spec.

pinging @gordonwoodhull since you had some interest in the other pull and you have an enormous wealth of knowledge from dc.js

Draw Horizontal line in the PCP chart

Is there any way to draw a horizontal line based on some value like we will have a separate Y axis scale then we want draw a horizontal line in the pcp chart.

when a hidden axis is revealed, it is detached from control (reorderable, brushes, etc)

@joshhjacobson has discovered this bug in issue #15
Thank @joshhjacobson for the detailed information

Thanks! This seems to have handled all the console errors, and axis reordering is mostly functional. While testing, I noticed a bug where the right-most axis seems to become disconnected from the canvas. You can still interact with all the other axes by dragging them around and brushing, but the right-most one is unresponsive. If you drag another axis toward it, the polylines will adjust accordingly, but the svg axis itself will remain fixed.

show

This was produced using the example above where I start with one axis hidden, and then click the button to 'show' it.

Axes configuration

pc.scale(input_axis, [lower, upper]) successfully adjusts the yscale domain and ticks of an axis, but the axis itself is the only thing affected -- the polylines are not adjusted. How would I go about updating the plot to match the new axis domain?

I'm guessing it has something to do with pc.applyAxisConfig() but I'm unsure what the correct parameters should be. Thanks for the help!

flip axes syntax?

Hi,

I'm wondering what the correct syntax to flip an individual axis or set of axes is? In the original parallel-coordinates library, it went something like this:

pc.flipAxes(["x", "y"]);

but when I try that code here, there is no effect. I noticed that the flipAxes syntax is found in the sideEffects.js file, but there is another file in the api called flip.js. The following does work, but only for one axis:

pc.flip(["x"])

When I try to apply it to more than one axis (i.e. pc.flip(["x", "y"])), I get the following error:

TypeError: Cannot read property 'yscale' of undefined
    at Function.flip (parcoords.esm.js:2898)

If you can point me in the direction of a solution, I may be able to implement this and submit a pull request. However, if it's a quick fix and you think it would be faster to take care of it yourself, that would be great too. Let me know!

Happy holidays,
Josh

Delegate styling to css

Currently it is not possible to change axis stroke color through css.

In the parcoords.css such css property is set to a default, but it has no effect because these properties are set with d3s .style() function, having priority over css.

The values set through javascript are the same as the ones on the css sheet leading me to believe they are set as defaults.

Some of these properties are merely stylistic in nature, which could be useful if configurable (through css specialy), however some of them could be tied to the shape of the plot.

I could find some properties that could outsourced solely to the css sheet making them instantly configurable:

Stroke and Fill in: (maybe shape-rendering)

axisElement
.selectAll('path')
.style('fill', 'none')
.style('stroke', '#222')
.style('shape-rendering', 'crispEdges');
axisElement
.selectAll('line')
.style('fill', 'none')
.style('stroke', '#222')
.style('shape-rendering', 'crispEdges');

axisElement
.selectAll('path')
.style('fill', 'none')
.style('stroke', '#222')
.style('shape-rendering', 'crispEdges');
axisElement
.selectAll('line')
.style('fill', 'none')
.style('stroke', '#222')
.style('shape-rendering', 'crispEdges');

Font in:

pc.svg = selection
.append('svg')
.attr('width', config.width)
.attr('height', config.height)
.style('font', '14px sans-serif')
.style('position', 'absolute')

Brush not appearing on axes which have string values?

Also tried on the 'reddit' example in the included demo folder.

Whenever there's a string axis, the brush doesn't appear and stuff is not filterable.
This feature works on the original parcoords.

Can this be fixed?
Were there heavy modifications in this fork?

How to correctly set brushExtents

Using the following code, I'm trying to set a brush extent, I just took this from the demo example.

this.parcoords = ParCoords()('#parcoords')
.data([
        [0,-0,0,0,0],
        [1,-1,1,2,1,
        [2,,4,4,0.5],
        [3,,9,6,],
        [4,-4,16,8,0.25]
      ])
      .render()
      .createAxes()
      .brushMode('1D-axes')
      .brushExtents({"2": [3,4]});

But when the brushExtents gets executed I get an error in the brushExtents function:

ERROR TypeError: pc.g(...).selectAll(...).reduce is not a function at Function.eval [as brushExtents] (parcoords.mjs:100)

BrushExtents function:

var brushExtents = function brushExtents(state, config, pc) {
  return function (extents) {
    var brushes = state.brushes;


    if (typeof extents === 'undefined') {
      return d3Collection.keys(config.dimensions).reduce(function (acc, cur) {
        var brush = brushes[cur];
        //todo: brush check
        if (brush !== undefined && d3Brush.brushSelection(brushNodes[cur]) !== null) {
          acc[d] = brush.extent();
        }

        return acc;
      }, {});
    } else {
      //first get all the brush selections
      var brushSelections = pc.g().selectAll('.brush').reduce(function (acc, cur) {
        acc[cur] = select(this);
        return acc;
      });

      // loop over each dimension and update appropriately (if it was passed in through extents)
      d3Collection.keys(config.dimensions).forEach(function (d) {
        if (extents[d] === undefined) {
          return;
        }

        var brush = brushes[d];
        if (brush !== undefined) {
          //update the extent
          brush.extent(extents[d]);

          //redraw the brush
          brushSelections[d].transition().duration(0).call(brush);

          //fire some events
          brush.event(brushSelections[d]);
        }
      });

      //redraw the chart
      pc.renderBrushed();

      return pc;
    }
  };
};

Provide a react demo

This is from discussion #72 Is it necessary to provide a React version for this library?
Originally posted by @jvmanke in #72 (comment)

Hey @BigFatDog maybe not build a separate library but maybe add some examples using it with react? I personally am struggling to get it working properly. Do you have a snippet I could look?

Need to provide a simple react app that with parcoords-es.

markedLineWidth option doesn't seem to work

I have a parcoords component set up and I'm trying to get the 'marked' data to appear very similar to selection via brushing. I've found that the line width option for marked doesn't actually change anything.

I'd appreciate also an easier way to make marked lines appear same as brushed lines. I'm using mark() to select data points that are selected in other components, and passed into parcoords. Brushed lines are used to propagate selected data back to other components.

Resize fixes in a sibling fork

@BigFatDog Thanks for this awesome port! I'm trying to embed parcoords-es in a way that supports resizing, brushing, and updating data. The combination of these three creates problems for me when using brush modes "1D-axes" and "1D-axes-multi".

It seems like some of this may be addressed by autodesk-forks/parallel-coordinates#1 and other recent commits in https://github.com/autodesk-forks/parallel-coordinates.

Is there any interest in trying to pull over these fixes? Or has the code diverged too much for that to be helpful?

flipAxisAndUpdatePCP() broken

Hi,

I believe this is a minor bug. When you double click the axis title to flip an axis, the polylines will update but the axis itself does not. The console gives: TypeError: brushes[d].event is not a function brushReset.js:24:10

Very best,
Josh

ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs 1035:12-17 Can't import the named export 'mouse' from non EcmaScript module (only default export is available)

Hi! I keep getting these errors on 'ng build' and before renaming the file './node_modules/parcoord-es/dist/parcoords.mjs' to something like './node_modules/parcoord-es/dist/Xparcoords.mjsX'. I use Angular 6. As I understand, there are some problems with webpack and .mjs files. What is the best way to deal with this problem. I keep getting these errors after each 'npm update' of parcoords-es:

ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1035:12-17 Can't import the named export 'mouse' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
103:29-35 Can't import the named export 'select' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1090:16-20 Can't import the named export 'drag' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1285:14-18 Can't import the named export 'drag' from non EcmaScript module (only default export is available)
.....
.....

Change highlight opacity?

There's a way to change the alphaOnBrushed setting which is great, but if I then use the highlight functionality that no longer gets respected. Is there a way to change the alpha for non highlighted polylines too?

Setting nullValueSeparator causes error

Set the nullValueSeparator to bottom causes the following error in console:

ERROR ReferenceError: h is not defined

It looks like the height property is not accessible. Maybe you've forgot to import the heigh utility in index,js file.

Any ideas?

Is it necessary to provide a React version for this library?

Hello guys,
I'm wondering if it is necessary to build a React version of this library.

Currently I'm using this library in React apps with React hooks.
I feel it would be better if there were a React version, but only slightly better because I cannot see too much improvements there. I haven't found reason that firmly demands a React version so far.

What do you think?
Yours
Yun Xing

updateAxes() broken?

When using the updateAxes function, I get the following error: TypeError: node is null

For a reproducible example, I've added it to brushing.html:

// load csv file and create the chart
        d3.csv('data/cars.csv').then(function(data) {
            parcoords
                .data(data)
                .hideAxis(["name"])
                .composite("darker")
                .render()
                .shadows()
                .reorderable()
                .brushMode("1D-axes")  // enable brushing
                .on("brushend", function(brushed) {

                  parcoords.updateAxes();

                });
        });

Any insight would be appreciated!

After Click-to-Reset 1d-axes-multi brush, paths are rendered in brush color

@ManiacalAce has discovered this bug in issue #10 Click-axis-to-reset-brush does not work with multi brush?

Thanks @ManiacalAce for the detailed descriptions, the bug is described as below:

@BigFatDog Seems like my issue stems from something else related to colors.

I was trying to have one color for regular, untouched stuff, and a different color for brushed items - which i could swear was possible in the original fork of this lib.

For example, If I have this (with color and brushedColor)

var pc = ParCoords({nullValueSeparator: "bottom"})("#example")
    .data([
        [0,-0,0,0,0,1],
        [1,-1,1,2,1,1],
        [2,,4,4,0.5,1],
        [3,,9,6,,],
        [4,-4,16,8,0.25,1]
    ])
    .color('#0000ff')
    .render()
    .shadows()
    .createAxes()
    .reorderable()
    .brushMode("1D-axes-multi")
    .brushedColor('#ff0000')

Initially, the lines are blue, as expected. Then when I brush some items, they become red. Then, when I click to reset, everything is red (when I expect it to be blue).

missing render and resize events

Thank you so much for converting this! I discovered that render and resize events are no longer exposed as they were before (see lines). Was this intentional?

Need best practice example of how to highlight from separate component

First of all, thank you for this amazing library!

In react app: I'd like to know how to call highlight on pc chart from a react-table or similar 'mouseover' row action.
App has 2 components:

  1. pc chart
  2. a table or grid below

How can the chart register to another component mouseover event. what's the best practice here so both component are not tightly coupled? any idea?

v2.29 multibrush and hideAxis bug

When using brushmode "1D-axes-multi" and performing a hideAxis call an error occurs in brus\1d-multi\brushreset.js

It seems properties are read in a forEach of an object (the axis that was just hidden?) that does not exist.

I modified the slickgrid example file to create a ready to use example, this example adds a button that removes three axes. This works OK for brushmode "1D-axes" but fails for "1D-axes-multi"

eg below code save as 'demo/slickgrid2.html'

<!doctype html>
<title>Linking to SlickGrid</title>

<!-- SlickGrid -->
<link rel="stylesheet" href="lib/slickgrid/slick.grid.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/jquery-ui-1.8.16.custom.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/examples.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/slick.pager.css" type="text/css"/>
<script src="lib/slickgrid/jquery-1.7.min.js"></script>
<script src="lib/slickgrid/jquery.event.drag-2.0.min.js"></script>
<script src="lib/slickgrid/slick.core.js"></script>
<script src="lib/slickgrid/slick.grid.js"></script>
<script src="lib/slickgrid/slick.pager.js"></script>
<script src="lib/slickgrid/slick.dataview.js"></script>
<!-- End SlickGrid -->

<link rel="stylesheet" type="text/css" href="./parcoords.css">
<link rel="stylesheet" type="text/css" href="style.css">
<style>
body, html {
  margin: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
  font-size: 12px;
}
#grid, #pager {
  position: fixed;
  width: 100%;
}
#grid {
  bottom: 0;
  height: 300px;
}
#pager {
  bottom: 306px;
  height: 20px;
}
.slick-row:hover {
  font-weight: bold;
  color: #069;
}
</style>
<script src="lib/d3.v5.min.js"></script>
<script src="./parcoords.standalone.js"></script>
<script src="lib/divgrid.js"></script>
<button id="show_ext">remove axes</button>
<div id="example" class="parcoords" style="height:240px;"></div>
<div id="grid"></div>
<div id="pager"></div>
<script id="brushing">

var parcoords = ParCoords()("#example")
    .alpha(0.4)
    .mode("queue") // progressive rendering
    .height(d3.max([document.body.clientHeight-326, 220]))
    .margin({
      top: 36,
      left: 0,
      right: 0,
      bottom: 16
    });

    d3.select('#show_ext').on('click', function() {
      let hiddencolumns =['cylinders', 'power (hp)', 'year'];
      parcoords.hideAxis(hiddencolumns);
      parcoords.render().updateAxes(0);
    });


// load csv file and create the chart
d3.csv('data/cars.csv').then(function(data) {
  // slickgrid needs each data element to have an id
  data.forEach(function(d,i) { d.id = d.id || i; });

  parcoords
    .data(data)
    .hideAxis(["name"])
    .render()
    .reorderable()
    .brushMode("1D-axes-multi");

  // setting up grid
  var column_keys = d3.keys(data[0]);
  var columns = column_keys.map(function(key,i) {
    return {
      id: key,
      name: key,
      field: key,
      sortable: true
    }
  });

  var options = {
    enableCellNavigation: true,
    enableColumnReorder: false,
    multiColumnSort: false
  };

  var dataView = new Slick.Data.DataView();
  var grid = new Slick.Grid("#grid", dataView, columns, options);
  var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));

  // wire up model events to drive the grid
  dataView.onRowCountChanged.subscribe(function (e, args) {
    grid.updateRowCount();
    grid.render();
  });

  dataView.onRowsChanged.subscribe(function (e, args) {
    grid.invalidateRows(args.rows);
    grid.render();
  });

  // column sorting
  var sortcol = column_keys[0];
  var sortdir = 1;

  function comparer(a, b) {
    var x = a[sortcol], y = b[sortcol];
    return (x == y ? 0 : (x > y ? 1 : -1));
  }
  
  // click header to sort grid column
  grid.onSort.subscribe(function (e, args) {
    sortdir = args.sortAsc ? 1 : -1;
    sortcol = args.sortCol.field;

    if ($.browser.msie && $.browser.version <= 8) {
      dataView.fastSort(sortcol, args.sortAsc);
    } else {
      dataView.sort(comparer, args.sortAsc);
    }
  });

  // highlight row in chart
  grid.onMouseEnter.subscribe(function(e,args) {
    // Get row number from grid
    var grid_row = grid.getCellFromEvent(e).row;

    // Get the id of the item referenced in grid_row
    var item_id = grid.getDataItem(grid_row).id;
    var d = parcoords.brushed() || data;

    // Get the element position of the id in the data object
    elementPos = d.map(function(x) {return x.id; }).indexOf(item_id);

    // Highlight that element in the parallel coordinates graph
    parcoords.highlight([d[elementPos]]);
  });

  grid.onMouseLeave.subscribe(function(e,args) {
    parcoords.unhighlight();
  });

  // fill grid with data
  gridUpdate(data);

  // update grid on brush
  parcoords.on("brush", function(d) {
    gridUpdate(d);
  });

  function gridUpdate(data) {
    dataView.beginUpdate();
    dataView.setItems(data);
    dataView.endUpdate();
  };

});
</script>

hideAxis is recently broken

In version 2.2.0, the bug fix in the brushFor function had the side effect of partially breaking hideAxis. The function works when data is first added to the chart, but if called individually there is an error. The following, taken from the brushing.html demo, demonstrates the issue:

d3.csv('data/cars.csv').then(function(data) {
            parcoords
                .data(data)
                .hideAxis(["name"])
                .composite("darker")
                .render()
                .shadows()
                .reorderable()
                .brushMode("1D-axes");  // enable brushing

            // next line is the problem (added for demonstration)
            parcoords.hideAxis(['year']).render().updateAxes(0);

        });

This gives:

Uncaught (in promise) TypeError: Cannot read property 'yscale' of undefined
    at convertBrushArguments (brushFor.js:29)
    at SVGGElement.<anonymous> (brushFor.js:63)
    at Dispatch.apply (dispatch.js:61)
    at customEvent (on.js:103)
    at Emitter.emit (brush.js:286)
    at Emitter.brush (brush.js:278)
    at SVGGElement.<anonymous> (brush.js:222)
    at Selection.selection_each [as each] (each.js:5)
    at brush.move (brush.js:212)
    at Selection.selection_call [as call] (call.js:4)

In versions prior to 2.2.0, this was not an issue. Now, it seems that the axis being referenced in brushFor.js here

const convertBrushArguments = args => {
    const args_array = Array.prototype.slice.call(args);
    const axis = args_array[0];
    // ordinal scales do not have invert
    const yscale = config.dimensions[axis].yscale;

has already been removed from config.dimensions in sideEffects.js here

.on('hideAxis', d => {
      pc.dimensions(pc.applyDimensionDefaults());
      pc.dimensions(without(config.dimensions, d.value));  // this line
    })

thus, config.dimensions[axis] is undefined.

I would attempt to fix this myself, but I'm not really sure why it's happening. @timelyportfolio do you have any thoughts on this? Maybe we could delay execution of pc.dimensions(without(config.dimensions, d.value)) until after brushFor has been executed?

add ability to brush null data

I like the concept of displaying null data outside of the main chart, but I also would like to be able to include items that have a null value in the selection when brushing on that axis.
Either by a switch (include_nulldata_in_brush) per viewer, or per axis or by using a multi brush per axis and extending the brushable area to the axis regions where the null values are plotted.

Why: we use the parallel coordinate viewer for selection but when a measurement was not (yet) made it is uncertain. So the items could be within the brush range, we dont know. To be safe we would like to include these items

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.