过滤树结构

时间:2015-04-22 10:37:48

标签: javascript filter tree coffeescript underscore.js

我正在尝试迭代一棵树,但不知怎的,我似乎无法让它像我想的那样工作。

我有一个带有整数的过滤器(由用户选择)

节点如下:

  • Id:Int
  • ParentId:Int
  • 儿童:{nodes(Objects)}

我的树:

树(根)

    • 儿童(ID:1)
        • 儿童(ID:2)
    • 儿童(身份证号码:3)
        • 儿童(身份证号码:4)
      • 儿童(ID:5)

我想结束这样的事情。选择的每个节点+所选节点的父节点一直到顶部。

树(根)

    • 儿童(ID:1)
        • 儿童(ID:2)
    • 儿童(身份证号码:3)
        • 儿童(ID:4)
      • 儿童(ID:5)

我目前的解决方案如下所示

  organizationIterator = (node, filter, parent, result) ->
    _.each(node, (leaf)->
      tempLeaf = _.clone(leaf)
      tempIndex = filter.indexOf(leaf.organizationId)
 
      if tempIndex > -1
        if result[leaf.parentOrganizationId]
          tempLeaf.subOrganizations = []
          parent.subOrganizations.push tempLeaf
          result[parent.organizationId] = parent
        else
          result[leaf.organizationId] = tempLeaf
      else
        tempLeaf.notSelected = true
 
      if leaf.subOrganizations
        tempLeaf.subOrganizations = []
        organizationIterator(leaf.subOrganizations, filter, tempLeaf, result)
    )

希望有人可以指导我找到合适的解决方案。

1 个答案:

答案 0 :(得分:1)

我不知道你是如何在Coffeescript中做到的,但在常规的Javascript中,它看起来如下所示。希望这为您提供了一个开始:

//setup 
var input = document.getElementById('filter'),
    tree = document.getElementById('tree'),
    selectedValues = [],
    items = tree.getElementsByTagName('li'), afterInsert;
for (var i = 0; i < items.length; i++) {
  afterInsert = items[i].firstChild.nextSibling;
  items[i].setAttribute('data-id', i);
  items[i].insertBefore(document.createTextNode(' ' + (i+1)), afterInsert);
}


input.addEventListener('change', function() { 
  selectedValues = input.value.split(','); 
  var count = /[0-9]/g.test(input.value) ? selectedValues.length : items.length;
  // if input is non-empty
  if (/[0-9]/g.test(input.value)) {
    // make the selected values from input of type number and zero-based
    while (count--) 
      selectedValues[count] = parseInt(selectedValues[count]-1);
    
    // THE RECURSIVE FUNCTION
    function addParent(node) {
      var index = parseInt(node.getAttribute('data-id'));
      if (node.nodeName == 'LI') {
        // only add an index if it's not already present
        if (selectedValues.indexOf(index) === -1)
          selectedValues.push(index);
        addParent(node.parentNode.parentNode);
        
      }
    }
    for (var i = selectedValues.length; i--;) {
      addParent(items[selectedValues[i]]);
    }
  // if input is empty, set all items to 'selectedValues'
  } else {
    while (count--) 
      selectedValues.push(count);
    
  }
  for (var i = items.length; i--;) {
    if (selectedValues.indexOf(i) !== -1)
      items[i].style.display = 'list-item';
    else
      items[i].style.display = 'none';
  }
}, false);
<p>Write different numbers as comma-separated into the input field</p>Filter: <input type="text" id="filter">
<ul id="tree">
  <li>item</li>
  <li>item
    <ul>
      <li>item</li>
      <li>item
        <ul>
          <li>item</li>
        </ul>
      </li>
      <li>item</li>
    </ul>
  </li>
  <li>item
    <ul>
      <li>item
        <ul>
          <li>item</li>
          <li>item</li>
        </ul>
      </li>
      <li>item</li>
    </ul>
  </li>
</ul>