Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
todomvc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Sven Franck
todomvc
Commits
e7ae5b55
Commit
e7ae5b55
authored
Apr 21, 2012
by
Sindre Sorhus
Browse files
Options
Browse Files
Download
Plain Diff
Close #127: Spine rewrite. Fixes #70
parents
ae5baf13
2d644b75
Changes
23
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
724 additions
and
1262 deletions
+724
-1262
architecture-examples/spine/Cakefile
architecture-examples/spine/Cakefile
+18
-0
architecture-examples/spine/README.md
architecture-examples/spine/README.md
+15
-0
architecture-examples/spine/css/app.css
architecture-examples/spine/css/app.css
+208
-0
architecture-examples/spine/css/application.css
architecture-examples/spine/css/application.css
+0
-169
architecture-examples/spine/images/destroy.png
architecture-examples/spine/images/destroy.png
+0
-0
architecture-examples/spine/index.html
architecture-examples/spine/index.html
+58
-46
architecture-examples/spine/js/app.js
architecture-examples/spine/js/app.js
+114
-45
architecture-examples/spine/js/controllers/tasks.js
architecture-examples/spine/js/controllers/tasks.js
+0
-65
architecture-examples/spine/js/controllers/todos.js
architecture-examples/spine/js/controllers/todos.js
+70
-0
architecture-examples/spine/js/lib/local.js
architecture-examples/spine/js/lib/local.js
+30
-0
architecture-examples/spine/js/lib/route.min.js
architecture-examples/spine/js/lib/route.min.js
+7
-0
architecture-examples/spine/js/lib/spine.min.js
architecture-examples/spine/js/lib/spine.min.js
+23
-0
architecture-examples/spine/js/models/task.js
architecture-examples/spine/js/models/task.js
+0
-47
architecture-examples/spine/js/models/todo.js
architecture-examples/spine/js/models/todo.js
+44
-0
architecture-examples/spine/lib/jquery.min.js
architecture-examples/spine/lib/jquery.min.js
+0
-4
architecture-examples/spine/lib/jquery.tmpl.min.js
architecture-examples/spine/lib/jquery.tmpl.min.js
+0
-10
architecture-examples/spine/lib/local.js
architecture-examples/spine/lib/local.js
+0
-28
architecture-examples/spine/lib/spine.js
architecture-examples/spine/lib/spine.js
+0
-751
architecture-examples/spine/src/app.coffee
architecture-examples/spine/src/app.coffee
+85
-43
architecture-examples/spine/src/controllers/tasks.coffee
architecture-examples/spine/src/controllers/tasks.coffee
+0
-39
architecture-examples/spine/src/controllers/todos.coffee
architecture-examples/spine/src/controllers/todos.coffee
+40
-0
architecture-examples/spine/src/models/task.coffee
architecture-examples/spine/src/models/task.coffee
+0
-15
architecture-examples/spine/src/models/todo.coffee
architecture-examples/spine/src/models/todo.coffee
+12
-0
No files found.
architecture-examples/spine/Cakefile
0 → 100755
View file @
e7ae5b55
{
print
}
=
require
'util'
{
spawn
}
=
require
'child_process'
task
'build'
,
'Build js/ from src/'
,
->
coffee
=
spawn
'coffee'
,
[
'-c'
,
'-o'
,
'js'
,
'src'
]
coffee
.
stderr
.
on
'data'
,
(
data
)
->
process
.
stderr
.
write
data
.
toString
()
coffee
.
stdout
.
on
'data'
,
(
data
)
->
print
data
.
toString
()
coffee
.
on
'exit'
,
(
code
)
->
callback
?
()
if
code
is
0
task
'watch'
,
'Watch src/ for changes'
,
->
coffee
=
spawn
'coffee'
,
[
'-w'
,
'-c'
,
'-o'
,
'js'
,
'src'
]
coffee
.
stderr
.
on
'data'
,
(
data
)
->
process
.
stderr
.
write
data
.
toString
()
coffee
.
stdout
.
on
'data'
,
(
data
)
->
print
data
.
toString
()
\ No newline at end of file
architecture-examples/spine/README.md
0 → 100644
View file @
e7ae5b55
# Spine.js TodoMVC app
## Getting started
You need
[
CoffeScript
](
http://coffeescript.org
)
to compile if you make changes to the files in the
`src`
folder.
### Compile
Open Terminal in this folder.
-
`cake build`
to compile once
-
`cake watch`
to compile on save
\ No newline at end of file
architecture-examples/spine/css/app.css
0 → 100755
View file @
e7ae5b55
html
,
body
{
margin
:
0
;
padding
:
0
;
}
body
{
font
:
14px
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
line-height
:
1.4em
;
background
:
#eeeeee
;
color
:
#333333
;
width
:
520px
;
margin
:
0
auto
;
-webkit-font-smoothing
:
antialiased
;
}
#todoapp
{
background
:
#fff
;
padding
:
20px
;
margin-bottom
:
40px
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-ms-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-webkit-border-radius
:
0
0
5px
5px
;
-moz-border-radius
:
0
0
5px
5px
;
-ms-border-radius
:
0
0
5px
5px
;
-o-border-radius
:
0
0
5px
5px
;
border-radius
:
0
0
5px
5px
;
}
#todoapp
h1
{
font-size
:
36px
;
font-weight
:
bold
;
text-align
:
center
;
padding
:
0
0
10px
0
;
}
#todoapp
input
[
type
=
"text"
]
{
width
:
466px
;
font-size
:
24px
;
font-family
:
inherit
;
line-height
:
1.4em
;
border
:
0
;
outline
:
none
;
padding
:
6px
;
border
:
1px
solid
#999999
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
-ms-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
}
#todoapp
input
::-webkit-input-placeholder
{
font-style
:
italic
;
}
#main
{
display
:
none
;
}
#todo-list
{
margin
:
10px
0
;
padding
:
0
;
list-style
:
none
;
}
#todo-list
li
{
padding
:
18px
20px
18px
0
;
position
:
relative
;
font-size
:
24px
;
border-bottom
:
1px
solid
#cccccc
;
}
#todo-list
li
:last-child
{
border-bottom
:
none
;
}
#todo-list
li
.done
label
{
color
:
#777777
;
text-decoration
:
line-through
;
}
#todo-list
li
.destroy
{
display
:
none
;
position
:
absolute
;
top
:
20px
;
right
:
10px
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
background
:
url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAABGdBTUEAALGPC/xhBQAAACdQTFRFzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAA////zMzMhnu0WAAAAAt0Uk5T5u3pqtV3jFQEKAC0bVelAAAAfUlEQVQI12NYtWpFsc8R865VqxhWrZpyBgg8QcylZ8AgCsjMgTCPrWJYfgYKqhjWwJgaDDVnzpw+c2bPmTPHGWzOnNm95/TuM2cOM/AARXfvBooeZAAp270bRCIz4QoOIGtDMqwJZoUEQzvCYrhzuhhWtUKYEahOX7UK6iEA3A6NUGwCTZIAAAAASUVORK5CYII=')
no-repeat
center
center
;
}
#todo-list
li
:hover
.destroy
{
display
:
block
;
}
#todo-list
li
.editing
{
border-bottom
:
none
;
margin-top
:
-1px
;
padding
:
0
;
}
#todo-list
li
.editing
:last-child
{
margin-bottom
:
-1px
;
}
#todo-list
li
.editing
.edit
{
display
:
block
;
width
:
444px
;
padding
:
13px
15px
14px
20px
;
margin
:
0
;
}
#todo-list
li
.editing
.view
{
display
:
none
;
}
#todo-list
li
.view
label
{
word-break
:
break-word
;
}
#todo-list
li
.edit
{
display
:
none
;
}
#todoapp
footer
{
display
:
none
;
margin
:
0
-20px
-20px
-20px
;
overflow
:
hidden
;
color
:
#555555
;
background
:
#f4fce8
;
border-top
:
1px
solid
#ededed
;
padding
:
0
20px
;
line-height
:
37px
;
-webkit-border-radius
:
0
0
5px
5px
;
-moz-border-radius
:
0
0
5px
5px
;
-ms-border-radius
:
0
0
5px
5px
;
-o-border-radius
:
0
0
5px
5px
;
border-radius
:
0
0
5px
5px
;
}
#clear-completed
{
display
:
none
;
float
:
right
;
line-height
:
20px
;
text-decoration
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
color
:
#555555
;
font-size
:
11px
;
margin-top
:
8px
;
margin-bottom
:
8px
;
padding
:
0
10px
1px
;
cursor
:
pointer
;
-webkit-border-radius
:
12px
;
-moz-border-radius
:
12px
;
-ms-border-radius
:
12px
;
-o-border-radius
:
12px
;
border-radius
:
12px
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
-ms-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
}
#clear-completed
:hover
{
background
:
rgba
(
0
,
0
,
0
,
0.15
);
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
-ms-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
}
#clear-completed
:active
{
position
:
relative
;
top
:
1px
;
}
#todo-count
span
{
font-weight
:
bold
;
}
#instructions
{
margin
:
10px
auto
;
color
:
#777777
;
text-shadow
:
rgba
(
255
,
255
,
255
,
0.8
)
0
1px
0
;
text-align
:
center
;
}
#instructions
a
{
color
:
#336699
;
}
#credits
{
margin
:
30px
auto
;
color
:
#999
;
text-shadow
:
rgba
(
255
,
255
,
255
,
0.8
)
0
1px
0
;
text-align
:
center
;
}
#credits
a
{
color
:
#888
;
}
\ No newline at end of file
architecture-examples/spine/css/application.css
deleted
100644 → 0
View file @
ae5baf13
html
,
body
{
margin
:
0
;
padding
:
0
;
}
body
{
font-family
:
"Helvetica Neue"
,
helvetica
,
arial
,
sans-serif
;
font-size
:
14px
;
line-height
:
1.4em
;
background
:
#eeeeee
;
color
:
#333333
;
}
#views
{
width
:
520px
;
margin
:
0
auto
40px
auto
;
background
:
white
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
2px
6px
0
;
-moz-border-radius
:
0
0
5px
5px
;
-o-border-radius
:
0
0
5px
5px
;
-webkit-border-radius
:
0
0
5px
5px
;
border-radius
:
0
0
5px
5px
;
}
#tasks
{
padding
:
20px
;
}
#tasks
h1
{
font-size
:
36px
;
font-weight
:
bold
;
text-align
:
center
;
padding
:
0
0
10px
0
;
}
#tasks
input
[
type
=
"text"
]
{
width
:
466px
;
font-size
:
24px
;
font-family
:
inherit
;
line-height
:
1.4em
;
border
:
0
;
outline
:
none
;
padding
:
6px
;
border
:
1px
solid
#999999
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
1px
2px
0
inset
;
}
#tasks
input
::-webkit-input-placeholder
{
font-style
:
italic
;
}
#tasks
.items
{
margin
:
10px
0
;
list-style
:
none
;
}
#tasks
.item
{
padding
:
15px
20px
15px
0
;
position
:
relative
;
font-size
:
24px
;
border-bottom
:
1px
solid
#cccccc
;
}
#tasks
.item.done
span
{
color
:
#777777
;
text-decoration
:
line-through
;
}
#tasks
.item
.destroy
{
position
:
absolute
;
right
:
10px
;
top
:
16px
;
display
:
none
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
background
:
url(../images/destroy.png)
no-repeat
center
center
;
}
#tasks
.item
:hover
.destroy
{
display
:
block
;
}
#tasks
.item
.edit
{
display
:
none
;
}
#tasks
.item.editing
.edit
{
display
:
block
;
}
#tasks
.item.editing
.view
{
display
:
none
;
}
#tasks
footer
{
display
:
block
;
margin
:
20px
-20px
-20px
-20px
;
overflow
:
hidden
;
color
:
#555555
;
background
:
#f4fce8
;
border-top
:
1px
solid
#ededed
;
padding
:
0
20px
;
line-height
:
36px
;
-moz-border-radius
:
0
0
5px
5px
;
-o-border-radius
:
0
0
5px
5px
;
-webkit-border-radius
:
0
0
5px
5px
;
border-radius
:
0
0
5px
5px
;
}
#tasks
.clear
{
display
:
block
;
float
:
right
;
line-height
:
20px
;
text-decoration
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
color
:
#555555
;
font-size
:
11px
;
margin-top
:
8px
;
margin-bottom
:
8px
;
padding
:
0
10px
1px
;
-moz-border-radius
:
12px
;
-webkit-border-radius
:
12px
;
-o-border-radius
:
12px
;
border-radius
:
12px
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
-1px
0
0
;
cursor
:
pointer
;
}
/* focus is actually pointless here as it's not
possible to tab to the anchor for some reason */
#tasks
.clear
:hover
,
#tasks
.clear
:focus
{
background
:
rgba
(
0
,
0
,
0
,
0.15
);
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.3
)
0
-1px
0
0
;
}
#tasks
.clear
:active
{
position
:
relative
;
top
:
1px
;
}
#tasks
.count
span
{
font-weight
:
bold
;
}
#credits
{
width
:
520px
;
margin
:
30px
auto
;
color
:
#999
;
text-shadow
:
rgba
(
255
,
255
,
255
,
0.8
)
0
1px
0
;
text-align
:
center
;
}
#credits
a
{
color
:
#888
;
}
architecture-examples/spine/images/destroy.png
deleted
100644 → 0
View file @
ae5baf13
1.19 KB
architecture-examples/spine/index.html
View file @
e7ae5b55
<!
DOCTYPE
html>
<html>
<!
doctype
html>
<html
lang=
"en"
>
<head>
<title>
Spine.js
</title>
<link
rel=
"stylesheet"
href=
"css/application.css"
type=
"text/css"
charset=
"utf-8"
>
<script
src=
"lib/jquery.min.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"lib/jquery.tmpl.min.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"lib/spine.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"lib/local.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"js/controllers/tasks.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"js/models/task.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<script
src=
"js/app.js"
type=
"text/javascript"
charset=
"utf-8"
></script>
<meta
charset=
"utf-8"
>
<title>
Spine.js • TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"../../assets/base.css"
>
</head>
<body>
<div
id=
"views"
>
<div
id=
"tasks"
>
<h1>
Todos
</h1>
<form
id=
"new-task"
>
<input
name=
"name"
type=
"text"
placeholder=
"What needs to be done?"
>
</form>
<div
class=
"items"
>
<script
type=
"text/html"
id=
"task-template"
>
<
div
class
=
"
item {{if done}}done{{/if}}
"
>
<
div
class
=
"
view
"
title
=
"
Double click to edit...
"
>
<
input
type
=
"
checkbox
"
{{
if
done
}}
checked
=
"
checked
"
{{
/if}}
>
<
span
>
$
{
name
}
<
/span> <a class="destroy"></
a
>
<
/div
>
<
form
class
=
"
edit
"
>
<
input
type
=
"
text
"
name
=
"
name
"
value
=
"
${name}
"
>
<
/form
>
<
/div
>
</script>
</div>
<footer>
<a
class=
"clear"
>
Clear completed
</a>
<div
class=
"count"
><span
class=
"countVal"
></span>
left
</div>
</footer>
</div>
</div>
<div
id=
"credits"
>
Based on the official
<a
href=
"https://github.com/maccman/spine.todos"
>
Spine.Todos
</a>
.
</div>
<section
id=
"todoapp"
>
<header
id=
"header"
>
<h1>
Todos
</h1>
<input
id=
"new-todo"
placeholder=
"What needs to be done?"
>
</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"
><strong>
1
</strong>
item left
</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"
>
Clear completed
</button>
</footer>
</section>
<footer
id=
"info"
>
<p>
Double-click to edit a todo
</p>
<!-- delete this ↓ -->
<p>
Inspired by the official
<a
href=
"https://github.com/maccman/spine.todos"
>
Spine.Todos
</a></p>
<!-- change this out with your name and url ↓ -->
<p>
Created by
<a
href=
"http://sindresorhus.com"
>
Sindre Sorhus
</a></p>
</footer>
<script
type=
"text/x-handlebars-template"
id=
"todo-template"
>
{{
#
this
}}
<
li
{{
#
if
completed
}}
class
=
"
completed
"
{{
/if}}
>
<
div
class
=
"
view
"
>
<
input
class
=
"
toggle
"
type
=
"
checkbox
"
{{
#
if
completed
}}
checked
{{
/if}}
>
<
label
>
{{
title
}}
<
/label
>
<
button
class
=
"
destroy
"
><
/button
>
<
/div
>
<
input
class
=
"
edit
"
value
=
"
{{title}}
"
>
<
/li
>
{{
/
this
}}
</script>
<script
src=
"../../assets/jquery.min.js"
></script>
<script
src=
"../../assets/handlebars.min.js"
></script>
<script
src=
"js/lib/spine.min.js"
></script>
<script
src=
"js/lib/route.min.js"
></script>
<script
src=
"js/lib/local.js"
></script>
<script
src=
"js/controllers/todos.js"
></script>
<script
src=
"js/models/todo.js"
></script>
<script
src=
"js/app.js"
></script>
</body>
</html>
\ No newline at end of file
architecture-examples/spine/js/app.js
View file @
e7ae5b55
(
function
()
{
var
TaskApp
;
var
__bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
},
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
var
TodoApp
,
__bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
},
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
TaskApp
=
(
function
()
{
TodoApp
=
(
function
(
_super
)
{
var
ENTER_KEY
;
__extends
(
T
askApp
,
Spine
.
Controll
er
);
__extends
(
T
odoApp
,
_sup
er
);
TaskApp
.
prototype
.
elements
=
{
'
.items
'
:
'
tasks
'
,
'
.countVal
'
:
'
counter
'
,
'
a.clear
'
:
'
clearCompleted
'
,
'
form#new-task input[name=name]
'
:
'
newTaskName
'
ENTER_KEY
=
13
;
TodoApp
.
prototype
.
elements
=
{
'
#new-todo
'
:
'
newTodoInput
'
,
'
#toggle-all
'
:
'
toggleAllElem
'
,
'
#main
'
:
'
main
'
,
'
#todo-list
'
:
'
todos
'
,
'
#footer
'
:
'
footer
'
,
'
#todo-count
'
:
'
count
'
,
'
#filters a
'
:
'
filters
'
,
'
#clear-completed
'
:
'
clearCompleted
'
};
TaskApp
.
prototype
.
events
=
{
'
submit form#new-task
'
:
'
new
'
,
'
click a.clear
'
:
'
clearCompleted
'
TodoApp
.
prototype
.
events
=
{
'
keyup #new-todo
'
:
'
new
'
,
'
click #toggle-all
'
:
'
toggleAll
'
,
'
click #clear-completed
'
:
'
clearCompleted
'
};
function
TaskApp
()
{
this
.
toggleClearCompleted
=
__bind
(
this
.
toggleClearCompleted
,
this
);
this
.
renderCounter
=
__bind
(
this
.
renderCounter
,
this
);
this
.
renderAll
=
__bind
(
this
.
renderAll
,
this
);
this
.
renderNew
=
__bind
(
this
.
renderNew
,
this
);
TaskApp
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
Task
.
bind
(
'
create
'
,
this
.
renderNew
);
Task
.
bind
(
'
refresh
'
,
this
.
renderAll
);
Task
.
bind
(
'
refresh change
'
,
this
.
renderCounter
);
Task
.
bind
(
'
refresh change
'
,
this
.
toggleClearCompleted
);
Task
.
fetch
();
function
TodoApp
()
{
this
.
renderFooter
=
__bind
(
this
.
renderFooter
,
this
);
this
.
toggleElems
=
__bind
(
this
.
toggleElems
,
this
);
this
.
addAll
=
__bind
(
this
.
addAll
,
this
);
this
.
addNew
=
__bind
(
this
.
addNew
,
this
);
TodoApp
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
Todo
.
bind
(
'
create
'
,
this
.
addNew
);
Todo
.
bind
(
'
refresh
'
,
this
.
addAll
);
Todo
.
bind
(
'
refresh change
'
,
this
.
toggleElems
);
Todo
.
bind
(
'
refresh change
'
,
this
.
renderFooter
);
Todo
.
fetch
();
this
.
routes
({
'
/:filter
'
:
function
(
param
)
{
this
.
filter
=
param
.
filter
;
/*
TODO: Need to figure out why the route doesn't trigger `change` event
*/
Todo
.
trigger
(
'
refresh
'
);
return
this
.
filters
.
removeClass
(
'
selected
'
).
filter
(
"
[href='#/
"
+
this
.
filter
+
"
']
"
).
addClass
(
'
selected
'
);
}
});
}
TaskApp
.
prototype
[
"
new
"
]
=
function
(
e
)
{
e
.
preventDefault
();
Task
.
fromForm
(
'
form#new-task
'
).
save
();
return
this
.
newTaskName
.
val
(
''
);
TodoApp
.
prototype
[
"
new
"
]
=
function
(
e
)
{
var
val
;
val
=
$
.
trim
(
this
.
newTodoInput
.
val
());
if
(
e
.
which
===
ENTER_KEY
&&
val
)
{
Todo
.
create
({
title
:
val
});
return
this
.
newTodoInput
.
val
(
''
);
}
};
TodoApp
.
prototype
.
getByFilter
=
function
()
{
switch
(
this
.
filter
)
{
case
'
active
'
:
return
Todo
.
active
();
case
'
completed
'
:
return
Todo
.
completed
();
default
:
return
Todo
.
all
();
}
};
T
askApp
.
prototype
.
renderNew
=
function
(
task
)
{
T
odoApp
.
prototype
.
addNew
=
function
(
todo
)
{
var
view
;
view
=
new
T
ask
s
({
t
ask
:
task
view
=
new
T
odo
s
({
t
odo
:
todo
});
return
this
.
t
ask
s
.
append
(
view
.
render
().
el
);
return
this
.
t
odo
s
.
append
(
view
.
render
().
el
);
};
TaskApp
.
prototype
.
renderAll
=
function
()
{
return
Task
.
each
(
this
.
renderNew
);
TodoApp
.
prototype
.
addAll
=
function
()
{
var
todo
,
_i
,
_len
,
_ref
,
_results
;
this
.
todos
.
empty
();
_ref
=
this
.
getByFilter
();
_results
=
[];
for
(
_i
=
0
,
_len
=
_ref
.
length
;
_i
<
_len
;
_i
++
)
{
todo
=
_ref
[
_i
];
_results
.
push
(
this
.
addNew
(
todo
));
}
return
_results
;
};
TodoApp
.
prototype
.
toggleAll
=
function
(
e
)
{
return
Todo
.
each
(
function
(
todo
)
{
/*
TODO: Model updateAttribute sometimes won't stick:
https://github.com/maccman/spine/issues/219
*/
todo
.
updateAttribute
(
'
completed
'
,
e
.
target
.
checked
);
return
todo
.
trigger
(
'
update
'
,
todo
);
});
};
T
askApp
.
prototype
.
renderCounter
=
function
()
{
return
this
.
counter
.
text
(
Task
.
active
().
length
);
T
odoApp
.
prototype
.
clearCompleted
=
function
()
{
return
Todo
.
destroyCompleted
(
);
};
TaskApp
.
prototype
.
toggleClearCompleted
=
function
()
{
if
(
Task
.
done
().
length
)
{
return
this
.
clearCompleted
.
show
();
}
else
{
return
this
.
clearCompleted
.
hide
();
TodoApp
.
prototype
.
toggleElems
=
function
()
{
var
isTodos
;
isTodos
=
!!
Todo
.
count
();
this
.
main
.
toggle
(
isTodos
);
this
.
footer
.
toggle
(
isTodos
);
this
.
clearCompleted
.
toggle
(
!!
Todo
.
completed
().
length
);
if
(
!
Todo
.
completed
().
length
)
{
return
this
.
toggleAllElem
.
removeAttr
(
'
checked
'
);
}
};
TaskApp
.
prototype
.
clearCompleted
=
function
()
{
return
Task
.
destroyDone
();
TodoApp
.
prototype
.
renderFooter
=
function
()
{
var
active
,
completed
,
text
;
text
=
function
(
count
)
{
if
(
count
===
1
)
{
return
'
item
'
;
}
else
{
return
'
items
'
;
}
};
active
=
Todo
.
active
().
length
;
completed
=
Todo
.
completed
().
length
;
this
.
count
.
html
(
"
<b>
"
+
active
+
"
</b>
"
+
(
text
(
active
))
+
"
left
"
);
return
this
.
clearCompleted
.
text
(
"
Clear completed (
"
+
completed
+
"
)
"
);
};
return
T
ask
App
;
return
T
odo
App
;
})();
})(
Spine
.
Controller
);
$
(
function
()
{
return
new
Task
App
({
el
:
$
(
'
#t
asks
'
)
new
Todo
App
({
el
:
$
(
'
#t
odoapp
'
)
});
return
Spine
.
Route
.
setup
();
});
}).
call
(
this
);
architecture-examples/spine/js/controllers/tasks.js
deleted
100644 → 0
View file @
ae5baf13
(
function
()
{
var
__bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
},
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
window
.
Tasks
=
(
function
()
{
var
ENTER_KEY
,
ESCAPE_KEY
;
__extends
(
Tasks
,
Spine
.
Controller
);
ENTER_KEY
=
13
;
ESCAPE_KEY
=
27
;
Tasks
.
prototype
.
elements
=
{
'
form.edit
'
:
'
form
'
};
Tasks
.
prototype
.
events
=
{
'
click a.destroy
'
:
'
remove
'
,
'
click input[type=checkbox]
'
:
'
toggleStatus
'
,
'
dblclick .view
'
:
'
edit
'
,
'
keypress input[type=text]
'
:
'
finishEditOnEnter
'
,
'
blur input[type=text]
'
:
'
finishEdit
'
};
function
Tasks
()
{
this
.
render
=
__bind
(
this
.
render
,
this
);
Tasks
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
this
.
task
.
bind
(
'
update
'
,
this
.
render
);
this
.
task
.
bind
(
'
destroy
'
,
this
.
release
);
}
Tasks
.
prototype
.
render
=
function
()
{
this
.
replace
(
$
(
'
#task-template
'
).
tmpl
(
this
.
task
));
return
this
;
};
Tasks
.
prototype
.
remove
=
function
()
{
return
this
.
task
.
destroy
();
};
Tasks
.
prototype
.
toggleStatus
=
function
()
{
return
this
.
task
.
updateAttribute
(
'
done
'
,
!
this
.
task
.
done
);
};
Tasks
.
prototype
.
edit
=
function
()
{
this
.
el
.
addClass
(
'
editing
'
);
return
this
.
$
(
'
input[name=name]
'
).
focus
();
};
Tasks
.
prototype
.
finishEdit
=
function
()
{
this
.
el
.
removeClass
(
'
editing
'
);
return
this
.
task
.
fromForm
(
this
.
form
).
save
();
};
Tasks
.
prototype
.
finishEditOnEnter
=
function
(
e
)
{
var
_ref
;
if
((
_ref
=
e
.
keyCode
)
===
ENTER_KEY
||
_ref
===
ESCAPE_KEY
)
{
return
this
.
finishEdit
();
}
};
return
Tasks
;
})();
}).
call
(
this
);
architecture-examples/spine/js/controllers/todos.js
0 → 100644
View file @
e7ae5b55
(
function
()
{
var
__bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
},
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
window
.
Todos
=
(
function
(
_super
)
{
var
ENTER_KEY
,
TPL
;
__extends
(
Todos
,
_super
);
ENTER_KEY
=
13
;
TPL
=
Handlebars
.
compile
(
$
(
'
#todo-template
'
).
html
());
Todos
.
prototype
.
elements
=
{
'
.edit
'
:
'
editElem
'
};
Todos
.
prototype
.
events
=
{
'
click .destroy
'
:
'
remove
'
,
'
click .toggle
'
:
'
toggleStatus
'
,
'
dblclick .view
'
:
'
edit
'
,
'
keyup .edit
'
:
'
finishEditOnEnter
'
,
'
blur .edit
'
:
'
finishEdit
'
};
function
Todos
()
{
this
.
render
=
__bind
(
this
.
render
,
this
);
Todos
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
this
.
todo
.
bind
(
'
update
'
,
this
.
render
);
this
.
todo
.
bind
(
'
destroy
'
,
this
.
release
);
}
Todos
.
prototype
.
render
=
function
()
{
this
.
replace
(
TPL
(
this
.
todo
));
return
this
;
};
Todos
.
prototype
.
remove
=
function
()
{
return
this
.
todo
.
destroy
();
};
Todos
.
prototype
.
toggleStatus
=
function
()
{
return
this
.
todo
.
updateAttribute
(
'
completed
'
,
!
this
.
todo
.
completed
);
};
Todos
.
prototype
.
edit
=
function
()
{
this
.
el
.
addClass
(
'
editing
'
);
return
this
.
editElem
.
focus
();
};
Todos
.
prototype
.
finishEdit
=
function
()
{
var
val
;
this
.
el
.
removeClass
(
'
editing
'
);
val
=
$
.
trim
(
this
.
editElem
.
val
());
if
(
val
)
{
return
this
.
todo
.
updateAttribute
(
'
title
'
,
val
);
}
else
{
return
this
.
remove
();
}
};
Todos
.
prototype
.
finishEditOnEnter
=
function
(
e
)
{
if
(
e
.
which
===
ENTER_KEY
)
return
this
.
finishEdit
();
};
return
Todos
;
})(
Spine
.
Controller
);
}).
call
(
this
);
architecture-examples/spine/js/lib/local.js
0 → 100755
View file @
e7ae5b55
(
function
()
{
if
(
typeof
Spine
===
"
undefined
"
||
Spine
===
null
)
Spine
=
require
(
'
spine
'
);
var
NS
=
'
spine
'
;
Spine
.
Model
.
Local
=
{
extended
:
function
()
{
this
.
change
(
this
.
saveLocal
);
return
this
.
fetch
(
this
.
loadLocal
);
},
saveLocal
:
function
()
{
var
result
;
result
=
JSON
.
stringify
(
this
);
return
localStorage
[
NS
+
'
-
'
+
this
.
className
]
=
result
;
},
loadLocal
:
function
()
{
var
result
;
result
=
localStorage
[
NS
+
'
-
'
+
this
.
className
];
return
this
.
refresh
(
result
||
[],
{
clear
:
true
});
}
};
if
(
typeof
module
!==
"
undefined
"
&&
module
!==
null
)
{
module
.
exports
=
Spine
.
Model
.
Local
;
}
}).
call
(
this
);
\ No newline at end of file
architecture-examples/spine/js/lib/route.min.js
0 → 100755
View file @
e7ae5b55
(
function
(){
var
f
,
i
,
j
,
h
,
k
,
l
=
Object
.
prototype
.
hasOwnProperty
,
m
=
function
(
d
,
b
){
function
e
(){
this
.
constructor
=
d
}
for
(
var
a
in
b
)
l
.
call
(
b
,
a
)
&&
(
d
[
a
]
=
b
[
a
]);
e
.
prototype
=
b
.
prototype
;
d
.
prototype
=
new
e
;
d
.
__super__
=
b
.
prototype
;
return
d
},
n
=
Array
.
prototype
.
slice
;
if
(
"
undefined
"
===
typeof
Spine
||
null
===
Spine
)
Spine
=
require
(
"
spine
"
);
f
=
Spine
.
$
;
j
=
/^#*/
;
h
=
/:
([\w\d]
+
)
/g
;
k
=
/
\*([\w\d]
+
)
/g
;
i
=
/
[
-[
\]
{}()+?.,
\\
^$|#
\s]
/g
;
Spine
.
Route
=
function
(
d
){
function
b
(
a
,
b
){
var
c
;
this
.
path
=
a
;
this
.
callback
=
b
;
this
.
names
=
[];
if
(
"
string
"
===
typeof
a
){
for
(
h
.
lastIndex
=
0
;
null
!==
(
c
=
h
.
exec
(
a
));)
this
.
names
.
push
(
c
[
1
]);
a
=
a
.
replace
(
i
,
"
\\
$&
"
).
replace
(
h
,
"
([^/]*)
"
).
replace
(
k
,
"
(.*?)
"
);
this
.
route
=
RegExp
(
"
^
"
+
a
+
"
$
"
)}
else
this
.
route
=
a
}
var
e
;
m
(
b
,
d
);
b
.
extend
(
Spine
.
Events
);
b
.
historySupport
=
null
!=
(
null
!=
(
e
=
window
.
history
)?
e
.
pushState
:
void
0
);
b
.
routes
=
[];
b
.
options
=
{
trigger
:
!
0
,
history
:
!
1
,
shim
:
!
1
};
b
.
add
=
function
(
a
,
b
){
var
c
,
d
,
g
;
if
(
"
object
"
===
typeof
a
&&!
(
a
instanceof
RegExp
)){
g
=
[];
for
(
c
in
a
)
d
=
a
[
c
],
g
.
push
(
this
.
add
(
c
,
d
));
return
g
}
return
this
.
routes
.
push
(
new
this
(
a
,
b
))};
b
.
setup
=
function
(
a
){
null
==
a
&&
(
a
=
{});
this
.
options
=
f
.
extend
({},
this
.
options
,
a
);
this
.
options
.
history
&&
(
this
.
history
=
this
.
historySupport
&&
this
.
options
.
history
);
if
(
!
this
.
options
.
shim
)
return
this
.
history
?
f
(
window
).
bind
(
"
popstate
"
,
this
.
change
):
f
(
window
).
bind
(
"
hashchange
"
,
this
.
change
),
this
.
change
()};
b
.
unbind
=
function
(){
return
this
.
history
?
f
(
window
).
unbind
(
"
popstate
"
,
this
.
change
):
f
(
window
).
unbind
(
"
hashchange
"
,
this
.
change
)};
b
.
navigate
=
function
(){
var
a
,
b
,
c
;
a
=
1
<=
arguments
.
length
?
n
.
call
(
arguments
,
0
):[];
c
=
{};
b
=
a
[
a
.
length
-
1
];
"
object
"
===
typeof
b
?
c
=
a
.
pop
():
"
boolean
"
===
typeof
b
&&
(
c
.
trigger
=
a
.
pop
());
c
=
f
.
extend
({},
this
.
options
,
c
);
a
=
a
.
join
(
"
/
"
);
if
(
this
.
path
!==
a
&&
(
this
.
path
=
a
,
this
.
trigger
(
"
navigate
"
,
this
.
path
),
c
.
trigger
&&
this
.
matchRoute
(
this
.
path
,
c
),
!
c
.
shim
))
return
this
.
history
?
history
.
pushState
({},
document
.
title
,
this
.
path
):
window
.
location
.
hash
=
this
.
path
};
b
.
getPath
=
function
(){
var
a
;
a
=
window
.
location
.
pathname
;
"
/
"
!==
a
.
substr
(
0
,
1
)
&&
(
a
=
"
/
"
+
a
);
return
a
};
b
.
getHash
=
function
(){
return
window
.
location
.
hash
};
b
.
getFragment
=
function
(){
return
this
.
getHash
().
replace
(
j
,
""
)};
b
.
getHost
=
function
(){
return
(
document
.
location
+
""
).
replace
(
this
.
getPath
()
+
this
.
getHash
(),
""
)};
b
.
change
=
function
(){
var
a
;
a
=
""
!==
this
.
getFragment
()?
this
.
getFragment
():
this
.
getPath
();
if
(
a
!==
this
.
path
)
return
this
.
path
=
a
,
this
.
matchRoute
(
this
.
path
)};
b
.
matchRoute
=
function
(
a
,
b
){
var
c
,
d
,
g
,
e
;
e
=
this
.
routes
;
d
=
0
;
for
(
g
=
e
.
length
;
d
<
g
;
d
++
)
if
(
c
=
e
[
d
],
c
.
match
(
a
,
b
))
return
this
.
trigger
(
"
change
"
,
c
,
a
),
c
};
b
.
prototype
.
match
=
function
(
a
,
b
){
var
c
,
d
,
e
,
f
;
null
==
b
&&
(
b
=
{});
c
=
this
.
route
.
exec
(
a
);
if
(
!
c
)
return
!
1
;
b
.
match
=
c
;
e
=
c
.
slice
(
1
);
if
(
this
.
names
.
length
){
c
=
0
;
for
(
f
=
e
.
length
;
c
<
f
;
c
++
)
d
=
e
[
c
],
b
[
this
.
names
[
c
]]
=
d
}
return
!
1
!==
this
.
callback
.
call
(
null
,
b
)};
return
b
}(
Spine
.
Module
);
Spine
.
Route
.
change
=
Spine
.
Route
.
proxy
(
Spine
.
Route
.
change
);
Spine
.
Controller
.
include
({
route
:
function
(
d
,
b
){
return
Spine
.
Route
.
add
(
d
,
this
.
proxy
(
b
))},
routes
:
function
(
d
){
var
b
,
e
,
a
;
a
=
[];
for
(
b
in
d
)
e
=
d
[
b
],
a
.
push
(
this
.
route
(
b
,
e
));
return
a
},
navigate
:
function
(){
return
Spine
.
Route
.
navigate
.
apply
(
Spine
.
Route
,
arguments
)}});
"
undefined
"
!==
typeof
module
&&
null
!==
module
&&
(
module
.
exports
=
Spine
.
Route
)}).
call
(
this
);
\ No newline at end of file
architecture-examples/spine/js/lib/spine.min.js
0 → 100755
View file @
e7ae5b55
This diff is collapsed.
Click to expand it.
architecture-examples/spine/js/models/task.js
deleted
100644 → 0
View file @
ae5baf13
(
function
()
{
var
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
window
.
Task
=
(
function
()
{
__extends
(
Task
,
Spine
.
Model
);
function
Task
()
{
Task
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
}
Task
.
configure
(
'
Task
'
,
'
name
'
,
'
done
'
);
Task
.
extend
(
Spine
.
Model
.
Local
);
Task
.
prototype
.
validate
=
function
()
{
if
(
!
$
.
trim
(
this
.
name
))
return
'
Task name is required
'
;
};
Task
.
active
=
function
()
{
return
this
.
select
(
function
(
task
)
{
return
!
task
.
done
;
});
};
Task
.
done
=
function
()
{
return
this
.
select
(
function
(
task
)
{
return
!!
task
.
done
;
});
};
Task
.
destroyDone
=
function
()
{
var
task
,
_i
,
_len
,
_ref
,
_results
;
_ref
=
this
.
done
();
_results
=
[];
for
(
_i
=
0
,
_len
=
_ref
.
length
;
_i
<
_len
;
_i
++
)
{
task
=
_ref
[
_i
];
_results
.
push
(
task
.
destroy
());
}
return
_results
;
};
return
Task
;
})();
}).
call
(
this
);
architecture-examples/spine/js/models/todo.js
0 → 100644
View file @
e7ae5b55
(
function
()
{
var
__hasProp
=
Object
.
prototype
.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
;
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
window
.
Todo
=
(
function
(
_super
)
{
__extends
(
Todo
,
_super
);
function
Todo
()
{
Todo
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
}
Todo
.
configure
(
'
Todo
'
,
'
title
'
,
'
completed
'
);
Todo
.
extend
(
Spine
.
Model
.
Local
);
Todo
.
active
=
function
()
{
return
this
.
select
(
function
(
todo
)
{
return
!
todo
.
completed
;
});
};
Todo
.
completed
=
function
()
{
return
this
.
select
(
function
(
todo
)
{
return
!!
todo
.
completed
;
});
};
Todo
.
destroyCompleted
=
function
()
{
var
todo
,
_i
,
_len
,
_ref
,
_results
;
_ref
=
this
.
completed
();
_results
=
[];
for
(
_i
=
0
,
_len
=
_ref
.
length
;
_i
<
_len
;
_i
++
)
{
todo
=
_ref
[
_i
];
_results
.
push
(
todo
.
destroy
());
}
return
_results
;
};
return
Todo
;
})(
Spine
.
Model
);
}).
call
(
this
);
architecture-examples/spine/lib/jquery.min.js
deleted
100644 → 0
View file @
ae5baf13
This diff is collapsed.
Click to expand it.
architecture-examples/spine/lib/jquery.tmpl.min.js
deleted
100644 → 0
View file @
ae5baf13
/*
* jQuery Templates Plugin 1.0.0pre
* http://github.com/jquery/jquery-tmpl
* Requires jQuery 1.4.2
*
* Copyright Software Freedom Conservancy, Inc.
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(
function
(
a
){
var
r
=
a
.
fn
.
domManip
,
d
=
"
_tmplitem
"
,
q
=
/^
[^
<
]
*
(
<
[\w\W]
+>
)[^
>
]
*$|
\{\{\!
/
,
b
=
{},
f
=
{},
e
,
p
=
{
key
:
0
,
data
:{}},
i
=
0
,
c
=
0
,
l
=
[];
function
g
(
g
,
d
,
h
,
e
){
var
c
=
{
data
:
e
||
(
e
===
0
||
e
===
false
)?
e
:
d
?
d
.
data
:{},
_wrap
:
d
?
d
.
_wrap
:
null
,
tmpl
:
null
,
parent
:
d
||
null
,
nodes
:[],
calls
:
u
,
nest
:
w
,
wrap
:
x
,
html
:
v
,
update
:
t
};
g
&&
a
.
extend
(
c
,
g
,{
nodes
:[],
parent
:
d
});
if
(
h
){
c
.
tmpl
=
h
;
c
.
_ctnt
=
c
.
_ctnt
||
c
.
tmpl
(
a
,
c
);
c
.
key
=++
i
;(
l
.
length
?
f
:
b
)[
i
]
=
c
}
return
c
}
a
.
each
({
appendTo
:
"
append
"
,
prependTo
:
"
prepend
"
,
insertBefore
:
"
before
"
,
insertAfter
:
"
after
"
,
replaceAll
:
"
replaceWith
"
},
function
(
f
,
d
){
a
.
fn
[
f
]
=
function
(
n
){
var
g
=
[],
i
=
a
(
n
),
k
,
h
,
m
,
l
,
j
=
this
.
length
===
1
&&
this
[
0
].
parentNode
;
e
=
b
||
{};
if
(
j
&&
j
.
nodeType
===
11
&&
j
.
childNodes
.
length
===
1
&&
i
.
length
===
1
){
i
[
d
](
this
[
0
]);
g
=
this
}
else
{
for
(
h
=
0
,
m
=
i
.
length
;
h
<
m
;
h
++
){
c
=
h
;
k
=
(
h
>
0
?
this
.
clone
(
true
):
this
).
get
();
a
(
i
[
h
])[
d
](
k
);
g
=
g
.
concat
(
k
)}
c
=
0
;
g
=
this
.
pushStack
(
g
,
f
,
i
.
selector
)}
l
=
e
;
e
=
null
;
a
.
tmpl
.
complete
(
l
);
return
g
}});
a
.
fn
.
extend
({
tmpl
:
function
(
d
,
c
,
b
){
return
a
.
tmpl
(
this
[
0
],
d
,
c
,
b
)},
tmplItem
:
function
(){
return
a
.
tmplItem
(
this
[
0
])},
template
:
function
(
b
){
return
a
.
template
(
b
,
this
[
0
])},
domManip
:
function
(
d
,
m
,
k
){
if
(
d
[
0
]
&&
a
.
isArray
(
d
[
0
])){
var
g
=
a
.
makeArray
(
arguments
),
h
=
d
[
0
],
j
=
h
.
length
,
i
=
0
,
f
;
while
(
i
<
j
&&!
(
f
=
a
.
data
(
h
[
i
++
],
"
tmplItem
"
)));
if
(
f
&&
c
)
g
[
2
]
=
function
(
b
){
a
.
tmpl
.
afterManip
(
this
,
b
,
k
)};
r
.
apply
(
this
,
g
)}
else
r
.
apply
(
this
,
arguments
);
c
=
0
;
!
e
&&
a
.
tmpl
.
complete
(
b
);
return
this
}});
a
.
extend
({
tmpl
:
function
(
d
,
h
,
e
,
c
){
var
i
,
k
=!
c
;
if
(
k
){
c
=
p
;
d
=
a
.
template
[
d
]
||
a
.
template
(
null
,
d
);
f
=
{}}
else
if
(
!
d
){
d
=
c
.
tmpl
;
b
[
c
.
key
]
=
c
;
c
.
nodes
=
[];
c
.
wrapped
&&
n
(
c
,
c
.
wrapped
);
return
a
(
j
(
c
,
null
,
c
.
tmpl
(
a
,
c
)))}
if
(
!
d
)
return
[];
if
(
typeof
h
===
"
function
"
)
h
=
h
.
call
(
c
||
{});
e
&&
e
.
wrapped
&&
n
(
e
,
e
.
wrapped
);
i
=
a
.
isArray
(
h
)?
a
.
map
(
h
,
function
(
a
){
return
a
?
g
(
e
,
c
,
d
,
a
):
null
}):[
g
(
e
,
c
,
d
,
h
)];
return
k
?
a
(
j
(
c
,
null
,
i
)):
i
},
tmplItem
:
function
(
b
){
var
c
;
if
(
b
instanceof
a
)
b
=
b
[
0
];
while
(
b
&&
b
.
nodeType
===
1
&&!
(
c
=
a
.
data
(
b
,
"
tmplItem
"
))
&&
(
b
=
b
.
parentNode
));
return
c
||
p
},
template
:
function
(
c
,
b
){
if
(
b
){
if
(
typeof
b
===
"
string
"
)
b
=
o
(
b
);
else
if
(
b
instanceof
a
)
b
=
b
[
0
]
||
{};
if
(
b
.
nodeType
)
b
=
a
.
data
(
b
,
"
tmpl
"
)
||
a
.
data
(
b
,
"
tmpl
"
,
o
(
b
.
innerHTML
));
return
typeof
c
===
"
string
"
?(
a
.
template
[
c
]
=
b
):
b
}
return
c
?
typeof
c
!==
"
string
"
?
a
.
template
(
null
,
c
):
a
.
template
[
c
]
||
a
.
template
(
null
,
q
.
test
(
c
)?
c
:
a
(
c
)):
null
},
encode
:
function
(
a
){
return
(
""
+
a
).
split
(
"
<
"
).
join
(
"
<
"
).
split
(
"
>
"
).
join
(
"
>
"
).
split
(
'
"
'
).
join
(
"
"
"
).
split
(
"
'
"
).
join
(
"
'
"
)}});
a
.
extend
(
a
.
tmpl
,{
tag
:{
tmpl
:{
_default
:{
$2
:
"
null
"
},
open
:
"
if($notnull_1){__=__.concat($item.nest($1,$2));}
"
},
wrap
:{
_default
:{
$2
:
"
null
"
},
open
:
"
$item.calls(__,$1,$2);__=[];
"
,
close
:
"
call=$item.calls();__=call._.concat($item.wrap(call,__));
"
},
each
:{
_default
:{
$2
:
"
$index, $value
"
},
open
:
"
if($notnull_1){$.each($1a,function($2){with(this){
"
,
close
:
"
}});}
"
},
"
if
"
:{
open
:
"
if(($notnull_1) && $1a){
"
,
close
:
"
}
"
},
"
else
"
:{
_default
:{
$1
:
"
true
"
},
open
:
"
}else if(($notnull_1) && $1a){
"
},
html
:{
open
:
"
if($notnull_1){__.push($1a);}
"
},
"
=
"
:{
_default
:{
$1
:
"
$data
"
},
open
:
"
if($notnull_1){__.push($.encode($1a));}
"
},
"
!
"
:{
open
:
""
}},
complete
:
function
(){
b
=
{}},
afterManip
:
function
(
f
,
b
,
d
){
var
e
=
b
.
nodeType
===
11
?
a
.
makeArray
(
b
.
childNodes
):
b
.
nodeType
===
1
?[
b
]:[];
d
.
call
(
f
,
b
);
m
(
e
);
c
++
}});
function
j
(
e
,
g
,
f
){
var
b
,
c
=
f
?
a
.
map
(
f
,
function
(
a
){
return
typeof
a
===
"
string
"
?
e
.
key
?
a
.
replace
(
/
(
<
\w
+
)(?=[\s
>
])(?![^
>
]
*_tmplitem
)([^
>
]
*
)
/g
,
"
$1
"
+
d
+
'
="
'
+
e
.
key
+
'
" $2
'
):
a
:
j
(
a
,
e
,
a
.
_ctnt
)}):
e
;
if
(
g
)
return
c
;
c
=
c
.
join
(
""
);
c
.
replace
(
/^
\s
*
([^
<
\s][^
<
]
*
)?(
<
[\w\W]
+>
)([^
>
]
*
[^
>
\s])?\s
*$/
,
function
(
f
,
c
,
e
,
d
){
b
=
a
(
e
).
get
();
m
(
b
);
if
(
c
)
b
=
k
(
c
).
concat
(
b
);
if
(
d
)
b
=
b
.
concat
(
k
(
d
))});
return
b
?
b
:
k
(
c
)}
function
k
(
c
){
var
b
=
document
.
createElement
(
"
div
"
);
b
.
innerHTML
=
c
;
return
a
.
makeArray
(
b
.
childNodes
)}
function
o
(
b
){
return
new
Function
(
"
jQuery
"
,
"
$item
"
,
"
var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('
"
+
a
.
trim
(
b
).
replace
(
/
([\\
'
])
/g
,
"
\\
$1
"
).
replace
(
/
[\r\t\n]
/g
,
"
"
).
replace
(
/
\$\{([^\}]
*
)\}
/g
,
"
{{= $1}}
"
).
replace
(
/
\{\{(\/?)(\w
+|.
)(?:\(((?:[^\}]
|
\}(?!\}))
*
?)?\))?(?:\s
+
(
.*
?)?)?(\(((?:[^\}]
|
\}(?!\}))
*
?)\))?\s
*
\}\}
/g
,
function
(
m
,
l
,
k
,
g
,
b
,
c
,
d
){
var
j
=
a
.
tmpl
.
tag
[
k
],
i
,
e
,
f
;
if
(
!
j
)
throw
"
Unknown template tag:
"
+
k
;
i
=
j
.
_default
||
[];
if
(
c
&&!
/
\w
$/
.
test
(
b
)){
b
+=
c
;
c
=
""
}
if
(
b
){
b
=
h
(
b
);
d
=
d
?
"
,
"
+
h
(
d
)
+
"
)
"
:
c
?
"
)
"
:
""
;
e
=
c
?
b
.
indexOf
(
"
.
"
)
>-
1
?
b
+
h
(
c
):
"
(
"
+
b
+
"
).call($item
"
+
d
:
b
;
f
=
c
?
e
:
"
(typeof(
"
+
b
+
"
)==='function'?(
"
+
b
+
"
).call($item):(
"
+
b
+
"
))
"
}
else
f
=
e
=
i
.
$1
||
"
null
"
;
g
=
h
(
g
);
return
"
');
"
+
j
[
l
?
"
close
"
:
"
open
"
].
split
(
"
$notnull_1
"
).
join
(
b
?
"
typeof(
"
+
b
+
"
)!=='undefined' && (
"
+
b
+
"
)!=null
"
:
"
true
"
).
split
(
"
$1a
"
).
join
(
f
).
split
(
"
$1
"
).
join
(
e
).
split
(
"
$2
"
).
join
(
g
||
i
.
$2
||
""
)
+
"
__.push('
"
})
+
"
');}return __;
"
)}
function
n
(
c
,
b
){
c
.
_wrap
=
j
(
c
,
true
,
a
.
isArray
(
b
)?
b
:[
q
.
test
(
b
)?
b
:
a
(
b
).
html
()]).
join
(
""
)}
function
h
(
a
){
return
a
?
a
.
replace
(
/
\\
'/g
,
"
'
"
).
replace
(
/
\\\\
/g
,
"
\\
"
):
null
}
function
s
(
b
){
var
a
=
document
.
createElement
(
"
div
"
);
a
.
appendChild
(
b
.
cloneNode
(
true
));
return
a
.
innerHTML
}
function
m
(
o
){
var
n
=
"
_
"
+
c
,
k
,
j
,
l
=
{},
e
,
p
,
h
;
for
(
e
=
0
,
p
=
o
.
length
;
e
<
p
;
e
++
){
if
((
k
=
o
[
e
]).
nodeType
!==
1
)
continue
;
j
=
k
.
getElementsByTagName
(
"
*
"
);
for
(
h
=
j
.
length
-
1
;
h
>=
0
;
h
--
)
m
(
j
[
h
]);
m
(
k
)}
function
m
(
j
){
var
p
,
h
=
j
,
k
,
e
,
m
;
if
(
m
=
j
.
getAttribute
(
d
)){
while
(
h
.
parentNode
&&
(
h
=
h
.
parentNode
).
nodeType
===
1
&&!
(
p
=
h
.
getAttribute
(
d
)));
if
(
p
!==
m
){
h
=
h
.
parentNode
?
h
.
nodeType
===
11
?
0
:
h
.
getAttribute
(
d
)
||
0
:
0
;
if
(
!
(
e
=
b
[
m
])){
e
=
f
[
m
];
e
=
g
(
e
,
b
[
h
]
||
f
[
h
]);
e
.
key
=++
i
;
b
[
i
]
=
e
}
c
&&
o
(
m
)}
j
.
removeAttribute
(
d
)}
else
if
(
c
&&
(
e
=
a
.
data
(
j
,
"
tmplItem
"
))){
o
(
e
.
key
);
b
[
e
.
key
]
=
e
;
h
=
a
.
data
(
j
.
parentNode
,
"
tmplItem
"
);
h
=
h
?
h
.
key
:
0
}
if
(
e
){
k
=
e
;
while
(
k
&&
k
.
key
!=
h
){
k
.
nodes
.
push
(
j
);
k
=
k
.
parent
}
delete
e
.
_ctnt
;
delete
e
.
_wrap
;
a
.
data
(
j
,
"
tmplItem
"
,
e
)}
function
o
(
a
){
a
=
a
+
n
;
e
=
l
[
a
]
=
l
[
a
]
||
g
(
e
,
b
[
e
.
parent
.
key
+
n
]
||
e
.
parent
)}}}
function
u
(
a
,
d
,
c
,
b
){
if
(
!
a
)
return
l
.
pop
();
l
.
push
({
_
:
a
,
tmpl
:
d
,
item
:
this
,
data
:
c
,
options
:
b
})}
function
w
(
d
,
c
,
b
){
return
a
.
tmpl
(
a
.
template
(
d
),
c
,
b
,
this
)}
function
x
(
b
,
d
){
var
c
=
b
.
options
||
{};
c
.
wrapped
=
d
;
return
a
.
tmpl
(
a
.
template
(
b
.
tmpl
),
b
.
data
,
c
,
b
.
item
)}
function
v
(
d
,
c
){
var
b
=
this
.
_wrap
;
return
a
.
map
(
a
(
a
.
isArray
(
b
)?
b
.
join
(
""
):
b
).
filter
(
d
||
"
*
"
),
function
(
a
){
return
c
?
a
.
innerText
||
a
.
textContent
:
a
.
outerHTML
||
s
(
a
)})}
function
t
(){
var
b
=
this
.
nodes
;
a
.
tmpl
(
null
,
null
,
null
,
this
).
insertBefore
(
b
[
0
]);
a
(
b
).
remove
()}})(
jQuery
);
\ No newline at end of file
architecture-examples/spine/lib/local.js
deleted
100755 → 0
View file @
ae5baf13
(
function
()
{
var
storageName
=
'
todos-spine
'
;
if
(
typeof
Spine
===
"
undefined
"
||
Spine
===
null
)
{
Spine
=
require
(
'
spine
'
);
}
Spine
.
Model
.
Local
=
{
extended
:
function
()
{
this
.
change
(
this
.
saveLocal
);
return
this
.
fetch
(
this
.
loadLocal
);
},
saveLocal
:
function
()
{
var
result
;
result
=
JSON
.
stringify
(
this
);
return
localStorage
[
storageName
]
=
result
;
},
loadLocal
:
function
()
{
var
result
;
result
=
localStorage
[
storageName
];
return
this
.
refresh
(
result
||
[],
{
clear
:
true
});
}
};
if
(
typeof
module
!==
"
undefined
"
&&
module
!==
null
)
{
module
.
exports
=
Spine
.
Model
.
Local
;
}
}).
call
(
this
);
architecture-examples/spine/lib/spine.js
deleted
100755 → 0
View file @
ae5baf13
This diff is collapsed.
Click to expand it.
architecture-examples/spine/src/app.coffee
View file @
e7ae5b55
class
TaskApp
extends
Spine
.
Controller
elements
:
'.items'
:
'tasks'
'.countVal'
:
'counter'
'a.clear'
:
'clearCompleted'
'form#new-task input[name=name]'
:
'newTaskName'
events
:
'submit form#new-task'
:
'new'
'click a.clear'
:
'clearCompleted'
constructor
:
->
super
Task
.
bind
'create'
,
@
renderNew
Task
.
bind
'refresh'
,
@
renderAll
Task
.
bind
'refresh change'
,
@
renderCounter
Task
.
bind
'refresh change'
,
@
toggleClearCompleted
Task
.
fetch
()
new
:
(
e
)
->
e
.
preventDefault
()
Task
.
fromForm
(
'form#new-task'
).
save
()
@
newTaskName
.
val
(
''
)
renderNew
:
(
task
)
=>
view
=
new
Tasks
(
task
:
task
)
@
tasks
.
append
view
.
render
().
el
renderAll
:
=>
Task
.
each
@
renderNew
renderCounter
:
=>
@
counter
.
text
Task
.
active
().
length
toggleClearCompleted
:
=>
if
Task
.
done
().
length
@
clearCompleted
.
show
()
else
@
clearCompleted
.
hide
()
clearCompleted
:
->
Task
.
destroyDone
()
class
TodoApp
extends
Spine
.
Controller
ENTER_KEY
=
13
elements
:
'#new-todo'
:
'newTodoInput'
'#toggle-all'
:
'toggleAllElem'
'#main'
:
'main'
'#todo-list'
:
'todos'
'#footer'
:
'footer'
'#todo-count'
:
'count'
'#filters a'
:
'filters'
'#clear-completed'
:
'clearCompleted'
events
:
'keyup #new-todo'
:
'new'
'click #toggle-all'
:
'toggleAll'
'click #clear-completed'
:
'clearCompleted'
constructor
:
->
super
Todo
.
bind
'create'
,
@
addNew
Todo
.
bind
'refresh'
,
@
addAll
Todo
.
bind
'refresh change'
,
@
toggleElems
Todo
.
bind
'refresh change'
,
@
renderFooter
Todo
.
fetch
()
@
routes
'/:filter'
:
(
param
)
->
@
filter
=
param
.
filter
###
TODO: Need to figure out why the route doesn't trigger `change` event
###
Todo
.
trigger
(
'refresh'
)
@
filters
.
removeClass
(
'selected'
)
.
filter
(
"[href='#/
#{
@
filter
}
']"
).
addClass
(
'selected'
);
new
:
(
e
)
->
val
=
$
.
trim
@
newTodoInput
.
val
()
if
e
.
which
is
ENTER_KEY
and
val
Todo
.
create
title
:
val
@
newTodoInput
.
val
''
getByFilter
:
->
switch
@
filter
when
'active'
Todo
.
active
()
when
'completed'
Todo
.
completed
()
else
Todo
.
all
()
addNew
:
(
todo
)
=>
view
=
new
Todos
todo
:
todo
@
todos
.
append
view
.
render
().
el
addAll
:
=>
@
todos
.
empty
()
@
addNew
todo
for
todo
in
@
getByFilter
()
toggleAll
:
(
e
)
->
Todo
.
each
(
todo
)
->
###
TODO: Model updateAttribute sometimes won't stick:
https://github.com/maccman/spine/issues/219
###
todo
.
updateAttribute
'completed'
,
e
.
target
.
checked
todo
.
trigger
'update'
,
todo
clearCompleted
:
->
Todo
.
destroyCompleted
()
toggleElems
:
=>
isTodos
=
!!
Todo
.
count
()
@
main
.
toggle
isTodos
@
footer
.
toggle
isTodos
@
clearCompleted
.
toggle
!!
Todo
.
completed
().
length
@
toggleAllElem
.
removeAttr
'checked'
if
!
Todo
.
completed
().
length
renderFooter
:
=>
text
=
(
count
)
->
if
count
is
1
then
'item'
else
'items'
active
=
Todo
.
active
().
length
completed
=
Todo
.
completed
().
length
@
count
.
html
"<b>
#{
active
}
</b>
#{
text
active
}
left"
@
clearCompleted
.
text
"Clear completed (
#{
completed
}
)"
$
->
new
TaskApp
(
el
:
$
(
'#tasks'
))
new
TodoApp
el
:
$
(
'#todoapp'
)
Spine
.
Route
.
setup
()
\ No newline at end of file
architecture-examples/spine/src/controllers/tasks.coffee
deleted
100644 → 0
View file @
ae5baf13
class
window
.
Tasks
extends
Spine
.
Controller
ENTER_KEY
=
13
ESCAPE_KEY
=
27
elements
:
'form.edit'
:
'form'
events
:
'click a.destroy'
:
'remove'
'click input[type=checkbox]'
:
'toggleStatus'
'dblclick .view'
:
'edit'
'keypress input[type=text]'
:
'finishEditOnEnter'
'blur input[type=text]'
:
'finishEdit'
constructor
:
->
super
@
task
.
bind
'update'
,
@
render
@
task
.
bind
'destroy'
,
@
release
render
:
=>
@
replace
$
(
'#task-template'
).
tmpl
(
@
task
)
this
remove
:
->
@
task
.
destroy
()
toggleStatus
:
->
@
task
.
updateAttribute
'done'
,
!
@
task
.
done
edit
:
->
@
el
.
addClass
(
'editing'
)
@
$
(
'input[name=name]'
).
focus
()
finishEdit
:
->
@
el
.
removeClass
(
'editing'
)
@
task
.
fromForm
(
@
form
).
save
()
finishEditOnEnter
:
(
e
)
->
if
e
.
keyCode
in
[
ENTER_KEY
,
ESCAPE_KEY
]
then
@
finishEdit
()
architecture-examples/spine/src/controllers/todos.coffee
0 → 100644
View file @
e7ae5b55
class
window
.
Todos
extends
Spine
.
Controller
ENTER_KEY
=
13
TPL
=
Handlebars
.
compile
$
(
'#todo-template'
).
html
()
elements
:
'.edit'
:
'editElem'
events
:
'click .destroy'
:
'remove'
'click .toggle'
:
'toggleStatus'
'dblclick .view'
:
'edit'
'keyup .edit'
:
'finishEditOnEnter'
'blur .edit'
:
'finishEdit'
constructor
:
->
super
@
todo
.
bind
'update'
,
@
render
@
todo
.
bind
'destroy'
,
@
release
render
:
=>
@
replace
TPL
(
@
todo
)
@
remove
:
->
@
todo
.
destroy
()
toggleStatus
:
->
@
todo
.
updateAttribute
'completed'
,
!
@
todo
.
completed
edit
:
->
@
el
.
addClass
'editing'
@
editElem
.
focus
()
finishEdit
:
->
@
el
.
removeClass
'editing'
val
=
$
.
trim
@
editElem
.
val
()
if
val
then
@
todo
.
updateAttribute
(
'title'
,
val
)
else
@
remove
()
finishEditOnEnter
:
(
e
)
->
@
finishEdit
()
if
e
.
which
is
ENTER_KEY
\ No newline at end of file
architecture-examples/spine/src/models/task.coffee
deleted
100644 → 0
View file @
ae5baf13
class
window
.
Task
extends
Spine
.
Model
@
configure
'Task'
,
'name'
,
'done'
@
extend
Spine
.
Model
.
Local
validate
:
->
'Task name is required'
unless
$
.
trim
(
@
name
)
@
active
:
->
@
select
(
task
)
->
!
task
.
done
@
done
:
->
@
select
(
task
)
->
!!
task
.
done
@
destroyDone
:
->
task
.
destroy
()
for
task
in
@
done
()
architecture-examples/spine/src/models/todo.coffee
0 → 100644
View file @
e7ae5b55
class
window
.
Todo
extends
Spine
.
Model
@
configure
'Todo'
,
'title'
,
'completed'
@
extend
Spine
.
Model
.
Local
@
active
:
->
@
select
(
todo
)
->
!
todo
.
completed
@
completed
:
->
@
select
(
todo
)
->
!!
todo
.
completed
@
destroyCompleted
:
->
todo
.
destroy
()
for
todo
in
@
completed
()
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment