Skip to content

Instantly share code, notes, and snippets.

@twetzel
Forked from jaigouk/db.coffee
Last active September 5, 2015 21:39
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 twetzel/bbb770ccd0b959c8a529 to your computer and use it in GitHub Desktop.
Save twetzel/bbb770ccd0b959c8a529 to your computer and use it in GitHub Desktop.
Riot.js Todo MVC in coffeescript https://github.com/moot/riotjs
DB = (key) ->
store = window.localStorage
get: ->
JSON.parse store[key] or "{}"
put: (data) ->
store[key] = JSON.stringify(data)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Riot! JS | The 1kb framework</title>
<link rel="stylesheet" href="../bower_components/todomvc-common/base.css">
</head>
<script type="html/todo">
<li id="{id}">
<div class="view">
<input class="toggle" type="checkbox">
<label>{name}</label>
<button class="destroy"/>
</div>
<input class="edit" value="{name}">
</li>
</script>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul>
</section>
<footer id="footer">
<span id="todo-count"></span>
<ul id="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed"></button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Template by <a href="https://moot.it/blog">Tero Piirainen &bull; Moot</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="../bower_components/todomvc-common/base.js"></script>
<script src="../bower_components/jquery/jquery.min.js"></script>
<script src="../jquery.riot.js"></script>
<script src="../ext/render.js"></script>
<script src="store.js"></script>
<script src="api.js"></script>
<script src="app.js"></script>
</body>
</html>
# The model
Todo = (db) ->
db = db or DB("todo-riot")
self = $.observable(this)
items = db.get()
self.add = (name) ->
item =
id: "_" + ("" + Math.random()).slice(2)
name: name
items[item.id] = item
self.trigger "add", item
self.edit = (item) ->
items[item.id] = item
self.trigger "edit", item
self.remove = (filter) ->
els = self.items(filter)
$.each els, ->
delete items[@id]
self.trigger "remove", els
self.toggle = (id) ->
item = items[id]
item.done = not item.done
self.trigger "toggle", item
# @param filter: <empty>, id, "active", "completed"
self.items = (filter) ->
ret = []
$.each items, (id, item) ->
ret.push item if not filter or filter is id or filter is ((if item.done then "completed" else "active"))
ret
# sync database
self.on "add remove toggle edit", ->
db.put items
# The presenter
(->
#
# A Model instance exposed to global space so you can
# use the Todo APi from the console. For example:
#
# todo.add("My task");
#
# HTML for a single todo item
# Listen to user events
# Listen to model events
# counts
# Routing
# clear list and add new ones
# selected class
# update counts
# Private functions
toggle = (el, flag) ->
el.toggleClass "completed", flag
$(":checkbox", el).prop "checked", flag
add = (item) ->
blur = ->
el.removeClass "editing"
item = this if @id
el = $($.render(template, item)).appendTo(root)
input = $(".edit", el)
$(".toggle", el).click ->
todo.toggle item.id
toggle el, !!item.done
# edit
input.blur(blur).keydown (e) ->
val = $.trim(@value)
if e.which is 13 and val
item.name = val
todo.edit item
blur() if e.which is 27
$("label", el).dblclick ->
el.addClass "editing"
input.focus()[0].select()
# remove
$(".destroy", el).click ->
todo.remove item.id
counts = ->
active = todo.items("active").length
done = todo.items("completed").length
$("#todo-count").html "<strong>" + active + "</strong> item" + ((if active is 1 then "" else "s")) + " left"
$("#clear-completed").toggle(done > 0).text "Clear completed (" + done + ")"
$("#footer").toggle active + done > 0
"use strict"
window.todo = new Todo()
template = $("[type='html/todo']").html()
root = $("#todo-list")
nav = $("#filters a")
$("#new-todo").keyup (e) ->
val = $.trim(@value)
if e.which is 13 and val
todo.add val
@value = ""
$("#toggle-all").click ->
$("li", root).each ->
todo.toggle @id
$("#clear-completed").click ->
todo.remove "completed"
todo.on("add", add).on("remove", (items) ->
$.each items, ->
$("#" + @id).remove()
).on("toggle", (item) ->
toggle $("#" + item.id), !!item.done
).on("edit", (item) ->
el = $("#" + item.id)
el.removeClass "editing"
$("label, .edit", el).text(item.name).val item.name
).on "add remove toggle", counts
nav.click ->
$.route $(this).attr("href")
$.route (hash) ->
root.empty() and $.each(todo.items(hash.slice(2)), add)
nav.removeClass("selected").filter("[href='" + hash + "']").addClass "selected"
counts()
)()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment