Tree diagram: multiple on one page - javascript

I am attempting to put 2 d3.js tree diagrams, as seen here http://bl.ocks.org/1249394
on one page. Both trees will be loaded with different data from Javascript objects. The first one will appear in:
<div id="chart"></div>
and the second tree will be loaded in:
<div id="chart2"></div>
Both #chart and #chart2 are on the same page, with the first tree (#chart) appearing at the top of the page, and the 2nd (#chart2) right under it as that is how the chart divs are arranged. To do this I have applied the same code from http://bl.ocks.org/1249394 twice. One for each div with the only difference between the 2 pieces of code being the location of the tree that is tree 1:#chart and tree 2:#chart2.
Tree 1:
var vis = d3.select("#chart").append("svg:svg")
Tree 2:
var vis = d3.select("#chart2").append("svg:svg")
Everything else remains the same including variable and function names.
This works great and both diagrams show up as they should, except for the click function (last function in the code: ) Only the second tree is able to collapse and expand on click of tree nodes, the first tree is no longer able to do this, the first is no longer interactive.
How do I fix this?

You are overwriting the vis variable when you draw the second tree which the interaction depends on. If you are going to create multiple charts, you need to create a closure so that each tree is in its own scope. This way they won't interfere with each other.
Mike wrote up a nice post about creating reusable charts at http://bost.ocks.org/mike/chart/. He walks through creating a closure and surfacing properties.

Related

Pivottable like HTML constructor without aggregation to show grouped elements

I'm trying to build an HTML component that will provide a pivottable-like view on my data, but with custom html elements inside the pivotarea rather than a sum or count; in the example below I'll just use a string of text, but I'd like it to be any HTML element (img, div, text etc.).
I'm finding it difficult to choose a direction, writing my own code to generate it (with jQuery) or using a library like Pivottable. I've tried the latter, but couldn't even find the proper direction w.r.t. customizing the aggregator function.
I could see myself re-using the html generated by js pivottable (with a simple count) and appending items afterwards in jQuery, but this seems like a rather hacky solution, along with a lack of customization options. Pros of this approach include the fact that at some point I'd like to include filtering/customization of the colums in the web-ui.
What am I looking for? Given a JSON array with multiple rows having attributes [Columngroup1, Columngroup2], and [Rowgroup 1, rowgroup2, rowgroup3], I'd like to layout it according as following (built in Tableau):
In the example above, [Businessline, Type, Product] are the Row-groups and [Active_or_roadmap, Roadmap Quarter] are the column groups. The granularity of the dataset is one level deeper, each 'Product' can consist of multiple subproducts, which should be placed either in the 'active' column (period header) or one of the roadmap quarter columns. This can be seen by subproducts 15.03 and 15.01 being grouped in the same 'row' visually.
What difficulties am I facing?
Do I use an HTML table for this, should I go with divs with classes indicating the rows/column, or a combination of both? Added complexity: at some point I'd like the non-header columns to be 'scrollable' horizontally (if too wide).
In a situation where I'd like to filter out some rows, should I regenerate the entire table or (mis)use visibility:hidden? In the latter case: how would I deal with a Product group being partially filtered (i.e. subproduct 15.01 should not be visible, subproduct 15.03 does need to be visible)
How would I 'embed' the object details in the DOM element? i.e., in the case of a hover/clickevent, how would I know which row in the JSON object corresponds to the name that was clicked?
Note that I'm not necessarily looking for an answer that fully does what I'm saying above, I'm primarily looking for a direction w.r.t. the code to go from the JSON to the above table in a structurally decent and flexible manner.
Any help is greatly appreciated, I have a codepen that contains some sample data and a rather poor attempt.
function load_data(callback){
$.getJSON('https://s3-us-west-2.amazonaws.com/s.cdpn.io/997352/data_portfolioroadmap.json', function(data){
callback(data)
});
}
I'm thinking something like this
{[
{productTitle:"Product 01.01",state:"Active","quarter":"2017Q1"},
{productTitle:"Product 01.02",state:"Roadmap","quarter":"none"}
]}
With this you should be able to loop over the array and place each element. I would use custom divs. First loop over the quarters and build those out. The loop over the state and filter grabbing the ones you need. Put the filtered results in a new var and sort it. The place each item in the proper column position as you are building out your rows. Then repeat with the next state.
Hope this make sense.
I think that managing that complex structure could force you to think of this table as a embeded components. Thinking of that maybe React (https://facebook.github.io/react/) could be appropriate solution for that.
Thinking about extending existing library is crucial for making this cost-effective, so please see https://react.rocks/example/orb (http://github.com/nnajm/orb) that maybe could be easier to extend using component matter of React that was used there.

Draw tree structure in HTML

I'm doing a school assignment to visualize in-depth search algorithm and i'd like to visualize the tree javascript creates. I've written the javascript to implement in-depth search but i'm in trouble visualizing the tree.Currently i've created an object for a node which has attributes:
function createNode(parent,name,suur,vaike){
var Node = new Object();
Node["name"]= name;
Node["children"] = [];
Node["parent"] = parent;
return Node;
}
In general it wouldn't be really difficult to draw a tree in HTML but i would like to get my head around it before i start writing any code for visualizing. The main issues i've stated is that the length of branches have to dynamically change - if new children are added to the tree then the tree will expand so different elements wouldn't collapse.
This is an image from Wikipedia and i'd love to get something like this as a result.
What my question is that i'd like to get some pointers how to dynamically expand the branch lengths so that different children wouldn't collapse.
For this particular task i used Treant.js. Really simple to use and drew nicely fitted tree. Had about 60 elements in the tree and no collision.
Here's a little snip from the result (it's scrollable, couldn't fit all on one page)
I would recommend using a VS Code for all extensions that rainbow color the HTML code structure and others, besides all unique CSS Selectors
I have dropped all #rainbow extensions I use. I hope that would help.
enter image description here

Animate several on change events in arc/pie D3.js graph using jQuery

I am in the same boat many have been in with D3 trying to get to the next level. I have a graph that is close to what I want but I can't figure out how to animate the change. There are many events and have the different parts placed into different functions. I call them with the following if else if:
if ($("#chart1Pie").is(":checked")) {
updateOne();
} else if ($("#chart2Pie").is(":checked")) {
updateTwo();
};
Do I have it wrong by having the different parts in different functions? The full code is on jsfiddle.
http://jsfiddle.net/rocky1616/ghfqmygh/
You are using D3 absolutely incorrectly. You have ONE graph, but two sets of data - for Smith and for Jones. You don't need to remove stuff inside #chart using jQuery and then rebuild the whole graph from the scratch. In general, if you want to remove and add elements you should use D3 methods .enter() and .exit().
In your case you don't need to remove anything. All you need to do on update is recalculate attribute "d" for of your paths.
Check these examples: one, two.

Unable to render an angularjs template inside a popover

I am trying to get a popover show some html content (it could be angularjs compiled content) and when I click on my "View" link, I do not see my custom directive getting processed and showing correctly (all other content is rendering okay including one that has an ng-repeat inside it suggesting that angularjs saw my angular content right)
http://plnkr.co/edit/Jy8Qlp1rsghwj4NNF2Dn?p=preview
<div ng-controller="ChordCtrl">
<chord-layout chord-matrix="{{matrix}}">
<div id="chordLayoutHolder"></div>
</chord-layout>
</div>
There is a lot going on in this plunkr but the bottom line is when I click on any of the "View" inside the table, I expect dynamic contents of report1.html to show up in my tooltip - Clearly all the other contents show up but it somehow failed to do my complex chord layout rendering - The chord layout diagram rendering is tested independently in another plunkr - http://plnkr.co/edit/q5DDdKHs11OuW6SfLtTG?p=preview
Any help in determining why my chord layout chart is not rendering would be helpful.
Regards
You're having issues because you're using id for your chordLayoutHolder. To be honest, I'm not sure why this is an issue. Perhaps Angular pre-compiles the template and clones it, such that the id is no longer unique. I would be curious to know.
In any case, remove <div id="chordLayoutHolder"></div> and just append to the directive element:
<chord-layout chord-matrix="{{matrix}}">
</chord-layout>
Then, in your directive, change the following lines (that refer to chordLayoutHolder):
$("#chordLayoutHolder").empty();
var svg = d3.select("#chordLayoutHolder")
...
to:
element.empty();
var domElement = angular.element(element)[0];
var svg = d3.select(domElement)
...
to append to the element itself, rather than another placeholder.
Then it would work. Here's the plunker.

Raphael JS: bring set to front

I was hoping someone could tell me how to bring an entire set of elements toFront in Raphael JS.
I am working with some dynamically generated sets of raphael elements, each of which is stored in an array making it easier to interact with and target individual sets. When a user interacts with the various sets I would like to be able to bring the full set to the front of the application.
I have tried using .toFront() as outlined here: http://raphaeljs.com/reference.html#Element.toFront
However this hasn't worked properly. Each set contains either a circle or a circle sector, a text element and either an additional circle or an additional sector.
Any ideas? At any one point a user may have up to 40/50 of these sets so bringing sets to front is going to be a necessity regardless.
i've had similar issues with the toFront() function ...
well i'd say there are two ways to do it ...
The first one (not quite recommended) apply a loop on all the elements of the set to bring them to front but still they'd be ordered according to the sequence in the set .... not good approach ...
set.forEach(el){
e.toFront();}
The second one is really sexy :) my fav :) beautifully explained by mister phrogz here
I recommend using the 'g' tag ... simple javascript . let all your sets be enclosed in a g tag
var mySet = document.createElementNS("http://www.w3.org/2000/svg", "g");
mySet.setAttribute('id','myset');
//should look something like this
//use jQuery append or javaScript appendChild to add your set elements to this group
<g id = 'myset'>
<rect>
<circle>
//etc etc
</g>
now
mySet.parentNode.appendChild(mySet); //the key line
this would simply take it to the bottom of the svg container, hence being drawn last and shown at the top according to the painters model also mentioned by mister phrogz in the link .... you could use javascript to manipulate your own z-index if required...

Categories

Resources