将嵌套集模型放入 <ul>但隐藏“关闭"子树 [英] Getting nested set model into a <ul> but hiding "closed" subtrees

查看:38
本文介绍了将嵌套集模型放入 <ul>但隐藏“关闭"子树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于 获取修改前序树遍历模型(嵌套集)成<ul>

其中一个答案给出了显示完整树的正确代码.我需要的是始终显示活动列表项的第一级(深度= 0)和兄弟姐妹+孩子.目标是当用户选择列表项时扩展树的可见部分,列表项是更多列表项的父项.

One of answers gave right code to display full tree. What i need is to always show first level (depth=0) and siblings+childrens for active list item. Goal is to expand visible part of tree when user selects list item which is parent for more list items.

所以,如果我得到这个列表:

So, if i got this list:

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.",列表应该是这样的:

and if current list item is "2.", list should look like that:

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.",列表应该是这样的:

and if current list item is "2.2.", list should look like that:

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 来解决我的问题.

Below there is an example code which works well for me to display full tree. I also added lft/rgt/current which will be needed to solve my issue.

<?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);
?>

推荐答案

既然您已经设法对序列进行排序,为什么不直接根据需要输出?

As you already managed to sort the sequence, why not just output as needed?

由于一些叶子需要看起来是关闭的,所以迭代器应该能够跳过未选择节点的子节点.

As some leafs need to appear closed, so the iterator should be able to skip children of non-selected nodes.

这样做让我想到了解决终止输出树的问题(输出=解析).如果序列中最后一个有效节点的深度大于 0,该怎么办?我为此附加了一个 NULL 终止符.因此,可以在循环完成之前关闭仍然打开的级别.

Doing so lead me to an idea to solve the problem of terminating the output tree (output = parsing). What to do if the last valid node in the sequence is at a higher depth than 0? I appended a NULL terminator for that. So still open levels can be closed before the loop finishes.

此外,迭代器重载节点以提供通用方法,例如与当前选择的元素进行比较.

Additionally the iterator overloads nodes to offer common methods on them, like comparing against the currently selected element.

MyRenderTree 函数(Demo/完整代码)

The MyRenderTree function (Demo/Full code)

演示键盘有问题,这里是源代码:Gist
将嵌套集模型放入一个隐藏的封闭"子树

The Demo Codepad has problems, here is the source-code: Gist
Getting nested set model into a but hiding "closed" subtrees

function MyRenderTree($tree = array(array('name'=>'','depth'=>'', 'lft'=>'','rgt'=>'')) , $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 迭代器 更好.

This can be solved as well in a single foreach and some variables, however I think for re-useablilty, the implementation based on the SPL Iterators is better.

这篇关于将嵌套集模型放入 &lt;ul&gt;但隐藏“关闭"子树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆