Skip to content

Commit cee83c0

Browse files
authored
Merge pull request #20 from seanpdoyle/provide-field-elements
Support `scope:` option to scope selector query and `fields:` option to skip selector query
2 parents 9358f76 + 357e2f8 commit cee83c0

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ The `restoreResumableFields(id: string, options)` function supports optional con
6161
The `persistResumableFields(id: string, options)` function supports optional configurations:
6262

6363
* `storage:` - [`Storage`][] instance (defaults to [`window.sessionStorage`][])
64-
* `selector:` - `string` used to query field elements (defaults to `".js-session-resumable"`)
64+
* `storageFilter:` - `(field: HTMLInputElement | HTMLTextAreaElement) => boolean` predicate to determine whether or not to store a field (defaults to `(field) => field.value !== field.defaultValue`)
6565
* `keyPrefix:` - `string` prepended onto the storage key (defaults to `"session-resume"`)
66+
* `scope:` - `ParentNode` used to query field elements (defaults to `document`)
67+
* `selector:` - `string` used to query field elements (defaults to `".js-session-resumable"`)
68+
* `fields:` - `NodeList | Node[]` provide field elements as an alternative to querying (defaults to `options.scope.querySelectorAll(options.selector)`)
69+
70+
**Note:** When `fields` is specified, `scope` and `selectors` will be ignored.
6671

6772
[`Storage`]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
6873
[`window.sessionStorage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

src/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,29 @@ function valueIsUnchanged(field: HTMLInputElement | HTMLTextAreaElement): boolea
1111

1212
type StorageFilter = (field: HTMLInputElement | HTMLTextAreaElement) => boolean
1313

14-
type PersistOptions = {
14+
type PersistOptionsWithSelector = {
15+
scope?: ParentNode
1516
selector?: string
17+
fields?: never
18+
}
19+
20+
type PersistOptionsWithFields = {
21+
fields?: NodeList | Node[]
22+
selector?: never
23+
scope?: never
24+
}
25+
26+
type PersistOptions = (PersistOptionsWithSelector | PersistOptionsWithFields) & {
1627
keyPrefix?: string
1728
storage?: Pick<Storage, 'getItem' | 'setItem'>
1829
storageFilter?: StorageFilter
1930
}
2031

2132
// Write all ids and values of the selected fields on the page into sessionStorage.
2233
export function persistResumableFields(id: string, options?: PersistOptions): void {
34+
const scope = options?.scope ?? document
2335
const selector = options?.selector ?? '.js-session-resumable'
36+
const elements = options?.fields ?? scope.querySelectorAll(selector)
2437
const keyPrefix = options?.keyPrefix ?? 'session-resume:'
2538
const storageFilter = options?.storageFilter ?? valueIsUnchanged
2639

@@ -35,7 +48,7 @@ export function persistResumableFields(id: string, options?: PersistOptions): vo
3548
const key = `${keyPrefix}${id}`
3649
const resumables = []
3750

38-
for (const el of document.querySelectorAll(selector)) {
51+
for (const el of elements) {
3952
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
4053
resumables.push(el)
4154
}

test/test.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// eslint-disable-next-line import/no-unresolved, import/extensions
1+
// eslint-disable-next-line import/extensions, import/no-unresolved
22
import {persistResumableFields, restoreResumableFields} from '../dist/index.js'
33

44
describe('session-resume', function () {
@@ -156,5 +156,48 @@ describe('session-resume', function () {
156156
['my-second-field', 'test2']
157157
])
158158
})
159+
160+
it('scopes fields based on the selector: option', function () {
161+
document.getElementById('my-first-field').value = 'test1'
162+
document.getElementById('my-second-field').value = 'test2'
163+
164+
sessionStorage.clear()
165+
persistResumableFields('test-persist', {selector: '#my-first-field'})
166+
167+
assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [['my-first-field', 'test1']])
168+
})
169+
170+
it('scopes fields based on the scope: option', function () {
171+
// eslint-disable-next-line github/no-inner-html
172+
document.body.innerHTML = `
173+
<form>
174+
<input id="my-first-field" value="first-field-value" class="js-session-resumable" />
175+
<input id="my-second-field" value="second-field-value" class="js-session-resumable" />
176+
</form>
177+
<input id="my-third-field" value="second-third-value" class="js-session-resumable" />
178+
`
179+
document.getElementById('my-first-field').value = 'test1'
180+
document.getElementById('my-second-field').value = 'test2'
181+
document.getElementById('my-third-field').value = 'test3'
182+
183+
sessionStorage.clear()
184+
persistResumableFields('test-persist', {scope: document.querySelector('form')})
185+
186+
assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
187+
['my-first-field', 'test1'],
188+
['my-second-field', 'test2']
189+
])
190+
})
191+
it('scopes fields based on the fields: option', function () {
192+
document.getElementById('my-first-field').value = 'test1'
193+
document.getElementById('my-second-field').value = 'test2'
194+
195+
sessionStorage.clear()
196+
persistResumableFields('test-persist', {fields: document.querySelectorAll('#my-second-field')})
197+
198+
assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
199+
['my-second-field', 'test2']
200+
])
201+
})
159202
})
160203
})

0 commit comments

Comments
 (0)