简体   繁体   中英

Programmatically open nested, collapsed (hidden) nodes in d3.js v4

I am trying to programmatically open d3.js nodes in a collapsible tree:

d3_collapsible_tree_viz

I load the data with the following d3.js snippet (which collapses the nodes after the second level),

d3.json("js/ontology.json", function(error, treeData) {
  if (error) throw error;
  root = d3.hierarchy(treeData, function(d) { return d.children; });
  root.x0 = height / 2;
  root.y0 = 0;
  // Collapse after the second level:
  root.children.forEach(collapse);
  update(root);
});

I then use the following d3.js code

var nodeEnter = node.enter().append('g')
    .attr('class', 'node')
    .attr('node-name', d => d.data.name.toLowerCase())
    .attr("transform", function(d) {
      return "translate(" + source.y0 + "," + source.x0 + ")";
  })
.on('click', click);

and this function

function expandNode() {
  const node = d3.select('.node[node-name="Nature"]').node();
  console.log('NODE: ', node);
  node.dispatchEvent(new Event('click'));
  }
expandNode();

to programmatically open the "Nature" node.

However, when I substitute "Nature" (visible node) with "Earth" (nested child of "Nature", not visible) this expression

const node = d3.select('.node[node-name="Earth"]').node();

will expand the "Earth" node only if it is visible.

That statement will not expand "Nature" to show "Earth" (and subsequently expand "Earth") if "Earth" is not visible.

Suggestions?


Edit 1. This is closely related to my earlier StackOverflow question,

Programmatically opening d3.js v4 collapsible tree nodes?

If needed, please refer to the JSFiddle referenced there,

https://jsfiddle.net/vstuart/acx5zfgn/62/

The labels are different but otherwise the data and code are similar.


Edit 2. Follow-on question

Accessing promised data in d3.js v6 [programmatically opening nested collapsed nodes]

relating to:

  • d3.js v6;
  • loading external JSON data via d3.js callback/promise;
  • this question, in that updated context.

ontology.json

{ "name": "Root",
  "children": [
    { "name": "Culture",
      "children": [
        { "name": "LGBT" }
      ]
    },

    { "name": "Nature",
      "id": "nature",
      "children": [
        { "name": "Earth",
          "id": "earth",
          "children": [
            { "name": "Environment" },
            { "name": "Geography" },
            { "name": "Geology" },
            { "name": "Geopolitical" },
            { "name": "Geopolitical - Countries" },
            { "name": "Geopolitical - Countries - Canada" },
            { "name": "Geopolitical - Countries - United States" },
            { "name": "Nature" },
            { "name": "Regions" }
          ]
        },
        { "name": "Cosmos" },
        { "name": "Outer space" }
      ]
    },

    { "name": "Humanities",
      "children": [
          { "name": "History" },
          { "name": "Philosophy" },
          { "name": "Philosophy - Theology" }
      ]
    },

    { "name": "Miscellaneous",
      "children": [
          { "name": "Wikipedia",
            "url": "https://wikipedia.com" },
          { "name": "Example.com",
            "url": "https://example.com" }
      ]
    },
      
    { "name": "Science",
      "children": [
          { "name": "Biology" },
          { "name": "Health" },
          { "name": "Health - Medicine" },
          { "name": "Sociology" }
      ]
    },

    { "name": "Technology",
      "children": [
            { "name": "Computers" },
            { "name": "Computers - Hardware" },
            { "name": "Computers - Software" },
            { "name": "Computing" },
            { "name": "Computing - Programming" },
            { "name": "Internet" },
            { "name": "Space" },
          { "name": "Transportation" }
      ]
    },

  { "name": "Society",
      "children": [
            { "name": "Business" },
            { "name": "Economics" },
            { "name": "Economics - Business" },
            { "name": "Economics - Capitalism" },
            { "name": "Economics - Commerce" },
            { "name": "Economics - Finance" },
            { "name": "Politics" },
          { "name": "Public services" }
      ]
    }
  ]
}

You need to discover the node ancestors recursively and then expand them on by one:

const findNodeAncestors = (root, name) => {
  if (root.name === name) {
    return [name];
  }

  if (root.children) {
    for (let i = 0; i < root.children.length; i++) {
      const chain = findNodeAncestors(root.children[i], name);
      if (chain) {
        chain.push(root.name);
        return chain;
      }
    }
  }
  return null;
}; 
   

const chain = findNodeAncestors(treeData.data, 'Earth');
  
for (let i = chain.length - 1; i >= 0; i--) {
  const node = d3.select(`.node[node-name="${chain[i]}"]`);
  const nodeData = node.datum();
  if (!nodeData.children && nodeData.data.children) {  // Node has children and collapsed
    node.node().dispatchEvent(new Event('click'));     // Expand the node
  }
}

See it's working in a fiddle .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM