mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
style creator rework
This commit is contained in:
parent
49a8a9f7c7
commit
8c41639839
2 changed files with 146 additions and 130 deletions
|
|
@ -309,9 +309,9 @@
|
||||||
|
|
||||||
<div id="styleContent" class="tabcontent">
|
<div id="styleContent" class="tabcontent">
|
||||||
<p data-tip="Select a style preset. State labels may required regeneration if font is changed" style="display: inline-block">Style preset:</p>
|
<p data-tip="Select a style preset. State labels may required regeneration if font is changed" style="display: inline-block">Style preset:</p>
|
||||||
<select data-tip="Select a style preset" id="stylePreset" onchange="changeStylePreset(this.value)" style="width:45%; text-transform: capitalize"></select>
|
<select data-tip="Select a style preset" id="stylePreset" onchange="requestStylePresetChange(this.value)" style="width:45%; text-transform: capitalize;"></select>
|
||||||
<button id="addStyleButton" data-tip="Click to save current style as a new preset" class="icon-plus sideButton" style="display: inline-block" onclick="addStylePreset()"></button>
|
<button id="addStyleButton" data-tip="Click to save current style as a new preset" class="icon-plus sideButton" style="display: inline-block" onclick="addStylePreset()"></button>
|
||||||
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus sideButton" style="display: none" onclick="removeStylePreset()"></button>
|
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus sideButton" style="display: none" onclick="requestRemoveStylePreset()"></button>
|
||||||
|
|
||||||
<p data-tip="Select an element to edit its style" style="display: inline-block;">Select element:</p>
|
<p data-tip="Select an element to edit its style" style="display: inline-block;">Select element:</p>
|
||||||
<select data-tip="Select an element to edit its style (list is ordered alphabetically)" id="styleElementSelect" style="width:42%">
|
<select data-tip="Select an element to edit its style (list is ordered alphabetically)" id="styleElementSelect" style="width:42%">
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,61 @@
|
||||||
// UI module to control the style presets
|
// UI module to control the style presets
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const defaultStyles = ["default", "ancient", "gloom", "clean", "light", "watercolor", "cyberpunk", "monochrome"];
|
const systemPresets = ["default", "ancient", "gloom", "clean", "light", "watercolor", "cyberpunk", "monochrome"];
|
||||||
|
const customPresetPrefix = "fmgStyle";
|
||||||
|
|
||||||
// add styles to list
|
// add style presets to list
|
||||||
{
|
{
|
||||||
const defaultOptions = defaultStyles.map(styleName => `<option value="${styleName}">${styleName}</option>`);
|
const systemOptions = systemPresets.map(styleName => `<option value="${styleName}">${styleName}</option>`);
|
||||||
const storedStyles = Object.keys(localStorage).filter(key => key.startsWith("fmgStyle"));
|
const storedStyles = Object.keys(localStorage).filter(key => key.startsWith(customPresetPrefix));
|
||||||
const customOptions = storedStyles.map(styleName => `<option value="${styleName}">${styleName.replace("fmgStyle", "")} [custom]</option>`);
|
const customOptions = storedStyles.map(styleName => `<option value="${styleName}">${styleName.replace(customPresetPrefix, "")} [custom]</option>`);
|
||||||
const options = defaultOptions.join("") + customOptions.join("");
|
const options = systemOptions.join("") + customOptions.join("");
|
||||||
document.getElementById("stylePreset").innerHTML = options;
|
document.getElementById("stylePreset").innerHTML = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyStyleOnLoad() {
|
async function applyStyleOnLoad() {
|
||||||
let preset = localStorage.getItem("presetStyle") || "default";
|
const desiredPreset = localStorage.getItem("presetStyle") || "default";
|
||||||
let style = {};
|
const styleData = await getStylePreset(desiredPreset);
|
||||||
|
const [appliedPreset, style] = styleData;
|
||||||
const isCustom = !defaultStyles.includes(preset);
|
|
||||||
if (isCustom) {
|
|
||||||
const storedStyleJSON = localStorage.getItem(preset);
|
|
||||||
if (!storedStyleJSON) {
|
|
||||||
console.error(`Custom style ${preset} in not found in localStorage. Appliying default style`);
|
|
||||||
preset = "default";
|
|
||||||
} else {
|
|
||||||
const isValid = JSON.isValid(storedStyleJSON);
|
|
||||||
if (isValid) {
|
|
||||||
style = JSON.parse(storedStyleJSON);
|
|
||||||
} else {
|
|
||||||
console.error(`Custom style ${preset} stored in localStorage is not valid. Appliying default style`);
|
|
||||||
preset = "default";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const defaultStyle = await fetch(`/styles/${preset}.json`)
|
|
||||||
.then(res => res.json())
|
|
||||||
.catch(err => {
|
|
||||||
console.error("Error on loading style", preset, err);
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
style = defaultStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyStyle(style);
|
applyStyle(style);
|
||||||
updateMapFilter();
|
updateMapFilter();
|
||||||
stylePreset.value = stylePreset.dataset.old = preset;
|
stylePreset.value = stylePreset.dataset.old = appliedPreset;
|
||||||
|
setPresetRemoveButtonVisibiliy();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getStylePreset(desiredPreset) {
|
||||||
|
let presetToLoad = desiredPreset;
|
||||||
|
|
||||||
|
const isCustom = !systemPresets.includes(desiredPreset);
|
||||||
|
if (isCustom) {
|
||||||
|
const storedStyleJSON = localStorage.getItem(desiredPreset);
|
||||||
|
if (!storedStyleJSON) {
|
||||||
|
console.error(`Custom style ${desiredPreset} in not found in localStorage. Applying default style`);
|
||||||
|
presetToLoad = "default";
|
||||||
|
} else {
|
||||||
|
const isValid = JSON.isValid(storedStyleJSON);
|
||||||
|
if (isValid) return [desiredPreset, JSON.parse(storedStyleJSON)];
|
||||||
|
|
||||||
|
console.error(`Custom style ${desiredPreset} stored in localStorage is not valid. Applying default style`);
|
||||||
|
presetToLoad = "default";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const style = await fetchSystemPreset(presetToLoad);
|
||||||
|
return [presetToLoad, style];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchSystemPreset(preset) {
|
||||||
|
const style = await fetch(`/styles/${preset}.json`)
|
||||||
|
.then(res => res.json())
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error on loading style preset", preset, err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!style) throw new Error("Cannot fetch style preset", preset);
|
||||||
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyStyle(style) {
|
function applyStyle(style) {
|
||||||
|
|
@ -67,67 +79,51 @@ function applyStyle(style) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// change current style preset to another saved one
|
function requestStylePresetChange(preset) {
|
||||||
function changeStylePreset(preset) {
|
const isConfirmed = sessionStorage.getItem("styleChangeConfirmed");
|
||||||
if (customization) return tip("Please exit the customization mode first", false, "error");
|
if (isConfirmed) {
|
||||||
|
changeStyle(preset);
|
||||||
if (sessionStorage.getItem("styleChangeWarningShown")) {
|
return;
|
||||||
changeStyle();
|
|
||||||
} else {
|
|
||||||
sessionStorage.setItem("styleChangeWarningShown", true);
|
|
||||||
alertMessage.innerHTML = "Are you sure you want to change the style preset? All unsaved style changes will be lost";
|
|
||||||
$("#alert").dialog({
|
|
||||||
resizable: false,
|
|
||||||
title: "Change style preset",
|
|
||||||
width: "23em",
|
|
||||||
buttons: {
|
|
||||||
Change: function () {
|
|
||||||
changeStyle();
|
|
||||||
$(this).dialog("close");
|
|
||||||
},
|
|
||||||
Cancel: function () {
|
|
||||||
stylePreset.value = stylePreset.dataset.old;
|
|
||||||
$(this).dialog("close");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeStyle() {
|
confirmationDialog({
|
||||||
const customPreset = localStorage.getItem(preset);
|
title: "Change style preset",
|
||||||
if (customPreset) {
|
message: "Are you sure you want to change the style preset? All unsaved style changes will be lost",
|
||||||
if (JSON.isValid(customPreset)) applyStyle(JSON.parse(customPreset));
|
confirm: "Change",
|
||||||
else {
|
onConfirm: () => {
|
||||||
tip("Cannot parse stored style JSON. Default style applied", false, "error", 5000);
|
sessionStorage.setItem("styleChangeConfirmed", true);
|
||||||
applyDefaultStyle();
|
changeStyle(preset);
|
||||||
}
|
},
|
||||||
} else if (defaultStyles[preset]) {
|
onCancel: () => {
|
||||||
const style = defaultStyles[preset];
|
stylePreset.value = stylePreset.dataset.old;
|
||||||
if (JSON.isValid(style)) applyStyle(JSON.parse(style));
|
}
|
||||||
else tip("Cannot parse style JSON", false, "error", 5000);
|
});
|
||||||
} else applyDefaultStyle();
|
}
|
||||||
|
|
||||||
const isDefault = defaultStyles.includes(stylePreset.value);
|
async function changeStyle(desiredPreset) {
|
||||||
removeStyleButton.style.display = isDefault ? "none" : "inline-block";
|
const styleData = await getStylePreset(desiredPreset);
|
||||||
updateElements(); // change elements
|
const [appliedPreset, style] = styleData;
|
||||||
selectStyleElement(); // re-select element to trigger values update
|
localStorage.setItem("presetStyle", appliedPreset);
|
||||||
updateMapFilter();
|
applyStyleWithUiRefresh(style);
|
||||||
localStorage.setItem("presetStyle", preset); // save preset to use it onload
|
}
|
||||||
stylePreset.dataset.old = stylePreset.value; // save current value
|
|
||||||
}
|
function applyStyleWithUiRefresh(style) {
|
||||||
|
applyStyle(style);
|
||||||
|
updateElements();
|
||||||
|
selectStyleElement(); // re-select element to trigger values update
|
||||||
|
updateMapFilter();
|
||||||
|
stylePreset.dataset.old = stylePreset.value;
|
||||||
|
|
||||||
|
invokeActiveZooming();
|
||||||
|
setPresetRemoveButtonVisibiliy();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStylePreset() {
|
function addStylePreset() {
|
||||||
$("#styleSaver").dialog({
|
$("#styleSaver").dialog({title: "Style Saver", width: "26em", position: {my: "center", at: "center", of: "svg"}});
|
||||||
title: "Style Saver",
|
|
||||||
width: "26em",
|
|
||||||
position: {my: "center", at: "center", of: "svg"}
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentPreset = document.getElementById("stylePreset").selectedOptions[0];
|
const styleName = stylePreset.value.replace(customPresetPrefix, "");
|
||||||
const styleName = currentPreset ? currentPreset.text : "custom";
|
|
||||||
document.getElementById("styleSaverName").value = styleName;
|
document.getElementById("styleSaverName").value = styleName;
|
||||||
styleSaverJSON.value = JSON.stringify(getStyle(), null, 2);
|
styleSaverJSON.value = JSON.stringify(collectStyleData(), null, 2);
|
||||||
checkName();
|
checkName();
|
||||||
|
|
||||||
if (modules.saveStyle) return;
|
if (modules.saveStyle) return;
|
||||||
|
|
@ -138,11 +134,9 @@ function addStylePreset() {
|
||||||
document.getElementById("styleSaverSave").addEventListener("click", saveStyle);
|
document.getElementById("styleSaverSave").addEventListener("click", saveStyle);
|
||||||
document.getElementById("styleSaverDownload").addEventListener("click", styleDownload);
|
document.getElementById("styleSaverDownload").addEventListener("click", styleDownload);
|
||||||
document.getElementById("styleSaverLoad").addEventListener("click", () => styleToLoad.click());
|
document.getElementById("styleSaverLoad").addEventListener("click", () => styleToLoad.click());
|
||||||
document.getElementById("styleToLoad").addEventListener("change", function () {
|
document.getElementById("styleToLoad").addEventListener("change", loadStyleFile);
|
||||||
uploadFile(this, styleUpload);
|
|
||||||
});
|
|
||||||
|
|
||||||
function getStyle() {
|
function collectStyleData() {
|
||||||
const style = {};
|
const style = {};
|
||||||
const attributes = {
|
const attributes = {
|
||||||
"#map": ["background-color", "filter", "data-filter"],
|
"#map": ["background-color", "filter", "data-filter"],
|
||||||
|
|
@ -226,65 +220,82 @@ function addStylePreset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkName() {
|
function checkName() {
|
||||||
let tip = "";
|
const styleName = customPresetPrefix + styleSaverName.value;
|
||||||
const v = "style" + styleSaverName.value;
|
|
||||||
const listed = Array.from(stylePreset.options).some(o => o.value == v);
|
const isSystem = systemPresets.includes(styleName) || systemPresets.includes(styleSaverName.value);
|
||||||
const stored = localStorage.getItem(v);
|
if (isSystem) return (styleSaverTip.innerHTML = "default");
|
||||||
if (!stored && listed) tip = "default";
|
|
||||||
else if (stored) tip = "existing";
|
const isExisting = Array.from(stylePreset.options).some(option => option.value == styleName);
|
||||||
else if (styleSaverName.value) tip = "new";
|
if (isExisting) return (styleSaverTip.innerHTML = "existing");
|
||||||
styleSaverTip.innerHTML = tip;
|
|
||||||
|
styleSaverTip.innerHTML = "new";
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveStyle() {
|
function saveStyle() {
|
||||||
if (!styleSaverJSON.value) return tip("Please provide a style JSON", false, "error");
|
const styleJSON = styleSaverJSON.value;
|
||||||
if (!JSON.isValid(styleSaverJSON.value)) return tip("JSON string is not valid, please check the format", false, "error");
|
const desiredName = styleSaverName.value;
|
||||||
if (!styleSaverName.value) return tip("Please provide a preset name", false, "error");
|
|
||||||
|
if (!styleJSON) return tip("Please provide a style JSON", false, "error");
|
||||||
|
if (!JSON.isValid(styleJSON)) return tip("JSON string is not valid, please check the format", false, "error");
|
||||||
|
if (!desiredName) return tip("Please provide a preset name", false, "error");
|
||||||
if (styleSaverTip.innerHTML === "default") return tip("You cannot overwrite default preset, please change the name", false, "error");
|
if (styleSaverTip.innerHTML === "default") return tip("You cannot overwrite default preset, please change the name", false, "error");
|
||||||
|
|
||||||
const preset = "style" + styleSaverName.value;
|
const presetName = customPresetPrefix + desiredName;
|
||||||
applyOption(stylePreset, preset, styleSaverName.value); // add option
|
applyOption(stylePreset, presetName, desiredName + " [custom]");
|
||||||
localStorage.setItem("presetStyle", preset); // mark preset as default
|
localStorage.setItem("presetStyle", presetName);
|
||||||
localStorage.setItem(preset, styleSaverJSON.value); // save preset
|
localStorage.setItem(presetName, styleJSON);
|
||||||
|
|
||||||
applyStyle(JSON.parse(styleSaverJSON.value));
|
|
||||||
updateMapFilter();
|
|
||||||
invokeActiveZooming();
|
|
||||||
|
|
||||||
|
applyStyleWithUiRefresh(JSON.parse(styleJSON));
|
||||||
|
tip("Style preset is saved and applied", false, "success", 4000);
|
||||||
$("#styleSaver").dialog("close");
|
$("#styleSaver").dialog("close");
|
||||||
removeStyleButton.style.display = "inline-block";
|
|
||||||
tip("Style preset is saved", false, "success", 4000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function styleDownload() {
|
function styleDownload() {
|
||||||
if (!styleSaverJSON.value) return tip("Please provide a style JSON", false, "error");
|
const styleJSON = styleSaverJSON.value;
|
||||||
if (!JSON.isValid(styleSaverJSON.value)) return tip("JSON string is not valid, please check the format", false, "error");
|
const styleName = styleSaverName.value;
|
||||||
if (!styleSaverName.value) return tip("Please provide a preset name", false, "error");
|
|
||||||
|
|
||||||
const data = styleSaverJSON.value;
|
if (!styleJSON) return tip("Please provide a style JSON", false, "error");
|
||||||
if (!data) return tip("Please provide a style JSON", false, "error");
|
if (!JSON.isValid(styleJSON)) return tip("JSON string is not valid, please check the format", false, "error");
|
||||||
downloadFile(data, "style" + styleSaverName.value + ".json", "application/json");
|
if (!styleName) return tip("Please provide a preset name", false, "error");
|
||||||
|
|
||||||
|
downloadFile(styleJSON, styleName + ".json", "application/json");
|
||||||
}
|
}
|
||||||
|
|
||||||
function styleUpload(dataLoaded) {
|
function loadStyleFile() {
|
||||||
if (!dataLoaded) return tip("Cannot load the file. Please check the data format", false, "error");
|
const fileName = this.files[0]?.name.replace(/\.[^.]*$/, "");
|
||||||
const data = JSON.stringify(JSON.parse(dataLoaded), null, 2);
|
uploadFile(this, styleUpload);
|
||||||
styleSaverJSON.value = data;
|
|
||||||
|
function styleUpload(dataLoaded) {
|
||||||
|
if (!dataLoaded) return tip("Cannot load the file. Please check the data format", false, "error");
|
||||||
|
const isValid = JSON.isValid(dataLoaded);
|
||||||
|
if (!isValid) return tip("Loaded data is not a valid JSON, please check the format", false, "error");
|
||||||
|
|
||||||
|
styleSaverJSON.value = JSON.stringify(JSON.parse(dataLoaded), null, 2);
|
||||||
|
styleSaverName.value = fileName;
|
||||||
|
checkName();
|
||||||
|
tip("Style preset is uploaded", false, "success", 4000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeStylePreset() {
|
function requestRemoveStylePreset() {
|
||||||
const isDefault = defaultStyles.includes(stylePreset.value);
|
const isDefault = systemPresets.includes(stylePreset.value);
|
||||||
if (isDefault) return tip("Cannot remove system preset", false, "error");
|
if (isDefault) return tip("Cannot remove system preset", false, "error");
|
||||||
|
|
||||||
|
confirmationDialog({
|
||||||
|
title: "Remove style preset",
|
||||||
|
message: "Are you sure you want to remove the style preset? This action cannot be undone.",
|
||||||
|
confirm: "Remove",
|
||||||
|
onConfirm: removeStylePreset
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStylePreset() {
|
||||||
localStorage.removeItem("presetStyle");
|
localStorage.removeItem("presetStyle");
|
||||||
localStorage.removeItem(stylePreset.value);
|
localStorage.removeItem(stylePreset.value);
|
||||||
stylePreset.selectedOptions[0].remove();
|
stylePreset.selectedOptions[0].remove();
|
||||||
removeStyleButton.style.display = "none";
|
|
||||||
|
|
||||||
applyDefaultStyle();
|
changeStyle("default");
|
||||||
updateMapFilter();
|
|
||||||
invokeActiveZooming();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMapFilter() {
|
function updateMapFilter() {
|
||||||
|
|
@ -293,3 +304,8 @@ function updateMapFilter() {
|
||||||
if (!filter) return;
|
if (!filter) return;
|
||||||
mapFilters.querySelector("#" + filter).classList.add("pressed");
|
mapFilters.querySelector("#" + filter).classList.add("pressed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPresetRemoveButtonVisibiliy() {
|
||||||
|
const isDefault = systemPresets.includes(stylePreset.value);
|
||||||
|
removeStyleButton.style.display = isDefault ? "none" : "inline-block";
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue