diff --git a/src/layers/index.js b/src/layers/index.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/layers/init.js b/src/layers/init.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/layers/renderers/index.js b/src/layers/renderers/index.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/layers/utils.js b/src/layers/utils.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/main.js b/src/main.js
index 1c3d3a78..4dc5cd03 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,8 +1,6 @@
// Azgaar (azgaar.fmg@yandex.com). Minsk, 2017-2022. MIT License
// https://github.com/Azgaar/Fantasy-Map-Generator
-console.log("Hello World");
-
import "./components";
import {ERROR, INFO, TIME, WARN} from "./config/logging";
import {UINT16_MAX} from "./constants";
@@ -954,7 +952,7 @@ function drawCoastline() {
);
const landMask = defs.select("#land");
const waterMask = defs.select("#water");
- const lineGen = d3.line().curve(d3.curveBasis);
+ const lineGen = d3.line().curve(d3.curveBasisClosed);
for (const i of cells.i) {
const startFromEdge = !i && cells.h[i] >= 20;
diff --git a/src/modules/io/load.js b/src/modules/io/load.js
index ad97bc12..4e9db819 100644
--- a/src/modules/io/load.js
+++ b/src/modules/io/load.js
@@ -1,11 +1,12 @@
+import {updatePresetInput} from "/src/modules/ui/layers";
import {restoreDefaultEvents} from "/src/scripts/events";
-import {calculateVoronoi, findCell} from "/src/utils/graphUtils";
-import {last} from "/src/utils/arrayUtils";
-import {tip} from "/src/scripts/tooltips";
-import {parseError} from "/src/utils/errorUtils";
-import {rn, minmax} from "/src/utils/numberUtils";
-import {link} from "/src/utils/linkUtils";
import {ldb} from "/src/scripts/indexedDB";
+import {tip} from "/src/scripts/tooltips";
+import {last} from "/src/utils/arrayUtils";
+import {parseError} from "/src/utils/errorUtils";
+import {calculateVoronoi, findCell} from "/src/utils/graphUtils";
+import {link} from "/src/utils/linkUtils";
+import {minmax, rn} from "/src/utils/numberUtils";
function quickLoad() {
ldb.get("lastMap", blob => {
@@ -424,7 +425,7 @@ async function parseLoadedData(data) {
if (notHidden(ruler)) turnOn("toggleRulers");
if (notHidden(scaleBar)) turnOn("toggleScaleBar");
- getCurrentPreset();
+ updatePresetInput();
})();
void (function restoreEvents() {
diff --git a/src/modules/ui/heightmap-editor.js b/src/modules/ui/heightmap-editor.js
index eb184cbf..b9360468 100644
--- a/src/modules/ui/heightmap-editor.js
+++ b/src/modules/ui/heightmap-editor.js
@@ -1,14 +1,14 @@
+import {turnLayerButtonOff, turnLayerButtonOn, updatePresetInput} from "/src/modules/ui/layers";
import {restoreDefaultEvents} from "/src/scripts/events";
-import {findGridCell, findGridAll, findCell, getPackPolygon, getGridPolygon} from "/src/utils/graphUtils";
-import {last, createTypedArray} from "/src/utils/arrayUtils";
-import {tip, showMainTip, clearMainTip} from "/src/scripts/tooltips";
-import {byId} from "/src/utils/shorthands";
-import {rn, minmax, lim} from "/src/utils/numberUtils";
-import {link} from "/src/utils/linkUtils";
import {prompt} from "/src/scripts/prompt";
-import {throttle} from "/src/utils/functionUtils";
-import {turnLayerButtonOn, turnLayerButtonOff} from "/src/modules/ui/layers";
+import {clearMainTip, showMainTip, tip} from "/src/scripts/tooltips";
+import {createTypedArray, last} from "/src/utils/arrayUtils";
import {getColorScheme, getHeightColor} from "/src/utils/colorUtils";
+import {throttle} from "/src/utils/functionUtils";
+import {findCell, findGridAll, findGridCell, getGridPolygon, getPackPolygon} from "/src/utils/graphUtils";
+import {link} from "/src/utils/linkUtils";
+import {lim, minmax, rn} from "/src/utils/numberUtils";
+import {byId} from "/src/utils/shorthands";
export function editHeightmap(options) {
const {mode, tool} = options || {};
@@ -202,7 +202,7 @@ export function editHeightmap(options) {
// turn on
else if (!editHeightmap.layers.includes(e.id) && layerIsOn(e.id)) e.click(); // turn off
});
- getCurrentPreset();
+ updatePresetInput();
}
function regenerateErasedData() {
diff --git a/src/modules/ui/hotkeys.js b/src/modules/ui/hotkeys.js
index 288ec5fa..be58ef5a 100644
--- a/src/modules/ui/hotkeys.js
+++ b/src/modules/ui/hotkeys.js
@@ -1,7 +1,9 @@
-"use strict";
+import {byId} from "/src/utils/shorthands";
+import {toggleLayer} from "/src/modules/ui/layers";
+
// Hotkeys, see github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys
-document.addEventListener("keydown", handleKeydown);
-document.addEventListener("keyup", handleKeyup);
+document.on("keydown", handleKeydown);
+document.on("keyup", handleKeyup);
function handleKeydown(event) {
if (!allowHotkeys()) return; // in some cases (e.g. in a textarea) hotkeys are not allowed
@@ -29,7 +31,7 @@ function handleKeyup(event) {
else if (code === "Tab") toggleOptions(event);
else if (code === "Escape") closeAllDialogs();
else if (code === "Delete") removeElementOnKey();
- else if (code === "KeyO" && document.getElementById("canvas3d")) toggle3dOptions();
+ else if (code === "KeyO" && byId("canvas3d")) toggle3dOptions();
else if (ctrl && code === "KeyQ") toggleSaveReminder();
else if (ctrl && code === "KeyS") dowloadMap();
else if (ctrl && code === "KeyC") saveToDropbox();
@@ -63,33 +65,33 @@ function handleKeyup(event) {
else if (alt && code === "KeyC") console.table(pack.cultures);
else if (alt && code === "KeyR") console.table(pack.religions);
else if (alt && code === "KeyF") console.table(pack.features);
- else if (code === "KeyX") toggleTexture();
- else if (code === "KeyH") toggleHeight();
- else if (code === "KeyB") toggleBiomes();
- else if (code === "KeyE") toggleCells();
- else if (code === "KeyG") toggleGrid();
- else if (code === "KeyO") toggleCoordinates();
- else if (code === "KeyW") toggleCompass();
- else if (code === "KeyV") toggleRivers();
- else if (code === "KeyF") toggleRelief();
- else if (code === "KeyC") toggleCultures();
- else if (code === "KeyS") toggleStates();
- else if (code === "KeyP") toggleProvinces();
- else if (code === "KeyZ") toggleZones();
- else if (code === "KeyD") toggleBorders();
- else if (code === "KeyR") toggleReligions();
- else if (code === "KeyU") toggleRoutes();
- else if (code === "KeyT") toggleTemp();
- else if (code === "KeyN") togglePopulation();
- else if (code === "KeyJ") toggleIce();
- else if (code === "KeyA") togglePrec();
- else if (code === "KeyY") toggleEmblems();
- else if (code === "KeyL") toggleLabels();
- else if (code === "KeyI") toggleIcons();
- else if (code === "KeyM") toggleMilitary();
- else if (code === "KeyK") toggleMarkers();
- else if (code === "Equal") toggleRulers();
- else if (code === "Slash") toggleScaleBar();
+ else if (code === "KeyX") toggleLayer("toggleTexture");
+ else if (code === "KeyH") toggleLayer("toggleHeight");
+ else if (code === "KeyB") toggleLayer("toggleBiomes");
+ else if (code === "KeyE") toggleLayer("toggleCells");
+ else if (code === "KeyG") toggleLayer("toggleGrid");
+ else if (code === "KeyO") toggleLayer("toggleCoordinates");
+ else if (code === "KeyW") toggleLayer("toggleCompass");
+ else if (code === "KeyV") toggleLayer("toggleRivers");
+ else if (code === "KeyF") toggleLayer("toggleRelief");
+ else if (code === "KeyC") toggleLayer("toggleCultures");
+ else if (code === "KeyS") toggleLayer("toggleStates");
+ else if (code === "KeyP") toggleLayer("toggleProvinces");
+ else if (code === "KeyZ") toggleLayer("toggleZones");
+ else if (code === "KeyD") toggleLayer("toggleBorders");
+ else if (code === "KeyR") toggleLayer("toggleReligions");
+ else if (code === "KeyU") toggleLayer("toggleRoutes");
+ else if (code === "KeyT") toggleLayer("toggleTemp");
+ else if (code === "KeyN") toggleLayer("togglePopulation");
+ else if (code === "KeyJ") toggleLayer("toggleIce");
+ else if (code === "KeyA") toggleLayer("togglePrec");
+ else if (code === "KeyY") toggleLayer("toggleEmblems");
+ else if (code === "KeyL") toggleLayer("toggleLabels");
+ else if (code === "KeyI") toggleLayer("toggleIcons");
+ else if (code === "KeyM") toggleLayer("toggleMilitary");
+ else if (code === "KeyK") toggleLayer("toggleMarkers");
+ else if (code === "Equal") toggleLayer("toggleRulers");
+ else if (code === "Slash") toggleLayer("toggleScaleBar");
else if (code === "ArrowLeft") zoom.translateBy(svg, 10, 0);
else if (code === "ArrowRight") zoom.translateBy(svg, -10, 0);
else if (code === "ArrowUp") zoom.translateBy(svg, 0, 10);
@@ -120,22 +122,17 @@ function pressNumpadSign(key) {
const change = key === "+" ? 1 : -1;
let brush = null;
- if (document.getElementById("brushRadius")?.offsetParent) brush = document.getElementById("brushRadius");
- else if (document.getElementById("biomesManuallyBrush")?.offsetParent)
- brush = document.getElementById("biomesManuallyBrush");
- else if (document.getElementById("statesManuallyBrush")?.offsetParent)
- brush = document.getElementById("statesManuallyBrush");
- else if (document.getElementById("provincesManuallyBrush")?.offsetParent)
- brush = document.getElementById("provincesManuallyBrush");
- else if (document.getElementById("culturesManuallyBrush")?.offsetParent)
- brush = document.getElementById("culturesManuallyBrush");
- else if (document.getElementById("zonesBrush")?.offsetParent) brush = document.getElementById("zonesBrush");
- else if (document.getElementById("religionsManuallyBrush")?.offsetParent)
- brush = document.getElementById("religionsManuallyBrush");
+ if (byId("brushRadius")?.offsetParent) brush = byId("brushRadius");
+ else if (byId("biomesManuallyBrush")?.offsetParent) brush = byId("biomesManuallyBrush");
+ else if (byId("statesManuallyBrush")?.offsetParent) brush = byId("statesManuallyBrush");
+ else if (byId("provincesManuallyBrush")?.offsetParent) brush = byId("provincesManuallyBrush");
+ else if (byId("culturesManuallyBrush")?.offsetParent) brush = byId("culturesManuallyBrush");
+ else if (byId("zonesBrush")?.offsetParent) brush = byId("zonesBrush");
+ else if (byId("religionsManuallyBrush")?.offsetParent) brush = byId("religionsManuallyBrush");
if (brush) {
const value = minmax(+brush.value + change, +brush.min, +brush.max);
- brush.value = document.getElementById(brush.id + "Number").value = value;
+ brush.value = byId(brush.id + "Number").value = value;
return;
}
diff --git a/src/modules/ui/layers.js b/src/modules/ui/layers.js
index 3bb2b5cb..124936bb 100644
--- a/src/modules/ui/layers.js
+++ b/src/modules/ui/layers.js
@@ -13,35 +13,6 @@ import {convertTemperature} from "/src/utils/unitUtils";
import {getColorScheme, getHeightColor} from "/src/utils/colorUtils";
let presets = {};
-restoreCustomPresets(); // run on-load
-addLayerListeners();
-
-function restoreCustomPresets() {
- const storedPresets = JSON.parse(stored("presets"));
- if (!storedPresets) {
- presets = defaultPresets.slice();
- return;
- }
-
- for (const preset in storedPresets) {
- if (presets[preset]) continue;
- byId("layersPreset").add(new Option(preset, preset));
- }
-
- presets = storedPresets;
-}
-
-function addLayerListeners() {
- byId("mapLayers").on("click", toggleLayer);
- byId("savePresetButton").on("click", savePreset);
- byId("removePresetButton").on("click", removePreset);
-}
-
-function toggleLayer(event) {
- const targetId = event.target.id;
- if (!targetId || targetId === "mapLayers" || !layerTogglesMap[targetId]) return;
- layerTogglesMap[targetId]();
-}
const defaultPresets = {
political: [
@@ -139,6 +110,81 @@ const layerTogglesMap = {
toggleZones
};
+restoreCustomPresets(); // run on-load
+addLayerListeners();
+
+function restoreCustomPresets() {
+ const storedPresets = JSON.parse(stored("presets"));
+ if (!storedPresets) {
+ presets = structuredClone(defaultPresets);
+ return;
+ }
+
+ for (const preset in storedPresets) {
+ if (presets[preset]) continue;
+ byId("layersPreset").add(new Option(preset, preset));
+ }
+
+ presets = storedPresets;
+}
+
+function addLayerListeners() {
+ byId("mapLayers").on("click", toggleLayerOnClick);
+ byId("savePresetButton").on("click", savePreset);
+ byId("removePresetButton").on("click", removePreset);
+
+ // allow to move layers by dragging layer button (jquery)
+ $("#mapLayers").sortable({items: "li:not(.solid)", containment: "parent", cancel: ".solid", update: moveLayer});
+}
+
+// connection between option layer buttons and actual svg groups to move the element
+const layerButtonToElementMap = {
+ toggleBiomes: "biomes",
+ toggleBorders: "borders",
+ toggleCells: "cells",
+ toggleCompass: "compass",
+ toggleCoordinates: "coordinates",
+ toggleCultures: "cults",
+ toggleEmblems: "emblems",
+ toggleGrid: "gridOverlay",
+ toggleHeight: "terrs",
+ toggleIce: "ice",
+ toggleIcons: "icons",
+ toggleLabels: "labels",
+ toggleMarkers: "markers",
+ toggleMilitary: "armies",
+ togglePopulation: "population",
+ togglePrec: "prec",
+ toggleProvinces: "provs",
+ toggleRelief: "terrain",
+ toggleReligions: "relig",
+ toggleRivers: "rivers",
+ toggleRoutes: "routes",
+ toggleRulers: "ruler",
+ toggleStates: "regions",
+ toggleTemp: "temperature",
+ toggleTexture: "texture",
+ toggleZones: "zones"
+};
+
+function moveLayer(event, $layerButton) {
+ const getLayer = buttonId => $("#" + layerButtonToElementMap[buttonId]);
+ const layer = getLayer($layerButton.item.attr("id"));
+ if (!layer) return;
+
+ const prev = getLayer($layerButton.item.prev().attr("id"));
+ const next = getLayer($layerButton.item.next().attr("id"));
+
+ if (prev) layer.insertAfter(prev);
+ else if (next) layer.insertBefore(next);
+}
+
+function toggleLayerOnClick(event) {
+ const targetId = event.target.id;
+ if (!targetId || targetId === "mapLayers" || !layerTogglesMap[targetId]) return;
+ layerTogglesMap[targetId]();
+}
+
// run on map generation
export function applyPreset() {
const preset = stored("preset") || byId("layersPreset")?.value || "political";
@@ -216,22 +262,26 @@ export function restoreLayers() {
if (!layerIsOn("toggleRivers")) rivers.selectAll("*").remove();
}
+export function toggleLayer(layerId) {
+ layerTogglesMap[layerId]();
+}
+
export function layerIsOn(el) {
const buttonoff = byId(el).classList.contains("buttonoff");
return !buttonoff;
}
-function turnLayerButtonOn(el) {
+export function turnLayerButtonOn(el) {
byId(el).classList.remove("buttonoff");
updatePresetInput();
}
-function turnLayerButtonOff(el) {
+export function turnLayerButtonOff(el) {
byId(el).classList.add("buttonoff");
updatePresetInput();
}
-function updatePresetInput() {
+export function updatePresetInput() {
const $toggledOnLayers = byId("mapLayers").querySelectorAll("li:not(.buttonoff)");
const currentLayers = Array.from($toggledOnLayers)
.map(node => node.id)
@@ -251,6 +301,10 @@ function updatePresetInput() {
byId("savePresetButton").style.display = "inline-block";
}
+// ***
+// Specific layer toggles and renderers
+// ***
+
function toggleHeight(event) {
if (customization === 1) {
tip("You cannot turn off the layer when heightmap is in edit mode", false, "error");
@@ -271,7 +325,7 @@ function toggleHeight(event) {
}
}
-function drawHeightmap() {
+export function drawHeightmap() {
TIME && console.time("drawHeightmap");
terrs.selectAll("*").remove();
@@ -285,20 +339,9 @@ function drawHeightmap() {
const skip = +terrs.attr("skip") + 1;
const simplification = +terrs.attr("relax");
- const lineGen = d3.line().curve(d3.curveBasis);
- switch (+terrs.attr("curve")) {
- case 0:
- lineGen.curve(d3.curveBasisClosed);
- break;
- case 1:
- lineGen.curve(d3.curveLinear);
- break;
- case 2:
- lineGen.curve(d3.curveStep);
- break;
- default:
- lineGen.curve(d3.curveBasisClosed);
- }
+ const curveMap = {0: d3.curveBasisClosed, 1: d3.curveLinear, 2: d3.curveStep};
+ const curve = curveMap[+terrs.attr("curve") || 0];
+ const lineGen = d3.line().curve(curve);
let currentLayer = 20;
const heights = cells.i.sort((a, b) => cells.h[a] - cells.h[b]);
@@ -328,6 +371,7 @@ function drawHeightmap() {
for (const i of d3.range(20, 101)) {
if (paths[i].length < 10) continue;
const color = getHeightColor(i, scheme);
+
if (terracing)
terrs
.append("path")
@@ -385,7 +429,7 @@ function toggleTemp(event) {
}
}
-function drawTemp() {
+export function drawTemp() {
TIME && console.time("drawTemp");
temperature.selectAll("*").remove();
@@ -517,7 +561,7 @@ function toggleBiomes(event) {
}
}
-function drawBiomes() {
+export function drawBiomes() {
biomes.selectAll("path").remove();
const cells = pack.cells,
vertices = pack.vertices,
@@ -593,7 +637,7 @@ function togglePrec(event) {
}
}
-function drawPrec() {
+export function drawPrec() {
prec.selectAll("circle").remove();
const {cells, points} = grid;
@@ -652,7 +696,7 @@ function togglePopulation(event) {
}
}
-function drawPopulation(event) {
+export function drawPopulation(event) {
population.selectAll("line").remove();
const cells = pack.cells,
p = cells.p,
@@ -707,7 +751,7 @@ function toggleCells(event) {
}
}
-function drawCells() {
+export function drawCells() {
cells.selectAll("path").remove();
const data = customization === 1 ? grid.cells.i : pack.cells.i;
const polygon = customization === 1 ? getGridPolygon : getPackPolygon;
@@ -732,7 +776,7 @@ function toggleIce(event) {
}
}
-function drawIce() {
+export function drawIce() {
const cells = grid.cells,
vertices = grid.vertices,
n = cells.i.length,
@@ -822,7 +866,7 @@ function toggleCultures(event) {
}
}
-function drawCultures() {
+export function drawCultures() {
TIME && console.time("drawCultures");
cults.selectAll("path").remove();
@@ -896,7 +940,7 @@ function toggleReligions(event) {
}
}
-function drawReligions() {
+export function drawReligions() {
TIME && console.time("drawReligions");
relig.selectAll("path").remove();
@@ -1171,7 +1215,6 @@ function toggleBorders(event) {
}
}
-// draw state and province borders
export function drawBorders() {
TIME && console.time("drawBorders");
borders.selectAll("path").remove();
@@ -1434,7 +1477,7 @@ function toggleGrid(event) {
}
}
-function drawGrid() {
+export function drawGrid() {
gridOverlay.selectAll("*").remove();
const pattern = "#pattern_" + (gridOverlay.attr("type") || "pointyHex");
const stroke = gridOverlay.attr("stroke") || "#808080";
@@ -1692,36 +1735,35 @@ function drawMarkers() {
markers.html(html.join(""));
}
-const getPin = (shape = "bubble", fill = "#fff", stroke = "#000") => {
- if (shape === "bubble")
- return ``;
- if (shape === "pin")
- return ``;
- if (shape === "square")
- return ``;
- if (shape === "squarish")
- return ``;
- if (shape === "diamond") return ``;
- if (shape === "hex") return ``;
- if (shape === "hexy") return ``;
- if (shape === "shieldy")
- return ``;
- if (shape === "shield")
- return ``;
- if (shape === "pentagon") return ``;
- if (shape === "heptagon")
- return ``;
- if (shape === "circle") return ``;
- if (shape === "no") return "";
+const pinShapeMap = {
+ bubble: (stroke, fill) =>
+ ``,
+ pin: (stroke, fill) =>
+ ``,
+ square: (stroke, fill) =>
+ ``,
+ squarish: (stroke, fill) => ``,
+ diamond: (stroke, fill) => ``,
+ hex: (stroke, fill) => ``,
+ hexy: (stroke, fill) => ``,
+ shieldy: (stroke, fill) =>
+ ``,
+ shield: (stroke, fill) =>
+ ``,
+ pentagon: (stroke, fill) => ``,
+ heptagon: (stroke, fill) =>
+ ``,
+ circle: (stroke, fill) => ``,
+ no: (stroke, fill) => ""
};
function drawMarker(marker, rescale = 1) {
- const {i, icon, x, y, dx = 50, dy = 50, px = 12, size = 30, pin, fill, stroke} = marker;
+ const {i, icon, x, y, dx = 50, dy = 50, px = 12, size = 30, pin = "bubble", fill = "#fff", stroke = "#000"} = marker;
const id = `marker${i}`;
const zoomSize = rescale ? Math.max(rn(size / 5 + 24 / scale, 2), 1) : size;
const viewX = rn(x - zoomSize / 2, 1);
const viewY = rn(y - zoomSize, 1);
- const pinHTML = getPin(pin, fill, stroke);
+ const pinHTML = pinShapeMap[pin](fill, stroke);
return ``;
}
@@ -1820,7 +1862,7 @@ function toggleEmblems(event) {
}
}
-function drawEmblems() {
+export function drawEmblems() {
TIME && console.time("drawEmblems");
const {states, provinces, burgs} = pack;
@@ -1929,42 +1971,3 @@ function drawEmblems() {
TIME && console.timeEnd("drawEmblems");
}
-
-// move layers on mapLayers dragging (jquery sortable)
-$("#mapLayers").sortable({items: "li:not(.solid)", containment: "parent", cancel: ".solid", update: moveLayer});
-function moveLayer(event, ui) {
- const el = getLayer(ui.item.attr("id"));
- if (!el) return;
- const prev = getLayer(ui.item.prev().attr("id"));
- const next = getLayer(ui.item.next().attr("id"));
- if (prev) el.insertAfter(prev);
- else if (next) el.insertBefore(next);
-}
-
-// define connection between option layer buttons and actual svg groups to move the element
-function getLayer(id) {
- if (id === "toggleHeight") return $("#terrs");
- if (id === "toggleBiomes") return $("#biomes");
- if (id === "toggleCells") return $("#cells");
- if (id === "toggleGrid") return $("#gridOverlay");
- if (id === "toggleCoordinates") return $("#coordinates");
- if (id === "toggleCompass") return $("#compass");
- if (id === "toggleRivers") return $("#rivers");
- if (id === "toggleRelief") return $("#terrain");
- if (id === "toggleReligions") return $("#relig");
- if (id === "toggleCultures") return $("#cults");
- if (id === "toggleStates") return $("#regions");
- if (id === "toggleProvinces") return $("#provs");
- if (id === "toggleBorders") return $("#borders");
- if (id === "toggleRoutes") return $("#routes");
- if (id === "toggleTemp") return $("#temperature");
- if (id === "togglePrec") return $("#prec");
- if (id === "togglePopulation") return $("#population");
- if (id === "toggleIce") return $("#ice");
- if (id === "toggleTexture") return $("#texture");
- if (id === "toggleEmblems") return $("#emblems");
- if (id === "toggleLabels") return $("#labels");
- if (id === "toggleIcons") return $("#icons");
- if (id === "toggleMarkers") return $("#markers");
- if (id === "toggleRulers") return $("#ruler");
-}