Skip to content

Instantly share code, notes, and snippets.

@angusgrant
Created November 20, 2022 17:05
Show Gist options
  • Save angusgrant/2321140c3194a24a565d5ffb8c2f16e3 to your computer and use it in GitHub Desktop.
Save angusgrant/2321140c3194a24a565d5ffb8c2f16e3 to your computer and use it in GitHub Desktop.
<!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