基于
Getting a modified preorder tree traversal model (nested set) into a <ul>
其中一个答案给出了正确的代码来显示完整的树.我需要的是总是显示一级(深度= 0)和兄弟姐妹的活动列表项.目标是在用户选择更多列表项目的父项的列表项时展开树的可见部分.
所以,如果我得到这个列表:
1. item 2. item 2.1. item 2.2. item 2.2.1. item 2.2.2. item 2.2.3. item 2.3. item 2.4. item 2.4.1. item 2.4.2. item 3. item 4. item 4.1. item 4.2. item 4.2.1. item 4.2.2. item 5. item
如果当前列表项为“2.”,列表应如下所示:
1. item 2. item // this needs class .selected 2.1. item 2.2. item 2.3. item 2.4. item 3. item 4. item 5. item
如果当前列表项是“2.2”,则列表应如下所示:
1. item 2. item // this needs class .selected 2.1. item 2.2. item // this needs class .selected 2.2.1. item 2.2.2. item 2.2.3. item 2.3. item 2.4. item 3. item 4. item 5. item
下面是一个示例代码,对我来说显示完整的树很好.我还添加了需要解决我的问题的lft / rgt / current.
<?PHP function MyRenderTree ( $tree = array(array('name'=>'','depth'=>'','lft'=>'','rgt'=>'')),$current=false){ $current_depth = 0; $counter = 0; $result = '<ul>'; foreach($tree as $node){ $node_depth = $node['depth']; $node_name = $node['name']; $node_id = $node['category_id']; if($node_depth == $current_depth){ if($counter > 0) $result .= '</li>'; } elseif($node_depth > $current_depth){ $result .= '<ul>'; $current_depth = $current_depth + ($node_depth - $current_depth); } elseif($node_depth < $current_depth){ $result .= str_repeat('</li></ul>',$current_depth - $node_depth).'</li>'; $current_depth = $current_depth - ($current_depth - $node_depth); } $result .= '<li id="c'.$node_id.'"'; $result .= $node_depth < 2 ?' class="open"':''; $result .= '><a href="#">'.$node_name.'</a>'; ++$counter; } $result .= str_repeat('</li></ul>',$node_depth).'</li>'; $result .= '</ul>'; return $result; } // "$current" may contain category_id,lft,rgt for active list item print MyRenderTree($categories,$current); ?>
当您已经设法排序序列时,为什么不根据需要输出?
由于某些叶需要关闭,所以迭代器应该能够跳过非选定节点的子节点.
这样做导致我想到解决终止输出树(output = parsing)的问题.如果序列中的最后一个有效节点的深度高于0,该怎么办?我附加了一个NULL终结符.因此,在循环完成之前,仍然可以关闭开放级别.
此外,迭代器重载节点以提供常见的方法,如与当前选择的元素进行比较.
MyRenderTree函数(Demo/Full code)
编辑:Demo键盘有问题,这里是源代码:Gist
Getting nested set model into a but hiding “closed” subtrees
function MyRenderTree($tree = array(array('name'=>'',$current=false) { $sequence = new SequenceTreeIterator($tree); echo '<ul>'; $hasChildren = FALSE; foreach($sequence as $node) { if ($close = $sequence->getCloseLevels()) { echo str_repeat('</ul></li>',$close); $hasChildren = FALSE; } if (!$node && $hasChildren) { echo '</li>',"\n"; } if (!$node) break; # terminator $hasChildren = $node->hasChildren(); $isSelected = $node->isSupersetOf($current); $classes = array(); $isSelected && ($classes[] = 'selected') && $hasChildren && $classes[] = 'open'; $node->isSame($current) && $classes[] = 'current'; printf('<li class="%s">%s',implode(' ',$classes),$node['name']); if ($hasChildren) if ($isSelected) echo '<ul>'; else $sequence->skipChildren() ; else echo '</li>' ; } echo '</ul>'; }
这可以在一个单一的foreach和一些变量中解决,但是我认为可重用,基于SPL Iterators的实现更好.