Jump to content

MarkupSimpleNavigation


Soma

Recommended Posts

EDIT: False alarm. Was on the subpage when checking ... (as I said, I missed something very obvious). Sure it wasn't collapsed there. Going to have a break now.

Hi Folks,

feel like an idiot, but (no idea why) i can't get the collapsed => true option to work ...

$navoptions = array(
    'collapsed' => true,
    'show_root' => true,
    'levels' => true,
    'max_levels' => 2
);

Everything works just fine, but the menu tree doesn't get collapsed (very simple page tree down to level 2). What is the obvious thing I'm missing?

Thanks!

Link to comment
Share on other sites

  • 1 month later...

Thanks for this fab module Soma. I've managed to get it work just fine on most of my simple sites, but now I'm having a bit of a headache and wonder if someone can help.  This is for a responsive template with dropdown menus and a megamenu (which I haven't attempted to integrate yet). 

The dropdowns work fine on a standard screen, but on mobile or tablet the menu items in the dropdown don't work and don't open the relevant page.  I think the problem is with the classes.  Here's a sample of what the menu should look like (to the third level):

<li class="sep"></li>
<li class="primary"> 
   <a href="features-neko-shortcodes.html" class="firstLevel hasSubMenu" >Features</a>
	<ul class="subMenu">
	   <li><a href="features-neko-shortcodes.html">Neko shortcodes</a></li>
	   <li><a href="features-animation.html">Neko animations</a></li>
	   <li><a href="features-footers.html">Footers</a></li>
	   <li class="dropdownSubmenu last"><a href="#" class="hasSubMenu">Sub menu</a>
		<ul class="subMenu">
		    <li><a href="#" class="">Third level 1</a></li>
		    <li><a href="#" class="">Third level 2</a></li>
		    <li class="last"><a href="#" class="">Third level 3</a></li>
		</ul>
           </li>
	</ul>
     </li>
<li class="sep"></li>

So after several tries this is how I have my MSN call in the template:

<?php
$treeMenu = $modules->get("MarkupSimpleNavigation"); // load the module
                                                        
$options = array(
    'parent_class' => 'primary',
    'current_class' => 'current',
    'has_children_class' => '',
    'levels' => true,
    'levels_prefix' => '',
    'max_levels' => null,
    'firstlast' => true,
    'collapsed' => false,
    'show_root' => true,
    'selector' => '',
    'selector_field' => 'nav_selector',
    'outer_tpl' => '<ul class="nav navbar-nav pull-right">||</ul>',
    'inner_tpl' => '<ul class="subMenu">||</ul>',
    'list_tpl' => '<li%s>||</li>',
    'list_field_class' => '',
    'item_tpl' => '<a class="firstLevel hasSubMenu"  href="{url}">{title}</a>',
    'item_current_tpl' => '<a href="{url}">{title}</a>',
    'xtemplates' => '',
    'xitem_tpl' => '<a href="{url}">{title}</a>',
    'xitem_current_tpl' => '<span>{title}</span>',
    'date_format' => 'Y/m/d',
    'code_formatting' => false,
    'debug' => false
);
echo $treeMenu->render($options, $page, $rootPage);
?>

As I said I've got this working for regular displays but it won't work for other devices, and when I view page source, the classes aren't really correct. One thing is I'm still struggling with how to vary the a href classes for the different levels, and how to change the li classes for the third level menu. I'm sure there are many other things wrong with it, so would appreciate another set of eyes.

cheers

Link to comment
Share on other sites

you may have reached a point where MSN can't exactly output the precise markup you need, though maybe its possible; MSN is really amazing and can do some really complex menu structures; but if you want to build a megamenu, then you might want to consider doing your own menu system:

https://processwire.com/talk/topic/2787-custom-menu-not-related-to-page-tree/?hl=%2Bcustom+%2Bmenu

i just setup a menu for a site which uses both regular menu drops and also mega menu; i was able to get that to work by putting an option in my menu-item template for it to activate the mega menu, then there is a way to group the child items of that into columns etc..

  • Like 1
Link to comment
Share on other sites

you may have reached a point where MSN can't exactly output the precise markup you need, though maybe its possible; MSN is really amazing and can do some really complex menu structures; but if you want to build a megamenu, then you might want to consider doing your own menu system:

https://processwire.com/talk/topic/2787-custom-menu-not-related-to-page-tree/?hl=%2Bcustom+%2Bmenu

i just setup a menu for a site which uses both regular menu drops and also mega menu; i was able to get that to work by putting an option in my menu-item template for it to activate the mega menu, then there is a way to group the child items of that into columns etc..

Thanks for the reply. I probably won't need to use the mega menu, I just need to get the dropdowns working for now. I'll take a look at the link you've posted to see if I should just go for a custom menu system and forget about using MSN for this.

cheers

Link to comment
Share on other sites

@einsteinboi

This setup is somehow strange and very unusual. I try to avoid having too much classes. For example no need for classes on <a> items. It's more flexible if using class only on <li>'s since you can style containing links. You now have twice the class for a dropdown:

<li class="dropdownSubmenu last"><a href="#" class="hasSubMenu">Sub menu</a> ...

Makes no sense and don't see why that's needed. A lot what you have in the markup example doesn't make sense to me to do it this way.

I usually build my navigations with little to no classes and work with what MSN has by default, instead of trying to adapt MSN. With right CSS and JS every type of navigation is possible without doing much.

You can however modify a lot with MSN options and simple hooks. Almost everything is possible, and even if it takes some time, writing own nested lists with all those features wouldn't be less difficult. 

  • Like 1
Link to comment
Share on other sites

Since I'm not keen to do the work for everyone here, as I already had done a lot and multiple times in this very thread. It's all here and more even in the readme of this module. With a little study you'd be able to do what you wan't. 

  • Like 1
Link to comment
Share on other sites

@einsteinboi

This setup is somehow strange and very unusual. I try to avoid having too much classes. For example no need for classes on <a> items. It's more flexible if using class only on <li>'s since you can style containing links. You now have twice the class for a dropdown:

<li class="dropdownSubmenu last"><a href="#" class="hasSubMenu">Sub menu</a> ...

Makes no sense and don't see why that's needed. A lot what you have in the markup example doesn't make sense to me to do it this way.

I usually build my navigations with little to no classes and work with what MSN has by default, instead of trying to adapt MSN. With right CSS and JS every type of navigation is possible without doing much.

You can however modify a lot with MSN options and simple hooks. Almost everything is possible, and even if it takes some time, writing own nested lists with all those features wouldn't be less difficult. 

Soma, I agree with you about the many classes, but this is the HTML/CSS template as it was handed to me by the client to port into PW, so not much I can do about it, especially because I'm not a front end HTML/CSS dev.  But I'll try to figure it out some more, was just seeking some help on how to apply MSN for all the levels of classes in this particular nav

Since I'm not keen to do the work for everyone here, as I already had done a lot and multiple times in this very thread. It's all here and more even in the readme of this module. With a little study you'd be able to do what you wan't. 

No problem Soma, I'm not really asking or expecting anyone to do any work for me :)  Thanks for your response.

Link to comment
Share on other sites

  • 2 weeks later...
  • 2 weeks later...

I am new and have been looking, but honestly wouldn't recognize what I'm looking for. I just want to be able to choose which pages I want to show in my navigation bar. Can anyone help me out on how to do that? Thank you. 

Link to comment
Share on other sites

There's various approaches, that as well can be mixed. Just some using the custom "selector" option, that will be used by the module to run the nested queries. By default all pages that are not hidden will be shown. But there's some options to do more.

- Easiest in admin: setting pages or only parents of branches to hidden in the admin, they won't show in navigation. 

- Or through a checkbox to hide or show a page, always by the laws of hierarchy and physics. Then use the "selector" option to *checkboxfieldname=1" and include or exclude in MarkupSimpleNavigation.

"selector" => "show_in_nav=0" // only the unchecked ones, don't show checked ones

- Or by a selector and by template name.

"selector" => "template=basic-page" // only pages with template basic-page.

Just play around and think about what would be simple approach in your scenario.

See and try out more options seen in docu.

Link to comment
Share on other sites

  • 3 weeks later...

I looked at some things and pushed some changed to 1.3.1, I think you'll be able to do what you need

Changes in 1.3.1
 
  • Minor refactoring and optimizations
  • Added support for having placeholder in inner_tpl's opening tag.
 
So you can now also add dynamic values to the opening tag like, much like in the item_tpl
'inner_tpl' => "<ul id='{name}' class='drop-down'>||</ul>",
That will result in {name} being replaced by the name of the page (containing the inner childs)
 

To hook into the parsing of the the list opening template you can use the "MarkupSimpleNavigation::getInnerStringOpen" and do you're own conditional replacements.

Good day!

Could you please suggest how to implement a structure like this:

<ul class="nav-level1">
    <li>
        <ul class="nav-level2">
            <li>
                <ul class="nav-level3">
                </ul>
            </li>
        </ul>
    </li>
</ul>

I guess the option should be something like:

'inner_tpl' => '<ul class="nav-level{ ???}">||</ul>'

Link to comment
Share on other sites

The level isn't supported as a placeholder, but you could add a hook to it and since "interation" is a updated property in the module you can use that to get the level without adding more overhead.

// module load
$nav = $modules->MarkupSimpleNavigation;

// add hook to before parsing of the "inner_tpl" opening tag
$nav->addHookBefore("getInnerStringOpen", null, function($event){
    
    // get the current level 
    $level = $event->object->iteration;
    
    // "<ul class='level-{level}'>"
    $tpl = $event->arguments("tpl"); 
    
    // replace {level} with number and send tpl back to the argument
    $event->setArgument("tpl", str_replace("{level}", $level, $tpl));
    
});

// render navigation output
echo $nav->render(array(
    'max_levels' => 3,
    'outer_tpl' => "<ul class='level-1'>||</ul>",
    'inner_tpl' => "<ul class='level-{level}'>||</ul>",
    )); 

Since the opening tpl doesn't support parsing but only is used once, you can add the level-1 fixed.

Also wanted to point out that these classes are something not really needed as you can do it via CSS

ul {
    (level1)
}

ul ul {
    (level2)
}

ul ul ul {
    (level3)
}
  • Like 1
Link to comment
Share on other sites

Thank you Soma, It worked like a charm. Now i am trying to understand how )

I want to add these classes just because i am trying to follow some css recomendations like SMACSS, OOCSS and BOM. They suggest not making those nested css rules, at least not making them too deep. If one uses ""ul ul ul" type of rules, he has to redefine each next level. So if not putting special classes in ul tags i would have went with "ul > li > ul" rules instead.

Anyway, level placeholder could be used frequently. Of course i really suggest adding it to the core as i need it, but it is because i need it of course )

By the way, i couldn't find any documentation on those template strings and placeholders, which could be used in them. Please lead me to the light if you will.

Link to comment
Share on other sites

Maybe I'm old fashion for class names. But I do like the ' ul ul ul ' way Soma suggested. I see a few advantages in doing it the Soma way:

  1. Portability ( you don't rely on 'variable' class names, so you could drop that code to an other project without problems )
  2. It's apparent from the CSS how the DOM looks like.
  3. It doesn't clutter the DOM with classes as CSS can handle it self on element level.

Where I do use classes in menu's is for the last-child. :first-child is widely supported if elements are already in the DOM from the beginning. But :last-child, is only supported from IE9 and up.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Hi folks. First of all, I love this module, thanks Soma!

I'm having a little problem though. I have created a page reference field "catColor" which is used by my templates.

I've set up a number of reference pages that hold a title such as "green" or "red".

Using the page reference field this displays a radio list of pre-defined colors (green, red etc) and my client can select a colour to be used to colour the nav item.

I dropped this field catColor into the code like so:

'item_tpl' => '<a class="{catColor}" href="{url}" title="Link to: {title}">{title}</a>',

The problem is that catColor pulls through a path such as "/colour/green/" when all I want it to do is pull through the title of the reference page "green".

I'm not brilliant with php and have tried things like...

'item_tpl' => '<a class="{catColor->title}" href="{url}" title="Link to: {title}">{title}</a>',

... with no luck.

Can anyone give me an example of how I would write it so that it shows the title from the page reference field only (.ie "green")?

Many thanks in advance for any help.

Link to comment
Share on other sites

Ah yes there's no support for subfields, only the page field will replaced with url.

But you could custom replace a placeholder with a hook. For example name the placeholder something like "color" can be anything. Then add a hook like

$nav = $modules->MarkupSimpleNavigation;

$nav->addHookBefore("getItemString", null, function($event){
    $tpl = $event->arguments("tpl");
    $page = $event->arguments("page");
    // maybe some condition do whatever you need
    if($page->catColor){ 
        $tpl = str_replace('{mycolor}', $page->catColor->title, $tpl); // replace the placeholder
        $event->setArgument('tpl', $tpl); // send back the tpl argument
    }
});

// then render as usual using the {mycolor}
echo $nav->render(array(
    'item_tpl' => '<a class="{mycolor}" href="{url}" title="Link to: {title}">{title}</a>',
));

The method getItemString() is just the method that runs a parser to replace the placeholders with real values, so we hook into it before.

  • Like 4
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
×
×
  • Create New...