Desirability:
I wonder if this is something I would use in my projects, because I think this will create a less than optimal user experience.
The regular pages probably show a nice header and title for context, while when navigating to child modules the user finds himself midway a page without header and context. I think this behaviour is not consistent and hence confusing. Besides, why using a modular page if you present the child pages as being separate content already?
I haven’t used modular pages in my themes (yet) and I think I would use them as follows:
As the only page for a single page website:
The ‘onpage_menu: true’ would make it easy for users to jump to sections. It feels natural to the user.
For multi-page website:
I would switch off the ‘onpage_menu’ and show the page as a single regular page.
Solution using Quark theme:
Steps: (Skip to code below if not interested in process/explaination…)
In ‘modular.md’ set ‘onpage_menu: false’
The modular page will now use ‘partials/navigation.html.twig’ to generate the menu containing ‘Home Page1 page2’.
Combine part of ‘modular.html.twig’ navigation with ‘partials/navigation.html.twig’ and use “page.tempate == ‘modular’” to discriminated between the page types.
Construct the anchor urls for the modular children by combining the url of the modular page and the menu of the child module: href="{{p.url}}/#{{ _self.pageLinkName(module.menu) }}"
The menu will now show: ‘Home Module1 Module2 Page1 Page2’
Unfortunately, the smooth scrolling and menu highlighting has disappeared from the modular page. This is because the required javascript is only run with ‘onpage_menu=true’.
Fix:
In ‘modular.html.twig’, remove the surrounding if-statements in {% block javascripts %} and {% block bottom %} to add the required javascripts.
In ‘navigation.html.twig’ add class ‘navigation’ to the ‘<ul>’
But now, because of the enabled javascript, we cannot navigate to ‘Page1’ and ‘Page2’ anymore… Sigh…
Fix:
Add class ‘regular’ to all menu-items of regular pages in ‘navigation.html.twig’.
Tell the javascript in ‘modular.html.twig’ to exclude the menuitems with class ‘regular’ by setting its filter to filter: ':not(.external):not(.regular)'
It should work now…
Code:
‘modular.html.twig’:
{% extends 'partials/base.html.twig' %}
{% set show_onpage_menu = header.onpage_menu == true or header.onpage_menu is null %}
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% block javascripts %}
{# {% if show_onpage_menu %} #} {# Comment out #}
{% do assets.add('theme://js/singlepagenav.min.js') %}
{# {% endif %} #} {# Comment out #}
{{ parent() }}
{% endblock %}
{% block bottom %}
{{ parent() }}
{# {% if show_onpage_menu %} #} {# Comment out #}
<script>
// singlePageNav initialization & configuration
$('ul.navigation').singlePageNav({
offset: $('#header').outerHeight(),
filter: ':not(.external):not(.regular)', // Add filter
updateHash: true,
currentClass: 'active'
});
</script>
{# {% endif %} #} {# Comment out #}
{% endblock %}
{% block header_navigation %}
{% if show_onpage_menu %}
<ul class="navigation">
{% for module in page.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li><a class="{{ current_module }}" href="#{{ _self.pageLinkName(module.menu) }}">{{ module.menu }}</a></li>
{% endfor %}
{% for mitem in site.menu %}
<li>
<a {% if mitem.class %}class="{{ mitem.class }}"{% endif %} href="{{ mitem.url }}">
{% if mitem.icon %}<i class="fa fa-{{ mitem.icon }}"></i>{% endif %}
{{ mitem.text }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
{% block hero %}
{% for module in page.collection() if module.template == 'modular/hero' %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
{% block body %}
{% for module in page.collection() if module.template != 'modular/hero' %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
‘/partials/navigation.html.twig’:
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% macro nav_loop(page) %}
{% for p in page.children.visible %}
{% if p.template != 'modular' %} {# Add if #}
{% set active_page = (p.active or p.activeChild) ? 'active' : '' %}
{% if p.children.visible.count > 0 %}
<li>
<a href="{{ p.url }}" class="regular {{ active_page }}"> {# Add class 'regular' #}
{{ p.menu }}
</a>
<ul>
{{ _self.nav_loop(p) }}
</ul>
</li>
{% else %}
<li>
<a href="{{ p.url }}" class="regular {{ active_page }}"> {# Add class 'regular' #}
{{ p.menu }}
</a>
</li>
{% endif %}
{% else %} {# Add code to loop through modules #}
{% for module in p.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li><a class="{{ current_module }}" href="{{p.url}}/#{{ _self.pageLinkName(module.menu) }}">{{ module.menu }}</a></li>
{% endfor %}
{% endif %}
{% endfor %}
{% endmacro %}
<ul {{ tree ? 'class="navigation tree"' : 'class="navigation"' }}> {# Add class 'navigation' required by javascript #}
{{ _self.nav_loop(pages) }}
</ul>
Wow At first pamtbaau thank you very much for giving this answer in such a detailed way and with this hints, tips and explanation. i appreciate that very much!!! and sorry for the delay in reply.
To the navigation: It is a Onepage-website. The 2 pages that a non-modular, are pages that the user “normally” dont uses, and they sit in the footer (not the main navigation) because they have to be there by law (impressum,privacy statement). So i think there is no problem with not consistent/confusing user experience.
and that is as well the reason why i dont wont a menu
Home Module1 Module2 Page1 Page2
do you (or anybody else) see a way to get the onpage_menu on the non-modular pages (=page1, page2) so that i can jump back to the main onepage site like
Home Module1 Module2
my workround for the moment is
{# menu for non modulare pages#}
{% if not page.home() %}
{% for page in pages.children %}
{% if page.visible %}
<li class= "backhome">
<a href="{{ page.url }}">
back to home
</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
@pgrav Wished I had understood your requirements a little bit better the first time…
I find it hard to judge whether there is a better or more correct way, while I only see fragments of the code without the total picture.
Nonetheless, a suggestion I have is to make it a little bit less error prone in case the menu’s of the modules might contain uppercase characters and/or spaces…
You might want to add the following macro to the twig file:
@anon76427325
Thanks for your explanations. I have another problem with the code you gave, when I click on a drop down menu item, the black menu doesn’t close. Do you have the solution?