Jump to content

A recursive navigation of selectable pages containing home, with parent menu items not having their own page to show


dlen
 Share

Recommended Posts

Hi there,

i just want to share the code of what the subject line says.

The pages to appear in the menu have a custom field "in_main_menu" of type checkbox checked.

The item <li>s of the actually shown page and in the direttissima upwards - except home - get the class "current".

The item <ul>s of submenus get the class "submenu".

This is basically Ryans Code from here run through a meatgrinder.

I hope useful for any beginners like me looking for a solution to a similar problem.

Any improvement welcome!

Now the code:

/**
* A recursive menu containing home. (It is added to the list of menu items while $level =1).
* In order to be included, a page must have a custom field "in_main_menu" of type "checkbox",
* and the latter has to be checked.
* All submenu <ul>s get class "submenu".
* All <li>s in the direttissima upwards of the page shown - except home - get the class "current".
* Takes $root out of the recursion in order to not have all pages twice.
* All menu items, that have children, do not have a link to their content, but act merely as switches.
* You can switch this behaviour off by replacing
*
*       $href = (  $item == $root  ||  !$item->numChildren  ?   "$item->url"  :  "#"  );
*
* with
*
*       $href = $item->url;
*
* Or you can make it conditional by querying a second custom field "has_own_page", e.g.
*
*       $href = (  $item == $root  ||  !$item->numChildren  || $item->has_own_page  ?   "$item->url"  :  "#"  );
*
* Intended to be used without arguments, i.e.   "selectiveMenu();"  , i.e. always starting with site root.
*/

function selectiveMenu(Page $root = null) {

        $shownPage = wire('page');
        if(is_null($root)) $root = wire('pages')->get('/');

        $level = count($root->parents);
        $ul_class_string = (($level > 0)  ?  "class='submenu'"  :  "");

        $out = "\n<ul {$ul_class_string}>";

        $parents = $shownPage->parents;
        $items = $root->children;
        if ($level == 0) $items->prepend($root);

        foreach( $items as $item) {

                if ($item->in_main_menu) {

                        $s = '';

                        $li_class_string = ( ( $parents->has($item) && $item !== $root ) || $item === $shownPage  ? "class='current'" : "" );

                        if($item->numChildren && $item !== $root) {
                                $s = str_replace("\n", "\n\t\t", selectiveMenu($item));
                        }

                        $href = (  $item == $root  ||  !$item->numChildren  ?   "$item->url"  :  "#"  );

                        $out .= "\n\t<li {$li_class_string}>\n\t\t<a href='{$href}'>{$item->title}</a>$s\n\t</li>";
                }
        }
        $out .= "\n</ul>";
        return $out;
}
  • Like 1
Link to comment
Share on other sites

  • 1 month later...

An updated version with some more features

/** 
* A recursive menu containing home. 
* If no root page is given, site root will be taken.
* If and only if the second parameter is given, only pages will be included, that have a custom field of type "checkbox",
* and the latter has to be checked. This field is the parameter to be given. Example with field "in_main_menu":
* 
*      selectiveMenu(null, $fields->in_main_menu);
*
* All submenu <ul>s get class "submenu".
* All <li>s in the direttissima upwards of the page shown - except home - get the class "current".
* All menu items, that have the template name 'no_content' do not have a link to their content, but act merely as switches 
* to their subpages. This template must have also the selector field, if the parameter is given.
* 
* Intended to be used without arguments, i.e.   "selectiveMenu();"  , i.e. always starting with site root.
*
* @param Page                       root page of the menu
* @param Field menu_selector_field  pages with this "checkbox" field in their template set to "checked" are represented
* @param string menu_id             The id the outermost ul - tag gets.
* @return string
*/

function selectiveMenu(Page $root = null, Field $menu_selector_field = null, $menu_id = null) {

        $shownPage = wire('page');
        if(is_null($root)) $root = wire('pages')->get('/');

        $level = count($root->parents); 
        $ul_class_string = (($level > 0)  ?  "class='submenu'"  :  "");
        $ul_id_string = ($menu_id  ?  "id='$menu_id'"  :  "");

        $out = "\n<ul {$ul_class_string} {$ul_id_string}>";

        $parents = $shownPage->parents;
        $items = $root->children;
        if ($level == 0) $items->prepend($root); 

        foreach( $items as $item) {

                if ($item->$menu_selector_field || !$menu_selector_field) {

                        $s = '';

                        $li_class_string = ( ( $parents->has($item) && $item !== $root ) || $item === $shownPage  ? "class='current'" : "" );

                        if($item->numChildren(true) && $item !== $root) {
                                $s = str_replace("\n", "\n\t\t", selectiveMenu($item, $menu_selector_field));
                        }

                        $href_attr = (  $item == $root  ||  $item->template->name != 'no_content'  ?   "href='$item->url'"  :  ""  );

                        $out .= "\n\t<li {$li_class_string}>\n\t\t<a $href_attr>{$item->title}</a>$s\n\t</li>";
                }
        }
        $out .= "\n</ul>";
        return $out;
}

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...