dropbox - import changes from alpha

This commit is contained in:
Azgaar 2021-09-01 21:33:49 +03:00
parent 7865497cd2
commit c783301de9
7 changed files with 208 additions and 129 deletions

View file

@ -358,14 +358,11 @@ div.tab > button#optionsHide {
} }
#options { #options {
margin: 10px;
font-family: Consolas, monospace;
position: absolute; position: absolute;
font-family: Consolas, monospace;
border: solid 1px #5e4fa2; border: solid 1px #5e4fa2;
width: 300px; margin: 10px;
background-position: center; padding-bottom: 0.3em;
background-size: cover;
background-blend-mode: color-dodge;
} }
#options input, #options input,
@ -576,14 +573,16 @@ input[type="color"]::-webkit-color-swatch-wrapper {
padding-left: 2.5px; padding-left: 2.5px;
} }
#sticked {
display: flex;
justify-content: space-evenly;
width: 100%;
}
#sticked button { #sticked button {
background-color: #997c8900; background-color: transparent;
padding: 0;
margin-bottom: 2px;
width: 22%;
font-size: 1em;
border: 0;
font-weight: bold; font-weight: bold;
border: 0;
} }
#sticked button:hover { #sticked button:hover {

View file

@ -1447,11 +1447,11 @@
<div id="sticked"> <div id="sticked">
<button id="newMapButton" data-tip="Generate a new map based on options. Shortcut: F2">New Map</button> <button id="newMapButton" data-tip="Generate a new map based on options. Shortcut: F2">New Map</button>
<button id="saveButton" data-tip="Select format to save map">Save</button> <button id="exportButton" data-tip="Select format to download image or export map data">Export</button>
<button id="loadButton" data-tip="Load fully functional map in a .map format">Load</button> <button id="saveButton" data-tip="Save fully-functional map in .map format">Save</button>
<button id="loadButton" data-tip="Load fully-functional map in .map format">Load</button>
<button id="zoomReset" data-tip="Reset map zoom. Shortcut: 0">Reset Zoom</button> <button id="zoomReset" data-tip="Reset map zoom. Shortcut: 0">Reset Zoom</button>
</div> </div>
</div> </div>
</div> </div>
@ -3447,36 +3447,66 @@
</div> </div>
</div> </div>
<div id="preview3d" class="dialog stable" style="display: none; padding: 0px"></div> <div id="preview3d" class="dialog stable" style="display: none; padding: 0px" />
<div id="saveMapData" style="display: none" class="dialog"> <div id="exportMapData" style="display: none" class="dialog">
<div style="margin-bottom: .3em; font-weight: bold">Please select saving method:</div> <div style="margin-bottom: .3em; font-weight: bold">Download image</div>
<div> <div>
<button onclick="saveMap()" data-tip="Download the project in internal .map format (reliable). Then open via 'Load' in menu. Shortcut: Ctrl + S">.map</button> <button onclick="saveSVG()" data-tip="Download the map as vector image (open directly in browser or Inkscape)">.svg</button>
<button onclick="saveSVG()" data-tip="Download the map as vector image (open in browser or Inkscape)">.svg</button>
<button onclick="savePNG()" data-tip="Download visible part of the map as .png (lossless compressed)">.png</button> <button onclick="savePNG()" data-tip="Download visible part of the map as .png (lossless compressed)">.png</button>
<button onclick="saveJPEG()" data-tip="Download visible part of the map as .jpeg (lossy compressed) image">.jpeg</button> <button onclick="saveJPEG()" data-tip="Download visible part of the map as .jpeg (lossy compressed) image">.jpeg</button>
<button onclick="openSaveTiles()" data-tip="Split map into smaller png tiles and download as zip archive">tiles</button> <button onclick="openSaveTiles()" data-tip="Split map into smaller png tiles and download as zip archive">tiles</button>
<button onclick="saveGeoJSON()" data-tip="Download map data in GeoJSON format">.json</button> <span data-tip="Check to not allow system to automatically hide labels">
<button onclick="quickSave()" data-tip="Save the project to browser storage (unreliable). Shortcut: F6">storage</button> <input id="showLabels" class="checkbox" type="checkbox" onchange="hideLabels.checked = !this.checked; invokeActiveZooming()" checked="">
<label for="showLabels" class="checkbox-label">Show all labels</label>
</span>
</div> </div>
<p style="font-style: italic">Keep noted that the only reliable project saving method is having .map file stored on your machine. There is no way to restore map if .map file is lost. We don't keep any data on our side.</p>
<p style="font-style: italic">Generator uses pop-up window to download files. Please ensure your browser does not block popups.</p>
<div data-tip="Define scale of a saved png/jpeg image (e.g. 5x). Saving big images is slow and may cause a browser crash!" style="margin-bottom: .3em"> <div data-tip="Define scale of a saved png/jpeg image (e.g. 5x). Saving big images is slow and may cause a browser crash!" style="margin-bottom: .3em">
PNG / JPEG scale: PNG / JPEG scale:
<input id="pngResolutionInput" data-stored="pngResolution" type="range" min=1 max=8 value=1 style="width: 14em"> <input id="pngResolutionInput" data-stored="pngResolution" type="range" min=1 max=8 value=1 style="width: 10em">
<input id="pngResolutionOutput" data-stored="pngResolution" type="number" min=1 max=8 value=1> <input id="pngResolutionOutput" data-stored="pngResolution" type="number" min=1 max=8 value=1>
</div> </div>
<div data-tip="Check to not allow system to automatically hide labels">
<input id="showLabels" class="checkbox" type="checkbox" onchange="hideLabels.checked = !this.checked; invokeActiveZooming()" checked=""> <div style="margin: 1em 0 .3em; font-weight: bold">Export to GeoJSON</div>
<label for="showLabels" class="checkbox-label">Show all labels</label> <div>
<button onclick="saveGeoJSON_Cells()" data-tip="Download cells data in GeoJSON format">cells</button>
<button onclick="saveGeoJSON_Routes()" data-tip="Download routes data in GeoJSON format">routes</button>
<button onclick="saveGeoJSON_Rivers()" data-tip="Download rivers data in GeoJSON format">rivers</button>
<button onclick="saveGeoJSON_Markers()" data-tip="Download markers data in GeoJSON format">markers</button>
</div>
<p style="font-style: italic">GeoJSON format is used in GIS tools such as QGIS. Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance</p>
<p style="font-style: italic">Generator uses pop-up window to download files. Please ensure your browser does not block popups.</p>
<p style="font-style: italic">It's also possible to export map to Foundry VTT, see <a href="https://github.com/Ethck/azgaar-foundry" target="_blank">the module.</a></p>
</div>
<div id="saveMapData" style="display: none" class="dialog">
<div style="margin-top: .3em">
<strong>Save map to</strong>
<button onclick="dowloadMap()" data-tip="Download .map file to your local disk. Shortcut: Ctrl + S">machine</button>
<button onclick="saveToDropbox()" data-tip="Save .map file to your Dropbox">dropbox</button>
<button onclick="quickSave()" data-tip="Save the project to browser storage (quick save). It can be unreliable. Shortcut: F6">browser</button>
</div>
<p style="font-style: italic">Maps are saved in <i>.map</i> format, that can be loaded back via 'Load' in menu. Please keep noted that we do not keep any data on our side. There is no way to restore the progress if .map file is lost. Please keep old .map files on your machine or cloud storage as backups.</p>
<p style="font-style: italic">Saving to Dropbox may not be allowed for big files. In this case open <a href="https://www.dropbox.com/home/FMG" target="_blank">Dropbox</a>, download the .map file and upload it manually.</p>
<div style="margin-top: .3em" data-tip="Select .map file on dropbox and share a sharable link">
<strong>Create sharable link</strong>
<button onclick="createSharableDropboxLink()">select file</button>
<div id="sharableLinkContainer" style="display: none">
<a id="sharableLink" target="_blank"></a>
<i data-tip="Copy link to the clipboard" onclick="copyLinkToClickboard()" class="icon-clone pointer"></i>
</div>
</div> </div>
</div> </div>
<div id="loadMapData" style="display: none" class="dialog"> <div id="loadMapData" style="display: none" class="dialog">
<div style="margin-bottom: .3em">Load map from:</div> <div style="margin-bottom: .3em">Load map from</div>
<div> <div>
<button onclick="mapToLoad.click()" data-tip="Load .map file from local disk">local disk</button> <button onclick="mapToLoad.click()" data-tip="Load .map file from local disk">local disk</button>
<button onclick="loadFromDropbox()" data-tip="Load .map file from your Dropbox">Dropbox</button>
<button onclick="loadURL()" data-tip="Load .map file from URL (server should allow CORS)">URL</button> <button onclick="loadURL()" data-tip="Load .map file from URL (server should allow CORS)">URL</button>
<button onclick="quickLoad()" data-tip="Load map from browser storage (if saved before)">storage</button> <button onclick="quickLoad()" data-tip="Load map from browser storage (if saved before)">storage</button>
</div> </div>
@ -4265,5 +4295,6 @@
<script defer src="libs/jquery.ui.touch-punch.min.js"></script> <script defer src="libs/jquery.ui.touch-punch.min.js"></script>
<script defer src="libs/pell.min.js"></script> <script defer src="libs/pell.min.js"></script>
<script defer src="libs/jszip.min.js"></script> <script defer src="libs/jszip.min.js"></script>
<script defer src="https://www.dropbox.com/static/api/2/dropins.js" id="dropboxjs" data-app-key="pdr9ae64ip0qno4"></script>
</body> </body>
</html> </html>

31
main.js
View file

@ -219,37 +219,6 @@ void (function checkLoadParameters() {
generateMapOnLoad(); generateMapOnLoad();
})(); })();
function loadMapFromURL(maplink, random) {
const URL = decodeURIComponent(maplink);
fetch(URL, {method: "GET", mode: "cors"})
.then(response => {
if (response.ok) return response.blob();
throw new Error("Cannot load map from URL");
})
.then(blob => uploadMap(blob))
.catch(error => {
showUploadErrorMessage(error.message, URL, random);
if (random) generateMapOnLoad();
});
}
function showUploadErrorMessage(error, URL, random) {
ERROR && console.error(error);
alertMessage.innerHTML = `Cannot load map from the ${link(URL, "link provided")}.
${random ? `A new random map is generated. ` : ""}
Please ensure the linked file is reachable and CORS is allowed on server side`;
$("#alert").dialog({
title: "Loading error",
width: "32em",
buttons: {
OK: function () {
$(this).dialog("close");
}
}
});
}
function generateMapOnLoad() { function generateMapOnLoad() {
applyStyleOnLoad(); // apply default of previously selected style applyStyleOnLoad(); // apply default of previously selected style
generate(); // generate map generate(); // generate map

View file

@ -12,6 +12,18 @@ function quickLoad() {
}); });
} }
function loadFromDropbox() {
const options = {
success: function (files) {
const url = files[0].link;
loadMapFromURL(url);
},
linkType: "direct",
extensions: [".map"]
};
Dropbox.choose(options);
}
function loadMapPrompt(blob) { function loadMapPrompt(blob) {
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
if (workingTime < 5) { if (workingTime < 5) {
@ -46,6 +58,37 @@ function loadMapPrompt(blob) {
} }
} }
function loadMapFromURL(maplink, random) {
const URL = decodeURIComponent(maplink);
fetch(URL, {method: "GET", mode: "cors"})
.then(response => {
if (response.ok) return response.blob();
throw new Error("Cannot load map from URL");
})
.then(blob => uploadMap(blob))
.catch(error => {
showUploadErrorMessage(error.message, URL, random);
if (random) generateMapOnLoad();
});
}
function showUploadErrorMessage(error, URL, random) {
ERROR && console.error(error);
alertMessage.innerHTML = `Cannot load map from the ${link(URL, "link provided")}.
${random ? `A new random map is generated. ` : ""}
Please ensure the linked file is reachable and CORS is allowed on server side`;
$("#alert").dialog({
title: "Loading error",
width: "32em",
buttons: {
OK: function () {
$(this).dialog("close");
}
}
});
}
function uploadMap(file, callback) { function uploadMap(file, callback) {
uploadMap.timeStart = performance.now(); uploadMap.timeStart = performance.now();
@ -54,14 +97,12 @@ function uploadMap(file, callback) {
if (callback) callback(); if (callback) callback();
document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
const dataLoaded = fileLoadedEvent.target.result; const result = fileLoadedEvent.target.result;
const dataLoaded = last(result) === "=" ? decodeURIComponent(atob(result)) : result; // map can be encoded base64
const data = dataLoaded.split("\r\n"); const data = dataLoaded.split("\r\n");
const mapVersion = data[0].split("|")[0] || data[0]; const mapVersion = data[0].split("|")[0] || data[0];
if (mapVersion === version) { if (mapVersion === version) return parseLoadedData(data);
parseLoadedData(data);
return;
}
const archive = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog", "archived version"); const archive = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog", "archived version");
const parsed = parseFloat(mapVersion); const parsed = parseFloat(mapVersion);

View file

@ -367,68 +367,65 @@ function inlineStyle(clone) {
// prepare map data for saving // prepare map data for saving
function getMapData() { function getMapData() {
TIME && console.time("createMapDataBlob"); TIME && console.time("createMapData");
return new Promise(resolve => { const date = new Date();
const date = new Date(); const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator"; const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|");
const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|"); const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].join("|");
const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].join("|"); const coords = JSON.stringify(mapCoordinates);
const coords = JSON.stringify(mapCoordinates); const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|"); const notesData = JSON.stringify(notes);
const notesData = JSON.stringify(notes); const rulersString = rulers.toString();
const rulersString = rulers.toString();
// clone svg // save svg
const cloneEl = document.getElementById("map").cloneNode(true); const cloneEl = document.getElementById("map").cloneNode(true);
// set transform values to default // reset transform values to default
cloneEl.setAttribute("width", graphWidth); cloneEl.setAttribute("width", graphWidth);
cloneEl.setAttribute("height", graphHeight); cloneEl.setAttribute("height", graphHeight);
cloneEl.querySelector("#viewbox").removeAttribute("transform"); cloneEl.querySelector("#viewbox").removeAttribute("transform");
// always remove rulers cloneEl.querySelector("#ruler").innerHTML = ""; // always remove rulers
cloneEl.querySelector("#ruler").innerHTML = "";
const svg_xml = new XMLSerializer().serializeToString(cloneEl); const serializedSVG = new XMLSerializer().serializeToString(cloneEl);
const gridGeneral = JSON.stringify({spacing: grid.spacing, cellsX: grid.cellsX, cellsY: grid.cellsY, boundary: grid.boundary, points: grid.points, features: grid.features}); const {spacing, cellsX, cellsY, boundary, points, features} = grid;
const features = JSON.stringify(pack.features); const gridGeneral = JSON.stringify({spacing, cellsX, cellsY, boundary, points, features});
const cultures = JSON.stringify(pack.cultures); const packFeatures = JSON.stringify(pack.features);
const states = JSON.stringify(pack.states); const cultures = JSON.stringify(pack.cultures);
const burgs = JSON.stringify(pack.burgs); const states = JSON.stringify(pack.states);
const religions = JSON.stringify(pack.religions); const burgs = JSON.stringify(pack.burgs);
const provinces = JSON.stringify(pack.provinces); const religions = JSON.stringify(pack.religions);
const rivers = JSON.stringify(pack.rivers); const provinces = JSON.stringify(pack.provinces);
const rivers = JSON.stringify(pack.rivers);
// store name array only if it is not the same as default // store name array only if not the same as default
const defaultNB = Names.getNameBases(); const defaultNB = Names.getNameBases();
const namesData = nameBases const namesData = nameBases
.map((b, i) => { .map((b, i) => {
const names = defaultNB[i] && defaultNB[i].b === b.b ? "" : b.b; const names = defaultNB[i] && defaultNB[i].b === b.b ? "" : b.b;
return `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${names}`; return `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${names}`;
}) })
.join("/"); .join("/");
// round population to save resources // round population to save space
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4)); const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
// data format as below // data format as below
const data = [params, settings, coords, biomes, notesData, svg_xml, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, features, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString].join("\r\n"); const mapData = [params, settings, coords, biomes, notesData, serializedSVG, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, packFeatures, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString].join("\r\n");
const blob = new Blob([data], {type: "text/plain"}); TIME && console.timeEnd("createMapData");
return mapData;
TIME && console.timeEnd("createMapDataBlob");
resolve(blob);
});
} }
// Download .map file // Download .map file
async function saveMap() { function dowloadMap() {
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
closeDialogs("#alert"); closeDialogs("#alert");
const blob = await getMapData(); const mapData = getMapData();
const blob = new Blob([mapData], {type: "text/plain"});
const URL = window.URL.createObjectURL(blob); const URL = window.URL.createObjectURL(blob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = getFileName() + ".map"; link.download = getFileName() + ".map";
@ -438,6 +435,44 @@ async function saveMap() {
window.URL.revokeObjectURL(URL); window.URL.revokeObjectURL(URL);
} }
function saveToDropbox() {
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
closeDialogs("#alert");
const mapData = getMapData();
const URL = "data:text/plain; base64," + btoa(encodeURIComponent(mapData));
const filename = getFileName() + ".map";
const options = {
success: () => tip("Map is saved to your Dropbox", true, "success", 8000),
error: function (errorMessage) {
tip("Cannot save .map to your Dropbox", true, "error", 8000);
console.error(errorMessage);
}
};
Dropbox.save(URL, filename, options);
}
function createSharableDropboxLink() {
const sharableLink = document.getElementById("sharableLink");
const sharableLinkContainer = document.getElementById("sharableLinkContainer");
const options = {
success: function (files) {
const url = files[0].link;
const fmg = window.location.href.split("?")[0];
const link = `${fmg}/?maplink=${url}`;
const shortLink = link.slice(0, 50) + "...";
sharableLinkContainer.style.display = "block";
sharableLink.innerText = shortLink;
sharableLink.setAttribute("href", link);
},
linkType: "direct",
extensions: [".map"]
};
Dropbox.choose(options);
}
function saveGeoJSON_Cells() { function saveGeoJSON_Cells() {
const json = {type: "FeatureCollection", features: []}; const json = {type: "FeatureCollection", features: []};
const cells = pack.cells; const cells = pack.cells;
@ -556,9 +591,11 @@ function getRiverPoints(node) {
return points; return points;
} }
async function quickSave() { function quickSave() {
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
const blob = await getMapData();
const mapData = getMapData();
const blob = new Blob([mapData], {type: "text/plain"});
if (blob) ldb.set("lastMap", blob); // auto-save map if (blob) ldb.set("lastMap", blob); // auto-save map
tip("Map is saved to browser memory. Please also save as .map file to secure progress", true, "success", 2000); tip("Map is saved to browser memory. Please also save as .map file to secure progress", true, "success", 2000);
} }

View file

@ -7,7 +7,7 @@ function editHeightmap() {
<p><i>Erase</i> mode also allows you Convert an Image into a heightmap or use Template Editor.</p> <p><i>Erase</i> mode also allows you Convert an Image into a heightmap or use Template Editor.</p>
<p>You can <i>keep</i> the data, but you won't be able to change the coastline.</p> <p>You can <i>keep</i> the data, but you won't be able to change the coastline.</p>
<p>Try <i>risk</i> mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors.</p> <p>Try <i>risk</i> mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors.</p>
<p>Please <span class="pseudoLink" onclick=saveMap(); editHeightmap();>save the map</span> before editing the heightmap!</p> <p>Please <span class="pseudoLink" onclick=dowloadMap(); editHeightmap();>save the map</span> before editing the heightmap!</p>
<p>Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.</p>`; <p>Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.</p>`;
$("#alert").dialog({ $("#alert").dialog({

View file

@ -621,6 +621,7 @@ document.getElementById("sticked").addEventListener("click", function (event) {
const id = event.target.id; const id = event.target.id;
if (id === "newMapButton") regeneratePrompt(); if (id === "newMapButton") regeneratePrompt();
else if (id === "saveButton") showSavePane(); else if (id === "saveButton") showSavePane();
else if (id === "exportButton") showExportPane();
else if (id === "loadButton") showLoadPane(); else if (id === "loadButton") showLoadPane();
else if (id === "zoomReset") resetZoom(1000); else if (id === "zoomReset") resetZoom(1000);
}); });
@ -654,12 +655,13 @@ function regeneratePrompt() {
} }
function showSavePane() { function showSavePane() {
document.getElementById("showLabels").checked = !hideLabels.checked; const sharableLinkContainer = document.getElementById("sharableLinkContainer");
sharableLinkContainer.style.display = "none";
$("#saveMapData").dialog({ $("#saveMapData").dialog({
title: "Save map", title: "Save map",
resizable: false, resizable: false,
width: "30em", width: "27em",
position: {my: "center", at: "center", of: "svg"}, position: {my: "center", at: "center", of: "svg"},
buttons: { buttons: {
Close: function () { Close: function () {
@ -669,21 +671,21 @@ function showSavePane() {
}); });
} }
// download map data as GeoJSON function copyLinkToClickboard() {
function saveGeoJSON() { const shrableLink = document.getElementById("sharableLink");
alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS. const link = shrableLink.getAttribute("href");
Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export", "wiki-page")} for guidance`; navigator.clipboard.writeText(link).then(() => tip("Link is copied to the clipboard", true, "success", 8000));
}
$("#alert").dialog({ function showExportPane() {
title: "GIS data export", document.getElementById("showLabels").checked = !hideLabels.checked;
$("#exportMapData").dialog({
title: "Export map data",
resizable: false, resizable: false,
width: "35em", width: "26em",
position: {my: "center", at: "center", of: "svg"}, position: {my: "center", at: "center", of: "svg"},
buttons: { buttons: {
Cells: saveGeoJSON_Cells,
Routes: saveGeoJSON_Routes,
Rivers: saveGeoJSON_Rivers,
Markers: saveGeoJSON_Markers,
Close: function () { Close: function () {
$(this).dialog("close"); $(this).dialog("close");
} }
@ -695,7 +697,7 @@ function showLoadPane() {
$("#loadMapData").dialog({ $("#loadMapData").dialog({
title: "Load map", title: "Load map",
resizable: false, resizable: false,
width: "17em", width: "22em",
position: {my: "center", at: "center", of: "svg"}, position: {my: "center", at: "center", of: "svg"},
buttons: { buttons: {
Close: function () { Close: function () {