Zahari M. Posted July 20, 2013 Share Posted July 20, 2013 Hi Guys. First Post! Greetings from Malaysia. I'm trying to move over from WordPress and am absolutely delighted to have found ProcessWire!As I'm a really slow learner, it's been taking me quite some time tounderstand the ProcessWire conventions. But bit by bit I'm getting there... OK...as the question asks, I would be really grateful if someone could helpme out by telling me how we can go about excluding pages from theFoundation menu? I have downloaded and installed the Foundation template files for the standard Processwire site install. I have spent a long time trying to understand it and believe that the solution lies in editing renderTopNav that is located in _nav.php. function renderTopNav(PageArray $items, array $options = array(), $level = 0) { $defaults = array( 'tree' => 2, // number of levels it should recurse into the tree 'dividers' => true, 'repeat' => false, // whether to repeat items with children as first item in their children nav ); $options = array_merge($defaults, $options); $divider = $options['dividers'] ? "<li class='divider'></li>" : ""; $page = wire('page'); $out = ''; foreach($items as $item) { $numChildren = $item->numChildren(true); if($level+1 > $options['tree'] || $item->id == 1) $numChildren = 0; $class = ''; if($numChildren) $class .= "has-dropdown "; if($page->id == $item->id) $class .= "current "; if(($item->id > 1 && $page->parents->has($item)) || $page->id == $item->id) $class .= "active "; if($class) $class = " class='" . trim($class) . "'"; $out .= "$divider<li$class><a href='$item->url'>$item->title</a>"; if($numChildren) { $out .= "<ul class='dropdown'>"; if($options['repeat']) $out .= "$divider<li><a href='$item->url'>$item->title</a></li>"; $out .= renderTopNav($item->children, $options, $level+1); $out .= "</ul>"; } $out .= "</li>"; } return $out; } During a search, there was a thread here that discussed the various ways on how to exclude pages from the navigation. The only problem is that due to my limited skill set, it's just a bit beyond my abilities to adapt this into the function above! Couldanyone help me out with how to modify the function so that we canexclude pages from the Foundation menu by way creating a checkbox field? Many thanks! Zahari Link to comment Share on other sites More sharing options...
horst Posted July 20, 2013 Share Posted July 20, 2013 Hi Zahari, welcome to the forums. Great you have found PW ;-) ...Could anyone help me out with how to modify the function so that we can exclude pages from the Foundation menu by way creating a checkbox field? I assume you know how to add a checkbox-field to the templates (if not, please ask here again!) For example you may call this field "excludeFromTopnav" and after that you have to check in the foreach-loop in the function if the current item (what comes from an PageArray, so it is a $page) have this field checked or not: (Line 16) function renderTopNav(PageArray $items, array $options = array(), $level = 0) { $defaults = array( 'tree' => 2, // number of levels it should recurse into the tree 'dividers' => true, 'repeat' => false, // whether to repeat items with children as first item in their children nav ); $options = array_merge($defaults, $options); $divider = $options['dividers'] ? "<li class='divider'></li>" : ""; $page = wire('page'); $out = ''; foreach($items as $item) { if($item->excludeFromTopnav == 1) { continue; // should be excluded, so we skip and went to the next } $numChildren = $item->numChildren(true); if($level+1 > $options['tree'] || $item->id == 1) $numChildren = 0; $class = ''; if($numChildren) $class .= "has-dropdown "; if($page->id == $item->id) $class .= "current "; if(($item->id > 1 && $page->parents->has($item)) || $page->id == $item->id) $class .= "active "; if($class) $class = " class='" . trim($class) . "'"; $out .= "$divider<li$class><a href='$item->url'>$item->title</a>"; if($numChildren) { $out .= "<ul class='dropdown'>"; if($options['repeat']) $out .= "$divider<li><a href='$item->url'>$item->title</a></li>"; $out .= renderTopNav($item->children, $options, $level+1); $out .= "</ul>"; } $out .= "</li>"; } return $out; } So, not tested and I also haven't worked with the foundation profile, but it should work. Otherwise please come back here. Link to comment Share on other sites More sharing options...
Zahari M. Posted July 20, 2013 Author Share Posted July 20, 2013 Hi Horst! Thank you so much for the welcome. And even more so for helping me out! Thanks so much Horst for pointing me to the area that needed looking at. Your code works great! But it's brought up 2 slight issues as a result.... But first, for the benefit of other beginners like me looking at this..... I did change it ever so slightly. I really wanted the default behaviour to be the opposite and that is by default pages are not added.... so I ended up calling my checkbox field addtonavbar and did this: if($item->addtonavbar == 0) { continue; // should be excluded, so we skip and went to the next } Of course Horst you would've inverted it this way too I'm most certain ! The two "catches" or issues that I discovered when testing this that you have to be mindful of.... First is that if you "hide" a parent page, you will automatically lose any wanted child pages in the nav bar, even if you had "checked" some of these child pages to be displayed using our approach above. Second, and a minor one at that, is that if you only wanted to display a particular parent, and have all it's children hidden, then our nav bar confusingly still renders a dropdown triangle... I'm happy with the progress thus far and can live with this as the nav bar wont be flooded with a huge number of items!! But if these two "catches" could be resolved, then we all would have an uber "complete & refined" Foundation top nav bar solution ! Thanks again so much Horst! Zahari Link to comment Share on other sites More sharing options...
horst Posted July 21, 2013 Share Posted July 21, 2013 Hi Zahari, great there is some progress. Lets's look to the two issues now. And I once again want to say that I haven't used that profile, and I don't know it, - so if there is someone reading who knows it, come in and shed some light second one first: ...Second, and a minor one at that, is that if you only wanted to display a particular parent, and have all it's children hidden, then our nav bar confusingly still renders a dropdown triangle... As the original code is written to render the navbar fast and straight forward, we have to hack in and rearrange parts and also first have to buffer the (optional) childrens output. This very fast can become cumbersome. Here is a version that you may try. I haven't tried it and I don't know if it works. If I understand the original code and assume it's relations right, it should work, but I don't know. function renderTopNav(PageArray $items, array $options = array(), $level = 0) { $defaults = array( 'tree' => 2, // number of levels it should recurse into the tree 'dividers' => true, 'repeat' => false, // whether to repeat items with children as first item in their children nav ); $options = array_merge($defaults, $options); $divider = $options['dividers'] ? "<li class='divider'></li>" : ""; $page = wire('page'); $out = ''; foreach($items as $item) { if($item->addtonavbar == 0) { continue; // should be excluded, so we skip and went to the next } $numChildren = $item->numChildren(true); if($level+1 > $options['tree'] || $item->id == 1) $numChildren = 0; $buffer = ''; // we need to buffer all children output if($numChildren) { $buffer2 = renderTopNav($item->children, $options, $level+1); if(strlen(trim($buffer2))>0) { $buffer = "<ul class='dropdown'>"; if($options['repeat']) $buffer .= "$divider<li><a href='$item->url'>$item->title</a></li>"; $buffer .= $buffer2; $buffer .= "</ul>"; } } $class = ''; if($numChildren && strlen($buffer)>0) $class .= "has-dropdown "; // parent gets dropdown-triangle if it has numchildren and the childrens-buffer isn't empty if($page->id == $item->id) $class .= "current "; if(($item->id > 1 && $page->parents->has($item)) || $page->id == $item->id) $class .= "active "; if($class) $class = " class='" . trim($class) . "'"; $out .= "$divider<li$class><a href='$item->url'>$item->title</a>"; $out .= $buffer; // buffer is an empty string or contains complete ul-list of children $out .= "</li>"; } return $out; } ...First is that if you "hide" a parent page, you will automatically lose any wanted child pages in the nav bar, even if you had "checked" some of these child pages to be displayed using our approach above. I think it is logical if you don't show a parent, you cannot show it's children. They belong together. Link to comment Share on other sites More sharing options...
Zahari M. Posted July 21, 2013 Author Share Posted July 21, 2013 Hi Horst! Thanks so much for the reply and looking into this! I've tried your code Horst and guess what... it works! Awesome stuff! Your one clever guy! Using Google... ich danke Ihnen sehr 1 Link to comment Share on other sites More sharing options...
ryan Posted July 23, 2013 Share Posted July 23, 2013 Also, don't forget about the "hidden" checkbox on every page's "settings" menu. That by itself would enable you to hide items from the Foundation menu. This is the method that is used natively in the profile to hide things like the search page from appearing in the menu. 2 Link to comment Share on other sites More sharing options...
horst Posted July 23, 2013 Share Posted July 23, 2013 Also, don't forget about the "hidden" checkbox on every page's "settings" menu. That by itself would enable you to hide items from the Foundation menu. This is the method that is used natively in the profile to hide things like the search page from appearing in the menu. Thank's Ryan! I assumed that the pages only should excluded from the menu, but not from searches or maybe other lists (e.g. sitemap). But I only assumed that. I better first should ask for it, - what could save some coding, depending on the answer. Link to comment Share on other sites More sharing options...
cstevensjr Posted July 23, 2013 Share Posted July 23, 2013 @Horst, Thank you for greatly for working on this. This solved an issue where I had many tags showing up in the top navigation menu. Also, don't forget about the "hidden" checkbox on every page's "settings" menu. That by itself would enable you to hide items from the Foundation menu. This is the method that is used natively in the profile to hide things like the search page from appearing in the menu. @Ryan, that works under most situations, but it does not allow you to later search for those items. It would be nice to have a status of Hidden: Not excluded from lists and searches. Hopefully that makes sense to you. 1 Link to comment Share on other sites More sharing options...
kongondo Posted July 23, 2013 Share Posted July 23, 2013 @Ryan, that works under most situations, but it does not allow you to later search for those items. It would be nice to have a status of Hidden: Not excluded from lists and searches. Hopefully that makes sense to you. @cstevensjr I get what you are saying about different situations but of course you can still search for hidden and unpublished items by using "include=hidden" or "include=all" in your selectors. You can also use $pages->get to get one page, hidden or not. . I suppose it's about using what best suits the situation.. @Horst - the above code was definitely not a waste of time! 2 Link to comment Share on other sites More sharing options...
cstevensjr Posted July 23, 2013 Share Posted July 23, 2013 @Kongondo, Thanks for that tidbit. I'm still learning and appreciate the advice. Link to comment Share on other sites More sharing options...
kongondo Posted July 23, 2013 Share Posted July 23, 2013 You are welcome. I've updated my post with a link to the docs... Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now