Public
Edited
May 1, 2023
Importers
1 star
Insert cell
Insert cell
import { canvasValues } from "eb11a24ab32ae888"
Insert cell
Insert cell
import { enableSliderfunctions } from "60705e9a1108a1aa"
Insert cell
import { enableBoolOperationfunctions } from "dfbc05dadb18ddcb"
Insert cell
function clickListener(p) {
const div = document.createElement("div");

const updateSelectedShape = () => {
div.value = selection.hid(p);
};

document.addEventListener("formChange", () => {
updateSelectedShape();
// In the context of Observable, the Observable runtime itself listens to the "input" event.
// This informs the displayed cell to update upon click, if deleted, cell do not response to click.
div.dispatchEvent(new CustomEvent("input")); // Trigger an update in the reactive cell
});

updateSelectedShape(); // Set the initial value

return div;
}
Insert cell
function FormSyncFunction(p, selectedShape) {
if (selectedShape === null || selectedShape.length === 0) {
return htl.html`<i> </i>`;
}
var item = selectedShape;
//creating the Html Form for the current selection,
var form, fields;
[form, fields] = selectionToFormAndField(item, p);

//adding functionalities to the html form.
enableSliderfunctions(p, form, fields, item);
enableBoolOperationfunctions(item, form, p);

return form;
}
Insert cell
function selectionToFormAndField(item, p) {
var form, fields;
if (item.length === 0) {
return null;
}
if (item.length > 1) {
form = createForm(item, p, "path", true);
fields = formItem.path;
} else {
var singleItem = item[0];
if (singleItem.name.includes("Circle")) {
form = createForm(singleItem, p, "circle", false);
fields = formItem.circle;
} else if (singleItem.name.includes("Rectangle")) {
form = createForm(singleItem, p, "rectangle", false);
fields = formItem.rectangle;
} else if (singleItem.name.includes("Path")) {
form = createForm(singleItem, p, "path", false);
fields = formItem.path;
}
}
return [form, fields];
}
Insert cell
function createForm(item, p, shape, boolOp) {
var bound = p.view.bounds;
var center = p.view.center;
var hMin = (bound.left - center.x) / canvasValues.gridScale;
var hMax = (bound.right - center.x) / canvasValues.gridScale;
var vMin = (bound.top - center.y) / canvasValues.gridScale;
var vMax = (bound.bottom - center.y) / canvasValues.gridScale;
var fields;
if (shape === "circle") {
fields = createCircleFields(item, hMin, hMax, vMin, vMax);
} else if (shape === "rectangle") {
fields = createRectangleFields(item, hMin, hMax, vMin, vMax);
} else if (shape === "path") {
fields = createPathFields(item, hMin, hMax, vMin, vMax);
}
return createHtml(item, fields, boolOp);
}
Insert cell
function createHtml(item, fields, boolOp) {
return htl.html`
<form>
<style>
.opBtn {
height: 30px;
margin-left: 10px;
}
</style>
<div style="display: flex;">
<div>
${createSliderAndValue(fields)}
</div>
<div>
${createOperationButtons(boolOp)}
</div>
</div>
</form>
`;
}
Insert cell
function createSliderAndValue(fields) {
return fields.map(
(field) => htl.html`
<div>
<label for="${field.id}">${field.label}:</label>
<input id="${field.id}" type="range" min="${field.min}" max="${
field.max
}" step="0.01" value="${field.value}">
<input id="${field.id}Value" type="number" min="${field.min}" max="${
field.max
}" step="0.01" value="${field.value.toFixed(2)}" style="width: 50px;">
</div>
`
);
}
Insert cell
function createOperationButtons(boolOp) {
if (boolOp) {
return htl.html`
<button id="intersect" type="button" class="opBtn intersect">Intersect</button>
<button id="unite" type="button" class="opBtn union">Union</button>
<button id="subtract" type="button" class="opBtn subtract">Subtract</button>
`;
} else {
return "";
}
}
Insert cell
function createCircleFields(item, HorizMin, horizMax, vertMin, vertmax) {
return [
createGeomField("x", "x", HorizMin, horizMax, item.position.x),
createGeomField("y", "y", vertMin, vertmax, item.position.y),
createGeomField("r", "r", 0.05, horizMax * 2, item.bounds.width)
];
}
Insert cell
function createRectangleFields(item, HorizMin, horizMax, vertMin, vertmax) {
return [
createGeomField("x", "x", HorizMin, horizMax, item.position.x),
createGeomField("y", "y", vertMin, vertmax, item.position.y),
createGeomField("w", "w", 0.05, horizMax * 2, item.bounds.width),
createGeomField("h", "h", 0.05, vertmax * 2, item.bounds.height),
createGeomField("rotation", "rotation", 0, 360, 0)
];
}
Insert cell
function createPathFields(item, HorizMin, horizMax, vertMin, vertmax) {
var x, y;
// whether it is a group of path or single Path;
if (Array.isArray(item)) {
x = item.reduce((accu, cur) => accu + cur.position.x, 0) / item.length;
y = item.reduce((accu, cur) => accu + cur.position.y, 0) / item.length;
} else {
x = item.position.x;
y = item.position.y;
}
return [
createGeomField("x", "x", HorizMin, horizMax, x),
createGeomField("y", "y", vertMin, vertmax, y),
createGeomField("rotation", "rotation", 0, 360, 0),
createGeomField("scale", "scale", 0.05, 3, 1)
];
}
Insert cell
function createGeomField(id, label, min, max, value) {
return { id: id, label: label, min: min, max: max, value: value };
}
Insert cell
formItem = {
var formItem = {
circle: ["x", "y", "r"],
rectangle: ["x", "y", "w", "h", "rotation"],
path: ["x", "y", "rotation", "scale"]
};
return formItem;
}
Insert cell
function removeEventListeners(form, item, fields) {
item.forEach((eachItem) => {
fields.forEach((field) => {
// Remove input event listener
form
.querySelector(`#${field.id}`)
.removeEventListener(
"input" /* reference to the input event handler */
);

// Remove change event listener for the value element
form
.querySelector(`#${field.id}Value`)
.removeEventListener(
"change" /* reference to the change event handler */
);
});
});
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more