Created
November 20, 2022 17:05
-
-
Save angusgrant/2321140c3194a24a565d5ffb8c2f16e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Form Autosave - Form Status</title> | |
<style type="text/css"> | |
body { | |
margin: 1em auto; | |
max-width: 40em; | |
width: 88%; | |
} | |
label, | |
input, | |
textarea { | |
display: block; | |
width: 100%; | |
} | |
input, | |
textarea { | |
margin-bottom: 1em; | |
} | |
textarea { | |
height: 8em; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Form Autosave - Form Status</h1> | |
<form id="save-me"> | |
<label for="name">Name</label> | |
<input type="text" name="name" id="name"> | |
<label for="address">Address</label> | |
<input type="text" name="address" id="address"> | |
<label for="email">Email</label> | |
<input type="email" name="email" id="email"> | |
<label for="more">Additional thoughts?</label> | |
<textarea name="more" id="more"></textarea> | |
<p> | |
<button type="submit">Submit</button> | |
</p> | |
</form> | |
<script> | |
// Get the form element | |
let form = document.querySelector('#save-me'); | |
// localStorage prefix | |
let prefix = 'autosave_fields'; | |
/** | |
* Serialize all form data into an object | |
* @param {FormData} data The FormData object to serialize | |
* @return {String} The serialized form data | |
*/ | |
function serialize (data) { | |
let obj = {}; | |
for (let [key, value] of data) { | |
if (obj[key] !== undefined) { | |
if (!Array.isArray(obj[key])) { | |
obj[key] = [obj[key]]; | |
} | |
obj[key].push(value); | |
} else { | |
obj[key] = value; | |
} | |
} | |
return obj; | |
} | |
/** | |
* Handle input events | |
* @param {Event} event The event object | |
*/ | |
function inputHandler (event) { | |
let debounce; | |
// Serialize the form fields | |
let data = serialize(new FormData(form)); | |
// Stringify the object and save it to localStorage | |
localStorage.setItem(prefix, JSON.stringify(data)); | |
clearTimeout(debounce); | |
// Update the UI after one second to show save update has ocurred | |
// id don't use requestAnimationFrame as i don't think a quick response is important! | |
debounce = setTimeout(function () { | |
displayUpdateMessage(); | |
}, 1000); | |
} | |
function displayUpdateMessage() { | |
// Create a notification | |
let notification = form.querySelector('#notification'); | |
let removeNotification; | |
//if notification does not exist then create it. | |
if (!notification) { | |
notification = document.createElement('div'); | |
notification.setAttribute('role', 'status'); | |
notification.setAttribute('aria-live', 'polite'); | |
notification.id = 'notification'; | |
// Inject it into the DOM | |
form.append(notification); | |
setTimeout(function () { | |
notification.textContent ='Form data saved'; | |
}, 1); | |
} else { | |
//otherwise just extent its display. | |
clearTimeout(removeNotification) | |
} | |
// remove after 4 seconds | |
removeNotification = setTimeout(function () { | |
notification.remove(); | |
}, 4000); | |
} | |
/** | |
* Clear all of the saved fields from storage | |
*/ | |
function clearStorage () { | |
localStorage.removeItem(prefix); | |
} | |
/** | |
* Load saved data from localStorage | |
*/ | |
function loadSaved () { | |
// Get saved data from localStorage | |
// If there's nothing saved, bail | |
let saved = JSON.parse(localStorage.getItem(prefix)); | |
if (!saved) return; | |
// Get all of the fields in the form | |
let fields = form.elements; | |
// Loop through each one and load saved data if it exists | |
for (let field of fields) { | |
if (!saved[field.name]) continue; | |
field.value = saved[field.name]; | |
} | |
} | |
// Load saved data from localStorage | |
loadSaved(); | |
// Listen for DOM events | |
form.addEventListener('input', inputHandler); | |
form.addEventListener('submit', clearStorage); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment