JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://canjs.com/release/2.1.0/can.jquery.js"></script>
<script src="http://canjs.com/release/2.1.0/can.object.js"></script>
<script src="http://canjs.com/release/2.1.0/can.fixture.js"></script>
<div id="content">
</div>
<script id='appMustache' type='text/mustache'>
<todos-app>
<h2>Todays to-dos</h2>
{{#selectedTodo}}
<div id='editor'>
<input type='text' can-value='description' can-change="saveTodo"/>
</div>
{{/selectedTodo}}
<ul>
{{#each todos}}
<li>
<input type='checkbox' can-value='complete'>
<span class="description {{#if complete}}done{{/if}}" can-click='select'>{{description}}</span>
<button can-click="destroy"></button>
</li>
{{/each}}
</ul>
</todos-app>
</script>
CSS
/* @override
http://beta.canjs.com/example/example.css */
* {
font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
}
todos-app {
display: block;
}
#content {
max-width: 450px;
background-color: #ffffff;
}
h2 {
margin: 0 0 8px 2px;
font-size: 18px;
}
#editor {
position: relative;
height: 24px;
}
#editor > * {
display: block;
position: absolute;
}
#editor > input[type=text] {
height: 18px;
font-size: 14px;
font-family: Arial;
left: 18px;
right: 28px;
}
#editor > .spinner {
top: 0px;
right: 4px;
width: 16px;
cursor: pointer;
color: #4169be;
font-weight: bold;
}
#editor > .spinner.hidden {
display: none;
}
ul {
list-style: none;
padding-left: 0;
margin: 8px 0 0 0;
}
li {
position: relative;
padding: 2px 0;
height: 24px;
font-size: 14px;
}
li:hover {
background-color: #eeeeee;
}
li > * {
display: block;
position: absolute;
}
li > input {
top: 4px;
left: 2px;
}
li > .description {
top: 5px;
right: 20px;
left: 22px;
}
li > .description.done {
text-decoration: line-through;
}
li > button {
border: 0;
background: transparent;
top: 6px;
right: 0;
width: 16px;
}
li > button:after {
display: block;
cursor: pointer;
color: #d63129;
content: 'X';
}
JavaScript
// Here's where we get, save, and delete to-dos.
// (Yep, this is all we need to access the Todo
// REST endpoints!)
var Todo = can.Model.extend({
findAll: 'GET /todos',
findOne: 'GET /todos/{id}',
update: 'PUT /todos/{id}',
destroy: 'DELETE /todos/{id}'
}, {});
// For this example, we're not actually going out to
// a REST endpoint, so we'll use fixtures to emulate that.
// Fixtures help you test your application when you
// don't have access to your REST services.
var TODOS = [
'Download CanJS',
'Read the guides',
'Build your app',
'Become immortal',
'Haircut @ 2pm'
];
var todoStore = can.fixture.make(TODOS.length, function(i) {
return {
id: i + 1,
description: TODOS[i],
done: false
};
});
can.fixture({
'GET /todos': todoStore.findAll,
'GET /todos/{id}': todoStore.findOne,
'PUT /todos/{id}': todoStore.update,
'DELETE /todos/{id}': todoStore.destroy
});
// Let's drag this out a bit.
can.fixture.delay = 500;
can.Component.extend({
tag: "todos-app",
scope: {
selectedTodo: null,
todos: new Todo.List({}),
select: function(todo){
this.attr('selectedTodo', todo);
},
saveTodo: function(todo) {
todo.save();
this.removeAttr('selectedTodo');
}
}
})
// Start the application by rendering our template!
$("#content").html(can.view("appMustache", { }))