diff --git a/README.md b/README.md index 04f6e1f..9bee76e 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,13 @@ The `restoreResumableFields(id: string, options)` function supports optional con The `persistResumableFields(id: string, options)` function supports optional configurations: * `storage:` - [`Storage`][] instance (defaults to [`window.sessionStorage`][]) -* `selector:` - `string` used to query field elements (defaults to `".js-session-resumable"`) +* `storageFilter:` - `(field: HTMLInputElement | HTMLTextAreaElement) => boolean` predicate to determine whether or not to store a field (defaults to `(field) => field.value !== field.defaultValue`) * `keyPrefix:` - `string` prepended onto the storage key (defaults to `"session-resume"`) +* `scope:` - `ParentNode` used to query field elements (defaults to `document`) +* `selector:` - `string` used to query field elements (defaults to `".js-session-resumable"`) +* `fields:` - `NodeList | Node[]` provide field elements as an alternative to querying (defaults to `options.scope.querySelectorAll(options.selector)`) + +**Note:** When `fields` is specified, `scope` and `selectors` will be ignored. [`Storage`]: https://developer.mozilla.org/en-US/docs/Web/API/Storage [`window.sessionStorage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage diff --git a/src/index.ts b/src/index.ts index 29b94f8..2852d45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,8 +11,19 @@ function valueIsUnchanged(field: HTMLInputElement | HTMLTextAreaElement): boolea type StorageFilter = (field: HTMLInputElement | HTMLTextAreaElement) => boolean -type PersistOptions = { +type PersistOptionsWithSelector = { + scope?: ParentNode selector?: string + fields?: never +} + +type PersistOptionsWithFields = { + fields?: NodeList | Node[] + selector?: never + scope?: never +} + +type PersistOptions = (PersistOptionsWithSelector | PersistOptionsWithFields) & { keyPrefix?: string storage?: Pick storageFilter?: StorageFilter @@ -20,7 +31,9 @@ type PersistOptions = { // Write all ids and values of the selected fields on the page into sessionStorage. export function persistResumableFields(id: string, options?: PersistOptions): void { + const scope = options?.scope ?? document const selector = options?.selector ?? '.js-session-resumable' + const elements = options?.fields ?? scope.querySelectorAll(selector) const keyPrefix = options?.keyPrefix ?? 'session-resume:' const storageFilter = options?.storageFilter ?? valueIsUnchanged @@ -35,7 +48,7 @@ export function persistResumableFields(id: string, options?: PersistOptions): vo const key = `${keyPrefix}${id}` const resumables = [] - for (const el of document.querySelectorAll(selector)) { + for (const el of elements) { if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) { resumables.push(el) } diff --git a/test/test.js b/test/test.js index 1cd6a1a..1469062 100644 --- a/test/test.js +++ b/test/test.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line import/no-unresolved, import/extensions +// eslint-disable-next-line import/extensions, import/no-unresolved import {persistResumableFields, restoreResumableFields} from '../dist/index.js' describe('session-resume', function () { @@ -156,5 +156,48 @@ describe('session-resume', function () { ['my-second-field', 'test2'] ]) }) + + it('scopes fields based on the selector: option', function () { + document.getElementById('my-first-field').value = 'test1' + document.getElementById('my-second-field').value = 'test2' + + sessionStorage.clear() + persistResumableFields('test-persist', {selector: '#my-first-field'}) + + assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [['my-first-field', 'test1']]) + }) + + it('scopes fields based on the scope: option', function () { + // eslint-disable-next-line github/no-inner-html + document.body.innerHTML = ` +
+ + +
+ + ` + document.getElementById('my-first-field').value = 'test1' + document.getElementById('my-second-field').value = 'test2' + document.getElementById('my-third-field').value = 'test3' + + sessionStorage.clear() + persistResumableFields('test-persist', {scope: document.querySelector('form')}) + + assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [ + ['my-first-field', 'test1'], + ['my-second-field', 'test2'] + ]) + }) + it('scopes fields based on the fields: option', function () { + document.getElementById('my-first-field').value = 'test1' + document.getElementById('my-second-field').value = 'test2' + + sessionStorage.clear() + persistResumableFields('test-persist', {fields: document.querySelectorAll('#my-second-field')}) + + assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [ + ['my-second-field', 'test2'] + ]) + }) }) })