最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Find all the parents of each element - Stack Overflow

programmeradmin1浏览0评论

I'm trying to create a breadcrumb without using the url (the route provider) and without using jQuery. I have a tree like that

Humans
Trees
Animals
    Cats
    Lions
    Dogs
       Terrier 
       Bulldog
       Cocker
Cars

and I'd like when I click on Cocker to display

Animals / Dogs / Cocker

So, I created a recursive function in order to find parent/parents for each element that I click on but it doesn't work correctly. It finds that an element has a parent, it also finds the first parent of an element but it doesn't show the second parent. For instance instead of

Animals / Dogs / Cocker

it shows

Dogs / Cocker

That's my function

var count = 0;
function iterate(obj) {
    for(var key in obj) {
      var elem = obj[key];
      if(key === "children") {
        count++;
      }
      if(typeof elem === "object") {
        if(elem.children === undefined){
          elem.children = 1;
        }
        if(elem.children.length !==1){
          iterate(elem);
          $scope.showTrail = elem.children;
          $scope.elem = elem;
        }
      }
     }
    if($scope.elem === undefined){
      $scope.elem = {};
      $scope.elem.children = {};
      $scope.elem.roleName = {};
    }

    for (var i = 0; i<$scope.elem.children.length; i++) {
       if($scope.elem.children[i].roleName === selNode.roleName) {
          console.log($scope.elem.roleName + " is a parent of " + selNode.roleName);
       }
    }

  }
iterate($scope.treeData);

and that's the JSON

     [
          { "roleName" : "Humans", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]},
          { "roleName" : "Trees", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]},
          { "roleName" : "Animals", "roleId" : "role2", "children" : [
            { "roleName" : "Cats", "roleId" : "role11", "children" : [
             { "roleName" : "", "roleId" : "role11", "children" : [] }
            ]},
            { "roleName" : "Lions", "roleId" : "role11", "children" : [
             { "roleName" : "", "roleId" : "role11", "children" : [] }
            ]},
            { "roleName" : "Dogs", "roleId" : "role11", "children" : [
              { "roleName" : "Terrier", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
              { "roleName" : "Bulldog", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
              { "roleName" : "Cocker", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
            ]}
          ]},
          { "roleName" : "Cars", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]}
     ]

Any help please, any idea. Thank you very much.

I'm trying to create a breadcrumb without using the url (the route provider) and without using jQuery. I have a tree like that

Humans
Trees
Animals
    Cats
    Lions
    Dogs
       Terrier 
       Bulldog
       Cocker
Cars

and I'd like when I click on Cocker to display

Animals / Dogs / Cocker

So, I created a recursive function in order to find parent/parents for each element that I click on but it doesn't work correctly. It finds that an element has a parent, it also finds the first parent of an element but it doesn't show the second parent. For instance instead of

Animals / Dogs / Cocker

it shows

Dogs / Cocker

That's my function

var count = 0;
function iterate(obj) {
    for(var key in obj) {
      var elem = obj[key];
      if(key === "children") {
        count++;
      }
      if(typeof elem === "object") {
        if(elem.children === undefined){
          elem.children = 1;
        }
        if(elem.children.length !==1){
          iterate(elem);
          $scope.showTrail = elem.children;
          $scope.elem = elem;
        }
      }
     }
    if($scope.elem === undefined){
      $scope.elem = {};
      $scope.elem.children = {};
      $scope.elem.roleName = {};
    }

    for (var i = 0; i<$scope.elem.children.length; i++) {
       if($scope.elem.children[i].roleName === selNode.roleName) {
          console.log($scope.elem.roleName + " is a parent of " + selNode.roleName);
       }
    }

  }
iterate($scope.treeData);

and that's the JSON

     [
          { "roleName" : "Humans", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]},
          { "roleName" : "Trees", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]},
          { "roleName" : "Animals", "roleId" : "role2", "children" : [
            { "roleName" : "Cats", "roleId" : "role11", "children" : [
             { "roleName" : "", "roleId" : "role11", "children" : [] }
            ]},
            { "roleName" : "Lions", "roleId" : "role11", "children" : [
             { "roleName" : "", "roleId" : "role11", "children" : [] }
            ]},
            { "roleName" : "Dogs", "roleId" : "role11", "children" : [
              { "roleName" : "Terrier", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
              { "roleName" : "Bulldog", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
              { "roleName" : "Cocker", "roleId" : "role11", "children" : [
               { "roleName" : "", "roleId" : "role11", "children" : [] }
              ]},
            ]}
          ]},
          { "roleName" : "Cars", "roleId" : "role2", "children" : [
           { "roleName" : "", "roleId" : "role11", "children" : [] }
          ]}
     ]

Any help please, any idea. Thank you very much.

Share Improve this question edited Nov 24, 2013 at 13:44 jimakos17 asked Nov 18, 2013 at 16:35 jimakos17jimakos17 9354 gold badges15 silver badges34 bronze badges 3
  • Could you provide the real data structure (nested objects/arrays)? – user1636522 Commented Nov 18, 2013 at 16:47
  • create demo in plunker with directive that generates tree. SHould be able to create breadcrumb as attribute while directive gets piled – charlietfl Commented Nov 18, 2013 at 18:12
  • I updated the question by adding a recursive function which finds a parent element but not all the parents of each element. Any help please!!! – jimakos17 Commented Nov 19, 2013 at 12:09
Add a ment  | 

3 Answers 3

Reset to default 4 +50

You are iterating over the tree, but it won't help if you don't keep some information. The simplest solution to your problem is to build an index of all nodes that points to their parents.

This code will work if roleName has unique values across the whole tree:

var tree = [
    { "roleName" : "Humans", "roleId" : "role2", "children" : []},
    { "roleName" : "Trees", "roleId" : "role2", "children" : []},
    { "roleName" : "Animals", "roleId" : "role2", "children" : [
        { "roleName" : "Cats", "roleId" : "role11", "children" : []},
        { "roleName" : "Lions", "roleId" : "role11", "children" : []},
        { "roleName" : "Dogs", "roleId" : "role11", "children" : [
            { "roleName" : "Terrier", "roleId" : "role11", "children" : []},
            { "roleName" : "Bulldog", "roleId" : "role11", "children" : []},
            { "roleName" : "Cocker", "roleId" : "role11", "children" : []},
        ]}
    ]},
    { "roleName" : "Cars", "roleId" : "role2", "children" : []}
];

var index = {};

function buildIndex(root, children) {
    for(var i in children) {
        index[children[i].roleName] = root;
        buildIndex(children[i].roleName, children[i].children);
    }
}

buildIndex("Root", tree);

function getPath(leaf) {
    return index[leaf] ? getPath(index[leaf]).concat([leaf]) : [leaf];
}

getPath("Bulldog");// returns ["Root", "Animals", "Dogs", "Bulldog"]

JSFiddle: http://jsfiddle/E49Ey/

However it has nothing to do with Angular, except the data resides in the scope. If you have a DOM tree built from this data, then you could get the breadcrumb right from the DOM by going up the tree.

Hey I put together a quick plunkr doing what your looking for... except it doesn't reverse-traverse up the data tree.

http://embed.plnkr.co/wAJYiAjy58vUEsg4Kr2C

If your looking to actually looking to run up the data tree let me know and I'll modify the plunkr

You can of course solve it with a recursive function similar to what you showed in the question. What about a solution like this:

function getPath(obj, selNode, pathSoFar) {
    if (obj.roleName == selNode.roleName) {
       return pathSoFar + '\\' + obj.roleName;
    }
    else if (obj.children) {
      for (var i=0 ; i<obj.children.length ; i++) {
          var temp = getPath(obj.children[i], selNode, 
                  pathSoFar + '\\' + obj.roleName);
          if (temp != null) {
              return temp;
          }
       }
    }
    return null;
}

getPath(rootObj, selNode, '');

I hope it helps and explains the solution idea.

发布评论

评论列表(0)

  1. 暂无评论