ideaweb prototype
This commit is contained in:
parent
920e7b98d0
commit
c4e2b110cd
@ -34,4 +34,13 @@ export default class Graph {
|
||||
addLink(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,6 @@
|
||||
<script type="module">
|
||||
import Graph from "./graph.mjs";
|
||||
import ModalEditor from "./modal.mjs";
|
||||
const graph = new Graph();
|
||||
const editor = new ModalEditor(graph);
|
||||
|
||||
const width = 800;
|
||||
const height = 800;
|
||||
@ -18,6 +16,10 @@
|
||||
.attr("viewBox", [-width / 2, -height / 2, width, height])
|
||||
.attr("style", "max-width: 100%; height: auto;");
|
||||
const color = d3.scaleOrdinal(d3.schemeCategory10);
|
||||
|
||||
const graph = new Graph();
|
||||
const editor = new ModalEditor(graph);
|
||||
|
||||
const simulation = d3
|
||||
.forceSimulation(graph.nodes)
|
||||
.force(
|
||||
@ -28,6 +30,7 @@
|
||||
.force("x", d3.forceX())
|
||||
.force("y", d3.forceY());
|
||||
const selectionGroup = svg.append("g");
|
||||
const secondaryGroup = svg.append("g");
|
||||
const nodeGroup = svg.append("g");
|
||||
const linkGroup = svg
|
||||
.append("g")
|
||||
@ -74,6 +77,12 @@
|
||||
})
|
||||
.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.force("link").links(graph.links);
|
||||
simulation.alpha(1).restart();
|
||||
@ -84,8 +93,7 @@
|
||||
const commandBar = svg
|
||||
.append("g")
|
||||
.append("text")
|
||||
.attr("transform", `translate(50, 50)`)
|
||||
.attr("transform", `translate(${-width / 2 + 10}, ${height / 2})`)
|
||||
.attr("transform", `translate(${-width / 2 + 10}, ${height / 4})`)
|
||||
.style("font", "10px monospace")
|
||||
.text("command bar here")
|
||||
.style("fill", "darkgreen");
|
||||
@ -101,10 +109,14 @@
|
||||
nodeGroup
|
||||
.selectAll("g")
|
||||
.attr("transform", (d) => `translate(${d.x}, ${d.y})`);
|
||||
secondaryGroup
|
||||
.selectAll("circle")
|
||||
.attr("cx", (d) => d.x)
|
||||
.attr("cy", (d) => d.y);
|
||||
updateSelection();
|
||||
});
|
||||
|
||||
d3.select("body").on("keyup", function (e) {
|
||||
d3.select("body").on("keydown", function (e) {
|
||||
editor.handleKeyup(e);
|
||||
commandBar.text(editor.display());
|
||||
graphLayout();
|
||||
|
@ -1,47 +1,65 @@
|
||||
export default class ModalEditor {
|
||||
constructor(graph) {
|
||||
this.graph = graph;
|
||||
this.mode = "command";
|
||||
this.activeMode = this.commandMode;
|
||||
this.word = "";
|
||||
this.secondarySelection = [];
|
||||
}
|
||||
|
||||
handleKeyup(event) {
|
||||
console.log(event);
|
||||
switch (this.mode) {
|
||||
case "command":
|
||||
this.commandModeKey(event);
|
||||
break;
|
||||
case "insert":
|
||||
this.insertModeKey(event);
|
||||
break;
|
||||
}
|
||||
this.activeMode(event);
|
||||
}
|
||||
|
||||
commandModeKey(event) {
|
||||
commandMode(event) {
|
||||
switch (event.key) {
|
||||
case "i":
|
||||
this.mode = "insert";
|
||||
this.activeMode = this.insertMode;
|
||||
break;
|
||||
case "s":
|
||||
this.activeMode = this.searchMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
insertModeKey(event) {
|
||||
if (event.key === "Enter") {
|
||||
let newId = this.graph.insert(this.word, "unknown");
|
||||
this.graph.addLink(newId, this.graph.InboxId);
|
||||
gatherText(event) {
|
||||
if (event.key === "Escape" || event.key == "Enter") {
|
||||
this.activeMode = this.commandMode;
|
||||
this.word = "";
|
||||
this.mode = "command";
|
||||
} else if (event.key == "Backspace") {
|
||||
this.word = this.word.substring(0, this.word.length - 1);
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
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() {
|
||||
switch (this.mode) {
|
||||
case "insert":
|
||||
switch (this.activeMode) {
|
||||
case this.insertMode:
|
||||
return "insert> " + this.word;
|
||||
case "command":
|
||||
return "(i)nsert";
|
||||
case this.searchMode:
|
||||
return "search/ " + this.word;
|
||||
default:
|
||||
return "(i)nsert (s)earch";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
time-left.html
Normal file
36
time-left.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user