mirror of https://github.com/google/docsy.git
Tabpane: support persistence of all active tabs (#1611)
This commit is contained in:
parent
7f39b8280b
commit
b53f5f167c
|
@ -25,9 +25,9 @@
|
|||
|
||||
{{ $_persist := .Get "persist" -}}
|
||||
{{ with $_persist -}}
|
||||
{{ $matched := findRE "^(header|lang|none)$" . -}}
|
||||
{{ $matched := findRE "^(header|lang|disabled)$" . -}}
|
||||
{{ if not $matched -}}
|
||||
{{ errorf "Shortcode %q: parameter %q should be one of 'header', 'lang', or 'none'; but got %s. Error position: %s" $.Name "persist" $_persist $.Position -}}
|
||||
{{ errorf "Shortcode %q: parameter %q should be one of 'header', 'lang', or 'disabled'; but got %s. Error position: %s" $.Name "persist" $_persist $.Position -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
|||
{{ $langEqualsHeader := default false ($.Get "langEqualsHeader") -}}
|
||||
{{ $deprecatedPersistLang := $_persistLang | default true -}}
|
||||
{{ $persistKeyKind := $_persist | default (cond (eq $langPane "") "lang" "header") -}}
|
||||
{{ $persistTab := and $deprecatedPersistLang (ne $persistKeyKind "none") -}}
|
||||
{{ $persistTab := and $deprecatedPersistLang (ne $persistKeyKind "disabled") -}}
|
||||
{{ $rightPane := default false ($.Get "right") -}}
|
||||
{{ $activeSet := false -}}
|
||||
{{/* Scratchpad gets populated through call to .Inner */ -}}
|
||||
|
@ -106,7 +106,6 @@
|
|||
{{ if $disabled }} disabled{{ end -}}"
|
||||
id="{{ $tabid }}" data-bs-toggle="tab" data-bs-target="#{{ $entryid }}" role="tab"
|
||||
{{ if and $persistTab $persistKey -}}
|
||||
onclick="tdPersistActiveTab({{ $persistKey }});" {{/* */ -}}
|
||||
{{ printf "%s=%q " $tpPersistAttrName $persistKey | safeHTMLAttr -}}
|
||||
{{ end -}}
|
||||
aria-controls="{{- $entryid -}}" aria-selected="{{- cond ( and ( not $activeSet ) ( not $disabled ) ) "true" "false" -}}">
|
||||
|
|
|
@ -1,30 +1,116 @@
|
|||
// Storage key name also used as a data-* attribute suffix:
|
||||
const storageKeyName = 'td-tp-persist';
|
||||
// Storage key names and data attribute name:
|
||||
const td_persistStorageKeyNameBase = 'td-tp-persist';
|
||||
const td_persistCounterStorageKeyName = `${td_persistStorageKeyNameBase}-count`;
|
||||
const td_persistDataAttrName = `data-${td_persistStorageKeyNameBase}`;
|
||||
|
||||
function tdActivateTabsWithKey(key) {
|
||||
if (!key) return;
|
||||
document
|
||||
.querySelectorAll(`[data-${storageKeyName}="${key}"]`)
|
||||
.forEach((element) => {
|
||||
new bootstrap.Tab(element).show();
|
||||
});
|
||||
}
|
||||
// Utilities
|
||||
|
||||
function tdPersistActiveTab(activeTabKey) {
|
||||
if (!tdSupportsLocalStorage()) return;
|
||||
const _tdPersistCssSelector = (attrValue) =>
|
||||
attrValue
|
||||
? `[${td_persistDataAttrName}="${attrValue}"]`
|
||||
: `[${td_persistDataAttrName}]`;
|
||||
|
||||
const _tdStoragePersistKey = (tabKey) =>
|
||||
td_persistStorageKeyNameBase + ':' + (tabKey || '');
|
||||
|
||||
const _tdSupportsLocalStorage = () => typeof Storage !== 'undefined';
|
||||
|
||||
// Helpers
|
||||
|
||||
function tdPersistKey(key, value) {
|
||||
// @requires: tdSupportsLocalStorage();
|
||||
|
||||
try {
|
||||
localStorage.setItem(storageKeyName, activeTabKey);
|
||||
tdActivateTabsWithKey(activeTabKey);
|
||||
if (value) {
|
||||
localStorage.setItem(key, value);
|
||||
} else {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Unable to save active tab '${activeTabKey}' to localStorage:`, error);
|
||||
const action = value ? 'add' : 'remove';
|
||||
console.error(
|
||||
`Docsy tabpane: unable to ${action} localStorage key '${key}': `,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const tdSupportsLocalStorage = () => typeof Storage !== 'undefined';
|
||||
// Retrieve, increment, and store tab-select event count, then returns it.
|
||||
function tdGetTabSelectEventCountAndInc() {
|
||||
// @requires: tdSupportsLocalStorage();
|
||||
|
||||
// On page load, activate tabs
|
||||
if (tdSupportsLocalStorage()) {
|
||||
const activeTabKey = localStorage.getItem(storageKeyName);
|
||||
const storedCount = localStorage.getItem(td_persistCounterStorageKeyName);
|
||||
let numTabSelectEvents = parseInt(storedCount) || 0;
|
||||
numTabSelectEvents++;
|
||||
tdPersistKey(td_persistCounterStorageKeyName, numTabSelectEvents.toString());
|
||||
return numTabSelectEvents;
|
||||
}
|
||||
|
||||
// Main functions
|
||||
|
||||
function tdActivateTabsWithKey(key) {
|
||||
if (!key) return;
|
||||
|
||||
document.querySelectorAll(_tdPersistCssSelector(key)).forEach((element) => {
|
||||
new bootstrap.Tab(element).show();
|
||||
});
|
||||
}
|
||||
|
||||
function tdPersistActiveTab(activeTabKey) {
|
||||
if (!_tdSupportsLocalStorage()) return;
|
||||
|
||||
tdPersistKey(
|
||||
_tdStoragePersistKey(activeTabKey),
|
||||
tdGetTabSelectEventCountAndInc()
|
||||
);
|
||||
tdActivateTabsWithKey(activeTabKey);
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
||||
function tdGetAndActivatePersistedTabs(tabs) {
|
||||
// Get unique persistence keys of tabs in this page
|
||||
var keyOfTabsInThisPage = [
|
||||
...new Set(
|
||||
Array.from(tabs).map((el) => el.getAttribute(td_persistDataAttrName))
|
||||
),
|
||||
];
|
||||
|
||||
// Create a list of active tabs with their age:
|
||||
let key_ageList = keyOfTabsInThisPage
|
||||
// Map to [tab-key, last-activated-age]
|
||||
.map((k) => [
|
||||
k,
|
||||
parseInt(localStorage.getItem(_tdStoragePersistKey(k))) || 0,
|
||||
])
|
||||
// Exclude tabs that have never been activated
|
||||
.filter(([k, v]) => v)
|
||||
// Sort from oldest selected to most recently selected
|
||||
.sort((a, b) => a[1] - b[1]);
|
||||
|
||||
// Activate tabs from the oldest to the newest
|
||||
key_ageList.forEach(([key]) => {
|
||||
tdActivateTabsWithKey(key);
|
||||
});
|
||||
|
||||
return key_ageList;
|
||||
}
|
||||
|
||||
function tdRegisterTabClickHandler(tabs) {
|
||||
tabs.forEach((tab) => {
|
||||
tab.addEventListener('click', () => {
|
||||
const activeTabKey = tab.getAttribute(td_persistDataAttrName);
|
||||
tdPersistActiveTab(activeTabKey);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Register listeners and activate tabs
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
if (!_tdSupportsLocalStorage()) return;
|
||||
|
||||
var allTabsInThisPage = document.querySelectorAll(_tdPersistCssSelector());
|
||||
tdRegisterTabClickHandler(allTabsInThisPage);
|
||||
tdGetAndActivatePersistedTabs(allTabsInThisPage);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue