[IMP] odoo_theme: scroll the active menu entry into view
In large and deeply nested TOCs like finance/accounting/fiscal_localizations/localizations/... the user had to constantly scroll the menu to the menu entry they just clicked because the expanded menu would not fit entirely on the page. With this commit, the active menu entry is scrolled into view each time the page is reloaded. The previous behavior was also the reason for expanding the top menu entries on only the homepage. Thanks to the scroll, they now always expand. Part-of: odoo/documentation#3275
This commit is contained in:
parent
076534b1f0
commit
0ef10a1606
@ -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 (<li> elements) that are on the path of the displayed page receive the
|
||||
* `o_active_toc_entry` class, and their related (parent) TOC entry list (<ul> 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(?<layer>\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 <ul>
|
||||
@ -41,40 +45,58 @@
|
||||
element.classList.add('o_active_toc_entry'); // Highlight all active <li>
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user