// SPDX-FileCopyrightText: Chris Pressey, the creator of this work, has dedicated it to the public domain.
// For more information, please refer to <https://unlicense.org/>
// SPDX-License-Identifier: Unlicense
(function() {
function makeSaveable(config) {
config = config || {};
var editor = config.editor;
var onUpdate = config.onUpdate;
var nameSpacePrefix = config.nameSpacePrefix || "";
var input = DAM.maker('input');
var select = DAM.maker('select');
var option = DAM.maker('option');
var button = DAM.maker('button');
var div = DAM.maker('div');
var unsavedChanges = false;
var saveAreaVisible = false;
function stripNameSpacePrefix(key) {
return key.slice(nameSpacePrefix.length);
}
function updateSaveSlotOptions() {
saveSlotSelect.innerHTML = '';
saveSlotSelect.appendChild(option({ value: '' }, 'Select a save slot to load from'));
// Get all keys and sort them alphabetically
var keys = [];
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.startsWith(nameSpacePrefix)) {
keys.push(key);
}
}
keys.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
// Add sorted options to select
for (var i = 0; i < keys.length; i++) {
saveSlotSelect.appendChild(option({ value: keys[i] }, stripNameSpacePrefix(keys[i])));
}
}
function resetDropdownToDefault() {
saveSlotSelect.value = '';
}
function toggleSaveArea() {
saveAreaVisible = !saveAreaVisible;
saveArea.style.display = saveAreaVisible ? "inline-block" : "none";
toggleSaveAreaButton.textContent = saveAreaVisible ? "Save <<" : "Save >>";
}
function saveText() {
var name = nameInput.value.trim();
var text = editor.value;
if (!name) {
alert('Please enter a name before saving.');
return;
}
// Check if name already exists in localStorage
var key = nameSpacePrefix + name;
if (localStorage.getItem(key) !== null) {
if (!confirm('A save slot with this name already exists. Do you want to overwrite it?')) {
return; // User cancelled overwrite
}
}
localStorage.setItem(key, text);
updateSaveSlotOptions();
unsavedChanges = false;
toggleSaveArea(); // Hide save area after successful save
// Select the newly saved slot in the dropdown
saveSlotSelect.value = key;
}
function loadText(key) {
var savedText = localStorage.getItem(key);
if (savedText !== null) {
editor.value = savedText;
if (typeof onUpdate === "function") {
onUpdate(savedText);
}
nameInput.value = stripNameSpacePrefix(key);
unsavedChanges = false;
}
}
var saveSlotSelect = select(
option({ value: '' }, 'Select a save slot to load')
);
var nameInput = input({
type: 'text',
placeholder: 'Enter name'
});
var saveButton = button(
{ onclick: saveText },
'Save'
);
var saveArea = div(
{ style: "display: none" },
nameInput,
saveButton
);
var toggleSaveAreaButton = button(
{ onclick: toggleSaveArea },
'Save >>'
);
editor.addEventListener('input', function() {
unsavedChanges = true;
});
saveSlotSelect.addEventListener('change', function(event) {
var key = event.target.value; // key of selected save slot
if (key) {
if (unsavedChanges) {
if (confirm('You have unsaved changes. Are you sure you want to load?')) {
loadText(key);
} else {
// Reset dropdown to default when cancelled
resetDropdownToDefault();
}
} else {
loadText(key);
}
}
});
// Set up any presets (pre-set save slots) that aren't already in storage
if (Array.isArray(config.presets)) {
for (var i = 0; i < config.presets.length; i++) {
var preset = config.presets[i];
if (!Array.isArray(preset) || preset.length !== 2) {
throw new Error('Each preset must be a [name, content] pair');
}
var [name, content] = preset;
key = nameSpacePrefix + name;
if (localStorage.getItem(key) === null) {
localStorage.setItem(key, content);
}
}
}
updateSaveSlotOptions();
return div(
{ class: 'dam-saveable-widget' },
saveSlotSelect,
toggleSaveAreaButton,
saveArea
);
}
if (typeof module !== 'undefined') {
module.exports = { makeSaveable: makeSaveable };
} else if (typeof window !== 'undefined') {
window.DAM = window.DAM || {};
DAM.makeSaveable = makeSaveable;
}
})();