title: find specific nodes in d3js tree
body: <p>I am trying to find specific nodes on the tree layout.  I found this example on plunkr:</p>
  
  <pre><code>function collapse(d) {
  if (d.children) {
    d._children = d.children;
    d._children.forEach(function(d1){d1.parent = d; collapse(d1);});
    d.children = null;
  }}
  function find(d, name) {
  if (d.name == name){
    while(d.parent){
      d = d.parent;
      click(d)
    }
    return;
  }
  if (d.children) {
    d.children.forEach(function(d){find(d, name)});
  } else if(d._children){
    d._children.forEach(function(d){find(d, name)});
  }}
  [root].forEach(collapse);
  var name = "layout"
  find (root, name)
  update(root);
  </code></pre>
  
  <p><a href="http://plnkr.co/edit/Ce5Ub8PWXblSMcrYlkHa?p=preview" rel="nofollow noreferrer">http://plnkr.co/edit/Ce5Ub8PWXblSMcrYlkHa?p=preview</a> which finds a specif node given a name.  <br/>I adopted it to find a node given an ID.<br/>I have two problems with the implementation:
  <br/>1- The code generates an error in the console "Error:  attribute transform: Expected number, "translate(undefined,undefi…".  Which I think is due to the x and y coordinates becoming null, but I cannot identify the exact condition.  This error appears in the original example as well.<br/>
  <br/>2- If I call the find routine once (by clicking the find button which calls find_name() and commenting out the second call to the find function) , it works, however if I call it more than once (by un-commenting and enabling the second call to find), the tree collapses to the root node.</p>
  
  <p>Any help in understanding this behavior is much appreciated.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>&lt;!-- load the d3.js library --&gt; 
  &lt;script src="http://d3js.org/d3.v3.min.js"&gt;&lt;/script&gt;
   
  &lt;script&gt;
  
  // ************** Generate the tree diagram  *****************
  
  var data =[{"sid":"1","parent":"null","name_ar":"Hashim"},{"sid":"2","parent":"1","name_ar":"wahb"},{"sid":"3","parent":"1","name_ar":"Abdulmuttaleb"},{"sid":"4","parent":"2","name_ar":"Amina"},{"sid":"5","parent":"3","name_ar":"Abutaleb"},{"sid":"6","parent":"3","name_ar":"Abdulla"},{"sid":"7","parent":"3","name_ar":"Abbas"},{"sid":"8","parent":"3","name_ar":"Hamza"},{"sid":"9","parent":"6","name_ar":"Mohammed (Prophet)"},{"sid":"10","parent":"9","name_ar":"Alqassim"},{"sid":"11","parent":"9","name_ar":"Um Kalthoum"},{"sid":"12","parent":"9","name_ar":"Zainab"},{"sid":"13","parent":"9","name_ar":"Ruqaya"},{"sid":"14","parent":"9","name_ar":"Fatima"},{"sid":"15","parent":"9","name_ar":"Ibrahim"},{"sid":"16","parent":"9","name_ar":"Abdulla"},{"sid":"17","parent":"9","name_ar":"Muhsen"},{"sid":"18","parent":"5","name_ar":"Ali"},{"sid":"19","parent":"18","name_ar":"Hassan"},{"sid":"20","parent":"18","name_ar":"Hussain"},{"sid":"21","parent":"20","name_ar":"Ali Zain Alabbideen"},{"sid":"22","parent":"21","name_ar":"Mohammed Baqer"},{"sid":"23","parent":"22","name_ar":"Jafar Sadeq"},{"sid":"24","parent":"23","name_ar":"Mousa Kadim"},{"sid":"25","parent":"24","name_ar":"Ali AlAreed"},{"sid":"26","parent":"24","name_ar":"Ibrahim Murtada"},{"sid":"27","parent":"26","name_ar":"Mousa (the second)"},{"sid":"28","parent":"27","name_ar":"Ahmed"},{"sid":"29","parent":"28","name_ar":"Hussain"},{"sid":"30","parent":"29","name_ar":"Abu Alqassim Mohammed"},{"sid":"31","parent":"30","name_ar":"Najm Aldeen Mahdi"}];
  
  //------------------
  //the find function is global
  function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(function(d1){d1.parent = d; collapse(d1);});
        d.children = null;
      }
    }
  
    function find(d, sid) {
      if (d.sid == sid){
        while(d.parent){
          d = d.parent;
          click(d)
        }
        return;
      }
      if (d.children) {
        d.children.forEach(function(d){find(d, sid)});
      } else if(d._children){
        d._children.forEach(function(d){find(d, sid)});
      }
    }
    
    function find_name(){
     [root].forEach(collapse); //iterate each node and collapse
     find(root,25);
     find(root,31);
     update(root);
    }
  //------------------
  
  
  var margin = {top: 25, right: 120, bottom: 20, left: 120},
   width = 10000 - margin.right - margin.left,
   height = 5000 - margin.top - margin.bottom;
   
  var i = 0,
   duration = 750,
   rectW = 100,
      rectH = 30,
   root;
  var enteredId = 7402;
  
  //zoom functionality 
  var zoom = d3.behavior.zoom()
      .scaleExtent([1, 10])
      .on("zoom", zoomed);
  
  var tree = d3.layout.tree()
   .nodeSize([110, 50]);
   
  var diagonal = d3.svg.diagonal()
      .projection(function (d) { return [d.x + rectW / 2, d.y + rectH / 2]; }); 
      
  var svg = d3.select("body").append("svg")
   .attr("width", width + margin.right + margin.left)
   .attr("height", height + margin.top + margin.bottom)
   .call(zoom)
   .on("wheel.zoom", null) //disable zooming on mouse wheel scroll
     .append("g")
   .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
   //create a name-based map for the nodes
   //which starts with an empty object and iterates over the data array, adding an entry for each node
   //for the flat array
   var dataMap = data.reduce(function(map, node) {
   map[node.sid] = node;
   return map;
   }, {});
  
   //iteratively add each child to its parents, or to the root array if no parent is found
   //for the flat array
   var treeData = [];
   data.forEach(function(node) {
    // add to parent
    var parent = dataMap[node.parent];
    if (parent) {
     // create child array if it doesn't exist
     (parent.children || (parent.children = []))
      // add node to child array
      .push(node);
    } else {
     // parent is null or missing
     treeData.push(node);
    }
   });
  
   root = treeData[0];
   root.x0 = height / 2;
   root.y0 = 0;
  //------------------------------------------------------
   var nodes = tree.nodes(root);
   function collapseLevel(d) {
    if (d.children &amp;&amp; d.depth &gt; 23) {
     d._children = d.children;
     d._children.forEach(collapseLevel);
     d.children = null;
    } else if (d.children) {
     d.children.forEach(collapseLevel);
    }
   }
    root.children.forEach(collapseLevel);//iterate each node and collapse excluding node zero
     
  //------------------------------------------------------
   update(root);
  
  d3.select(self.frameElement).style("height", "500px");
   
  function zoomed() {
    svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  }
  
  function update(source) {
  
    // Compute the new tree layout.
    var nodes = tree.nodes(root).reverse(),
     links = tree.links(nodes);
  
    // Normalize for fixed-depth.
    nodes.forEach(function(d) { d.y = d.depth * 180; });
  
    // Update the nodes…
    var node = svg.selectAll("g.node")
     .data(nodes, function(d) { return d.id || (d.id = ++i); });
  
    // Enter any new nodes at the parent's previous position.
    //vertical tree by swaping y0 and x0
    var nodeEnter = node.enter().append("g")
     .attr("class", "node")
     .attr("transform", function(d) { return "translate(" + source.x0 + "," + source.y0 + ")"; })
     .on("click", click)
   .on("mouseover", function(d) {
            var g = d3.select(this); // The node
            // The class is used to remove the additional text later
            var info = g.append('text')
               .classed('info', true)
               .attr('x', 20)
               .attr('y', 10)
               .text(function(d) { return d.name_ar + " " + d.sid }); // need to put good background for tooltip
   })
   .on("mouseout", function() {
            // Remove the info text on mouse out.
            d3.select(this).select('text.info').remove()
   });
    ;
  
  nodeEnter.append("rect")
          .attr("width", rectW)
          .attr("height", rectH)
          .attr("stroke", "black")
          .attr("stroke-width", 1)
          .style("fill", function (d) {
          return d._children ? "lightsteelblue" : "#fff";
      });
  
   nodeEnter.append("text")
          .attr("x", rectW / 2)
          .attr("y", rectH / 2)
          .attr("dy", ".35em")
          .attr("text-anchor", "middle")
          .text(function(d) { return d.name_ar; })
          .style("fill-opacity", 1);
  
  //vertical
  var nodeUpdate = node.transition()
     .duration(duration)
     .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  
      nodeUpdate.select("rect")
          .attr("width", rectW)
          .attr("height", rectH)
          .attr("stroke", "black")
          .attr("stroke-width", 1)
          .style("fill", function (d) {
          return d._children ? "lightsteelblue" : "#fff";
      });
  
    nodeUpdate.select("text")
     .style("fill-opacity", 1);
  
  // Transition exiting nodes to the parent's new position.
  //vertical 
  var nodeExit = node.exit().transition()
     .duration(duration)
     .attr("transform", function(d) { return "translate(" + source.x + "," + source.y + ")"; })
     .remove();
  
      nodeExit.select("rect")
          .attr("width", rectW)
          .attr("height", rectH)
      .attr("stroke", "black")
          .attr("stroke-width", 1);
      nodeExit.select("text");
  
    // Update the links…
    var link = svg.selectAll("path.link")
     .data(links, function(d) { return d.target.id; });
  
    // Enter any new links at the parent's previous position.
    link.enter().insert("path", "g")
     .attr("class", "link")
     .attr("d", function(d) {
    var o = {x: source.x0, y: source.y0};
    return diagonal({source: o, target: o});
     });
  
    // Transition links to their new position.
    link.transition()
     .duration(duration)
     .attr("d", diagonal);
  
    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
     .duration(duration)
     .attr("d", function(d) {
    var o = {x: source.x, y: source.y};
    return diagonal({source: o, target: o});
     })
     .remove();
  
    // Stash the old positions for transition.
    nodes.forEach(function(d) {
   d.x0 = d.x;
   d.y0 = d.y;
    });
  }
  
  // Toggle children on click.
  function click(d) {
    if (d.children) {
   d._children = d.children;
   d.children = null;
    } else {
   d.children = d._children;
   d._children = null;
    }
    update(d);
  }
  //-------------------------------------
  &lt;/script&gt;</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code> .node {
    cursor: pointer;
   }
  
   .node circle {
     fill: #fff;
     stroke: steelblue;
     stroke-width: 3px;
   }
  
   .node text {
     font: 14px sans-serif;
   }
  
   .link {
     fill: none;
     stroke: #ccc;
     stroke-width: 2px;
   }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;
  &lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
    &lt;head&gt;
      &lt;meta charset="utf-8"&gt;
  
      &lt;title&gt;Tree Example&lt;/title&gt;
      &lt;header&gt;
    &lt;button onclick="find_name()"&gt;find&lt;/button&gt;
   &lt;/header&gt;
     
     &lt;/head&gt;</code></pre>
  </div>
  </div>
  </p>