Skip to content

Commit

Permalink
Merge pull request #16 from jklina/restore-fields-not-immediately-pre…
Browse files Browse the repository at this point in the history
…sent-on-dom

Track fields not always available in the DOM
  • Loading branch information
koddsson authored Apr 23, 2021
2 parents e2cd2a6 + 0d40211 commit 7e40603
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 14 deletions.
46 changes: 32 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,20 @@ export function persistResumableFields(id: string, options?: PersistOptions): vo
}
}

const fields = resumables.filter(field => shouldResumeField(field)).map(field => [field.id, field.value])
let fields = resumables.filter(field => shouldResumeField(field)).map(field => [field.id, field.value])

if (fields.length) {
try {
const previouslyStoredFieldsJson = sessionStorage.getItem(key)

if (previouslyStoredFieldsJson !== null) {
const previouslyStoredFields: string[][] = JSON.parse(previouslyStoredFieldsJson)
const fieldsNotReplaced: string[][] = previouslyStoredFields.filter(function (oldField) {
return !fields.some(field => field[0] === oldField[0])
})
fields = fields.concat(fieldsNotReplaced)
}

sessionStorage.setItem(key, JSON.stringify(fields))
} catch {
// Ignore browser private mode error.
Expand All @@ -46,13 +56,8 @@ export function restoreResumableFields(id: string, options?: RestoreOptions): vo

if (!fields) return

try {
sessionStorage.removeItem(key)
} catch {
// Ignore browser private mode error.
}

const changedFields: Array<HTMLInputElement | HTMLTextAreaElement> = []
const storedFieldsNotFound: string[][] = []

for (const [fieldId, value] of JSON.parse(fields)) {
const resumeEvent = new CustomEvent('session:resume', {
Expand All @@ -63,17 +68,30 @@ export function restoreResumableFields(id: string, options?: RestoreOptions): vo

if (document.dispatchEvent(resumeEvent)) {
const field = document.getElementById(fieldId)
if (
field &&
(field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement) &&
field.value === field.defaultValue
) {
field.value = value
changedFields.push(field)
if (field && (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement)) {
if (field.value === field.defaultValue) {
field.value = value
changedFields.push(field)
}
} else {
storedFieldsNotFound.push([fieldId, value])
}
}
}

// Some fields we want to restore are not always immediately present in the
// DOM and may be added later. This holds onto the values until
// they're needed.
if (storedFieldsNotFound.length === 0) {
try {
sessionStorage.removeItem(key)
} catch {
// Ignore browser private mode error.
}
} else {
sessionStorage.setItem(key, JSON.stringify(storedFieldsNotFound))
}

setTimeout(function () {
for (const el of changedFields) {
el.dispatchEvent(new CustomEvent('change', {bubbles: true, cancelable: true}))
Expand Down
59 changes: 59 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,38 @@ describe('session-resume', function () {
assert.equal(document.querySelector('#my-second-field').value, 'second-field-value')
})

it('leaves unrestored values in session storage', function () {
sessionStorage.setItem(
'session-resume:test-persist',
JSON.stringify([
['my-first-field', 'test2'],
['non-existant-field', 'test3']
])
)
document.querySelector('#my-first-field').value = 'first-field-value'
document.querySelector('#my-second-field').value = 'second-field-value'

restoreResumableFields('test-persist')

assert.equal(document.querySelector('#my-first-field').value, 'test2')
assert.equal(document.querySelector('#my-second-field').value, 'second-field-value')

// Some fields we want to restore are not always present in the DOM
// and may be added later. We hold onto the values until they're needed.
assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
['non-existant-field', 'test3']
])
})

it('removes the sessionStore key when all the fields were found', function () {
sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'test2']]))
restoreResumableFields('test-persist')

// Some fields we want to restore are not always present in the DOM
// and may be added later. We hold onto the values until they're needed.
assert.equal(sessionStorage.getItem('session-resume:test-persist'), null)
})

it('fires off session:resume events for changed fields', function () {
const fieldsRestored = {}
document.addEventListener('session:resume', function (event) {
Expand Down Expand Up @@ -55,5 +87,32 @@ describe('session-resume', function () {
['my-second-field', 'test2']
])
})

it('holds onto existing values in the store', function () {
sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['non-existant-field', 'test3']]))
document.querySelector('#my-first-field').value = 'test1'
document.querySelector('#my-second-field').value = 'test2'

persistResumableFields('test-persist')

assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
['my-first-field', 'test1'],
['my-second-field', 'test2'],
['non-existant-field', 'test3']
])
})

it('replaces old values with the latest field values', function () {
sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'old data']]))
document.querySelector('#my-first-field').value = 'test1'
document.querySelector('#my-second-field').value = 'test2'

persistResumableFields('test-persist')

assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
['my-first-field', 'test1'],
['my-second-field', 'test2']
])
})
})
})

0 comments on commit 7e40603

Please sign in to comment.