/* global _prepareAccordion */ //see utils.js (function ($) { document.addEventListener('DOMContentLoaded', () => { const navigationMenu = document.getElementById('o_main_toctree'); // Allow to automatically collapse and expand TOC entries _prepareAccordion(navigationMenu); // Allow to respectively highlight and expand the TOC entries and their related TOC entry // list whose page is displayed. const deepestActiveTocEntries = _flagActiveTocEntriesAndLists(navigationMenu); // 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); }); /** * Add the relevant classes on the TOC entries (and lists) whose page is displayed. * * 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 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 deepestActiveTocEntries = []; navigationMenu.querySelectorAll('.current').forEach(element => { if (element.tagName === 'UL') { element.classList.add('show'); // Expand all related <ul> } else if (element.tagName === 'LI') { 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) { // 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) { // The last active TOC entry is the deepest of its branch. deepestActiveTocEntries.push(lastTocEntry); } deepestActiveTocEntries.forEach(deepestTocEntry => { const childTocEntryList = deepestTocEntry.querySelector('ul'); if (childTocEntryList) { // The TOC entry has an associated TOC entry list. childTocEntryList.classList.add('show'); } deepestTocEntry.classList.add('o_deepest_active_toc_entry'); }); return deepestActiveTocEntries; }; /** * Add the `show` class on top-level menus. * * @param {HTMLElement} navigationMenu - The navigation menu. */ const _expandTopMenus = navigationMenu => { navigationMenu.querySelectorAll('.toctree-l1').forEach(tocEntry => { const childTocEntryList = tocEntry.querySelector('ul'); if (childTocEntryList) { // The TOC entry has an associated TOC entry list. childTocEntryList.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(); }); /** * Add/Remove the class `o_header_scrolled` on the header according to the scroll position. */ const _flagHeaderWithScrollPosition = () => { const header = document.querySelector('.o_main_header'); if (this.scrollY > 0) { header.classList.add('o_header_scrolled'); } else { header.classList.remove('o_header_scrolled'); } }; })();