From c2eba00a10da484ff034a12cb2985edd091448f7 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sun, 11 Aug 2019 20:59:45 +0200 Subject: [PATCH] luci-base: ui.js: rework tab state handling Properly preserve the selection state of nested tabs. Signed-off-by: Jo-Philipp Wich --- .../htdocs/luci-static/resources/ui.js | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index 2a7c44ad8..23a9d7bfd 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -1556,9 +1556,6 @@ return L.Class.extend({ document.addEventListener('dependency-update', this.updateTabs.bind(this)); this.updateTabs(); - - if (!groups.length) - this.setActiveTabId(-1, -1); }, initTabGroup: function(panes) { @@ -1576,6 +1573,7 @@ return L.Class.extend({ active = pane.getAttribute('data-tab-active') === 'true'; menu.appendChild(E('li', { + 'style': L.dom.isEmpty(pane) ? 'display:none' : null, 'class': active ? 'cbi-tab' : 'cbi-tab-disabled', 'data-tab': name }, E('a', { @@ -1590,7 +1588,7 @@ return L.Class.extend({ group.parentNode.insertBefore(menu, group); if (selected === null) { - selected = this.getActiveTabId(groupId); + selected = this.getActiveTabId(panes[0]); if (selected < 0 || selected >= panes.length || L.dom.isEmpty(panes[selected])) { for (var i = 0; i < panes.length; i++) { @@ -1605,8 +1603,24 @@ return L.Class.extend({ menu.childNodes[selected].classList.remove('cbi-tab-disabled'); panes[selected].setAttribute('data-tab-active', 'true'); - this.setActiveTabId(groupId, selected); + this.setActiveTabId(panes[selected], selected); + } + }, + + getPathForPane: function(pane) { + var path = [], node = null; + + for (node = pane ? pane.parentNode : null; + node != null && node.hasAttribute != null; + node = node.parentNode) + { + if (node.hasAttribute('data-tab')) + path.unshift(node.getAttribute('data-tab')); + else if (node.hasAttribute('data-section-id')) + path.unshift(node.getAttribute('data-section-id')); } + + return path.join('/'); }, getActiveTabState: function() { @@ -1614,23 +1628,26 @@ return L.Class.extend({ try { var val = JSON.parse(window.sessionStorage.getItem('tab')); - if (val.page === page && Array.isArray(val.groups)) + if (val.page === page && L.isObject(val.paths)) return val; } catch(e) {} window.sessionStorage.removeItem('tab'); - return { page: page, groups: [] }; + return { page: page, paths: {} }; }, - getActiveTabId: function(groupId) { - return +this.getActiveTabState().groups[groupId] || 0; + getActiveTabId: function(pane) { + var path = this.getPathForPane(pane); + return +this.getActiveTabState().paths[path] || 0; }, - setActiveTabId: function(groupId, tabIndex) { + setActiveTabId: function(pane, tabIndex) { + var path = this.getPathForPane(pane); + try { var state = this.getActiveTabState(); - state.groups[groupId] = tabIndex; + state.paths[path] = tabIndex; window.sessionStorage.setItem('tab', JSON.stringify(state)); } @@ -1642,9 +1659,12 @@ return L.Class.extend({ updateTabs: function(ev, root) { (root || document).querySelectorAll('[data-tab-title]').forEach(function(pane) { var menu = pane.parentNode.previousElementSibling, - tab = menu.querySelector('[data-tab="%s"]'.format(pane.getAttribute('data-tab'))), + tab = menu ? menu.querySelector('[data-tab="%s"]'.format(pane.getAttribute('data-tab'))) : null, n_errors = pane.querySelectorAll('.cbi-input-invalid').length; + if (!menu || !tab) + return; + if (L.dom.isEmpty(pane)) { tab.style.display = 'none'; tab.classList.remove('flash'); @@ -1690,7 +1710,7 @@ return L.Class.extend({ if (L.dom.matches(pane, '[data-tab]')) { if (pane.getAttribute('data-tab') === name) { pane.setAttribute('data-tab-active', 'true'); - L.ui.tabs.setActiveTabId(groupId, index); + L.ui.tabs.setActiveTabId(pane, index); } else { pane.setAttribute('data-tab-active', 'false'); -- 2.25.1