Skip to content

Instantly share code, notes, and snippets.

@matthewp
Forked from justinbmeyer/can-4.js
Last active November 30, 2017 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewp/7aab5d7d46074376f8c810c5c4ba422b to your computer and use it in GitHub Desktop.
Save matthewp/7aab5d7d46074376f8c810c5c4ba422b to your computer and use it in GitHub Desktop.
can-element full todoMVC
let todoAlgebra = new can.set.Algebra(
set.props.boolean("complete"),
set.props.id("id"),
set.props.sort("sort")
);
let todoStore = can.fixture.store([{
name: "mow lawn",
complete: false,
id: 5
},
{
name: "dishes",
complete: true,
id: 6
},
{
name: "learn canjs",
complete: false,
id: 7
}
], todoAlgebra);
can.fixture("/api/todos", todoStore);
can.fixture.delay = 1000;
class Todo extends can.Object {
constructor(props) {
super(props);
if (!this.hasOwnProperty("complete")) {
this.complete = false;
}
}
}
class TodoList extends can.Array {
get active() {
return this.filter(function(todo) {
return todo.complete === false;
});
}
get complete() {
return this.filter(function(todo) {
return todo.complete === true;
});
}
get allComplete() {
return this.length === this.complete.length;
}
get saving() {
return this.filter(function(todo) {
return todo.isSaving();
});
}
updateCompleteTo(value) {
this.forEach(function(todo) {
todo.complete = value;
todo.save();
});
}
destroyComplete() {
this.complete.forEach(function(todo) {
todo.destroy();
});
}
}
can.connect.baseMap({
url: "/api/todos",
Map: Todo,
List: TodoList,
name: "todo",
algebra: todoAlgebra
});
can.element({
tag: "todo-create",
view: `
<input id="new-todo"
placeholder="What needs to be done?"
value:bind="todo.name"
on:enter="createTodo()"/>
`,
data: {
todo: () => new Todo()
},
methods: {
createTodo() {
this.todo = new Todo();
}
}
});
can.element({
tag: "todo-list",
view: `
<ul id="todo-list">
{{#each(todos)}}
<li class="todo {{#if(./complete)}}completed{{/if}}
{{#if( isDestroying() )}}destroying{{/if}}
{{#if(../isEditing(this))}}editing{{/if}}">
<div class="view">
<input class="toggle" type="checkbox" checked:bind="complete">
<label on:dblclick="../edit(this)">{{name}}</label>
<button class="destroy" on:click="destroy()"></button>
</div>
<input class="edit" type="text"
value:bind="name"
on:enter="../updateName()"
focused:from="../isEditing(this)"
on:blur="../cancelEdit()"/>
</li>
{{/each}}
</ul>
`,
methods: {
isEditing(todo) {
return todo === this.editing;
}
edit(todo) {
this.backupName = todo.name;
this.editing = todo;
}
cancelEdit() {
if (this.editing) {
this.editing.name = this.backupName;
}
this.editing = null;
}
updateName() {
this.editing.save();
this.editing = null;
}
}
});
let TodoMVC = can.element({
tag: "todo-mvc",
props: {
todoList: {
enumerable: false,
value: null,
configurable: true,
writable: true
}
},
view: `
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<todo-create/>
</header>
<section id="main" class="">
<input id="toggle-all" type="checkbox"
checked:bind="allChecked"
disabled:from="todosList.saving.length"/>
<label for="toggle-all">Mark all as complete</label>
<todo-list todos:from="todosPromise.value"/>
</section>
<footer id="footer" class="">
<span id="todo-count">
<strong>{{todosPromise.value.active.length}}</strong> items left
</span>
<ul id="filters">
<li>
<a href="{{routeUrl(filter=undefined)}}"
{{#routeCurrent(filter=undefined)}}class='selected'{{/routeCurrent}}>All</a>
</li>
<li>
<a href="{{routeUrl(filter='active')}}"
{{#routeCurrent(filter='active')}}class='selected'{{/routeCurrent}}>Active</a>
</li>
<li>
<a href="{{routeUrl(filter='complete')}}"
{{#routeCurrent(filter='complete')}}class='selected'{{/routeCurrent}}>Completed</a>
</li>
</ul>
<button id="clear-completed"
on:click="todosList.destroyComplete()">
Clear completed ({{todosPromise.value.complete.length}})
</button>
</footer>
</section>
`,
computed: {
todosPromise() {
console.log("todosPromise");
if (!this.filter) {
return Todo.getList({});
} else {
return Todo.getList({
complete: this.filter === "complete"
});
}
},
allChecked() {
return this.todosList && this.todosList.allComplete;
},
allChecked(newVal) {
this.todosList && this.todosList.updateCompleteTo(newVal);
}
},
lifecycle: {
connected() {
this.listenTo("todosPromise", (promise) => {
promise.then((todos) => {
this.todosList = todos;
});
});
this.todosPromise.then((todos) => {
console.log(JSON.stringify(todos));
this.todosList = todos;
});
return this.stopListening.bind(this);
}
}
});
let app = new TodoMVC();
route.data = app;
route("{filter}");
route.start();
document.body.appendChild(app);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment