Add autosave script for forms to prevent data loss on reload
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Unique key for the current page URL
|
||||
const pageKey = window.location.pathname + window.location.search;
|
||||
const STORAGE_KEY = 'autosave_' + pageKey;
|
||||
// Expiration time: 12 hours
|
||||
const EXPIRATION_MS = 12 * 60 * 60 * 1000;
|
||||
|
||||
function saveFormData() {
|
||||
const forms = document.querySelectorAll('form');
|
||||
let formData = {};
|
||||
let hasData = false;
|
||||
|
||||
forms.forEach((form, formIndex) => {
|
||||
const inputs = form.querySelectorAll('input:not([type="password"]):not([type="hidden"]):not([type="submit"]):not([type="file"]), textarea, select');
|
||||
let formState = {};
|
||||
inputs.forEach(input => {
|
||||
// Ignore inputs without a name
|
||||
if (!input.name) return;
|
||||
|
||||
if (input.type === 'checkbox' || input.type === 'radio') {
|
||||
formState[input.name] = input.checked;
|
||||
} else {
|
||||
formState[input.name] = input.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(formState).length > 0) {
|
||||
formData[formIndex] = formState;
|
||||
hasData = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (hasData) {
|
||||
const dataToSave = {
|
||||
timestamp: new Date().getTime(),
|
||||
data: formData
|
||||
};
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(dataToSave));
|
||||
}
|
||||
}
|
||||
|
||||
function loadFormData() {
|
||||
const saved = localStorage.getItem(STORAGE_KEY);
|
||||
if (saved) {
|
||||
try {
|
||||
const parsed = JSON.parse(saved);
|
||||
const now = new Date().getTime();
|
||||
|
||||
// Discard data if it's older than expiration time
|
||||
if (now - parsed.timestamp > EXPIRATION_MS) {
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = parsed.data;
|
||||
const forms = document.querySelectorAll('form');
|
||||
|
||||
forms.forEach((form, formIndex) => {
|
||||
if (formData[formIndex]) {
|
||||
const formState = formData[formIndex];
|
||||
const inputs = form.querySelectorAll('input:not([type="password"]):not([type="hidden"]):not([type="submit"]):not([type="file"]), textarea, select');
|
||||
|
||||
inputs.forEach(input => {
|
||||
if (input.name && formState[input.name] !== undefined) {
|
||||
if (input.type === 'checkbox' || input.type === 'radio') {
|
||||
// Set checked state
|
||||
if (input.checked !== formState[input.name]) {
|
||||
input.checked = formState[input.name];
|
||||
}
|
||||
} else {
|
||||
// Set value
|
||||
if (input.value !== formState[input.name]) {
|
||||
input.value = formState[input.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Show a small non-intrusive toast notification
|
||||
showToast("Восстановлены несохраненные данные");
|
||||
} catch (e) {
|
||||
console.error("Error parsing autosave data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.textContent = message;
|
||||
toast.style.position = 'fixed';
|
||||
toast.style.bottom = '20px';
|
||||
toast.style.right = '20px';
|
||||
toast.style.backgroundColor = '#494bd6';
|
||||
toast.style.color = 'white';
|
||||
toast.style.padding = '10px 20px';
|
||||
toast.style.borderRadius = '5px';
|
||||
toast.style.zIndex = '9999';
|
||||
toast.style.fontFamily = '"Plus Jakarta Sans", sans-serif';
|
||||
toast.style.fontSize = '12px';
|
||||
toast.style.boxShadow = '0 4px 6px rgba(0,0,0,0.3)';
|
||||
toast.style.transition = 'opacity 0.5s ease';
|
||||
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(() => toast.remove(), 500);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Load data on page load
|
||||
loadFormData();
|
||||
|
||||
// Debounce function for saving data so it doesn't trigger on every single keystroke excessively
|
||||
let timeout;
|
||||
document.addEventListener('input', function(e) {
|
||||
if (['INPUT', 'TEXTAREA', 'SELECT'].includes(e.target.tagName)) {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(saveFormData, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Clear saved data on successful form submission
|
||||
document.addEventListener('submit', function(e) {
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
});
|
||||
});
|
||||
@@ -143,5 +143,7 @@
|
||||
</main>
|
||||
<!-- END: MainContent -->
|
||||
|
||||
{% load static %}
|
||||
<script src="{% static 'js/autosave.js' %}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user