0

I would like to use a collapsible force diagram which is collapsed by default (starting out with only one node). I ran across this: http://bl.ocks.org/david4096/6168323 but it is blank and not working. I'm using the latest Mozilla Firefox 43.0.4. I even put it to plunker with the same result - blank.

Can someone identify the problem?

Also would it be possible to have it partially collpased? That means the first set of children expanded but everything else collapsed?

My non-working example on plunker

I believe it can be achieved by modifying the update function.

Changing "children" to "_children" in the json data sheet does not work properly.

function update(d) {

  var nodes = flatten(root),
      links = d3.layout.tree().links(nodes);

  // Restart the force layout.
  force
      .nodes(nodes)
      .links(links)
      .start();

i looked here: d3.js collapsible force layout with all the nodes collapsed and here: How can I start with all the nodes collapsed in d3js?

None of the solution is working for me.

Will be thankful for any advice.

UPDATED 28.1.2018

Works nicely thanks to the answer below.

Here is a working example: http://plnkr.co/edit/QtFXa53Q7p65NQpO4z5f?p=preview

Community
  • 1
  • 1
matus
  • 53
  • 8

1 Answers1

2

Basically, I added ID's to the circles on the nodes based on names :

.append("circle").attr('id', function(d){ return d.name})

Then I populated an array of all the parents childrens names, i.e the nodes you want to collapse :

if(parentschildren.length<1){ //so it doesn't populate it more than once
          node.filter(function(d){
            //console.log(d.name)
            return d.name === 'PARENT' //return just the parent node
          }).each(function(d){
            for(i=0;i<d.children.length;i++){
              parentschildren.push(d.children[i].name);
            }

          });
          }

Then I used the populated array to loop through to select the nodes I want to click and call a click function which simulates a click on selected nodes :

function simulateClick(){


        $.fn.d3Click = function (i) { //simulate click
          //if(i===0){
  this.each(function (i, e) {

    var evt = document.createEvent("MouseEvents");
    evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
console.log(e);

    e.dispatchEvent(evt);
   // nodeEnter.on("click", click)
    evt.stopPropagation()


  }); //}
};

for(i=0;i<parentschildren.length;i++){ //loop through created array

$('#'+parentschildren[i]).d3Click(); //select element to click
}
    }

As for the unique id's i would do something like this :

node.each(function(d,i){ // use i to iterate through
d.uniqueID = 'uniqueNode' + i;
}

That piece of code will give each one a unique value. So the first one will be uniqueNode1 then uniqueNode2 and so on. Then to apply this to your nodes :

nodes.attr('id'(function(d){
return d.uniqueID;
})

As for your other question (which i think you should add to this question rather than in the comments so people know why my answer is so big) here is the answer to that.

To get all of the nodes started collapsed i made use of the recursive function you already have to populate an array to give you ever node that has children :

var nodes2 = [];
function flatten(root) {
      var nodes = [], i = 0;

      function recurse(node) {
        if (node.children) {
          nodes2.push(node.name) //push the name of the node to the array
          node.children.forEach(recurse);
        }
        if (!node.id) node.id = ++i;
        nodes.push(node);
    }

      recurse(root);
      console.log(nodes2)
      return nodes;
    }

Now, as i said before, i had given them id's based on name, so to select them all i have to do is go through this new node array (nodes2) and click on the node that has the same ID as each element in that array. But you can't do this straight away as this array starts from the highest point (PARENT) and goes down, so I had to reverse the array :

var newNodes = [];
  for(i=nodes2.length; i>=0; i--){
    newNodes.push(nodes2[i])
  }

Now use this array to itterate through to select the nodes that have the same ID:

for(i=0;i<newNodes.length;i++){
 if(newNodes[i]){ //check if i isnt undefined etc
   $('#'+newNodes[i]).d3Click();
 }

}

And then click the parent twice again (to close then open) as you wanted that selected:

$('#PARENT').d3Click();

$('#PARENT').d3Click();

Hope that solves all your problems and here is the final updated plnkr : http://plnkr.co/edit/QtFXa53Q7p65NQpO4z5f?p=preview

thatOneGuy
  • 9,977
  • 7
  • 48
  • 90
  • if you want to collapse everything so its only the parent node on show, instead of looping through the array, comment that out and select the parent : $('#PARENT').d3Click(); – thatOneGuy Jan 19 '16 at 11:33
  • I would use better ID's as I have here as it looks like you may have some similar names. Try creating unique ID's so it doesnt get mixed up – thatOneGuy Jan 19 '16 at 11:33
  • thank you very much @thisOneGuy!!! it looks great. Actually in the project some of the names of few children nodes are identical so I need to assign unique ids to the nodes. Can i do it so that in .json file i attribute unique ids to nodes eg. `"uniqueid": "blabla", ` and then edit your code to `.append("circle").attr('id', function(d){ return d.uniqueid})`? I'm an architect and this is already quite advanced for my understanding. I am really thankful for your generous help! – matus Jan 19 '16 at 12:19
  • One more thing. When I go to your updated [plnkr.co] (http://plnkr.co/edit/QtFXa53Q7p65NQpO4z5f?p=preview) Is it possible that parent node is selected by default and not the "E" node? When I click the node, the whole branch expands, would it be possible that it expands one by one? Children by children, depending on the click... Again thank you for your generosity! – matus Jan 19 '16 at 12:22
  • let me get back to you, fairly busy at the moment :) also, you should accept the answer since it's been solved. The questions you've just asked, really, should go in another question – thatOneGuy Jan 19 '16 at 12:53
  • I have accepted the answer @thisOneGuy. (I clicked on it some time ago already now it seems it has worked). I can make a different thread then. (But somehow i think it relates to collapsing the nodes. However if you think it should go to different thread I will make one soon. Also fairly busy atm.) – matus Jan 19 '16 at 13:06
  • No its ok dont make another thread. I can quickly respond. Your first question, I'd write some code, ill edit my answer to solve this. As for the second question, why don't you, afteryou loop through the children of the parent and simulate the click on them, simulate the click twice on the parent ? So that way the parent was the last clicked ? Bit of a hack I know, but it should work. – thatOneGuy Jan 19 '16 at 13:12
  • Thank you greatly @thisOneGuy !!! you are so much help! I'm sorry I'm such a dummy, but how do I simulate a click twice on the parent as you suggested? (So when I unclick the node only it's children expand and not the whole tree). – matus Jan 19 '16 at 19:42
  • I've already answered that and updated the answer. See last link. You just call the function i made (d3Click), twice on the parent node – thatOneGuy Jan 20 '16 at 09:59
  • I copied the `$('#PARENT').d3Click();` but it's seems it's not working. What I mean is when I click let's say the node B, only 1, 2, 3, 4 will open... then when I click 1, only Z1, Y1 and X1 will open. Do you think this is possible? Now it keeps unrolling the whole "branch" with all the children nodes connected to node B. Thank you very much! – matus Jan 20 '16 at 14:24
  • Do you not think you should give this a try yourself ? I mean all of the workings are there for you to simulate the click and so on ? All you have to do now is get all the nodes that have got children and simulate a click on them starting for the lowest node (the node furthest down the tree so to speak) – thatOneGuy Jan 20 '16 at 15:04
  • Thank you million times @thisOneGuy! You're a master! Btw, plnkr shows blank screen on plnkr.co on iphone is it possible it's some syntax error? Maybe i try later... I have already asked so much from you! Have a really nice day! M – matus Jan 21 '16 at 09:32
  • have you tried on desktop ? it works fine for me. Do you mean the link ive sent you or the actual plnkr website ? – thatOneGuy Jan 21 '16 at 09:36
  • 1
    thank you so much for helping me! I have cracked it now with identical names. i modyfied your answer little bit and used unique "value" attribute in json file. working example here: http://plnkr.co/edit/rqh8SD?p=preview – matus Jan 29 '16 at 09:07