获取嵌套集模型转换为< UL>但躲在"封闭"子树 [英] Getting nested set model into a <ul> but hiding "closed" subtrees

查看:127
本文介绍了获取嵌套集模型转换为< UL>但躲在"封闭"子树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据<α

href=\"http://stackoverflow.com/questions/1310649/getting-a-modified-$p$porder-tree-traversal-model-nested-set-into-a-ul\">Getting修改后的preorder树遍历模型(嵌套组)成&LT; UL&GT;

一个答案给权code显示全树。我需要的是始终显示第一级(深度= 0)和活动列表项的兄弟姐妹+儿童。目标是扩大在用户选择列表项这是多个列表项的父树的可见部分。

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

  1。项目
2.项目
  2.1。项目
  2.2。项目
    2.2.1。项目
    2.2.2。项目
    2.2.3。项目
  2.3。项目
  2.4。项目
    2.4.1。项目
    2.4.2。项目
3.项目
4.项目
  4.1。项目
  4.2。项目
    4.2.1。项目
    4.2.2。项目
5.项目

如果当前列表项为2,列表应该看起来像:

  1。项目
2.项目//这需要.selected类
  2.1。项目
  2.2。项目
  2.3。项目
  2.4。项目
3.项目
4.项目
5.项目

如果当前列表项就是2.2,列表应该看起来像:

  1。项目
2.项目//这需要.selected类
  2.1。项目
  2.2。项目//这需要.selected类
    2.2.1。项目
    2.2.2。项目
    2.2.3。项目
  2.3。项目
  2.4。项目
3.项目
4.项目
5.项目

下面有一个例子code这很适合我显示全树。我还添加了LFT / RGT /电流,将需要解决我的问题。

 &LT; PHP
功能MyRenderTree($树=阵列(阵列('名'=&GT;'','深度'=&GT;'','LFT'=&GT;'','RGT'=&GT;'')),$当前= FALSE){   $ current_depth = 0;
   $计数器= 0;   $结果='&L​​T; UL&GT;';   的foreach($树作为$节点){
       $ node_depth = $节点['深度'];
       $ NODE_NAME = $节点['名'];
       $ NODE_ID = $节点['CATEGORY_ID'];       如果($ node_depth == $ current_depth){
           如果($计数器大于0)$结果='&L​​T; /李&GT;';
       }
       ELSEIF($ node_depth&GT; $ current_depth){
           $结果='&L​​T; UL&GT;';
           $ current_depth = $ current_depth +($ node_depth - $ current_depth);
       }
       ELSEIF($ node_depth&LT; $ current_depth){
           $结果= str_repeat('&LT; /李&GT;&LT; / UL&GT;',$ current_depth - $ node_depth)'&LT; /李&GT;'。;
           $ current_depth = $ current_depth - ($ current_depth - $ node_depth);
       }
       $结果='&L​​T;李ID =C'。$ NODE_ID。'';
       $结果= $ node_depth&LT; 2?类=开放':'';
       $结果='&GT;&LT; A HREF =#&GT;'。$ NODE_NAME'&LT; / A&GT;'。
       ++ $计数器;
   }
   $结果= str_repeat。('&LT; /李&GT;&LT; / UL&GT;',$ node_depth)'&LT; /李&GT;'。   $结果='&L​​T; / UL&GT;';   返回$结果;
}//$当前可能含有CATEGORY_ID,LFT,RGT主动列表项
打印MyRenderTree($类,$电流);
?&GT;


解决方案

当你已经成功地顺序排序,为什么需要不只是输出?

由于一些叶子需要显示为关闭,所以该迭代器应该能够跳过未选择节点的孩子。

这样做使我的想法来解决终止输出树(输出=解析)的问题。做什么,如果该序列中的最后一个有效节点是在比0更高的深度是多少?我追加一个NULL终结符。所以还开着水平可以循环完成之前被关闭。

此外迭代器过载节点提供对他们常用的方法,如对当前所选元素比较。

该MyRenderTree功能(演示/满code

编辑:演示codePAD有问题,这里是源 - code:要点结果
获取嵌套集模型成隐藏,但封闭子树

 函数MyRenderTree($树=阵列(阵列('名'=&GT;'','深度'=&GT;'','LFT'=&GT;'',' RGT'=&GT;'')),$电流= FALSE)
{
    $序列=新SequenceTreeIterator($树);    呼应'&LT; UL&GT;';
    $ hasChildren = FALSE;
    的foreach($序列$节点)
    {
        如果($接近= $先后次序&GT; getCloseLevels())
        {
            回声str_repeat('&LT; / UL&GT;&LT; /李&GT;',$关闭);
            $ hasChildren = FALSE;
        }
        如果(!$节点放;&安培; $ hasChildren)
        {
            呼应'&LT; /李&GT;',\\ n;
        }
        如果(!$节点)打破; #终止        $ hasChildren = $于节点&GT; hasChildren();
        $ isSelected = $&于节点GT; isSupersetOf($电流);        $类=阵列();
        $ isSelected和放大器;&安培; ($类[] ='选择')及和放大器; $ hasChildren和放大器;&安培; $类[] ='开放';
        $于节点&GT; isSame($电流)及&放大器; $类[] ='目前';        的printf('&LT;李班=%S&GT;%s'的,爆('',$班),$节点['名']);        如果($ hasChildren)
            如果($ isSelected)
                呼应'&LT; UL&GT;';
            其他
                $序列 - &GT; skipChildren()
            ;
        其他
            呼应'&LT; /李&GT;'
        ;
    }
    呼应'&LT; / UL&GT;';
}

这可以在一个单一的foreach和一些变量来解决为好,但我觉得对于重新useablilty的基础上的 SPL迭代器是更好的。

Based on Getting a modified preorder tree traversal model (nested set) into a <ul>

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

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

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

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.

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.

The MyRenderTree function (Demo/Full code)

Edit: 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>';
}

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;但躲在&QUOT;封闭&QUOT;子树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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