diff --git a/extensions/odoo_theme/static/js/menu.js b/extensions/odoo_theme/static/js/menu.js
index fa6af0b59..9276acfb5 100644
--- a/extensions/odoo_theme/static/js/menu.js
+++ b/extensions/odoo_theme/static/js/menu.js
@@ -9,13 +9,16 @@
// Allow to respectively highlight and expand the TOC entries and their related TOC entry
// list whose page is displayed.
- _flagActiveTocEntriesAndLists(navigationMenu);
+ const deepestActiveTocEntries = _flagActiveTocEntriesAndLists(navigationMenu);
- // Expand the top-level menu items on the homepage.
+ // Expand the top-level menu items.
_expandTopMenus(navigationMenu);
// Show hidden menu when the css classes have been properly specified
navigationMenu.removeAttribute('hidden');
+
+ // Scroll the menu to the deepest active TOC entry.
+ _scrollToDeepestActiveTocEntry(deepestActiveTocEntries);
});
/**
@@ -23,17 +26,18 @@
*
* TOC entries (
elements) that are on the path of the displayed page receive the
* `o_active_toc_entry` class, and their related (parent) TOC entry list ( elements) receive
- * the `show` (Bootstrap) class. Also, the deepest TOC entries of their respective branch
+ * the `show` (Bootstrap) class. Also, the deepest active 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.
+ * @return {Array} - The deepest active TOC entries of their respective branch.
*/
const _flagActiveTocEntriesAndLists = navigationMenu => {
const regexLayer = /\btoctree-l(?\d+)\b/;
let lastLayer = undefined;
let lastTocEntry = undefined;
- const deepestTocEntries = [];
+ const deepestActiveTocEntries = [];
navigationMenu.querySelectorAll('.current').forEach(element => {
if (element.tagName === 'UL') {
element.classList.add('show'); // Expand all related
@@ -41,40 +45,58 @@
element.classList.add('o_active_toc_entry'); // Highlight all active -
let match = regexLayer.exec(element.className);
let currentLayer = parseInt(match.groups.layer, 10);
- if (lastLayer && currentLayer <= lastLayer) { // We just moved to another branch
- deepestTocEntries.push(lastTocEntry);
+ if (lastLayer && currentLayer <= lastLayer) { // Multiple lists are open.
+ // Flag the last active TOC entry as the deepest of its branch before moving to
+ // the next active branch.
+ deepestActiveTocEntries.push(lastTocEntry);
}
lastLayer = currentLayer;
lastTocEntry = element;
}
});
if (lastTocEntry) {
- deepestTocEntries.push(lastTocEntry); // The last TOC entry is the deepest of its branch
+ // The last active TOC entry is the deepest of its branch.
+ deepestActiveTocEntries.push(lastTocEntry);
}
- deepestTocEntries.forEach(deepestTocEntry => {
+ deepestActiveTocEntries.forEach(deepestTocEntry => {
+ let tocEntryToHighlight;
const childTocEntryList = deepestTocEntry.querySelector('ul');
- if (childTocEntryList) {
+ if (childTocEntryList) { // The TOC entry has an associated TOC entry list.
+ tocEntryToHighlight = deepestTocEntry;
childTocEntryList.classList.add('show');
- } else { // If the toc entry is not a TOC, add the class to its closest ancestor entry
- deepestTocEntry = deepestTocEntry.parentElement.parentElement;
+ } else { // The TOC entry is at the last level of its branch.
+ tocEntryToHighlight = deepestTocEntry.parentElement.parentElement;
}
- deepestTocEntry.classList.add('o_deepest_active_toc_entry');
+ tocEntryToHighlight.classList.add('o_deepest_active_toc_entry');
});
+ return deepestActiveTocEntries;
};
/**
- * Add the `show` class on top-level menus if the user is browsing the homepage.
+ * Add the `show` class on top-level menus.
*
* @param {HTMLElement} navigationMenu - The navigation menu.
*/
const _expandTopMenus = navigationMenu => {
navigationMenu.querySelectorAll('.toctree-l1').forEach(element => {
- if (!element.parentElement.classList.contains('current')) { // For the homepage only.
- element.querySelector('ul').classList.add('show'); // Expand the top-level menus.
- }
+ element.querySelector('ul').classList.add('show'); // Expand the top-level menus.
});
};
+ /**
+ * Scroll the active TOC entry into view.
+ *
+ * Note: this method must be called *after* the `_expandTopMenus` method and showing the menu.
+ *
+ * @param {Array} deepestActiveTocEntries - The deepest active TOC entries of their respective
+ * branch.
+ */
+ const _scrollToDeepestActiveTocEntry = deepestActiveTocEntries => {
+ if (deepestActiveTocEntries.length > 0) {
+ deepestActiveTocEntries[0].scrollIntoView({block: 'center'});
+ }
+ };
+
document.addEventListener('scroll', () => {
// Allow to hide the searchbar when the page is scrolled in mobile.
_flagHeaderWithScrollPosition();