ideaweb prototype

This commit is contained in:
James Turk 2024-10-14 01:47:07 -05:00
parent 920e7b98d0
commit c4e2b110cd
4 changed files with 100 additions and 25 deletions

View File

@ -34,4 +34,13 @@ export default class Graph {
addLink(source, target) { addLink(source, target) {
this.links.push({ source, target }); this.links.push({ source, target });
} }
*search(q) {
const re = new RegExp(q, "i");
for (let n of this.nodes) {
if (re.test(n.name)) {
yield n;
}
}
}
} }

View File

@ -6,8 +6,6 @@
<script type="module"> <script type="module">
import Graph from "./graph.mjs"; import Graph from "./graph.mjs";
import ModalEditor from "./modal.mjs"; import ModalEditor from "./modal.mjs";
const graph = new Graph();
const editor = new ModalEditor(graph);
const width = 800; const width = 800;
const height = 800; const height = 800;
@ -18,6 +16,10 @@
.attr("viewBox", [-width / 2, -height / 2, width, height]) .attr("viewBox", [-width / 2, -height / 2, width, height])
.attr("style", "max-width: 100%; height: auto;"); .attr("style", "max-width: 100%; height: auto;");
const color = d3.scaleOrdinal(d3.schemeCategory10); const color = d3.scaleOrdinal(d3.schemeCategory10);
const graph = new Graph();
const editor = new ModalEditor(graph);
const simulation = d3 const simulation = d3
.forceSimulation(graph.nodes) .forceSimulation(graph.nodes)
.force( .force(
@ -28,6 +30,7 @@
.force("x", d3.forceX()) .force("x", d3.forceX())
.force("y", d3.forceY()); .force("y", d3.forceY());
const selectionGroup = svg.append("g"); const selectionGroup = svg.append("g");
const secondaryGroup = svg.append("g");
const nodeGroup = svg.append("g"); const nodeGroup = svg.append("g");
const linkGroup = svg const linkGroup = svg
.append("g") .append("g")
@ -74,6 +77,12 @@
}) })
.attr("transform", (d) => `translate(${d.x}, ${d.y})`); .attr("transform", (d) => `translate(${d.x}, ${d.y})`);
const secondary = secondaryGroup
.selectAll("circle")
.data(editor.secondarySelection, (d) => d.id)
.join("circle")
.attr("r", 7)
.attr("fill", "purple");
simulation.nodes(graph.nodes); simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links); simulation.force("link").links(graph.links);
simulation.alpha(1).restart(); simulation.alpha(1).restart();
@ -84,8 +93,7 @@
const commandBar = svg const commandBar = svg
.append("g") .append("g")
.append("text") .append("text")
.attr("transform", `translate(50, 50)`) .attr("transform", `translate(${-width / 2 + 10}, ${height / 4})`)
.attr("transform", `translate(${-width / 2 + 10}, ${height / 2})`)
.style("font", "10px monospace") .style("font", "10px monospace")
.text("command bar here") .text("command bar here")
.style("fill", "darkgreen"); .style("fill", "darkgreen");
@ -101,10 +109,14 @@
nodeGroup nodeGroup
.selectAll("g") .selectAll("g")
.attr("transform", (d) => `translate(${d.x}, ${d.y})`); .attr("transform", (d) => `translate(${d.x}, ${d.y})`);
secondaryGroup
.selectAll("circle")
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
updateSelection(); updateSelection();
}); });
d3.select("body").on("keyup", function (e) { d3.select("body").on("keydown", function (e) {
editor.handleKeyup(e); editor.handleKeyup(e);
commandBar.text(editor.display()); commandBar.text(editor.display());
graphLayout(); graphLayout();

View File

@ -1,47 +1,65 @@
export default class ModalEditor { export default class ModalEditor {
constructor(graph) { constructor(graph) {
this.graph = graph; this.graph = graph;
this.mode = "command"; this.activeMode = this.commandMode;
this.word = ""; this.word = "";
this.secondarySelection = [];
} }
handleKeyup(event) { handleKeyup(event) {
console.log(event); console.log(event);
switch (this.mode) { this.activeMode(event);
case "command":
this.commandModeKey(event);
break;
case "insert":
this.insertModeKey(event);
break;
}
} }
commandModeKey(event) { commandMode(event) {
switch (event.key) { switch (event.key) {
case "i": case "i":
this.mode = "insert"; this.activeMode = this.insertMode;
break;
case "s":
this.activeMode = this.searchMode;
break; break;
} }
} }
insertModeKey(event) { gatherText(event) {
if (event.key === "Enter") { if (event.key === "Escape" || event.key == "Enter") {
let newId = this.graph.insert(this.word, "unknown"); this.activeMode = this.commandMode;
this.graph.addLink(newId, this.graph.InboxId);
this.word = ""; this.word = "";
this.mode = "command"; } else if (event.key == "Backspace") {
this.word = this.word.substring(0, this.word.length - 1);
event.stopPropagation();
} else { } else {
this.word += event.key; this.word += event.key;
} }
} }
insertMode(event) {
// override enter handler
if (event.key === "Enter") {
let newId = this.graph.insert(this.word, "unknown");
this.graph.addLink(newId, this.graph.InboxId);
this.word = "";
this.activeMode = this.commandMode;
} else {
this.gatherText(event);
}
}
searchMode(event) {
this.gatherText(event);
this.secondarySelection = Array.from(this.graph.search(this.word));
console.log(this.word, this.secondarySelection);
}
display() { display() {
switch (this.mode) { switch (this.activeMode) {
case "insert": case this.insertMode:
return "insert> " + this.word; return "insert> " + this.word;
case "command": case this.searchMode:
return "(i)nsert"; return "search/ " + this.word;
default:
return "(i)nsert (s)earch";
} }
} }
} }

36
time-left.html Normal file
View File

@ -0,0 +1,36 @@
<!doctype html>
<html>
<body>
<div id="container"></div>
<script src="js/d3.v7.js"></script>
<script type="module">
// create the <svg> element
const width = 800;
const height = 800;
const svg = d3.create("svg").attr("width", width).attr("height", height);
const years = 80;
const age = 37;
const freePerWeek = 8 * 5 + 32;
const weeksInYear = 52;
const freeUsed = age * freePerWeek * weeksInYear;
const freeLeft = (years - age) * freePerWeek * weeksInYear;
svg
.append("path")
.attr("transform", "translate(400,400)")
.attr(
"d",
d3.arc()({
innerRadius: 100,
outerRadius: 200,
startAngle: -Math.PI / 2,
endAngle: Math.PI / 2,
}),
);
// Append the SVG element.
container.append(svg.node());
</script>
</body>
</html>