diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js index 18a5695005f..08819f79f57 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -209,18 +209,14 @@ var FormRenderer = BasicRenderer.extend({ * @returns {Object} a map from notebook name to the active tab index */ getLocalState: function () { - var state = {}; - this.$('div.o_notebook').each(function () { - var $notebook = $(this); - var name = $notebook.data('name'); - var index = -1; - $notebook.find('.nav-link').each(function (i) { - if ($(this).hasClass('active')) { - index = i; - } - }); - state[name] = index; - }); + const state = {}; + for (const notebook of this.el.querySelectorAll(':scope div.o_notebook')) { + const name = notebook.dataset.name; + const navs = notebook.querySelectorAll(':scope .o_notebook_headers .nav-item > .nav-link'); + state[name] = [...navs].findIndex( + nav => nav.classList.contains('active') + ); + } return state; }, /** @@ -237,23 +233,36 @@ var FormRenderer = BasicRenderer.extend({ this.lastActivatedFieldIndex = -1; }, /** - * restore active tab pages for each notebook - * - * @todo make sure this method is called + * Restore active tab pages for each notebook. It relies on the implicit fact + * that each nav header corresponds to a tab page. * * @param {Object} state the result from a getLocalState call */ setLocalState: function (state) { - this.$('div.o_notebook').each(function () { - var $notebook = $(this); - var name = $notebook.data('name'); + for (const notebook of this.el.querySelectorAll(':scope div.o_notebook')) { + const name = notebook.dataset.name; if (name in state) { - var $page = $notebook.find('> .o_notebook_headers > .nav-tabs > .nav-item').eq(state[name]); - if (!$page.hasClass('o_invisible_modifier')) { - $page.find('a[data-toggle="tab"]').click(); + const navs = notebook.querySelectorAll(':scope .o_notebook_headers .nav-item'); + const pages = notebook.querySelectorAll(':scope .tab-content > .tab-pane'); + // We can't base the amount on the 'navs' length since some overrides + // are adding pageless nav items. + const validTabsAmount = pages.length; + let activeIndex = state[name]; + if (navs[activeIndex].classList.contains('o_invisible_modifier')) { + activeIndex = [...navs].findIndex( + nav => !nav.classList.contains('o_invisible_modifier') + ); } + if (activeIndex <= 0) { + continue; // No visible tab OR first tab = active tab (no change to make). + } + for (let i = 0; i < validTabsAmount; i++) { + navs[i].querySelector('.nav-link').classList.toggle('active', activeIndex === i); + pages[i].classList.toggle('active', activeIndex === i); + } + core.bus.trigger('DOM_updated'); } - }); + } }, /** * @override method from AbstractRenderer @@ -915,9 +924,8 @@ var FormRenderer = BasicRenderer.extend({ }); }); var $notebookHeaders = $('
').append($headers); - var $notebook = $('
') - .data('name', node.attrs.name || '_default_') - .append($notebookHeaders, $pages); + var $notebook = $('
').append($notebookHeaders, $pages); + $notebook[0].dataset.name = node.attrs.name || '_default_'; this._registerModifiers(node, this.state, $notebook); this._handleAttributes($notebook, node); return $notebook;