break up script into 4 smaller refactor scripts preparing it to be ported to modular library leveraing vuejs

This commit is contained in:
headwinds 2018-10-07 19:44:48 -04:00
parent f5c507a94b
commit a931013f3c
42 changed files with 39294 additions and 0 deletions

997
vue/public/refactor-two.js Normal file
View file

@ -0,0 +1,997 @@
function addRoutePoint(point) {
const controlPoints = debug.select(".controlPoints").size()
? debug.select(".controlPoints")
: debug.append("g").attr("class", "controlPoints");
controlPoints.append("circle")
.attr("cx", point.x).attr("cy", point.y).attr("r", 0.35)
.call(d3.drag().on("drag", routePointDrag))
.on("click", function(d) {
if ($("#routeSplit").hasClass('pressed')) {
routeSplitInPoint(this);
} else {
$(this).remove();
routeRedraw();
}
});
}
function routePointDrag() {
d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y);
routeRedraw();
}
function routeRedraw() {
let points = [];
debug.select(".controlPoints").selectAll("circle").each(function() {
const el = d3.select(this);
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
});
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
elSelected.attr("d", lineGen(points));
// get route distance
const l = elSelected.node().getTotalLength();
routeLength.innerHTML = rn(l * distanceScale.value) + " " + distanceUnit.value;
}
function addNewRoute() {
let routeType = elSelected && elSelected.node() ? elSelected.node().parentNode.id : "searoutes";
const group = routes.select("#"+routeType);
const id = routeType + "" + group.selectAll("*").size();
elSelected = group.append("path").attr("data-route", "new").attr("id", id).on("click", editRoute);
routeUpdateGroups();
$("#routeEditor").dialog({
title: "Edit Route", minHeight: 30, width: "auto", resizable: false,
close: function() {
if ($("#addRoute").hasClass('pressed')) completeNewRoute();
if ($("#routeSplit").hasClass('pressed')) $("#routeSplit").removeClass('pressed');
unselect();
}
});
}
function newRouteAddPoint() {
const point = d3.mouse(this);
const x = rn(point[0],2), y = rn(point[1],2);
addRoutePoint({x, y});
routeRedraw();
}
function completeNewRoute() {
$("#routeNew, #addRoute").removeClass('pressed');
restoreDefaultEvents();
if (!elSelected.size()) return;
if (elSelected.attr("data-route") === "new") {
routeRedraw();
elSelected.attr("data-route", "");
const node = elSelected.node();
const l = node.getTotalLength();
let pathCells = [];
for (let i = 0; i <= l; i ++) {
const p = node.getPointAtLength(i);
const cell = diagram.find(p.x, p.y);
if (!cell) {return;}
pathCells.push(cell.index);
}
const uniqueCells = [...new Set(pathCells)];
uniqueCells.map(function(c) {
if (cells[c].path !== undefined) {cells[c].path += 1;}
else {cells[c].path = 1;}
});
}
tip("", true);
}
function routeUpdateGroups() {
routeGroup.innerHTML = "";
routes.selectAll("g").each(function() {
const opt = document.createElement("option");
opt.value = opt.innerHTML = this.id;
routeGroup.add(opt);
});
}
function routeSplitInPoint(clicked) {
const group = d3.select(elSelected.node().parentNode);
$("#routeSplit").removeClass('pressed');
const points1 = [],points2 = [];
let points = points1;
debug.select(".controlPoints").selectAll("circle").each(function() {
const el = d3.select(this);
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
if (this === clicked) {
points = points2;
points.push({scX: +el.attr("cx"), scY: +el.attr("cy")});
}
el.remove();
});
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
elSelected.attr("d", lineGen(points1));
const id = routeGroup.value + "" + group.selectAll("*").size();
group.append("path").attr("id", id).attr("d", lineGen(points2)).on("click", editRoute);
routeDrawPoints();
}
$("#routeGroup").change(function() {
$(elSelected.node()).detach().appendTo($("#"+this.value));
});
// open legendsEditor
document.getElementById("routeLegend").addEventListener("click", function() {
let id = elSelected.attr("id");
editLegends(id, id);
});
$("#routeNew").click(function() {
if ($(this).hasClass('pressed')) {
completeNewRoute();
} else {
// enter creation mode
$(".pressed").removeClass('pressed');
$("#routeNew, #addRoute").addClass('pressed');
debug.select(".controlPoints").selectAll("*").remove();
addNewRoute();
viewbox.style("cursor", "crosshair").on("click", newRouteAddPoint);
tip("Click on map to add route point", true);
}
});
$("#routeRemove").click(function() {
alertMessage.innerHTML = `Are you sure you want to remove the route?`;
$("#alert").dialog({resizable: false, title: "Remove route",
buttons: {
Remove: function() {
$(this).dialog("close");
elSelected.remove();
$("#routeEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
})
});
}
function editIcon() {
if (customization) return;
if (elSelected) if (this.isSameNode(elSelected.node())) return;
unselect();
closeDialogs("#iconEditor, .stable");
elSelected = d3.select(this).call(d3.drag().on("start", elementDrag)).classed("draggable", true);
// update group parameters
const group = d3.select(this.parentNode);
iconUpdateGroups();
iconGroup.value = group.attr("id");
iconFillColor.value = group.attr("fill");
iconStrokeColor.value = group.attr("stroke");
iconSize.value = group.attr("size");
iconStrokeWidth.value = group.attr("stroke-width");
$("#iconEditor").dialog({
title: "Edit icon: " + group.attr("id"),
minHeight: 30, width: "auto", resizable: false,
position: {my: "center top+20", at: "top", of: d3.event},
close: unselect
});
if (modules.editIcon) {return;}
modules.editIcon = true;
$("#iconGroups").click(function() {
$("#iconEditor > button").not(this).toggle();
$("#iconGroupsSelection").toggle();
});
function iconUpdateGroups() {
iconGroup.innerHTML = "";
const anchor = group.attr("id").includes("anchor");
icons.selectAll("g").each(function(d) {
const id = d3.select(this).attr("id");
if (id === "burgs") return;
if (!anchor && id.includes("anchor")) return;
if (anchor && !id.includes("anchor")) return;
const opt = document.createElement("option");
opt.value = opt.innerHTML = id;
iconGroup.add(opt);
});
}
$("#iconGroup").change(function() {
const newGroup = this.value;
const to = $("#icons > #"+newGroup);
$(elSelected.node()).detach().appendTo(to);
});
$("#iconCopy").click(function() {
const group = d3.select(elSelected.node().parentNode);
const copy = elSelected.node().cloneNode();
copy.removeAttribute("data-id"); // remove assignment to burg if any
const tr = parseTransform(copy.getAttribute("transform"));
const shift = 10 / Math.sqrt(scale);
let transform = "translate(" + rn(tr[0] - shift, 1) + "," + rn(tr[1] - shift, 1) + ")";
for (let i=2; group.selectAll("[transform='" + transform + "']").size() > 0; i++) {
transform = "translate(" + rn(tr[0] - shift * i, 1) + "," + rn(tr[1] - shift * i, 1) + ")";
}
copy.setAttribute("transform", transform);
group.node().insertBefore(copy, null);
copy.addEventListener("click", editIcon);
});
$("#iconRemoveGroup").click(function() {
const group = d3.select(elSelected.node().parentNode);
const count = group.selectAll("*").size();
if (count < 2) {
group.remove();
$("#labelEditor").dialog("close");
return;
}
const message = "Are you sure you want to remove all '" + iconGroup.value + "' icons (" + count + ")?";
alertMessage.innerHTML = message;
$("#alert").dialog({resizable: false, title: "Remove icon group",
buttons: {
Remove: function() {
$(this).dialog("close");
group.remove();
$("#iconEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
});
});
$("#iconColors").click(function() {
$("#iconEditor > button").not(this).toggle();
$("#iconColorsSection").toggle();
});
$("#iconFillColor").change(function() {
const group = d3.select(elSelected.node().parentNode);
group.attr("fill", this.value);
});
$("#iconStrokeColor").change(function() {
const group = d3.select(elSelected.node().parentNode);
group.attr("stroke", this.value);
});
$("#iconSetSize").click(function() {
$("#iconEditor > button").not(this).toggle();
$("#iconSizeSection").toggle();
});
$("#iconSize").change(function() {
const group = d3.select(elSelected.node().parentNode);
const size = +this.value;
group.attr("size", size);
group.selectAll("*").each(function() {d3.select(this).attr("width", size).attr("height", size)});
});
$("#iconStrokeWidth").change(function() {
const group = d3.select(elSelected.node().parentNode);
group.attr("stroke-width", this.value);
});
$("#iconRemove").click(function() {
alertMessage.innerHTML = `Are you sure you want to remove the icon?`;
$("#alert").dialog({resizable: false, title: "Remove icon",
buttons: {
Remove: function() {
$(this).dialog("close");
elSelected.remove();
$("#iconEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
})
});
}
function editReliefIcon() {
if (customization) return;
if (elSelected) if (this.isSameNode(elSelected.node())) return;
unselect();
closeDialogs("#reliefEditor, .stable");
elSelected = d3.select(this).raise().call(d3.drag().on("start", elementDrag)).classed("draggable", true);
const group = elSelected.node().parentNode.id;
reliefGroup.value = group;
let bulkRemoveSection = document.getElementById("reliefBulkRemoveSection");
if (bulkRemoveSection.style.display != "none") reliefBulkRemove.click();
$("#reliefEditor").dialog({
title: "Edit relief icon",
minHeight: 30, width: "auto", resizable: false,
position: {my: "center top+40", at: "top", of: d3.event},
close: unselect
});
if (modules.editReliefIcon) {return;}
modules.editReliefIcon = true;
$("#reliefGroups").click(function() {
$("#reliefEditor > button").not(this).toggle();
$("#reliefGroupsSelection").toggle();
});
$("#reliefGroup").change(function() {
const type = this.value;
const bbox = elSelected.node().getBBox();
const cx = bbox.x;
const cy = bbox.y + bbox.height / 2;
const cell = diagram.find(cx, cy).index;
const height = cell !== undefined ? cells[cell].height : 50;
elSelected.remove();
elSelected = addReliefIcon(height / 100, type, cx, cy, cell);
elSelected.call(d3.drag().on("start", elementDrag));
});
$("#reliefCopy").click(function() {
const group = d3.select(elSelected.node().parentNode);
const copy = elSelected.node().cloneNode(true);
const tr = parseTransform(copy.getAttribute("transform"));
const shift = 10 / Math.sqrt(scale);
let transform = "translate(" + rn(tr[0] - shift, 1) + "," + rn(tr[1] - shift, 1) + ")";
for (let i=2; group.selectAll("[transform='" + transform + "']").size() > 0; i++) {
transform = "translate(" + rn(tr[0] - shift * i, 1) + "," + rn(tr[1] - shift * i, 1) + ")";
}
copy.setAttribute("transform", transform);
group.node().insertBefore(copy, null);
copy.addEventListener("click", editReliefIcon);
});
$("#reliefAddfromEditor").click(function() {
clickToAdd(); // to load on click event function
$("#addRelief").click();
});
$("#reliefRemoveGroup").click(function() {
const group = d3.select(elSelected.node().parentNode);
const count = group.selectAll("*").size();
if (count < 2) {
group.selectAll("*").remove();
$("#labelEditor").dialog("close");
return;
}
const message = "Are you sure you want to remove all '" + reliefGroup.value + "' icons (" + count + ")?";
alertMessage.innerHTML = message;
$("#alert").dialog({resizable: false, title: "Remove all icons within group",
buttons: {
Remove: function() {
$(this).dialog("close");
group.selectAll("*").remove();
$("#reliefEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
});
});
$("#reliefBulkRemove").click(function() {
$("#reliefEditor > button").not(this).toggle();
let section = document.getElementById("reliefBulkRemoveSection");
if (section.style.display === "none") {
section.style.display = "inline-block";
tip("Drag to remove relief icons in radius", true);
viewbox.style("cursor", "crosshair").call(d3.drag().on("drag", dragToRemoveReliefIcons));
customization = 5;
} else {
section.style.display = "none";
restoreDefaultEvents();
customization = 0;
}
});
function dragToRemoveReliefIcons() {
let point = d3.mouse(this);
let cell = diagram.find(point[0], point[1]).index;
let radius = +reliefBulkRemoveRadius.value;
let r = rn(6 / graphSize * radius, 1);
moveCircle(point[0], point[1], r);
let selection = defineBrushSelection(cell, radius);
if (selection) removeReliefIcons(selection);
}
function removeReliefIcons(selection) {
if (selection.length === 0) return;
selection.map(function(index) {
const selected = terrain.selectAll("g").selectAll("g[data-cell='"+index+"']");
selected.remove();
});
}
$("#reliefRemove").click(function() {
alertMessage.innerHTML = `Are you sure you want to remove the icon?`;
$("#alert").dialog({resizable: false, title: "Remove relief icon",
buttons: {
Remove: function() {
$(this).dialog("close");
elSelected.remove();
$("#reliefEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
})
});
}
function editBurg() {
if (customization) return;
unselect();
closeDialogs("#burgEditor, .stable");
elSelected = d3.select(this);
const id = +elSelected.attr("data-id");
if (id === undefined) return;
d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("start", elementDrag)).classed("draggable", true);
// update Burg details
const type = elSelected.node().parentNode.id;
const labelGroup = burgLabels.select("#"+type);
const iconGroup = burgIcons.select("#"+type);
burgNameInput.value = manors[id].name;
updateBurgsGroupOptions();
burgSelectGroup.value = labelGroup.attr("id");
burgSelectDefaultFont.value = fonts.indexOf(labelGroup.attr("data-font"));
burgSetLabelSize.value = labelGroup.attr("data-size");
burgLabelColorInput.value = toHEX(labelGroup.attr("fill"));
burgLabelOpacity.value = labelGroup.attr("opacity") === undefined ? 1 : +labelGroup.attr("opacity");
const tr = parseTransform(elSelected.attr("transform"));
burgLabelAngle.value = tr[2];
burgLabelAngleOutput.innerHTML = Math.abs(+tr[2]) + "°";
burgIconSize.value = iconGroup.attr("size");
burgIconFillOpacity.value = iconGroup.attr("fill-opacity") === undefined ? 1 : +iconGroup.attr("fill-opacity");
burgIconFillColor.value = iconGroup.attr("fill");
burgIconStrokeWidth.value = iconGroup.attr("stroke-width");
burgIconStrokeOpacity.value = iconGroup.attr("stroke-opacity") === undefined ? 1 : +iconGroup.attr("stroke-opacity");
burgIconStrokeColor.value = iconGroup.attr("stroke");
const cell = cells[manors[id].cell];
if (cell.region !== "neutral" && cell.region !== undefined) {
burgToggleCapital.disabled = false;
const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 1 : 0 : 0;
d3.select("#burgToggleCapital").classed("pressed", capital);
} else {
burgToggleCapital.disabled = true;
d3.select("#burgToggleCapital").classed("pressed", false);
}
d3.select("#burgTogglePort").classed("pressed", cell.port !== undefined);
burgPopulation.value = manors[id].population;
burgPopulationFriendly.value = rn(manors[id].population * urbanization.value * populationRate.value * 1000);
$("#burgEditor").dialog({
title: "Edit Burg: " + manors[id].name,
minHeight: 30, width: "auto", resizable: false,
position: {my: "center top+40", at: "top", of: d3.event},
close: function() {
d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("drag", null)).classed("draggable", false);
elSelected = null;
}
});
if (modules.editBurg) return;
modules.editBurg = true;
loadDefaultFonts();
function updateBurgsGroupOptions() {
burgSelectGroup.innerHTML = "";
burgIcons.selectAll("g").each(function(d) {
const opt = document.createElement("option");
opt.value = opt.innerHTML = d3.select(this).attr("id");
burgSelectGroup.add(opt);
});
}
$("#burgEditor > button").not("#burgAddfromEditor").not("#burgRelocate").not("#burgRemove").click(function() {
if ($(this).next().is(":visible")) {
$("#burgEditor > button").show();
$(this).next("div").hide();
} else {
$("#burgEditor > *").not(this).hide();
$(this).next("div").show();
}
});
$("#burgEditor > div > button").click(function() {
if ($(this).next().is(":visible")) {
$("#burgEditor > div > button").show();
$(this).parent().prev().show();
$(this).next("div").hide();
} else {
$("#burgEditor > div > button").not(this).hide();
$(this).parent().prev().hide();
$(this).next("div").show();
}
});
$("#burgSelectGroup").change(function() {
const id = +elSelected.attr("data-id");
const g = this.value;
moveBurgToGroup(id, g);
});
$("#burgInputGroup").change(function() {
let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, "");
if (Number.isFinite(+newGroup.charAt(0))) newGroup = "g" + newGroup;
if (burgLabels.select("#"+newGroup).size()) {
tip('The group "'+ newGroup + '" is already exists');
return;
}
burgInputGroup.value = "";
// clone old group assigning new id
const id = elSelected.node().parentNode.id;
const l = burgLabels.select("#"+id).node().cloneNode(false);
l.id = newGroup;
const i = burgIcons.select("#"+id).node().cloneNode(false);
i.id = newGroup;
burgLabels.node().insertBefore(l, null);
burgIcons.node().insertBefore(i, null);
// select new group
const opt = document.createElement("option");
opt.value = opt.innerHTML = newGroup;
burgSelectGroup.add(opt);
$("#burgSelectGroup").val(newGroup).change();
$("#burgSelectGroup, #burgInputGroup").toggle();
updateLabelGroups();
});
$("#burgAddGroup").click(function() {
if ($("#burgInputGroup").css("display") === "none") {
$("#burgInputGroup").css("display", "inline-block");
$("#burgSelectGroup").css("display", "none");
burgInputGroup.focus();
} else {
$("#burgSelectGroup").css("display", "inline-block");
$("#burgInputGroup").css("display", "none");
}
});
$("#burgRemoveGroup").click(function() {
const group = d3.select(elSelected.node().parentNode);
const type = group.attr("id");
const id = +elSelected.attr("data-id");
const count = group.selectAll("*").size();
const message = "Are you sure you want to remove all Burgs (" + count + ") of that group?";
alertMessage.innerHTML = message;
$("#alert").dialog({resizable: false, title: "Remove Burgs",
buttons: {
Remove: function() {
$(this).dialog("close");
group.selectAll("*").each(function(d) {
const id = +d3.select(this).attr("data-id");
if (id === undefined) return;
const cell = manors[id].cell;
const state = manors[id].region;
if (states[state]) {
if (states[state].capital === id) states[state].capital = "select";
states[state].burgs --;
}
manors[id].region = "removed";
cells[cell].manor = undefined;
});
burgLabels.select("#"+type).selectAll("*").remove();
burgIcons.select("#"+type).selectAll("*").remove();
$("#icons g[id*='anchors'] [data-id=" + id + "]").parent().children().remove();
closeDialogs(".stable");
updateCountryEditors();
$("#burgEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
});
});
$("#burgNameInput").on("input", function() {
if (this.value === "") {
tip("Name should not be blank, set opacity to 0 to hide label or remove button to delete");
return;
}
const id = +elSelected.attr("data-id");
burgLabels.selectAll("[data-id='" + id + "']").text(this.value);
manors[id].name = this.value;
$("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + this.value);
});
$("#burgNameReCulture, #burgNameReRandom").click(function() {
const id = +elSelected.attr("data-id");
const culture = this.id === "burgNameReCulture" ? manors[id].culture : Math.floor(Math.random() * cultures.length);
const name = generateName(culture);
burgLabels.selectAll("[data-id='" + id + "']").text(name);
manors[id].name = name;
burgNameInput.value = name;
$("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + name);
});
$("#burgToggleExternalFont").click(function() {
if ($("#burgInputExternalFont").css("display") === "none") {
$("#burgInputExternalFont").css("display", "inline-block");
$("#burgSelectDefaultFont").css("display", "none");
burgInputExternalFont.focus();
} else {
$("#burgSelectDefaultFont").css("display", "inline-block");
$("#burgInputExternalFont").css("display", "none");
}
});
$("#burgSelectDefaultFont").change(function() {
const type = elSelected.node().parentNode.id;
const group = burgLabels.select("#"+type);
if (burgSelectDefaultFont.value === "") return;
const font = fonts[burgSelectDefaultFont.value].split(':')[0].replace(/\+/g, " ");
group.attr("font-family", font).attr("data-font", fonts[burgSelectDefaultFont.value]);
});
$("#burgInputExternalFont").change(function() {
fetchFonts(this.value).then(fetched => {
if (!fetched) return;
burgToggleExternalFont.click();
burgInputExternalFont.value = "";
if (fetched === 1) $("#burgSelectDefaultFont").val(fonts.length - 1).change();
});
});
$("#burgSetLabelSize").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgLabels.select("#"+type);
group.attr("data-size", +this.value);
invokeActiveZooming();
});
$("#burgLabelColorInput").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgLabels.select("#"+type);
group.attr("fill", this.value);
});
$("#burgLabelOpacity").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgLabels.select("#"+type);
group.attr("opacity", +this.value);
});
$("#burgLabelAngle").on("input", function() {
const id = +elSelected.attr("data-id");
const el = burgLabels.select("[data-id='"+ id +"']");
const tr = parseTransform(el.attr("transform"));
const c = el.node().getBBox();
burgLabelAngleOutput.innerHTML = Math.abs(+this.value) + "°";
const angle = +this.value;
const transform = `translate(${tr[0]},${tr[1]}) rotate(${angle} ${(c.x+c.width/2)} ${(c.y+c.height/2)})`;
el.attr("transform", transform);
});
$("#burgIconSize").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
const size = +this.value;
group.attr("size", size);
group.selectAll("*").each(function() {d3.select(this).attr("r", size)});
});
$("#burgIconFillOpacity").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
group.attr("fill-opacity", +this.value);
});
$("#burgIconFillColor").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
group.attr("fill", this.value);
});
$("#burgIconStrokeWidth").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
group.attr("stroke-width", +this.value);
});
$("#burgIconStrokeOpacity").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
group.attr("stroke-opacity", +this.value);
});
$("#burgIconStrokeColor").on("input", function() {
const type = elSelected.node().parentNode.id;
const group = burgIcons.select("#"+type);
group.attr("stroke", this.value);
});
$("#burgToggleCapital").click(function() {
const id = +elSelected.attr("data-id");
const state = manors[id].region;
if (states[state] === undefined) return;
const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 0 : 1 : 1;
if (capital && states[state].capital !== "select") {
// move oldCapital to a town group
const oldCapital = states[state].capital;
moveBurgToGroup(oldCapital, "towns");
}
states[state].capital = capital ? id : "select";
d3.select("#burgToggleCapital").classed("pressed", capital);
const g = capital ? "capitals" : "towns";
moveBurgToGroup(id, g);
});
$("#burgTogglePort").click(function() {
const id = +elSelected.attr("data-id");
const cell = cells[manors[id].cell];
const markAsPort = cell.port === undefined ? true : undefined;
cell.port = markAsPort;
d3.select("#burgTogglePort").classed("pressed", markAsPort);
if (markAsPort) {
const type = elSelected.node().parentNode.id;
const ag = type === "capitals" ? "#capital-anchors" : "#town-anchors";
const group = icons.select(ag);
const size = +group.attr("size");
const x = rn(manors[id].x - size * 0.47, 2);
const y = rn(manors[id].y - size * 0.47, 2);
group.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", id)
.attr("x", x).attr("y", y).attr("width", size).attr("height", size)
.on("click", editIcon);
} else {
$("#icons g[id*='anchors'] [data-id=" + id + "]").remove();
}
});
$("#burgPopulation").on("input", function() {
const id = +elSelected.attr("data-id");
burgPopulationFriendly.value = rn(this.value * urbanization.value * populationRate.value * 1000);
manors[id].population = +this.value;
});
$("#burgRelocate").click(function() {
if ($(this).hasClass('pressed')) {
$(".pressed").removeClass('pressed');
restoreDefaultEvents();
tip("", true);
} else {
$(".pressed").removeClass('pressed');
const id = elSelected.attr("data-id");
$(this).addClass('pressed').attr("data-id", id);
viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick);
tip("Click on map to relocate burg. Hold Shift for continuous move", true);
}
});
// open legendsEditor
document.getElementById("burglLegend").addEventListener("click", function() {
let burg = +elSelected.attr("data-id");
let id = "burg" + burg;
let name = manors[burg].name;
editLegends(id, name);
});
// move burg to a different cell
function relocateBurgOnClick() {
const point = d3.mouse(this);
const index = getIndex(point);
const i = +$("#burgRelocate").attr("data-id");
if (isNaN(i) || !manors[i]) return;
if (cells[index].height < 20) {
tip("Cannot place burg in the water! Select a land cell", null, "error");
return;
}
if (cells[index].manor !== undefined && cells[index].manor !== i) {
tip("There is already a burg in this cell. Please select a free cell", null, "error");
$('#grid').fadeIn();
d3.select("#toggleGrid").classed("buttonoff", false);
return;
}
let region = cells[index].region;
const oldRegion = manors[i].region;
// relocating capital to other country you "conquer" target cell
if (states[oldRegion] && states[oldRegion].capital === i) {
if (region !== oldRegion) {
tip("Capital cannot be moved to another country!", null, "error");
return;
}
}
if (d3.event.shiftKey === false) {
$("#burgRelocate").removeClass("pressed");
restoreDefaultEvents();
tip("", true);
if (region !== oldRegion) {
recalculateStateData(oldRegion);
recalculateStateData(region);
updateCountryEditors();
}
}
const x = rn(point[0],2), y = rn(point[1],2);
burgIcons.select("circle[data-id='"+i+"']").attr("transform", null).attr("cx", x).attr("cy", y);
burgLabels.select("text[data-id='"+i+"']").attr("transform", null).attr("x", x).attr("y", y);
const anchor = icons.select("use[data-id='"+i+"']");
if (anchor.size()) {
const size = anchor.attr("width");
const xa = rn(x - size * 0.47, 2);
const ya = rn(y - size * 0.47, 2);
anchor.attr("transform", null).attr("x", xa).attr("y", ya);
}
cells[index].manor = i;
cells[manors[i].cell].manor = undefined;
manors[i].x = x, manors[i].y = y, manors[i].region = region, manors[i].cell = index;
}
// open in MFCG
$("#burgSeeInMFCG").click(function() {
const id = +elSelected.attr("data-id");
const name = manors[id].name;
const cell = manors[id].cell;
const pop = rn(manors[id].population);
const size = pop > 65 ? 65 : pop < 6 ? 6 : pop;
const s = seed + "" + id;
const hub = cells[cell].crossroad > 2 ? 1 : 0;
const river = cells[cell].river ? 1 : 0;
const coast = cells[cell].port !== undefined ? 1 : 0;
const sec = pop > 40 ? 1 : Math.random() < pop / 100 ? 1 : 0;
const thr = sec && Math.random() < 0.8 ? 1 : 0;
const url = "http://fantasycities.watabou.ru/";
let params = `?name=${name}&size=${size}&seed=${s}&hub=${hub}&random=0&continuous=0`;
params += `&river=${river}&coast=${coast}&citadel=${id&1}&plaza=${sec}&temple=${thr}&walls=${sec}&shantytown=${sec}`;
const win = window.open(url+params, '_blank');
win.focus();
});
$("#burgAddfromEditor").click(function() {
clickToAdd(); // to load on click event function
$("#addBurg").click();
});
$("#burgRemove").click(function() {
alertMessage.innerHTML = `Are you sure you want to remove the Burg?`;
$("#alert").dialog({resizable: false, title: "Remove Burg",
buttons: {
Remove: function() {
$(this).dialog("close");
const id = +elSelected.attr("data-id");
d3.selectAll("[data-id='" + id + "']").remove();
const cell = manors[id].cell;
const state = manors[id].region;
if (states[state]) {
if (states[state].capital === id) states[state].capital = "select";
states[state].burgs --;
}
manors[id].region = "removed";
cells[cell].manor = undefined;
closeDialogs(".stable");
updateCountryEditors();
},
Cancel: function() {$(this).dialog("close");}
}
})
});
}
function editMarker() {
if (customization) return;
unselect();
closeDialogs("#markerEditor, .stable");
elSelected = d3.select(this).call(d3.drag().on("start", elementDrag)).classed("draggable", true);
$("#markerEditor").dialog({
title: "Edit Marker",
minHeight: 30, width: "auto", maxWidth: 275, resizable: false,
position: {my: "center top+30", at: "bottom", of: d3.event},
close: unselect
});
// update inputs
let id = elSelected.attr("href");
let symbol = d3.select("#defs-markers").select(id);
let icon = symbol.select("text");
markerSelectGroup.value = id.slice(1);
markerIconSize.value = parseFloat(icon.attr("font-size"));
markerIconShiftX.value = parseFloat(icon.attr("x"));
markerIconShiftY.value = parseFloat(icon.attr("y"));
markerIconFill.value = icon.attr("fill");
markerIconStrokeWidth.value = icon.attr("stroke-width");
markerIconStroke.value = icon.attr("stroke");
markerSize.value = elSelected.attr("data-size");
markerBase.value = symbol.select("path").attr("fill");
markerFill.value = symbol.select("circle").attr("fill");
let opacity = symbol.select("circle").attr("opacity");
markerToggleBubble.className = opacity === "0" ? "icon-info" : "icon-info-circled";
let table = document.getElementById("markerIconTable");
let selected = table.getElementsByClassName("selected");
if (selected.length) selected[0].removeAttribute("class");
selected = document.querySelectorAll("#markerIcon" + icon.text().codePointAt());
if (selected.length) selected[0].className = "selected";
markerIconCustom.value = selected.length ? "" : icon.text();
if (modules.editMarker) return;
modules.editMarker = true;
$("#markerGroup").click(function() {
$("#markerEditor > button").not(this).toggle();
$("#markerGroupSection").toggle();
updateMarkerGroupOptions();
});
function updateMarkerGroupOptions() {
markerSelectGroup.innerHTML = "";
d3.select("#defs-markers").selectAll("symbol").each(function() {
let opt = document.createElement("option");
opt.value = opt.innerHTML = this.id;
markerSelectGroup.add(opt);
});
let id = elSelected.attr("href").slice(1);
markerSelectGroup.value = id;
}
// on add marker type click
document.getElementById("markerAddGroup").addEventListener("click", function() {
if ($("#markerInputGroup").css("display") === "none") {
$("#markerInputGroup").css("display", "inline-block");
$("#markerSelectGroup").css("display", "none");
markerInputGroup.focus();
} else {
$("#markerSelectGroup").css("display", "inline-block");
$("#markerInputGroup").css("display", "none");
}
});
// on marker type change
document.getElementById("markerSelectGroup").addEventListener("change", function() {
elSelected.attr("href", "#"+this.value);
elSelected.attr("data-id", "#"+this.value);
});
// on new type input
document.getElementById("markerInputGroup").addEventListener("change", function() {
let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, "");
if (Number.isFinite(+newGroup.charAt(0))) newGroup = "m" + newGroup;
if (d3.select("#defs-markers").select("#"+newGroup).size()) {
tip('The type "'+ newGroup + '" is already exists');
return;
}
markerInputGroup.value = "";
// clone old group assigning new id
let id = elSelected.attr("href");
let l = d3.select("#defs-markers").select(id).node().cloneNode(true);
l.id = newGroup;
elSelected.attr("href", "#"+newGroup);
elSelected.attr("data-id", "#"+newGroup);
document.getElementById("defs-markers").insertBefore(l, null);
// select new group
let opt = document.createElement("option");
opt.value = opt.innerHTML = newGroup;
markerSelectGroup.add(opt);
$("#markerSelectGroup").val(newGroup).change();
$("#markerSelectGroup, #markerInputGroup").toggle();
updateMarkerGroupOptions();
});
$("#markerIconButton").click(function() {
$("#markerEditor > button").not(this).toggle();
$("#markerIconButtons").toggle();
if (!$("#markerIconTable").text()) drawIconsList(icons);
});
$("#markerRemoveGroup").click(function() {
let id = elSelected.attr("href");
let used = document.querySelectorAll("use[data-id='"+id+"']");
let count = used.length === 1 ? "1 element" : used.length + " elements";
const message = "Are you sure you want to remove the marker (" + count + ")?";
alertMessage.innerHTML = message;
$("#alert").dialog({resizable: false, title: "Remove marker",
buttons: {
Remove: function() {
$(this).dialog("close");
if (id !== "#marker0") d3.select("#defs-markers").select(id).remove();
used.forEach(function(e) {e.remove();});
updateMarkerGroupOptions();
$("#markerEditor").dialog("close");
},
Cancel: function() {$(this).dialog("close");}
}
});
});