Jump to content

MarkupMenu


teppo
 Share

Recommended Posts

MarkupMenu is a markup module for generating menu trees. When provided a root page as a starting point, it generates a navigation tree (by default as a HTML "<ul>" element wrapped by a "<nav>" element) from that point onwards. If you've also provided it with current (active) page, the menu will be rendered accordingly, with current item highlighted and items rendered up to that item and its children (unless you disable the "collapsed" option, in which case the full page tree will be rendered instead).

Usage

As a markup module, MarkupMenu is intended for front-end use, but you can of course use it in a module as well. Typically you'll only need the render() method, which takes an array of options as its only argument:

echo $modules->get('MarkupMenu')->render([
    'root_page' => $pages->get(1),
    'current_page' => $page,
]);

Note: if you omit root_page, site root page is used by default. If you omit current_page, the menu will be rendered, but current (active) page won't be highlighted etc.

A slightly more complex example, based on what I'm using on one of my own sites to render a (single-level) top menu:

echo $modules->get('MarkupMenu')->render([
    'current_page' => $page,
    'templates' => [
        'nav' => '<nav class="{classes} menu--{menu_class_modifier}" aria-label="{aria_label}">%s</nav>',
        'item_current' => '<a class="menu__item menu__item--current" href="{item.url}" tabindex="0" aria-label="Current page: {item.title}">{item.title}</a>',
    ],
    'placeholders' => [
        'menu_class_modifier' => 'top',
        'aria_label' => 'Main navigation',
    ],
    'include' => [
        'root_page' => true,
    ],
    'exclude' => [
        'level_greater_than' => 1,
    ],
]);

Note: some things you see above may not be entirely sensible, such as the use of {menu_class_modifier} and {aria_label} placeholders. On the actual site the "nav" template is defined in site config, so I can define just these parts on a case-by-case basis while actual nav markup is maintained in one place.

Please check out the README file for available render options. I'd very much prefer not to keep this list up to date in multiple places. Basically there are settings for defining "templates" for different parts of the menu (list, item, etc.), include array for defining rules for including in the menu and exclude array for the opposite effect, classes and placeholders arrays for overriding default classes and injecting custom placeholders, etc. ?

MarkupMenu vs. MarkupSimpleNavigation

TL;DR: this is another take on the same concept. There are many similarities, but also some differences – especially when it comes to the supported options and syntax. If you're currently using MarkupSimpleNavigation then there's probably no reason to switch over.

I'd be surprised if someone didn't draw lines between this module and Soma's awesome MarkupSimpleNavigation. Simply put I've been using MSN (...) for years, and it's been great – but there are some issues with it, particularly in the markup generation area, and it also does some things in a way that doesn't quite work for me – the xtemplates thing being one of these. In some ways less about features, and more about style, I guess ?

Anyhow, in MarkupMenu I've tried to correct those little hiccups, modernise the default markup, and allow for more flexibility with placeholder variables and additional / different options. MarkupMenu was built for ProcessWire 3.0.112+ and with PHP 7.1+ in mind, it's installable with Composer, and I have a few additional ideas (such as conditional placeholders) still on my todo list.

One more small(ish) difference is that MarkupMenu supports overriding default options via $config->MarkupMenu. I find myself redefining the default markup for every site, which until now meant that each site had a wrapper function for MarkupSimpleNavigation (to avoid code / config repetition), and this way I've been able to leave that out ?

Requirements

  • ProcessWire >= 3.0.112
  • PHP >= 7.1.0

If you're working on an earlier version of ProcessWire or PHP, use MarkupSimpleNavigation instead.

  • Like 19
  • Thanks 1
Link to comment
Share on other sites

Great, thank you ? 

On 6/22/2019 at 1:18 PM, teppo said:

on my todo list.

On 6/22/2019 at 1:18 PM, teppo said:

$config->MarkupMenu. I find myself redefining the default markup for every site,

Would be great if you could add an option to set markup of some popular css frameworks easily on your todo list as well ? eg

$config->MarkupMenu = 'UIkit3';
// $config->MarkupMenu = 'Bootstrap4';
// ...

 

  • Like 2
Link to comment
Share on other sites

18 minutes ago, bernhard said:

Would be great if you could add an option to set markup of some popular css frameworks easily on your todo list as well ? eg


$config->MarkupMenu = 'UIkit3';
// $config->MarkupMenu = 'Bootstrap4';
// ...

 

I think that's a brilliant idea, so definitely going to my todo list – thanks for the suggestion! ?

  • Like 2
Link to comment
Share on other sites

  • 5 months later...

Just a quick heads-up that I've made a couple of updates to MarkupMenu recently:

## [0.8.0] - 2019-12-25

### Added
- Support for passing in a prepopulated PageArray of menu items via the menu_items option.

### Fixed
- Fixed an issue where include option root_page wasn't being properly reset (since 0.7.0).

## [0.7.0] - 2019-12-18

### Added
- New hookable method getItems().

### Changed
- Method renderTreeItem() made hookable.

0.7.0 made it possible to hook to the point when menu items are fetched (for an example if you need to inject a new item or remove an item at some specific point), and 0.8.0 added support for passing in a pre-defined PageArray to use as the first level of menu items (the need for this came up on a project where a menu was manually defined using a Page Reference field.)

  • Like 2
Link to comment
Share on other sites

  • 4 months later...
  • 2 years later...

Been over a year since last update, so another quick heads-up: MarkupMenu 0.11.0 adds support for menu items as an array (as an alternative for the module figuring the menu structure out from current and root page, or reading it from a PageArray) and template strings as callables. Needed these two for a project I'm working on 🙂

echo $modules->get('MarkupMenu')->render([
    'current_page' => $page,
    'menu_items' => [
        [
            'title' => 'Home',
            'url' => '/',
            'id' => 1,
        ],
        [
            'title' => 'About',
            'url' => '/about/',
            'id' => 29,
        ],
        [
            'title' => 'Parent',
            'children' => [
                // ...
            ],
        ],
    ],
    'templates' => [
        'item' => function($item) {
            return empty($item->url)
                ? '<span>{item.title}</span>'
                : '<a href="{item.url}" class="{classes} {class}--level-{level}">{item.title}</a>';
        },
    ],
]);

 

  • Like 3
Link to comment
Share on other sites

  • 8 months later...

Version 1.0.0 of the MarkupMenu module released: https://github.com/teppokoivula/MarkupMenu/releases/tag/1.0.0.

This release includes a relatively minor, but also potentially breaking change: new argument $root was added to the MarkupMenu::renderArrayItem() method, between some of the existing params. Since this method is hookable this could be a problem for existing code, so I figured it was best to increment major version.

  • Like 3
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...