nylen / d3-process-map

Web application to illustrate the relationships between objects in a process using d3.js.
MIT License
416 stars 196 forks source link

Adding drop down filters for data? #14

Closed sinetwo closed 9 years ago

sinetwo commented 9 years ago

Firstly, great project!!

Say if I have two objects (OBJ-A, OBJ-B) that depend on a lot of other objects: OBJ-A: OBJ-1 OBJ-A: OBJ-2 OBJ-A: OBJ-3 OBJ-B: OBJ-4 OBJ-B: OBJ-5 OBJ-B: OBJ-6

...then i'd like to be able to do a dropdown menu to select OBJ-A, to only display anything that depends on OBJ-A, so the resulting list/visible visualisations would be: OBJ-A: OBJ-1 OBJ-A: OBJ-2 OBJ-A: OBJ-3

Would you happen to know where in the code I'd look to implement a filter for the dataset? At the moment I'm trying to follow the standard documentation but I can't seem to find much relation between how you load the data and how D3 does it. If you know where to look and implement, I will ensure that we give push back to the project when we have a suitable solution to populate multiple filters.

nylen commented 9 years ago

Yeah, this would be really nice to have.

Loading the data is more convoluted than necessary. This is simply because I had a dataset in the format like objects.json that you see, and I needed to get it into the format that d3.layout.force consumes (data values + the links between them, with source and target properties).

Here is roughly the code path for transforming and loading the data:

  1. script.js#L17 - Browser makes a request to json.php
  2. common.php#L93 - Server reads objects.json which has depends (child dependencies) for each object, and uses them to compute dependedOnBy (parent dependencies). Also loads documentation for each object
  3. script.js#L83 - Browser computes graph.links which is the list of { source: x, target: y } objects that d3.layout.force() needs.

So, to implement a simple filter, I'd put some code in between steps 2 and 3 above. See #13 for a code sample.

To make the filter fully dynamic (so that it does not require a page refresh), there would be a good bit more work needed - I didn't anticipate that sort of usage when I wrote the code. When the filter changes, you'd probably want to track which objects and links are changing visibility as a result, and use the standard d3 enter and exit selections to add/remove them from the DOM. Then, you'd want to recompute the force layout with graph.force.start() or similar.

(A semi-related enhancement: update the layout when the browser window is resized. See #15 for that.)

sinetwo commented 9 years ago

Thanks for the detailed response Nylen, I'll let you know our findings and provide you with a sample once we have it working. I'll detail some simple tests as well and keep flexibility in mind so we can push it.

We may stick to the easier solution of refreshing the page as that's acceptable for our purpose.