diff options
Diffstat (limited to 'src/static/js/client')
| -rw-r--r-- | src/static/js/client/index.js | 85 | ||||
| -rw-r--r-- | src/static/js/client/sidebar-search.js | 17 |
2 files changed, 97 insertions, 5 deletions
diff --git a/src/static/js/client/index.js b/src/static/js/client/index.js index 53432a91..16ebe89f 100644 --- a/src/static/js/client/index.js +++ b/src/static/js/client/index.js @@ -75,6 +75,10 @@ const situationalSteps = { const stepInfoSymbol = Symbol(); +const boundSessionStorage = + window.hsmusicBoundSessionStorage = + Object.create(null); + for (const module of modules) { const {info} = module; @@ -159,12 +163,47 @@ for (const module of modules) { const storageKey = `hsmusic.${infoKey}.${key}`; + // There are two storage systems besides actual session storage in play. + // + // "Fallback" is for if session storage is not available, which may + // suddenly become the case, i.e. access is temporarily revoked or fails. + // The fallback value is controlled completely internally i.e. in this + // infrastructure, in this lexical scope. + // + // "Bound" is for if the value kept in session storage was saved to + // the page when the page was initially loaded, rather than a living + // window on session storage (which may be affected by pages later in + // the history stack). Whether or not bound storage is in effect is + // controlled at page load (of course), by each module's own logic. + // + // Asterisk: Bound storage can't work miracles and if the page is + // actually deloaded with its JavaScript state discarded, the bound + // values are lost, even if the browser recreates on-page form state. + let fallbackValue = defaultValue; + let boundValue = undefined; + + const updateBoundValue = (givenValue = undefined) => { + if (givenValue) { + if ( + infoKey in boundSessionStorage && + key in boundSessionStorage[infoKey] + ) { + boundSessionStorage[infoKey][key] = givenValue; + } + } else { + boundValue = boundSessionStorage[infoKey]?.[key]; + } + }; Object.defineProperty(info.session, key, { get: () => { + updateBoundValue(); + let value; - try { + if (boundValue !== undefined) { + value = boundValue ?? defaultValue; + } else try { value = sessionStorage.getItem(storageKey) ?? defaultValue; } catch (error) { if (error instanceof DOMException) { @@ -200,21 +239,23 @@ for (const module of modules) { return; } - let operation; + let sessionOperation; if (value === '') { fallbackValue = null; - operation = () => { + updateBoundValue(null); + sessionOperation = () => { sessionStorage.removeItem(storageKey); }; } else { fallbackValue = value; - operation = () => { + updateBoundValue(value); + sessionOperation = () => { sessionStorage.setItem(storageKey, value); }; } try { - operation(); + sessionOperation(); } catch (error) { if (!(error instanceof DOMException)) { throw error; @@ -244,6 +285,40 @@ for (const module of modules) { } } +function evaluateBindSessionStorageStep(bindSessionStorage) { + const {id: infoKey, session: moduleExposedSessionObject} = + bindSessionStorage[stepInfoSymbol]; + + const generator = bindSessionStorage(); + + let lastBoundValue; + while (true) { + const {value: key, done} = generator.next(lastBoundValue); + const storageKey = `hsmusic.${infoKey}.${key}`; + + let value = undefined; + try { + value = sessionStorage.getItem(storageKey); + } catch (error) { + if (!(error instanceof DOMException)) { + throw error; + } + } + + if (value === undefined) { + // This effectively gets the default value. + value = moduleExposedSessionObject[key]; + } + + boundSessionStorage[infoKey] ??= Object.create(null); + boundSessionStorage[infoKey][key] = value; + + lastBoundValue = value; + + if (done) break; + } +} + function evaluateStep(stepsObject, key) { for (const step of stepsObject[key]) { try { diff --git a/src/static/js/client/sidebar-search.js b/src/static/js/client/sidebar-search.js index 3cc3d218..0b905948 100644 --- a/src/static/js/client/sidebar-search.js +++ b/src/static/js/client/sidebar-search.js @@ -158,6 +158,17 @@ export const info = { }, }; +export function* bindSessionStorage() { + if (yield 'activeQuery') { + yield 'activeQueryContextPageName'; + yield 'activeQueryContextPagePathname'; + yield 'activeQueryContextPageColor'; + yield 'activeQueryResults'; + yield 'activeFilterType'; + yield 'resultsScrollOffset'; + } +} + export function getPageReferences() { info.pageContainer = document.getElementById('page-container'); @@ -443,6 +454,12 @@ export function mutatePageContent() { info.searchBox.appendChild(info.endSearchRule); info.searchBox.appendChild(info.endSearchLine); + + // Accommodate the web browser reconstructing the search input with a value + // that was previously entered (or restored after recall), i.e. because + // the user is traversing very far back in history and yet the browser is + // trying to rebuild the page as-was anyway, by telling it "no don't". + info.searchInput.value = ''; } export function addPageListeners() { |