www.spaceplanner.app

Web client to the spaceplanner API
git clone git://jacobedwards.org/www.spaceplanner.app
Log | Files | Refs

commit 5a343ab38cc91be760ddebe2a51580191096a280
parent 68579e4910209ab72d190226d5956f8ae154dc32
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Thu,  5 Sep 2024 12:10:14 -0700

Provide interface to all furniture parameters in editor

This is currently in the form of a menu. This isn't exactly how I
want it to be in the end, but it will do for now.

Diffstat:
Mfiles/css/main.css | 8++++++--
Mfiles/floorplans/floorplan/main.css | 20++++++++++++++++++++
Mfiles/floorplans/floorplan/main.js | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 197 insertions(+), 6 deletions(-)

diff --git a/files/css/main.css b/files/css/main.css @@ -147,8 +147,12 @@ form.credentials > input { margin-bottom: 2em; } -label.break { - display: block; +.break { + display: block !important; +} + +.hidden { + display: none !important; } .small { diff --git a/files/floorplans/floorplan/main.css b/files/floorplans/floorplan/main.css @@ -81,6 +81,26 @@ aside.menu > form > input[type=radio] { width: 100%; } +.furniture_menu { + background-color: #EEE; + border: thin solid #CCC; + border-radius: .2em; + padding: 1em; + position: absolute; + top: 5em; + left: 5em; + width: fit-content; +} + +.furniture_menu > label > input:is([name="width"], [name="depth"]) { + max-width: 6em; +} + +.furniture_menu > label { + display: inline-block; + margin: .1em .2em; +} + aside.message { position: absolute; box-sizing: border-box; diff --git a/files/floorplans/floorplan/main.js b/files/floorplans/floorplan/main.js @@ -614,11 +614,178 @@ function furnitureHandler(ev, editor) { if (editor.draw.findOne(".selected") != null) { return } - - let p = editor.draw.point(ev.clientX, ev.clientY) - console.log("Add furniture", editor.addMappedFurniture("table", p.x, p.y, { width: 500, depth: 500 })) - editor.finishAction() ev.preventDefault() + let menu = document.getElementById("furniture_menu") + if (menu != null) { + menu.remove() + } + menu = furnitureMenu(editor, editor.draw.point(ev.clientX, ev.clientY)) + menu.id = "furniture_menu" + document.body.append(menu) +} + +function enumSelection(input, values) { + let a = typeof(values.keys) === "function" + for (let i in values) { + console.log("EnumSel", i, values[i]) + let opt = input.appendChild(document.createElement("option")) + opt.appendChild(document.createTextNode(a ? values[i] : i)) + } +} + +function furnitureMenu(editor, p) { + if (p == null) { + p = { x: 0, y: 0 } + } + + let defaultType + for (let t in editor.furniture_types) { + defaultType = t + break + } + + let items = [ + menuItem("name", "Name"), + menuItem("type", "Type", { break: false, enum: editor.furniture_types, attributes: { required: true } }), + menuItem("variety", "Variety", { enum: editor.furniture_types[defaultType].varieties }), + menuItem("width", "Width", { attributes: { required: true } }), + menuItem("depth", "Depth", { attributes: { required: true } }), + menuItem("add", null, { attributes: { value: "Add", type: "Submit" } }) + ] + let keys = {} + for (let i in items) { + keys[items[i].attributes.name] = i + } + + const fromVariety = function(type, variety) { + let v + if (variety == null) { + v = { width: null, depth: null } + } else { + v = editor.furniture_types[type].varieties[variety] + } + items[keys.width].input.value = v.width + items[keys.depth].input.value = v.depth + } + const newVariety = function() { + let vars = editor.furniture_types[items[keys.type].input.value].varieties + if (vars == undefined) { + items[keys.variety].container.classList.add("hidden") + fromVariety() + return + } + let v = menuItem("variety", "Variety", { enum: vars }) + let c = makeItem(v) + c.addEventListener("change", function(ev) { + fromVariety(items[keys.type].input.value, ev.target.value) + }) + items[keys.variety].container.replaceWith(c) + items[keys.variety] = v + fromVariety(items[keys.type].input.value, items[keys.variety].input.value) + } + + let menu = makeMenu(items) + newVariety() + items[keys.type].input.addEventListener("change", function(ev) { + newVariety() + }) + menu.addEventListener("submit", function(ev) { + ev.preventDefault() + try { + let name = items[keys.name].input.value + if (name.length === 0) { + name = null + } + editor.addMappedFurniture(items[keys.type].input.value, p.x, p.y, { + width: items[keys.width].input.value, + depth: items[keys.depth].input.value, + name + }) + editor.finishAction() + } + catch(err) { + etc.error(err, menu) + } + menu.remove() + }) + + return menu +} + +function makeMenu(items) { + let c = document.createElement("form") + c.classList.add("furniture_menu") + + // In case I make c != form later + let form = c + + for (let i in items) { + form.append(makeItem(items[i])) + if (items[i].break) { + form.appendChild(document.createElement("br")) + } + } + + return c +} + +function makeItem(item) { + if (item.label != null) { + item.container = document.createElement("label") + let label = item.container + label.appendChild(document.createTextNode(item.label + ": ")) + } + + item.input = document.createElement(item.enum ? "select" : "input") + if (!item.container) { + item.container = item.input + } else { + item.container.appendChild(item.input) + } + + if (item.enum != null) { + enumSelection(item.input, item.enum) + } + for (let a in item.attributes ?? {}) { + item.input.setAttribute(a, item.attributes[a]) + } + for (let c in item.classes ?? {}) { + item.container.classList.add(item.classes[c]) + } + /* + if (item.break) { + // NOTE: Want this to be done in CSS instead of with <br>s + item.container.classList.add("break") + } + */ + return item.container +} + +function menuItem(name, label, options) { + options = options ?? {} + let attributes = options.attributes ?? {} + + if (options.enum != null && typeof options.enum != "object") { + throw new Error("Expected object for menuItem enum") + } + if (name == undefined) { + throw new Error("Must have name") + } + + attributes.name = name + if (options.value != undefined) { + attributes.value = options.value + } + if (attributes.title == undefined) { + attributes.title = label + } + + return { + label, + attributes, + enum: options.enum, + break: options.break == null ? true : options.break + } } function parseUserLength(editor, length) {