Welcome Guest, Not a member yet? Register   Sign In
MPTtree, Hieararchical trees in a database table

[eluser]jamieburchell[/eluser]
Hi there

I'm using this to build a HTML list item menu and I'm trying to figure out a way to highlight the top level node if one of the children are selected.

Before MPTree I used tree nodes (parent_id rather than nested set) and achieved this by setting a flag "selected" in the node and added a "is_selected()" method that returned true if itself was selected, or any of its child nodes. That meant that when I was outputting the menu I could simply call "is_selected()" on the node I was outputting and append a class name of "active" if true.

How might I achieve similar functionality with MPTree?

Thanks for your time.

[eluser]WanWizard[/eluser]
A node is the parent of another node if $child->lft > $parent->lft and $child->rgt < $parent->rgt.

Note that this is true for any parent of the child node, not only for the immediate parent. If you only need the immediate parent, you need to query the database, get all records where lft < $child['lft'], rgt > $child['rgt'], order ASC on rgt, and LIMIT 1 to get the parent node.

[eluser]jamieburchell[/eluser]
Thank you for getting back to me so quickly. Armed with your response and the fact that while generating the menu I am aware what the current page is, I was able to use the current page's lft and rgt values against the node I was outputting like so:

Code:
if ($current['lft'] >= $node['lft'] && $current['rgt'] <= $node['rgt']) {
   $classes[] = 'active';
}

This seems to be working and I'm now trying hard to understand the logic.

The only down side is that all of the nodes are children of "Home" and so on every page "Home" is also highlighted. I've put a temporary hack in place until I can think of a better solution.

[eluser]WanWizard[/eluser]
Since you're storing the result in an array, why not loop over it, and wipe all 'active' entries but the last one?

[eluser]jamieburchell[/eluser]
Not entirely sure I follow. A better snippet might have been...

Code:
foreach ($tree as $node) {
   $classes = array();
   if (($current['lft'] >= $node['lft'] && $current['rgt'] <= $node['rgt']) {
      $classes[] = 'active';
   }
   $str .= '<li' . (count($classes) ? ' class="' . implode(' ', $classes) . '"' : '') . '><a href="' . ($node['url']) . '">' . $node['menu_title'] . '</a>';

   if ($CI->page_tree->count_children($node['lft'], $node['rgt'])) {
      $str .= get_menu($CI->page_tree->get_children_where($node['lft'], $node['rgt'], array('hidden' => 0, 'date(publish_date) <=' => date("Y-m-d"), 'show_in_menu' => 1)), $current, $level+1, $max_level);
   }

   $str .= '</li>';
   $i++;
}

[eluser]WanWizard[/eluser]
I don't understand this code. If you have three parents, you'll end up with 'active active active' in the last <li>?

Why not:
Code:
// first the direct parent node of the current node
$active = false;
foreach ($tree as $index => $node) {
   if (($current['lft'] >= $node['lft'] && $current['rgt'] <= $node['rgt']) {
      $active = $index;
   }
}

foreach ($tree as $index => $node) {
   $str .= '<li' . ($index == $active) ? ' class="active"' : '') . '><a href="' . ($node['url']) . '">' . $node['menu_title'] . '</a>';

   if ($CI->page_tree->count_children($node['lft'], $node['rgt'])) {
      $str .= get_menu($CI->page_tree->get_children_where($node['lft'], $node['rgt'], array('hidden' => 0, 'date(publish_date) <=' => date("Y-m-d"), 'show_in_menu' => 1)), $current, $level+1, $max_level);
   }

   $str .= '</li>';
   $i++;
}

[eluser]jamieburchell[/eluser]
The code snippet is within a get_menu function, which is called recursively to process all child nodes.

If for example, you're on page "One A" the menu output ends up looking like (I've removed a tags this post won't send otherwise):

Code:
<ol>
   <li>Home</li>
   <li class="active">Item One
      <ol>
         <li class="active">One A</li>
         <li>One B</li>  
      </ol>
   </li>
   <li>Item Two</li>
   <li>Item Three</li>
</ol>

This allows me to highlight the top level parent item "Item One" in the menu

[eluser]Unknown[/eluser]
Hi to all!
I am pretty new at CI, but in the past two months I managed to learn quite a bit, and I already successfully completed two medium-size web project with this incredible framework.

This is my first serious approach at MVC pattern, and so fa I have to say that CI is really great because of his small footprint, loose dependencies and GREAT documentation.

I became interested in hyerarchical data representation in mysql, and I found this great library.

I am on CI 2.1.0, php 5.3.

I managed to adapt this 1.7.x library to work with CI 2.1 and I am currently correcting few bugs in the code, implementing some new methods and trying to implement transactions.

I am quite a newbie in (my)sql, but if I'm not wrong, it seems that this library does not play well with unstable mysql servers-connections: table locking is implemented but not transactions, and because the queries does not use the "select for update" statement, I think this library is not transaction-safe. There is risk of leaving gaps or breaking the tree if every single query is automatically auto-committed.

I am still a newbie in sql, so I didn't want to go through an entire query rewriting to remove table locks and rewrite every query in the form of "select for update" statement, to make them transacton and concurrency safe, so I decided to remove internal table locking and manually lock-unlock the tables when calling the library and executing an updating statement. At the same time, setting an autocommit = 0, a commit/rollback and an unlock tables at the right places seems to do the trick well.

Unfortunately I have not documented my editings on mpttree code, but If you confirm me that my work is going in the right direction, I could manage to take some time to tidy up my work and post an updated-modifyed version of mpttree, 2.1.x ready and with some new functions implemented.

For example, I doubled every function making an ***_byid($id) version, because pointing a node with his lft attribute doesn't play well with concurrency: InnoDB never assigns two identical Ids, but a $lft value intended to point a deleted node could erroneously point at a new/wrong node.. and this is obviously an unwanted behaviour.

I also tested and slightly edited the insert_sorted function, that I see it's not documented in the manual.
This function allows to insert a node at a specified place, and to order same-level children alphabetically.
This is a GREAT feature, because this way there's no need to alphabetically order the results of a traversing query, making for a slightly slower insert but for a super fast alphabetically ordered displaying. Great!


==> Let me know if you are interested in some contribution, but please keep in mind that I am quite a newbie in php-sql-ci, so I take no responsibility for problems or anti-patterns I may use.

Thank you Smile

[eluser]Unknown[/eluser]
Not sure if i am just being a spanner but I can't find a download of this library.
I followed this url http://ellislab.com/forums/viewthread/74114/P60/#481805

That says "For all those who are asking for the 1.6-fix2 version (the latest, which was posted on CI base), here it is." but there is no link.

Can anyone provide an updated link?

thanks
toby

[eluser]kev[/eluser]
Where is the download link? Can't find it anywhere




Theme © iAndrew 2016 - Forum software by © MyBB