Skip to content

Commit e954534

Browse files
authored
Tabpane updates (#1530)
[deploy]
1 parent be31998 commit e954534

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Storage key names and data attribute name:
2+
const td_persistStorageKeyNameBase = 'td-tp-persist';
3+
const td_persistCounterStorageKeyName = `${td_persistStorageKeyNameBase}-count`;
4+
const td_persistDataAttrName = `data-${td_persistStorageKeyNameBase}`;
5+
6+
// Utilities
7+
8+
const _tdPersistCssSelector = (attrValue) =>
9+
attrValue
10+
? `[${td_persistDataAttrName}="${attrValue}"]`
11+
: `[${td_persistDataAttrName}]`;
12+
13+
const _tdStoragePersistKey = (tabKey) =>
14+
td_persistStorageKeyNameBase + ':' + (tabKey || '');
15+
16+
const _tdSupportsLocalStorage = () => typeof Storage !== 'undefined';
17+
18+
// Helpers
19+
20+
function tdPersistKey(key, value) {
21+
// @requires: tdSupportsLocalStorage();
22+
23+
try {
24+
if (value) {
25+
localStorage.setItem(key, value);
26+
} else {
27+
localStorage.removeItem(key);
28+
}
29+
} catch (error) {
30+
const action = value ? 'add' : 'remove';
31+
console.error(
32+
`Docsy tabpane: unable to ${action} localStorage key '${key}': `,
33+
error
34+
);
35+
}
36+
}
37+
38+
function getActiveTabFromURL() {
39+
const urlParams = new URLSearchParams(window.location.search);
40+
const activeTab = urlParams.get('tab');
41+
return activeTab ? activeTab.toLowerCase() : null;
42+
}
43+
44+
function adjustTabContentHeights() {
45+
const contentTabs = document.querySelectorAll('.tab-content');
46+
47+
// Loop through each tabpane
48+
contentTabs.forEach(contentTab => {
49+
let maxHeight = 0;
50+
const tabPanes = contentTab.querySelectorAll('.tab-pane');
51+
52+
// Loop through each tab in the tabpanes list to find max
53+
tabPanes.forEach(tab => {
54+
tab.style.display = 'block';
55+
maxHeight = Math.max(maxHeight, tab.clientHeight);
56+
tab.style.display = '';
57+
});
58+
59+
// Loop through each tab in the tabpanes list to set height
60+
tabPanes.forEach(tab => {
61+
tab.style.height = maxHeight + 'px';
62+
});
63+
});
64+
}
65+
66+
// Retrieve, increment, and store tab-select event count, then returns it.
67+
function tdGetTabSelectEventCountAndInc() {
68+
// @requires: tdSupportsLocalStorage();
69+
70+
const storedCount = localStorage.getItem(td_persistCounterStorageKeyName);
71+
let numTabSelectEvents = parseInt(storedCount) || 0;
72+
numTabSelectEvents++;
73+
tdPersistKey(td_persistCounterStorageKeyName, numTabSelectEvents.toString());
74+
return numTabSelectEvents;
75+
}
76+
77+
// Main functions
78+
79+
function tdActivateTabsWithKey(key) {
80+
if (!key) return;
81+
82+
document.querySelectorAll(_tdPersistCssSelector(key)).forEach((element) => {
83+
new bootstrap.Tab(element).show();
84+
});
85+
}
86+
87+
function tdPersistActiveTab(activeTabKey) {
88+
if (!_tdSupportsLocalStorage()) return;
89+
90+
tdPersistKey(
91+
_tdStoragePersistKey(activeTabKey),
92+
tdGetTabSelectEventCountAndInc()
93+
);
94+
tdActivateTabsWithKey(activeTabKey);
95+
}
96+
97+
// Handlers
98+
99+
function tdGetAndActivatePersistedTabs(tabs) {
100+
// Get unique persistence keys of tabs in this page
101+
var keyOfTabsInThisPage = [
102+
...new Set(
103+
Array.from(tabs).map((el) => el.getAttribute(td_persistDataAttrName))
104+
),
105+
];
106+
107+
// Create a list of active tabs with their age:
108+
let key_ageList = keyOfTabsInThisPage
109+
// Map to [tab-key, last-activated-age]
110+
.map((k) => [
111+
k,
112+
parseInt(localStorage.getItem(_tdStoragePersistKey(k))) || 0,
113+
])
114+
// Exclude tabs that have never been activated
115+
.filter(([k, v]) => v)
116+
// Sort from oldest selected to most recently selected
117+
.sort((a, b) => a[1] - b[1]);
118+
119+
// Activate tabs from the oldest to the newest
120+
key_ageList.forEach(([key]) => {
121+
tdActivateTabsWithKey(key);
122+
});
123+
124+
return key_ageList;
125+
}
126+
127+
function tdRegisterTabClickHandler(tabs) {
128+
tabs.forEach((tab) => {
129+
tab.addEventListener('click', () => {
130+
const activeTabKey = tab.getAttribute(td_persistDataAttrName);
131+
tdPersistActiveTab(activeTabKey);
132+
});
133+
});
134+
}
135+
136+
// Register listeners and activate tabs
137+
138+
window.addEventListener('DOMContentLoaded', () => {
139+
if (!_tdSupportsLocalStorage()) return;
140+
141+
var allTabsInThisPage = document.querySelectorAll(_tdPersistCssSelector());
142+
tdRegisterTabClickHandler(allTabsInThisPage);
143+
144+
const activeTabKeyFromURL = getActiveTabFromURL();
145+
if (activeTabKeyFromURL) {
146+
tdActivateTabsWithKey(activeTabKeyFromURL);
147+
} else {
148+
tdGetAndActivatePersistedTabs(allTabsInThisPage);
149+
}
150+
// Adjust tab content heights
151+
adjustTabContentHeights();
152+
});

0 commit comments

Comments
 (0)