viewof suggested_preset = {
const _me = JSON.stringify(this && this.value);
const div = d3.select(DOM.element("div")).attr("style", "min-height: 18em");
const struct = JSON.parse(
JSON.stringify(
"temp" in reference_stack
? suggested_trees[reference_stack.temp]
: suggested_trees[+tree_option] || tree_test
)
),
visible = div.node();
visible.value = struct;
const form = div.append("form");
const onchange = function(attr) {
return () => {
form
.selectAll(".widget")
.each((d, i, e) => {
if (attr === "grid") {
const v = form.node()[attr + i].value;
struct.tree[i].gridding = v;
const relevant_mappings = ["color"].concat(ops(v));
d3.select(e[i])
.selectAll(".visual_mappings>div")
.style("display", function() {
if (
relevant_mappings.indexOf(
this.className.replace(/_mapping/, "")
) > -1
)
return "block";
else return "none";
});
} else if (attr === "attr") {
const group = form.node()[attr + i].value;
if (tidy.thresholds[group]) {
delete struct.tree[i].group;
struct.tree[i].cluster = group;
} else {
delete struct.tree[i].cluster;
struct.tree[i].group = group;
}
} /* "color", "valueX", "valueY", "valueWidth", "valueHeight" */ else {
if (form.node()[attr + i]) {
const v = form.node()[attr + i].value;
if (v) struct.tree[i][attr] = v;
else delete struct.tree[i][attr];
}
}
})
.selectAll(".miniplot")
.call(update_miniplot);
set_selection_highlight();
visible.dispatchEvent(new CustomEvent("input"));
};
};
fill_form();
function fill_form() {
form.selectAll(".widget").remove();
const widgets = form
.selectAll(".widget")
.data(struct.tree)
.join("div")
.classed("widget", true);
widgets
.each((d, i) => {
d.index = d.index || 1 + (d3.max(struct.tree, d => d.index) || 0);
})
.style("border-left", d => "solid 5px " + tree_color(d.index));
widgets.call(drag, visible, function() {
fill_form();
visible.dispatchEvent(new CustomEvent("input"));
});
widgets
.append("div")
.append("button")
.classed("add", true)
.html("+") // ADD
.on("click", (d, i) => {
struct.tree = struct.tree
.slice(0, i)
.concat([{ gridding: "grid", group: "…" }])
.concat(struct.tree.slice(i, Infinity));
fill_form();
});
widgets
.filter((_, i) => i < widgets.size() - 1)
.append("button")
.classed("remove", true)
.html("x") // REMOVE
.on("click", (d, i) => {
struct.tree = struct.tree
.slice(0, i)
.concat(struct.tree.slice(i + 1, Infinity));
fill_form();
visible.dispatchEvent(new CustomEvent("input"));
});
widgets.append("div").call(
flatmenu,
(d, i) =>
[{ name: "…" }, ...attributes.values()].map(o => ({
value: o,
selected: d.group == o.name,
name: "attr" + i,
text: o.name
})), // data
d => d.value.name, // value
d => `${d.value.name} [${d.value.type}]`, // text
(d, i) => "attr" + i, // name
onchange("attr"),
"blocks", // "select" vs "radio" vs "blocks"
struct.tree.length - 1 // last
);
widgets.append("div").classed("miniplot", true);
const sort_div = widgets.append("div").classed("sort", true);
sort_div
.append("button")
.attr("type", "button")
.html("<") // Sort descending
.on("click", (d, i) => {
struct.tree[i].sort = "desc";
onchange("sort")();
});
sort_div
.append("button")
.attr("type", "button")
.html(">") // Sort ascending
.on("click", (d, i) => {
struct.tree[i].sort = "asc";
onchange("sort")();
});
if (interface_tests)
widgets
.append("div")
.classed("binning", true)
.attr("title", "Binning");
widgets.call(
flatmenu,
(d, i) => {
return (i === struct.tree.length - 1
? ["color"]
: available_griddings
).map(o => ({
value: o,
selected: d.gridding == o,
name: "grid" + i,
text: o
}));
},
d => d.value,
d => d.value,
(d, i) => "grid" + i,
onchange("grid"),
"blocks", // "select" vs "radio" vs "blocks"
struct.tree.length - 1 // last
);
if (true) {
const visual_mappings_div = widgets
.filter((_, i) => i < struct.tree.length - 1)
.append("div")
.classed("visual_mappings", true);
["color", "valueHeight", "valueWidth", "valueX", "valueY"].forEach(
mapping => {
const div = visual_mappings_div
.append("div")
.classed(mapping + "_mapping", true)
.style("display", mapping === "color" ? "block" : "none");
div
.append("div")
.attr("title", mapping)
.classed(mapping + "-icon", true)
.classed("value-icon", true);
div.call(
flatmenu,
(d, i) =>
[{ name: "…" }, ...attributes.values()].map(o => ({
value: o,
selected: d[mapping] == o.name,
name: mapping + i,
text: o.name
})), // data
d => d.value.name, // value
d => `${d.value.name} [${d.value.type}]`, // text
(d, i) => mapping + i, // name
onchange(mapping),
"blocks", // "select" vs "radio" vs "blocks"
struct.tree.length - 1 // last
);
var aggreg = div
.append("div")
.classed("rectangle aggregation", true)
.attr("title", "aggregation")
.call(
flatmenu,
(d, i) =>
[
{ name: "mean" },
{ name: "sum" },
{ name: "count" },
{ name: "distinct" }
].map(o => ({
value: o,
selected: d[mapping + "_aggregation"] == o.name,
name: mapping + "_aggregation" + i,
text: o.name
})), // data
d => d.value.name, // value
d => `${d.value.name} [${d.value.type}]`, // text
(d, i) => mapping + "_aggregation" + i, // name
onchange(mapping + "_aggregation"),
"blocks", // "select" vs "radio" vs "blocks"
struct.tree.length - 1 // last
);
}
);
}
}
form.on("change", onchange("change"));
onchange("change")();
return visible;
}