Tutorial 3 - Completed
Behavior Graph Tutorial 3 Completed
by slevin11
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="styles.css" />
<script type="module" src="app.js"></script>
<title>Behavior Graph Tutorial 3</title>
</head>
<body>
<div class="list-container">
<div class="title">
Todo List
</div>
<div class="list-header">
<span id="action">Add</span> Item: <input id="new-item-text" type="text" />
<button id="save">Save</button>
</div>
<ul id="list">
</ul>
<div class="list-footer">
<div>Remaining items: <span id="remaining-count"></span></div>
</div>
<div id="templates" style="display:none;">
<li class="list-item"><input class="completed-checkbox" type="checkbox" />
<div class="item-text"></div><button class="item-delete">Delete</button>
</li>
</div>
</div>
</body>
</html>
CSS
.list-container {
border: 2px solid #333;
width: 400px;
padding: 30px;
font: 1em sans-serif;
}
.list-header {
background-color: #eee;
border: 1px solid #ccc;
padding: 4px;
}
.list-footer {
background-color: #eee;
border: 1px solid #ccc;
padding: 4px;
margin-bottom: 10px;
}
.list-item {
margin-bottom: 8px;
padding: 4px;
}
.item-text {
width: 200px;
display: inline-block;
margin-left: 4px;
}
.title {
text-decoration: underline;
margin-bottom: 10px;
}
.list-item.completed .item-text {
text-decoration: line-through;
color: gray;
}
.list-item.selected {
background-color: lightgreen;
}
JavaScript
import * as bg from "https://cdn.skypack.dev/behavior-graph";
class ListExtent extends bg.Extent {
constructor(graph) {
super(graph);
this.save = this.moment();
document.querySelector('#save').addEventListener('click', () => {
this.save.updateWithAction(document.querySelector('#new-item-text').value);
});
this.allItems = this.state([]);
this.removeItem = this.moment();
this.selectRequest = this.moment();
this.selected = this.state(null);
this.behavior()
.supplies(this.allItems)
.demands(this.save, this.removeItem)
.runs(() => {
if (this.save.justUpdated && this.selected.traceValue === null) {
let item = new ItemExtent(this.graph, this.save.value, this);
this.addChildLifetime(item);
item.addToGraph();
this.allItems.value.push(item);
this.allItems.updateForce(this.allItems.value);
this.sideEffect(() => {
document.querySelector('#list').appendChild(item.itemElement);
document.querySelector('#new-item-text').value = '';
});
} else if (this.removeItem.justUpdated) {
let item = this.removeItem.value;
item.removeFromGraph();
this.allItems.update(this.allItems.value.filter(listItem => listItem !== item));
this.sideEffect(() => {
document.querySelector('#list').removeChild(item.itemElement);
});
}
});
this.behavior()
.dynamicSupplies([this.allItems], () => {
return this.allItems.value.map(item => item.itemText);
})
.demands(this.save)
.runs(() => {
if (this.save.justUpdated && this.selected.traceValue !== null) {
this.selected.traceValue.itemText.update(this.save.value);
}
});
this.behavior()
.demands(this.allItems, this.addedToGraph)
.dynamicDemands([this.allItems], () => {
return this.allItems.value.map(item =>...