将嵌套集合模型放入中但隐藏“封闭”子树
答案之一给出了正确的代码来显示完整的树。我需要的是始终显示活动列表项的第一级(深度=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);
?>
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);
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
既然您已经成功地对序列进行了排序,为什么不根据需要输出呢?
由于某些叶子需要显示为关闭,因此迭代器应该能够跳过未选定节点的子节点。
这样做使我产生了解决终止输出树(输出=解析)问题的想法。如果序列中最后一个有效节点的深度大于 0 该怎么办?我为此附加了一个 NULL 终止符。因此,在循环结束之前可以关闭仍然打开的级别。
此外,迭代器会重载节点以在其上提供通用方法,例如与当前选定的元素进行比较。
MyRenderTree 函数(演示/完整代码)
编辑: 演示键盘有问题,这里是源代码:要点
将嵌套集模型放入但隐藏“封闭”子树中
这也可以在单个 foreach 和一些变量中解决,但是我认为为了可重用,基于 SPL 迭代器 更好。
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
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.
可以使用 Jquery,而不是使用 PHP 脚本来处理树导航。
一旦树生成,其余的事情将在客户端本身处理,它还将保存服务器请求。
请参阅示例 2 和 3
http://jquery.bassistance.de/treeview/demo/
< a href="http://docs.jquery.com/Plugins/Treeview" rel="nofollow">http://docs.jquery.com/Plugins/Treeview
它可能会根据您的要求有所帮助。
Instead of using PHP script for handling tree navigation, Jquery can be used.
Once the tree is generated rest of the things will handled on client itself, it will also save server requests.
See Sample 2 and 3
http://jquery.bassistance.de/treeview/demo/
http://docs.jquery.com/Plugins/Treeview
It may help as per your requirement.
该函数期望 $tree 按“左”排序。
我已根据“左”和“右”值将您的功能修改为选定的项目。希望这就是您所追求的。
修改后的功能:
用法:
The function expect the $tree is order by the 'left'.
I have modified your function to selected items based on the 'left' and 'right' value. Hope it's what you are after.
The modified function:
Usage:
http://www.jstree.com/ 是一个 jQuery 插件,它将为您更优雅地处理这个问题比尝试基于 PHP 的解决方案更快。
查看 http://www.jstree.com/demo 获取现场演示以及有关 Tom 如何实施的说明。
http://www.jstree.com/ is a jQuery plugin which will handle this for you far more elegantly and quickly than trying to do a PHP based solution.
Check out http://www.jstree.com/demo for a live demo and instruction on how tom implement.
基于 satrun77 的回答。我为 symfony + doctrine + nestedset (http://www.doctrine-project.org/projects/orm/1.2/docs/manual /hierarchical-data/en):
额外标签: tree, 节点
Based on answer by satrun77. I created a helper for symfony + doctrine + nestedset (http://www.doctrine-project.org/projects/orm/1.2/docs/manual/hierarchical-data/en):
Extra tags: tree, node
此方法检查该节点是否是所选节点的父节点、所选节点或深度=0。只有满足这些条件之一的节点的迭代才会将列表项添加到结果字符串中。所有节点都会获得选定的班级、开放班级或两者。否则,它就是你的代码。
// “$current”可能包含活动列表项的category_id、lft、rgt
打印 MyRenderTree($categories,$current);
?>
This method checks to see if the node is a parent of the selected node, the selected node, or depth=0. Only iterations for nodes which meet one of these conditions add list items to the result string. All of the nodes get either the selected class, open class or both. Otherwise, it is your code.
// "$current" may contain category_id, lft, rgt for active list item
print MyRenderTree($categories,$current);
?>
只是想提供一个 OOP、更干净的版本,这应该可以更轻松地添加除所选逻辑之外的任何类型的逻辑。
它可以与@satrun77 发布的数组结构一起正常工作。
Just wanted to provide a OOP, cleaner version, which should make it easier to add any sort of logic apart from the selected one.
It works properly with the array structure posted by @satrun77.
这不是最好的解决方案吗?为什么有这么多类、对象等等?
这个简单的功能在各方面都是完美且灵活的。
演示
isn't it the best solution. why there are so many classes, objects bla bla.. ?
this simple function is perfect and flexible in everyways.
DEMO