// UI module to control the options (preferences)
'use strict';
$('#optionsContainer').draggable({handle: '.drag-trigger', snap: 'svg', snapMode: 'both'});
$('#exitCustomization').draggable({handle: 'div'});
$('#mapLayers').disableSelection();
// remove glow if tip is aknowledged
if (localStorage.getItem('disable_click_arrow_tooltip')) {
clearMainTip();
optionsTrigger.classList.remove('glow');
}
// Show options pane on trigger click
function showOptions(event) {
if (!localStorage.getItem('disable_click_arrow_tooltip')) {
clearMainTip();
localStorage.setItem('disable_click_arrow_tooltip', true);
optionsTrigger.classList.remove('glow');
}
regenerate.style.display = 'none';
document.getElementById('options').style.display = 'block';
optionsTrigger.style.display = 'none';
if (event) event.stopPropagation();
}
// Hide options pane on trigger click
function hideOptions(event) {
document.getElementById('options').style.display = 'none';
optionsTrigger.style.display = 'block';
if (event) event.stopPropagation();
}
// To toggle options on hotkey press
function toggleOptions(event) {
if (document.getElementById('options').style.display === 'none') showOptions(event);
else hideOptions(event);
}
// Toggle "New Map!" pane on hover
optionsTrigger.addEventListener('mouseenter', function () {
if (optionsTrigger.classList.contains('glow')) return;
if (document.getElementById('options').style.display === 'none') regenerate.style.display = 'block';
});
collapsible.addEventListener('mouseleave', function () {
regenerate.style.display = 'none';
});
// Activate options tab on click
document
.getElementById('options')
.querySelector('div.tab')
.addEventListener('click', function (event) {
if (event.target.tagName !== 'BUTTON') return;
const id = event.target.id;
const active = document.getElementById('options').querySelector('.tab > button.active');
if (active && id === active.id) return; // already active tab is clicked
if (active) active.classList.remove('active');
document.getElementById(id).classList.add('active');
document
.getElementById('options')
.querySelectorAll('.tabcontent')
.forEach((e) => (e.style.display = 'none'));
if (id === 'layersTab') layersContent.style.display = 'block';
else if (id === 'styleTab') styleContent.style.display = 'block';
else if (id === 'optionsTab') optionsContent.style.display = 'block';
else if (id === 'toolsTab') customization === 1 ? (customizationMenu.style.display = 'block') : (toolsContent.style.display = 'block');
else if (id === 'aboutTab') aboutContent.style.display = 'block';
});
// show popup with a list of Patreon supportes (updated manually, to be replaced with API call)
function showSupporters() {
const supporters = `Aaron Meyer,Ahmad Amerih,AstralJacks,aymeric,Billy Dean Goehring,Branndon Edwards,Chase Mayers,Curt Flood,cyninge,Dino Princip,
E.M. White,es,Fondue,Fritjof Olsson,Gatsu,Johan Fröberg,Jonathan Moore,Joseph Miranda,Kate,KC138,Luke Nelson,Markus Finster,Massimo Vella,Mikey,
Nathan Mitchell,Paavi1,Pat,Ryan Westcott,Sasquatch,Shawn Spencer,Sizz_TV,Timothée CALLET,UTG community,Vlad Tomash,Wil Sisney,William Merriott,
Xariun,Gun Metal Games,Scott Marner,Spencer Sherman,Valerii Matskevych,Alloyed Clavicle,Stewart Walsh,Ruthlyn Mollett (Javan),Benjamin Mair-Pratt,
Diagonath,Alexander Thomas,Ashley Wilson-Savoury,William Henry,Preston Brooks,JOSHUA QUALTIERI,Hilton Williams,Katharina Haase,Hisham Bedri,Ian arless,
Karnat,Bird,Kevin,Jessica Thomas,Steve Hyatt,Logicspren,Alfred García,Jonathan Killstring,John Ackley,Invad3r233,Norbert Žigmund,Jennifer,
PoliticsBuff,_gfx_,Maggie,Connor McMartin,Jared McDaris,BlastWind,Franc Casanova Ferrer,Dead & Devil,Michael Carmody,Valerie Elise,naikibens220,
Jordon Phillips,William Pucs,The Dungeon Masters,Brady R Rathbun,J,Shadow,Matthew Tiffany,Huw Williams,Joseph Hamilton,FlippantFeline,Tamashi Toh,
kms,Stephen Herron,MidnightMoon,Whakomatic x,Barished,Aaron bateson,Brice Moss,Diklyquill,PatronUser,Michael Greiner,Steven Bennett,Jacob Harrington,
Miguel C.,Reya C.,Giant Monster Games,Noirbard,Brian Drennen,Ben Craigie,Alex Smolin,Endwords,Joshua E Goodwin,SirTobit ,Allen S. Rout,Allen Bull Bear,
Pippa Mitchell,R K,G0atfather,Ryan Lege,Caner Oleas Pekgönenç,Bradley Edwards,Tertiary ,Austin Miller,Jesse Holmes,Jan Dvořák,Marten F,Erin D. Smale,
Maxwell Hill,Drunken_Legends,rob bee,Jesse Holmes,YYako,Detocroix,Anoplexian,Hannah,Paul,Sandra Krohn,Lucid,Richard Keating,Allen Varney,Rick Falkvinge,
Seth Fusion,Adam Butler,Gus,StroboWolf,Sadie Blackthorne,Zewen Senpai,Dell McKnight,Oneiris,Darinius Dragonclaw Studios,Christopher Whitney,Rhodes HvZ,
Jeppe Skov Jensen,María Martín López,Martin Seeger,Annie Rishor,Aram Sabatés,MadNomadMedia,Eric Foley,Vito Martono,James H. Anthony,Kevin Cossutta,
Thirty-OneR,ThatGuyGW,Dee Chiu,MontyBoosh,Achillain,Jaden,SashaTK,Steve Johnson,Pierrick Bertrand,Jared Kennedy,Dylan Devenny,Kyle Robertson,
Andrew Rostaing,Daniel Gill,Char,Jack,Barna Csíkos,Ian Rousseau,Nicholas Grabstas,Tom Van Orden jr,Bryan Brake,Akylos,Riley Seaman,MaxOliver,Evan-DiLeo,
Alex Debus,Joshua Vaught,Kyle S,Eric Moore,Dean Dunakin,Uniquenameosaurus,WarWizardGames,Chance Mena,Jan Ka,Miguel Alejandro,Dalton Clark,Simon Drapeau,
Radovan Zapletal,Jmmat6,Justa Badge,Blargh Blarghmoomoo,Vanessa Anjos,Grant A. Murray,Akirsop,Rikard Wolff,Jake Fish,teco 47,Antiroo,Jakob Siegel,
Guilherme Aguiar,Jarno Hallikainen,Justin Mcclain,Kristin Chernoff,Rowland Kingman,Esther Busch,Grayson McClead,Austin,Hakon the Viking,Chad Riley,
Cooper Counts,Patrick Jones,Clonetone,PlayByMail.Net,Brad Wardell,Lance Saba,Egoensis,Brea Richards,Tiber,Chris Bloom,Maxim Lowe,Aquelion,
Page One Project,Spencer Morris,Paul Ingram,Dust Bunny,Adrian Wright,Eric Alexander Cartaya,GameNight,Thomas Mortensen Hansen,Zklaus,Drinarius,
Ed Wright,Lon Varnadore,Crys Cain,Heaven N Lee,Jeffrey Henning,Lazer Elf,Jordan Bellah,Alex Beard,Kass Frisson,Petro Lombaard,Emanuel Pietri,Rox,
PinkEvil,Gavin Madrigal,Martin Lorber,Prince of Morgoth,Jaryd Armstrong,Andrew Pirkola,ThyHolyDevil,Gary Smith,Tyshaun Wise,Ethan Cook,Jon Stroman,
Nobody679,良义 金,Chris Gray,Phoenix Boatwright,Mackenzie,Milo Cohen,Jason Matthew Wuerfel,Rasmus Legêne,Andrew Hines,Wexxler,Espen Sæverud,Binks,
Dominick Ormsby,Linn Browning,Václav Švec,Alan Buehne,George J.Lekkas,Alexandre Boivin,Tommy Mayfield,Skylar Mangum-Turner,Karen Blythe,Stefan Gugerel,
Mike Conley,Xavier privé,Hope You're Well,Mark Sprietsma,Robert Landry,Nick Mowry,steve hall,Markell,Josh Wren,Neutrix,BLRageQuit,Rocky,
Dario Spadavecchia,Bas Kroot,John Patrick Callahan Jr,Alexandra Vesey,D`;
const array = supporters
.replace(/(?:\r\n|\r|\n)/g, '')
.split(',')
.map((v) => capitalize(v.trim()))
.sort();
alertMessage.innerHTML = "
" + array.map((n) => `
${n}
`).join('') + '
';
$('#alert').dialog({resizable: false, title: 'Patreon Supporters', width: '54vw', position: {my: 'center', at: 'center', of: 'svg'}});
}
// on any option or dialog change
document.getElementById('options').addEventListener('change', checkIfStored);
document.getElementById('dialogs').addEventListener('change', checkIfStored);
document.getElementById('options').addEventListener('input', updateOutputToFollowInput);
document.getElementById('dialogs').addEventListener('input', updateOutputToFollowInput);
function checkIfStored(ev) {
if (ev.target.dataset.stored) lock(ev.target.dataset.stored);
}
function updateOutputToFollowInput(ev) {
const id = ev.target.id;
const value = ev.target.value;
// specific cases
if (id === 'manorsInput') return (manorsOutput.value = value == 1000 ? 'auto' : value);
// generic case
if (id.slice(-5) === 'Input') {
const output = document.getElementById(id.slice(0, -5) + 'Output');
if (output) output.value = value;
} else if (id.slice(-6) === 'Output') {
const input = document.getElementById(id.slice(0, -6) + 'Input');
if (input) input.value = value;
}
}
// Option listeners
const optionsContent = document.getElementById('optionsContent');
optionsContent.addEventListener('input', function (event) {
const id = event.target.id;
const value = event.target.value;
<<<<<<< HEAD
if (id === 'mapWidthInput' || id === 'mapHeightInput') mapSizeInputChange();
else if (id === 'pointsInput') changeCellsDensity(+value);
else if (id === 'culturesSet') changeCultureSet();
else if (id === 'regionsInput' || id === 'regionsOutput') changeStatesNumber(value);
else if (id === 'emblemShape') changeEmblemShape(value);
else if (id === 'tooltipSizeInput' || id === 'tooltipSizeOutput') changeTooltipSize(value);
else if (id === 'transparencyInput') changeDialogsTransparency(value);
=======
if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange();
else if (id === "pointsInput") changeCellsDensity(+value);
else if (id === "culturesSet") changeCultureSet();
else if (id === "regionsInput" || id === "regionsOutput") changeStatesNumber(value);
else if (id === "emblemShape") changeEmblemShape(value);
else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value);
else if (id === "themeHueInput") changeThemeHue(value);
else if (id === "themeColorInput") changeDialogsTheme(themeColorInput.value, transparencyInput.value);
else if (id === "transparencyInput") changeDialogsTheme(themeColorInput.value, value);
>>>>>>> master
});
optionsContent.addEventListener('change', function (event) {
const id = event.target.id;
const value = event.target.value;
<<<<<<< HEAD
if (id === 'zoomExtentMin' || id === 'zoomExtentMax') changeZoomExtent(value);
else if (id === 'optionsSeed') generateMapWithSeed();
else if (id === 'uiSizeInput' || id === 'uiSizeOutput') changeUIsize(value);
if (id === 'shapeRendering') viewbox.attr('shape-rendering', value);
else if (id === 'yearInput') changeYear();
else if (id === 'eraInput') changeEra();
=======
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
else if (id === "optionsSeed") generateMapWithSeed("seed change");
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value);
if (id === "shapeRendering") viewbox.attr("shape-rendering", value);
else if (id === "yearInput") changeYear();
else if (id === "eraInput") changeEra();
else if (id === "stateLabelsModeInput") options.stateLabelsMode = value;
>>>>>>> master
});
optionsContent.addEventListener('click', function (event) {
const id = event.target.id;
<<<<<<< HEAD
if (id === 'toggleFullscreen') toggleFullscreen();
else if (id === 'optionsSeedGenerate') generateMapWithSeed();
else if (id === 'optionsMapHistory') showSeedHistoryDialog();
else if (id === 'optionsCopySeed') copyMapURL();
else if (id === 'optionsEraRegenerate') regenerateEra();
else if (id === 'zoomExtentDefault') restoreDefaultZoomExtent();
else if (id === 'translateExtent') toggleTranslateExtent(event.target);
else if (id === 'speakerTest') testSpeaker();
=======
if (id === "toggleFullscreen") toggleFullscreen();
else if (id === "optionsMapHistory") showSeedHistoryDialog();
else if (id === "optionsCopySeed") copyMapURL();
else if (id === "optionsEraRegenerate") regenerateEra();
else if (id === "zoomExtentDefault") restoreDefaultZoomExtent();
else if (id === "translateExtent") toggleTranslateExtent(event.target);
else if (id === "speakerTest") testSpeaker();
else if (id === "themeColorRestore") restoreDefaultThemeColor();
>>>>>>> master
});
function mapSizeInputChange() {
changeMapSize();
localStorage.setItem('mapWidth', mapWidthInput.value);
localStorage.setItem('mapHeight', mapHeightInput.value);
}
// change svg size on manual size change or window resize, do not change graph size
function changeMapSize() {
svgWidth = Math.min(+mapWidthInput.value, window.innerWidth);
svgHeight = Math.min(+mapHeightInput.value, window.innerHeight);
svg.attr('width', svgWidth).attr('height', svgHeight);
const maxWidth = Math.max(+mapWidthInput.value, graphWidth);
const maxHeight = Math.max(+mapHeightInput.value, graphHeight);
zoom.translateExtent([
[0, 0],
[maxWidth, maxHeight]
]);
landmass.select('rect').attr('x', 0).attr('y', 0).attr('width', maxWidth).attr('height', maxHeight);
oceanPattern.select('rect').attr('x', 0).attr('y', 0).attr('width', maxWidth).attr('height', maxHeight);
oceanLayers.select('rect').attr('x', 0).attr('y', 0).attr('width', maxWidth).attr('height', maxHeight);
fogging.selectAll('rect').attr('x', 0).attr('y', 0).attr('width', maxWidth).attr('height', maxHeight);
defs.select('mask#fog > rect').attr('width', maxWidth).attr('height', maxHeight);
texture.select('image').attr('width', maxWidth).attr('height', maxHeight);
fitScaleBar();
if (window.fitLegendBox) fitLegendBox();
}
// just apply canvas size that was already set
function applyMapSize() {
const zoomMin = +zoomExtentMin.value;
const zoomMax = +zoomExtentMax.value;
graphWidth = +mapWidthInput.value;
graphHeight = +mapHeightInput.value;
svgWidth = Math.min(graphWidth, window.innerWidth);
svgHeight = Math.min(graphHeight, window.innerHeight);
svg.attr('width', svgWidth).attr('height', svgHeight);
zoom
.translateExtent([
[0, 0],
[graphWidth, graphHeight]
])
.scaleExtent([zoomMin, zoomMax])
.scaleTo(svg, zoomMin);
}
function toggleFullscreen() {
if (mapWidthInput.value != window.innerWidth || mapHeightInput.value != window.innerHeight) {
mapWidthInput.value = window.innerWidth;
mapHeightInput.value = window.innerHeight;
localStorage.removeItem('mapHeight');
localStorage.removeItem('mapWidth');
} else {
mapWidthInput.value = graphWidth;
mapHeightInput.value = graphHeight;
}
changeMapSize();
}
function toggleTranslateExtent(el) {
const on = (el.dataset.on = +!+el.dataset.on);
if (on)
zoom.translateExtent([
[-graphWidth / 2, -graphHeight / 2],
[graphWidth * 1.5, graphHeight * 1.5]
]);
else
zoom.translateExtent([
[0, 0],
[graphWidth, graphHeight]
]);
}
// add voice options
const voiceInterval = setInterval(function () {
const voices = speechSynthesis.getVoices();
if (voices.length) clearInterval(voiceInterval);
else return;
const select = document.getElementById('speakerVoice');
voices.forEach((voice, i) => {
select.options.add(new Option(voice.name, i, false));
});
if (stored('speakerVoice')) select.value = localStorage.getItem('speakerVoice');
// se voice to store
else select.value = voices.findIndex((voice) => voice.lang === 'en-US'); // or to first found English-US
}, 1000);
function testSpeaker() {
const text = `${mapName.value}, ${options.year} ${options.era}`;
const speaker = new SpeechSynthesisUtterance(text);
const voices = speechSynthesis.getVoices();
if (voices.length) {
const voiceId = +document.getElementById('speakerVoice').value;
speaker.voice = voices[voiceId];
}
speechSynthesis.speak(speaker);
}
<<<<<<< HEAD
function generateMapWithSeed() {
if (optionsSeed.value == seed) {
tip('The current map already has this seed', false, 'error');
return;
}
regeneratePrompt();
=======
function generateMapWithSeed(source) {
if (optionsSeed.value == seed) return tip("The current map already has this seed", false, "error");
regeneratePrompt(source);
>>>>>>> master
}
function showSeedHistoryDialog() {
const alert = mapHistory
.map(function (h, i) {
const created = new Date(h.created).toLocaleTimeString();
const button = ``;
return `