[IMP] odoo_theme: show the "On this page" section in mobile

When the page gets too small for the "On this page" section (local tree
of content) to fit on the page, the section is now moved above the menu
(global tree of content) rather than being hidden.

task-2800970

closes odoo/documentation#2179

Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Co-authored-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
Elisabeth Dickinson 2022-06-08 09:05:14 +00:00 committed by Antoine Vandevenne (anv)
parent fb700d98e8
commit c0040fa532
4 changed files with 82 additions and 53 deletions

View File

@ -62,12 +62,20 @@
</nav>
</noscript>
{# Shown when the JS has properly set all the classes on the TOC elements #}
<nav id="o_main_toctree" class="o_side_nav border-end" hidden>
{%- include "layout_templates/menu.html" %}
<nav id="o_menu" class="o_side_nav border-end">
{%- if 'hide-page-toc' not in meta %}
{# Shown when the JS has properly set all the classes on the TOC elements #}
<aside id="o_page_toc_in_nav" class="o_page_toc o_in_nav_toc border-bottom pb-3 mb-4" hidden>
{%- include "layout_templates/page_toc.html" %}
</aside>
{%- endif %}
<div id="o_main_toctree" class="o_main_toc" hidden>
{%- include "layout_templates/menu.html" %}
</div>
</nav>
<header class="o_main_header border-bottom navbar navbar-light navbar-expand-lg">
{%- include "layout_templates/header.html" %}
<button class="navbar-toggler p-0 border-0" type="button" data-bs-toggle="collapse" data-bs-target="#o_main_toctree" aria-label="Toggle navigation">
<button class="navbar-toggler p-0 border-0" type="button" data-bs-toggle="collapse" data-bs-target="#o_menu" aria-label="Toggle navigation">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>

View File

@ -2,17 +2,17 @@
(function ($) {
document.addEventListener('DOMContentLoaded', () => {
this.navigationMenu = document.getElementById('o_main_toctree');
const navigationMenu = document.getElementById('o_main_toctree');
// Allow to automatically collapse and expand TOC entries
_prepareAccordion(this.navigationMenu);
_prepareAccordion(navigationMenu);
// Allow to respectively highlight and expand the TOC entries and their related TOC
// entry list whose page is displayed.
_flagActiveTocEntriesAndLists();
_flagActiveTocEntriesAndLists(navigationMenu);
// Show hidden menu when the css classes have been properly specified
this.navigationMenu.removeAttribute('hidden');
navigationMenu.removeAttribute('hidden');
});
/**
@ -23,13 +23,15 @@
* the `show` (Bootstrap) class.
* Also, the deepest TOC entries of their respective branch receive the
* `o_deepest_active_toc_entry` class, and their child TOC entry lists receive the `show` class.
*
* @param {HTMLElement} navigationMenu - The navigation menu.
*/
const _flagActiveTocEntriesAndLists = () => {
const _flagActiveTocEntriesAndLists = navigationMenu => {
const regexLayer = /\btoctree-l(?<layer>\d+)\b/;
let lastLayer = undefined;
let lastTocEntry = undefined;
const deepestTocEntries = [];
this.navigationMenu.querySelectorAll('.current').forEach(element => {
navigationMenu.querySelectorAll('.current').forEach(element => {
if (element.tagName === 'UL') {
element.classList.add('show'); // Expand all related <ul>
} else if (element.tagName === 'LI') {

View File

@ -3,43 +3,48 @@
// Customize the page TOC
document.addEventListener('DOMContentLoaded', () => {
this.pageToc = document.getElementById('o_page_toc'); // The tree of content of the page
if (this.pageToc) { // The local toctree is not included for toctree pages (see layout.html)
this.headingRefs = this.pageToc.querySelectorAll('a'); // The references to all headings
// Loop on all tree of content of the page. There may be from 0 to 2 depending on the page.
document.querySelectorAll('.o_page_toc').forEach(pageToc => {
const headingRefs = pageToc.querySelectorAll('a'); // The references to all headings.
// If the page TOC has less than 2 headings, in addition to the title, hide it entirely
if (this.headingRefs.length <= 2) {
_hidePageToc();
// If the page TOC has less than 2 headings, in addition to the title, hide it entirely.
if (headingRefs.length <= 2) {
_hidePageToc(pageToc);
return;
}
// Allow to automatically collapse and expand TOC entries
_prepareAccordion(this.pageToc);
_prepareAccordion(pageToc);
// Allow to respectively highlight and expand the TOC entries and their related TOC
// entry list whose section is focused.
_flagActiveTocEntriesAndLists();
_flagActiveTocEntriesAndLists(pageToc, headingRefs);
// Allow to hide the TOC entry referring the title (<h1> heading)
_flagFirstHeadingRef();
_flagFirstHeadingRef(headingRefs);
// Show hidden menu when the css classes have been properly specified
this.pageToc.removeAttribute('hidden');
}
pageToc.removeAttribute('hidden');
});
});
/**
* Entirely hide the local tree of contents.
*
* @param {HTMLElement} pageToc - The tree of content of the page.
*/
const _hidePageToc = () => this.pageToc.style.display = 'none';
const _hidePageToc = pageToc => pageToc.style.display = 'none';
/**
* Add the relevant classes on the TOC entries (and lists) whose section is focused.
*
* TOC entries whose section is focused (<li> elements) receive the `o_active_toc_entry` class
* and their related TOC entry list (<ul> elements) receive the `show` (Bootstrap) class.
*
* @param {HTMLElement} pageToc - The tree of content of the page.
* @param {NodeList} headingRefs - The references to all headings.
*/
const _flagActiveTocEntriesAndLists = () => {
const _flagActiveTocEntriesAndLists = (pageToc, headingRefs) => {
const _updateFlags = () => {
const activeHeadingRef = clickedHeadingRef || _findActiveHeadingRef();
@ -56,8 +61,8 @@
};
const _findActiveHeadingRef = () => {
let activeHeadingRef = this.headingRefs[0];
this.headingRefs.forEach(headingRef => {
let activeHeadingRef = headingRefs[0];
headingRefs.forEach(headingRef => {
const href = headingRef.getAttribute('href');
if (href !== '#') {
const sectionId = href.replace('#', '');
@ -78,17 +83,17 @@
};
const _unflagAll = () => {
this.pageToc.querySelectorAll('li,ul').forEach(element => {
pageToc.querySelectorAll('li,ul').forEach(element => {
element.classList.remove('o_active_toc_entry', 'show');
});
this.pageToc.querySelectorAll('i').forEach(element => {
pageToc.querySelectorAll('i').forEach(element => {
element.setAttribute('aria-expanded', false);
});
};
const _flagActiveHierarchy = (headingRef) => {
let tocEntry = headingRef.parentElement;
while (tocEntry !== this.pageToc) {
while (tocEntry !== pageToc) {
if (tocEntry.tagName === 'LI') {
// Highlight all <li> in the active hierarchy
tocEntry.classList.add('o_active_toc_entry');
@ -104,7 +109,7 @@
};
let clickedHeadingRef = undefined;
this.pageToc.addEventListener('click', ev => {
pageToc.addEventListener('click', ev => {
clickedHeadingRef = ev.target.closest('a[href^="#"]'); // Highlight the clicked ref
});
let timeoutId = undefined;
@ -122,9 +127,11 @@
/**
* Add the class `o_page_toc_title` on the first heading reference.
*
* @param {NodeList} headingRefs - The references to all headings.
*/
const _flagFirstHeadingRef = () => {
this.headingRefs[0].parentNode.classList.add('o_page_toc_title');
const _flagFirstHeadingRef = headingRefs => {
headingRefs[0].parentNode.classList.add('o_page_toc_title');
}
})();

View File

@ -227,6 +227,23 @@ header.o_main_header {
font-weight: 600;
}
}
.o_main_toc {
> ul {
li {
&.o_active_toc_entry {
&:not(.toctree-l1) > .o_toc_entry_wrapper i[class^="i-"]:not(.collapsed), > a , > .o_toc_entry_wrapper a, > .o_toc_entry_wrapper i {
color: $o-violet-dark;
}
}
a {
&.current {
color: $o-violet-dark;
}
}
}
}
}
ul {
.o_deepest_active_toc_entry {
@ -235,20 +252,6 @@ header.o_main_header {
margin-left: -3px;
}
li {
&.o_active_toc_entry {
&:not(.toctree-l1) > .o_toc_entry_wrapper i[class^="i-"]:not(.collapsed), > a , > .o_toc_entry_wrapper a, > .o_toc_entry_wrapper i {
color: $o-violet-dark;
}
}
a {
&.current {
color: $o-violet-dark;
}
}
}
> .toctree-l1 {
&[class*="o_menu_"] > .o_toc_entry_wrapper > i:before {
@include o-inline-icon($i-doc-apps, 0 5px 0 0);
@ -292,7 +295,7 @@ header.o_main_header {
}
}
.o_side_nav, .o_page_toc_nav {
.o_main_toc, .o_page_toc_nav {
ul { // all uls in toc
list-style: none;
padding-left: $padding-s;
@ -350,19 +353,28 @@ header.o_main_header {
//------------------------------------------------------------------------------
aside.o_page_toc {
display: none;
color: $body-color;
@include font-size($font-size-secondary);
@include media-breakpoint-up(xl) {
display: block;
&:not(.o_in_nav_toc) {
display: none;
@include media-breakpoint-up(xl) {
display: block;
top: $o-header-height;
right: 0;
padding: $padding-l $padding-s $padding-l 0;
overflow-y: auto;
}
position: -webkit-sticky;
position: sticky;
top: $o-header-height;
right: 0;
width: $o-on-page-width;
height: 100%;
max-height: calc(100vh - #{$o-header-height});
padding: $padding-l $padding-s $padding-l 0;
overflow-y: auto;
}
&.o_in_nav_toc {
display: block;
@include media-breakpoint-up(xl) {
display: none;
}
}
h3 {
@ -1064,7 +1076,7 @@ header.o_main_header {
> div[class^="highlight-"]{
border: 0 !important;
}
> *:last-child {
margin-bottom: 0 !important;
}