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
Eugene Shen
todomvc
Commits
2a30629f
Commit
2a30629f
authored
Oct 13, 2012
by
Kevin Malakoff
Committed by
Sindre Sorhus
Oct 13, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Close GH-291: Updated to Latest Knockback and simplified the implementation (take 2).
parent
1bb1340f
Changes
26
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
443 additions
and
339 deletions
+443
-339
architecture-examples/knockback/Cakefile
architecture-examples/knockback/Cakefile
+4
-2
architecture-examples/knockback/index.html
architecture-examples/knockback/index.html
+24
-31
architecture-examples/knockback/js/app.js
architecture-examples/knockback/js/app.js
+0
-45
architecture-examples/knockback/js/lib/backbone-min.js
architecture-examples/knockback/js/lib/backbone-min.js
+0
-38
architecture-examples/knockback/js/lib/backbone.localStorage-min.js
...re-examples/knockback/js/lib/backbone.localStorage-min.js
+1
-1
architecture-examples/knockback/js/lib/knockback-full-stack-0.16.7.min.js
...mples/knockback/js/lib/knockback-full-stack-0.16.7.min.js
+169
-0
architecture-examples/knockback/js/lib/knockback.min.js
architecture-examples/knockback/js/lib/knockback.min.js
+0
-11
architecture-examples/knockback/js/lib/knockout-extended-bindings.js
...e-examples/knockback/js/lib/knockout-extended-bindings.js
+31
-0
architecture-examples/knockback/js/models/todo_collection.js
architecture-examples/knockback/js/models/todo_collection.js
+2
-4
architecture-examples/knockback/js/routers/app.js
architecture-examples/knockback/js/routers/app.js
+0
-36
architecture-examples/knockback/js/viewmodels/app.js
architecture-examples/knockback/js/viewmodels/app.js
+95
-0
architecture-examples/knockback/js/viewmodels/footer.js
architecture-examples/knockback/js/viewmodels/footer.js
+0
-28
architecture-examples/knockback/js/viewmodels/header.js
architecture-examples/knockback/js/viewmodels/header.js
+0
-22
architecture-examples/knockback/js/viewmodels/settings.js
architecture-examples/knockback/js/viewmodels/settings.js
+0
-9
architecture-examples/knockback/js/viewmodels/todo.js
architecture-examples/knockback/js/viewmodels/todo.js
+3
-36
architecture-examples/knockback/readme.md
architecture-examples/knockback/readme.md
+2
-5
architecture-examples/knockback/src/app.coffee
architecture-examples/knockback/src/app.coffee
+0
-31
architecture-examples/knockback/src/lib/knockout-extended-bindings.coffee
...mples/knockback/src/lib/knockout-extended-bindings.coffee
+15
-0
architecture-examples/knockback/src/models/todo.coffee
architecture-examples/knockback/src/models/todo.coffee
+3
-2
architecture-examples/knockback/src/models/todo_collection.coffee
...ture-examples/knockback/src/models/todo_collection.coffee
+2
-1
architecture-examples/knockback/src/routers/app.coffee
architecture-examples/knockback/src/routers/app.coffee
+0
-9
architecture-examples/knockback/src/viewmodels/app.coffee
architecture-examples/knockback/src/viewmodels/app.coffee
+67
-0
architecture-examples/knockback/src/viewmodels/footer.coffee
architecture-examples/knockback/src/viewmodels/footer.coffee
+0
-13
architecture-examples/knockback/src/viewmodels/header.coffee
architecture-examples/knockback/src/viewmodels/header.coffee
+0
-12
architecture-examples/knockback/src/viewmodels/settings.coffee
...tecture-examples/knockback/src/viewmodels/settings.coffee
+0
-3
architecture-examples/knockback/src/viewmodels/todo.coffee
architecture-examples/knockback/src/viewmodels/todo.coffee
+25
-0
No files found.
architecture-examples/knockback/Cakefile
View file @
2a30629f
...
...
@@ -4,7 +4,9 @@
task
'build'
,
'Build js/ from src/'
,
->
coffee
=
spawn
'coffee'
,
[
'-c'
,
'-o'
,
'js'
,
'src'
]
coffee
.
stderr
.
on
'data'
,
(
data
)
->
process
.
stderr
.
write
data
.
toString
()
message
=
data
.
toString
()
if
message
.
search
(
'is now called'
)
<
0
process
.
stderr
.
write
message
coffee
.
stdout
.
on
'data'
,
(
data
)
->
print
data
.
toString
()
coffee
.
on
'exit'
,
(
code
)
->
...
...
architecture-examples/knockback/index.html
View file @
2a30629f
...
...
@@ -10,68 +10,61 @@
<![endif]-->
</head>
<body>
<section
id=
"todoapp"
>
<section
id=
"todoapp"
kb-inject=
"AppViewModel"
>
<header
id=
"header"
>
<h1>
todos
</h1>
<input
id=
"new-todo"
type=
"text"
data-bind=
"value:
header.title, valueUpdate: 'afterkeydown', event: {keyup: header.
onAddTodo}"
placeholder=
"What needs to be done?"
autofocus
>
<input
id=
"new-todo"
type=
"text"
data-bind=
"value:
title, valueUpdate: 'afterkeydown', event: {keyup:
onAddTodo}"
placeholder=
"What needs to be done?"
autofocus
>
</header>
<section
id=
"main"
data-bind=
"block: t
odos.t
asks_exist"
>
<input
id=
"toggle-all"
type=
"checkbox"
data-bind=
"checked:
todos.
all_completed"
>
<section
id=
"main"
data-bind=
"block: tasks_exist"
>
<input
id=
"toggle-all"
type=
"checkbox"
data-bind=
"checked: all_completed"
>
<label
for=
"toggle-all"
>
Mark all as complete
</label>
<ul
id=
"todo-list"
data-bind=
"foreach: todos
.todos
"
>
<li
data-bind=
"css: {completed: completed, editing: editing}
, visible: visible
"
>
<div
class=
"view"
>
<ul
id=
"todo-list"
data-bind=
"foreach: todos"
>
<li
data-bind=
"css: {completed: completed, editing: editing}"
>
<div
class=
"view"
data-bind=
"event: {dblclick: onCheckEditBegin}"
>
<input
class=
"toggle"
type=
"checkbox"
data-bind=
"checked: completed"
checked
>
<label
data-bind=
"text: title
, event: {dblclick: onCheckEditBegin}
"
></label>
<label
data-bind=
"text: title"
></label>
<button
class=
"destroy"
data-bind=
"click: onDestroyTodo"
></button>
</div>
<input
class=
"edit"
type=
"text"
data-bind=
"value: title, selectAndFocus: editing, event: {blur: onCheckEditEnd, keyup: onCheckEditEnd}"
>
</li>
</ul>
</section>
<footer
id=
"footer"
data-bind=
"block: t
odos.t
asks_exist"
>
<span
id=
"todo-count"
data-bind=
"html:
footer.remaining_text
"
></span>
<footer
id=
"footer"
data-bind=
"block: tasks_exist"
>
<span
id=
"todo-count"
data-bind=
"html:
loc.remaining_message
"
></span>
<ul
id=
"filters"
>
<li>
<a
href=
"#/"
data-bind=
"css: {selected:
settings.
list_filter_mode()==''}"
>
All
</a>
<a
href=
"#/"
data-bind=
"css: {selected: list_filter_mode()==''}"
>
All
</a>
</li>
<li>
<a
href=
"#/active"
data-bind=
"css: {selected:
settings.
list_filter_mode()=='active'}"
>
Active
</a>
<a
href=
"#/active"
data-bind=
"css: {selected: list_filter_mode()=='active'}"
>
Active
</a>
</li>
<li>
<a
href=
"#/completed"
data-bind=
"css: {selected:
settings.
list_filter_mode()=='completed'}"
>
Completed
</a>
<a
href=
"#/completed"
data-bind=
"css: {selected: list_filter_mode()=='completed'}"
>
Completed
</a>
</li>
</ul>
<button
id=
"clear-completed"
data-bind=
"text:
footer.clear_text, block: footer.clear_text, click: footer.
onDestroyCompleted"
></button>
<button
id=
"clear-completed"
data-bind=
"text:
loc.clear_message, block: loc.clear_message, click:
onDestroyCompleted"
></button>
</footer>
</section>
<footer
id=
"info"
>
<p>
Double-click to edit a todo
</p>
<p>
Created by
<a
href=
"https://github.com/kmalakoff"
>
Kevin Malakoff
</a>
.
<br/>
Please try out the
<a
href=
"http://kmalakoff.github.com/knockback-todos/"
>
enhanced version
</a>
<br/>
Please try out the
<a
href=
"http://kmalakoff.github.com/knockback-todos
-app
/"
>
enhanced version
</a>
<br/>
with localization, priority colors, and lazy loading
<br/>
to see just how dynamic
<a
href=
"https://github.com/kmalakoff/knockback"
>
Knockback.js
</a>
can be!
</p>
<p>
Part of
<a
href=
"http://todomvc.com"
>
TodoMVC
</a></p>
</footer>
<!-- Demo Dependencies -->
<!-- App Dependencies -->
<script
src=
"../../assets/base.js"
></script>
<script
src=
"../../assets/jquery.min.js"
></script>
<!-- Knockback Dependencies -->
<script
src=
"../../assets/lodash.min.js"
></script>
<script
src=
"js/lib/backbone-min.js"
></script>
<script
src=
"js/lib/knockout-2.1.0.js"
></script>
<script
src=
"js/lib/knockback.min.js"
></script>
<!-- More Demo Dependencies -->
<script
src=
"js/lib/knockback-full-stack-0.16.7.min.js"
></script>
<script
src=
"js/lib/backbone.localStorage-min.js"
></script>
<!-- Demo Components -->
<!-- App and Components -->
<script
src=
"js/lib/knockout-extended-bindings.js"
></script>
<script
src=
"js/models/todo.js"
></script>
<script
src=
"js/models/todo_collection.js"
></script>
<script
src=
"js/viewmodels/settings.js"
></script>
<script
src=
"js/viewmodels/header.js"
></script>
<script
src=
"js/viewmodels/todos.js"
></script>
<script
src=
"js/viewmodels/footer.js"
></script>
<script
src=
"js/routers/app.js"
></script>
<!-- The Demo -->
<script
src=
"js/app.js"
></script>
<script
src=
"js/viewmodels/todo.js"
></script>
<script
src=
"js/viewmodels/app.js"
></script>
</body>
</html>
\ No newline at end of file
architecture-examples/knockback/js/app.js
deleted
100644 → 0
View file @
1bb1340f
// Generated by CoffeeScript 1.3.3
(
function
()
{
$
(
function
()
{
var
todos
;
ko
.
bindingHandlers
.
dblclick
=
{
init
:
function
(
element
,
value_accessor
)
{
return
$
(
element
).
dblclick
(
ko
.
utils
.
unwrapObservable
(
value_accessor
()));
}
};
ko
.
bindingHandlers
.
block
=
{
update
:
function
(
element
,
value_accessor
)
{
return
element
.
style
.
display
=
ko
.
utils
.
unwrapObservable
(
value_accessor
())
?
'
block
'
:
'
none
'
;
}
};
ko
.
bindingHandlers
.
selectAndFocus
=
{
init
:
function
(
element
,
value_accessor
,
all_bindings_accessor
)
{
ko
.
bindingHandlers
.
hasfocus
.
init
(
element
,
value_accessor
,
all_bindings_accessor
);
return
ko
.
utils
.
registerEventHandler
(
element
,
'
focus
'
,
function
()
{
return
element
.
focus
();
});
},
update
:
function
(
element
,
value_accessor
)
{
var
_this
=
this
;
ko
.
utils
.
unwrapObservable
(
value_accessor
());
return
_
.
defer
(
function
()
{
return
ko
.
bindingHandlers
.
hasfocus
.
update
(
element
,
value_accessor
);
});
}
};
window
.
app
=
{
viewmodels
:
{}
};
app
.
viewmodels
.
settings
=
new
SettingsViewModel
();
todos
=
new
TodoCollection
();
app
.
viewmodels
.
header
=
new
HeaderViewModel
(
todos
);
app
.
viewmodels
.
todos
=
new
TodosViewModel
(
todos
);
app
.
viewmodels
.
footer
=
new
FooterViewModel
(
todos
);
ko
.
applyBindings
(
app
.
viewmodels
,
$
(
'
#todoapp
'
)[
0
]);
new
AppRouter
();
Backbone
.
history
.
start
();
return
todos
.
fetch
();
});
}).
call
(
this
);
architecture-examples/knockback/js/lib/backbone-min.js
deleted
100644 → 0
View file @
1bb1340f
This diff is collapsed.
Click to expand it.
architecture-examples/knockback/js/lib/backbone.localStorage-min.js
View file @
2a30629f
architecture-examples/knockback/js/lib/knock
out-2.1.0
.js
→
architecture-examples/knockback/js/lib/knock
back-full-stack-0.16.7.min
.js
View file @
2a30629f
This diff is collapsed.
Click to expand it.
architecture-examples/knockback/js/lib/knockback.min.js
deleted
100644 → 0
View file @
1bb1340f
This diff is collapsed.
Click to expand it.
architecture-examples/knockback/js/lib/knockout-extended-bindings.js
0 → 100644
View file @
2a30629f
// Generated by CoffeeScript 1.3.3
(
function
()
{
ko
.
bindingHandlers
.
dblclick
=
{
init
:
function
(
element
,
value_accessor
)
{
return
$
(
element
).
dblclick
(
ko
.
utils
.
unwrapObservable
(
value_accessor
()));
}
};
ko
.
bindingHandlers
.
block
=
{
update
:
function
(
element
,
value_accessor
)
{
return
element
.
style
.
display
=
ko
.
utils
.
unwrapObservable
(
value_accessor
())
?
'
block
'
:
'
none
'
;
}
};
ko
.
bindingHandlers
.
selectAndFocus
=
{
init
:
function
(
element
,
value_accessor
,
all_bindings_accessor
)
{
ko
.
bindingHandlers
.
hasfocus
.
init
(
element
,
value_accessor
,
all_bindings_accessor
);
return
ko
.
utils
.
registerEventHandler
(
element
,
'
focus
'
,
function
()
{
return
element
.
select
();
});
},
update
:
function
(
element
,
value_accessor
)
{
ko
.
utils
.
unwrapObservable
(
value_accessor
());
return
_
.
defer
(
function
()
{
return
ko
.
bindingHandlers
.
hasfocus
.
update
(
element
,
value_accessor
);
});
}
};
}).
call
(
this
);
architecture-examples/knockback/js/models/todo_collection.js
View file @
2a30629f
...
...
@@ -32,16 +32,14 @@
};
TodoCollection
.
prototype
.
destroyCompleted
=
function
()
{
var
completed_tasks
,
model
,
_i
,
_len
,
_results
;
var
completed_tasks
,
model
,
_i
,
_len
;
completed_tasks
=
this
.
filter
(
function
(
todo
)
{
return
todo
.
completed
();
});
_results
=
[];
for
(
_i
=
0
,
_len
=
completed_tasks
.
length
;
_i
<
_len
;
_i
++
)
{
model
=
completed_tasks
[
_i
];
_results
.
push
(
model
.
destroy
()
);
model
.
destroy
(
);
}
return
_results
;
};
return
TodoCollection
;
...
...
architecture-examples/knockback/js/routers/app.js
deleted
100644 → 0
View file @
1bb1340f
// Generated by CoffeeScript 1.3.3
(
function
()
{
var
__hasProp
=
{}.
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
.
AppRouter
=
(
function
(
_super
)
{
__extends
(
AppRouter
,
_super
);
function
AppRouter
()
{
return
AppRouter
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
}
AppRouter
.
prototype
.
routes
=
{
""
:
"
all
"
,
"
active
"
:
"
active
"
,
"
completed
"
:
"
completed
"
};
AppRouter
.
prototype
.
all
=
function
()
{
return
app
.
viewmodels
.
settings
.
list_filter_mode
(
''
);
};
AppRouter
.
prototype
.
active
=
function
()
{
return
app
.
viewmodels
.
settings
.
list_filter_mode
(
'
active
'
);
};
AppRouter
.
prototype
.
completed
=
function
()
{
return
app
.
viewmodels
.
settings
.
list_filter_mode
(
'
completed
'
);
};
return
AppRouter
;
})(
Backbone
.
Router
);
}).
call
(
this
);
architecture-examples/knockback/js/viewmodels/app.js
0 → 100644
View file @
2a30629f
// Generated by CoffeeScript 1.3.3
(
function
()
{
var
ENTER_KEY
;
ENTER_KEY
=
13
;
window
.
AppViewModel
=
function
()
{
var
filter_fn
,
router
,
_this
=
this
;
this
.
collections
=
{
todos
:
new
TodoCollection
()
};
this
.
collections
.
todos
.
fetch
();
this
.
list_filter_mode
=
ko
.
observable
(
''
);
filter_fn
=
ko
.
computed
(
function
()
{
switch
(
_this
.
list_filter_mode
())
{
case
'
active
'
:
return
function
(
model
)
{
return
model
.
completed
();
};
case
'
completed
'
:
return
function
(
model
)
{
return
!
model
.
completed
();
};
default
:
return
function
()
{
return
false
;
};
}
});
this
.
todos
=
kb
.
collectionObservable
(
this
.
collections
.
todos
,
{
view_model
:
TodoViewModel
,
filters
:
filter_fn
});
this
.
todos_changed
=
kb
.
triggeredObservable
(
this
.
collections
.
todos
,
'
change add remove
'
);
this
.
tasks_exist
=
ko
.
computed
(
function
()
{
_this
.
todos_changed
();
return
!!
_this
.
collections
.
todos
.
length
;
});
this
.
title
=
ko
.
observable
(
''
);
this
.
onAddTodo
=
function
(
view_model
,
event
)
{
if
(
!
$
.
trim
(
_this
.
title
())
||
(
event
.
keyCode
!==
ENTER_KEY
))
{
return
true
;
}
_this
.
collections
.
todos
.
create
({
title
:
$
.
trim
(
_this
.
title
())
});
return
_this
.
title
(
''
);
};
this
.
remaining_count
=
ko
.
computed
(
function
()
{
_this
.
todos_changed
();
return
_this
.
collections
.
todos
.
remainingCount
();
});
this
.
completed_count
=
ko
.
computed
(
function
()
{
_this
.
todos_changed
();
return
_this
.
collections
.
todos
.
completedCount
();
});
this
.
all_completed
=
ko
.
computed
({
read
:
function
()
{
return
!
_this
.
remaining_count
();
},
write
:
function
(
completed
)
{
return
_this
.
collections
.
todos
.
completeAll
(
completed
);
}
});
this
.
onDestroyCompleted
=
function
()
{
return
_this
.
collections
.
todos
.
destroyCompleted
();
};
this
.
loc
=
{
remaining_message
:
ko
.
computed
(
function
()
{
return
"
<strong>
"
+
(
_this
.
remaining_count
())
+
"
</strong>
"
+
(
_this
.
remaining_count
()
===
1
?
'
item
'
:
'
items
'
)
+
"
left
"
;
}),
clear_message
:
ko
.
computed
(
function
()
{
var
count
;
if
((
count
=
_this
.
completed_count
()))
{
return
"
Clear completed (
"
+
count
+
"
)
"
;
}
else
{
return
''
;
}
})
};
router
=
new
Backbone
.
Router
;
router
.
route
(
''
,
null
,
function
()
{
return
_this
.
list_filter_mode
(
''
);
});
router
.
route
(
'
active
'
,
null
,
function
()
{
return
_this
.
list_filter_mode
(
'
active
'
);
});
router
.
route
(
'
completed
'
,
null
,
function
()
{
return
_this
.
list_filter_mode
(
'
completed
'
);
});
Backbone
.
history
.
start
();
};
}).
call
(
this
);
architecture-examples/knockback/js/viewmodels/footer.js
deleted
100644 → 0
View file @
1bb1340f
// Generated by CoffeeScript 1.3.3
(
function
()
{
window
.
FooterViewModel
=
function
(
todos
)
{
var
_this
=
this
;
this
.
todos
=
kb
.
collectionObservable
(
todos
);
this
.
todos
.
collection
().
bind
(
'
change
'
,
function
()
{
return
_this
.
todos
.
valueHasMutated
();
});
this
.
remaining_text
=
ko
.
computed
(
function
()
{
return
"
<strong>
"
+
(
_this
.
todos
.
collection
().
remainingCount
())
+
"
</strong>
"
+
(
_this
.
todos
.
collection
().
remainingCount
()
===
1
?
'
item
'
:
'
items
'
)
+
"
left
"
;
});
this
.
clear_text
=
ko
.
computed
(
function
()
{
var
count
;
count
=
_this
.
todos
.
collection
().
completedCount
();
if
(
count
)
{
return
"
Clear completed (
"
+
count
+
"
)
"
;
}
else
{
return
''
;
}
});
this
.
onDestroyCompleted
=
function
()
{
return
todos
.
destroyCompleted
();
};
return
this
;
};
}).
call
(
this
);
architecture-examples/knockback/js/viewmodels/header.js
deleted
100644 → 0
View file @
1bb1340f
// Generated by CoffeeScript 1.3.3
(
function
()
{
var
ENTER_KEY
;
ENTER_KEY
=
13
;
window
.
HeaderViewModel
=
function
(
todos
)
{
var
_this
=
this
;
this
.
title
=
ko
.
observable
(
''
);
this
.
onAddTodo
=
function
(
view_model
,
event
)
{
if
(
!
$
.
trim
(
_this
.
title
())
||
(
event
.
keyCode
!==
ENTER_KEY
))
{
return
true
;
}
todos
.
create
({
title
:
$
.
trim
(
_this
.
title
())
});
return
_this
.
title
(
''
);
};
return
this
;
};
}).
call
(
this
);
architecture-examples/knockback/js/viewmodels/settings.js
deleted
100644 → 0
View file @
1bb1340f
// Generated by CoffeeScript 1.3.3
(
function
()
{
window
.
SettingsViewModel
=
function
()
{
this
.
list_filter_mode
=
ko
.
observable
(
''
);
return
this
;
};
}).
call
(
this
);
architecture-examples/knockback/js/viewmodels/todo
s
.js
→
architecture-examples/knockback/js/viewmodels/todo.js
View file @
2a30629f
// Generated by CoffeeScript 1.3.3
(
function
()
{
var
TodoViewModel
;
TodoViewModel
=
function
(
model
)
{
window
.
TodoViewModel
=
function
(
model
)
{
var
_this
=
this
;
this
.
editing
=
ko
.
observable
(
false
);
this
.
completed
=
kb
.
observable
(
model
,
{
...
...
@@ -14,16 +13,6 @@
return
model
.
completed
(
completed
);
})
},
this
);
this
.
visible
=
ko
.
computed
(
function
()
{
switch
(
app
.
viewmodels
.
settings
.
list_filter_mode
())
{
case
'
active
'
:
return
!
_this
.
completed
();
case
'
completed
'
:
return
_this
.
completed
();
default
:
return
true
;
}
});
this
.
title
=
kb
.
observable
(
model
,
{
key
:
'
title
'
,
write
:
(
function
(
title
)
{
...
...
@@ -44,7 +33,8 @@
};
this
.
onCheckEditBegin
=
function
()
{
if
(
!
_this
.
editing
()
&&
!
_this
.
completed
())
{
return
_this
.
editing
(
true
);
_this
.
editing
(
true
);
return
$
(
'
.todo-input
'
).
focus
();
}
};
this
.
onCheckEditEnd
=
function
(
view_model
,
event
)
{
...
...
@@ -53,29 +43,6 @@
return
_this
.
editing
(
false
);
}
};
return
this
;
};
window
.
TodosViewModel
=
function
(
todos
)
{
var
_this
=
this
;
this
.
todos
=
kb
.
collectionObservable
(
todos
,
{
view_model
:
TodoViewModel
});
this
.
todos
.
collection
().
bind
(
'
change
'
,
function
()
{
return
_this
.
todos
.
valueHasMutated
();
});
this
.
tasks_exist
=
ko
.
computed
(
function
()
{
return
_this
.
todos
().
length
;
});
this
.
all_completed
=
ko
.
computed
({
read
:
function
()
{
return
!
_this
.
todos
.
collection
().
remainingCount
();
},
write
:
function
(
completed
)
{
return
_this
.
todos
.
collection
().
completeAll
(
completed
);
}
});
return
this
;
};
}).
call
(
this
);
architecture-examples/knockback/readme.md
View file @
2a30629f
# Knockback.js • [TodoMVC](http://todomvc.com)
Forked from https://github.com/kmalakoff/knockback-todos
## Getting started
[
CoffeeScript
](
http://coffeescript.org
)
is required to compile this application
if you make changes to the files in the
`src`
folder.
You need
[
CoffeScript
](
http://coffeescript.org
)
to compile
if you make changes to the files in the
`src`
folder.
## Compile
...
...
architecture-examples/knockback/src/app.coffee
deleted
100644 → 0
View file @
1bb1340f
$
->
# Add custom handlers to Knockout.js - adapted from Knockout.js Todos app: https://github.com/ashish01/knockoutjs-todos
ko
.
bindingHandlers
.
dblclick
=
init
:
(
element
,
value_accessor
)
->
$
(
element
).
dblclick
(
ko
.
utils
.
unwrapObservable
(
value_accessor
()))
ko
.
bindingHandlers
.
block
=
update
:
(
element
,
value_accessor
)
->
element
.
style
.
display
=
if
ko
.
utils
.
unwrapObservable
(
value_accessor
())
then
'block'
else
'none'
ko
.
bindingHandlers
.
selectAndFocus
=
init
:
(
element
,
value_accessor
,
all_bindings_accessor
)
->
ko
.
bindingHandlers
.
hasfocus
.
init
(
element
,
value_accessor
,
all_bindings_accessor
)
ko
.
utils
.
registerEventHandler
(
element
,
'focus'
,
->
element
.
focus
())
update
:
(
element
,
value_accessor
)
->
ko
.
utils
.
unwrapObservable
(
value_accessor
())
# create dependency
_
.
defer
(
=>
ko
.
bindingHandlers
.
hasfocus
.
update
(
element
,
value_accessor
))
# Create and bind the app viewmodels
window
.
app
=
{
viewmodels
:
{}}
app
.
viewmodels
.
settings
=
new
SettingsViewModel
()
todos
=
new
TodoCollection
()
app
.
viewmodels
.
header
=
new
HeaderViewModel
(
todos
)
app
.
viewmodels
.
todos
=
new
TodosViewModel
(
todos
)
app
.
viewmodels
.
footer
=
new
FooterViewModel
(
todos
)
ko
.
applyBindings
(
app
.
viewmodels
,
$
(
'#todoapp'
)[
0
])
# Start the app routing
new
AppRouter
()
Backbone
.
history
.
start
()
# Load the todos
todos
.
fetch
()
# kb.vmRelease(app.viewmodels) # Destroy when finished with the view model
architecture-examples/knockback/src/lib/knockout-extended-bindings.coffee
0 → 100644
View file @
2a30629f
# Add custom handlers to Knockout.js - adapted from Knockout.js Todos app: https://github.com/ashish01/knockoutjs-todos
ko
.
bindingHandlers
.
dblclick
=
init
:
(
element
,
value_accessor
)
->
$
(
element
).
dblclick
(
ko
.
utils
.
unwrapObservable
(
value_accessor
()))
ko
.
bindingHandlers
.
block
=
update
:
(
element
,
value_accessor
)
->
element
.
style
.
display
=
if
ko
.
utils
.
unwrapObservable
(
value_accessor
())
then
'block'
else
'none'
ko
.
bindingHandlers
.
selectAndFocus
=
init
:
(
element
,
value_accessor
,
all_bindings_accessor
)
->
ko
.
bindingHandlers
.
hasfocus
.
init
(
element
,
value_accessor
,
all_bindings_accessor
)
ko
.
utils
.
registerEventHandler
(
element
,
'focus'
,
->
element
.
select
())
update
:
(
element
,
value_accessor
)
->
ko
.
utils
.
unwrapObservable
(
value_accessor
())
# create dependency
_
.
defer
(
->
ko
.
bindingHandlers
.
hasfocus
.
update
(
element
,
value_accessor
))
\ No newline at end of file
architecture-examples/knockback/src/models/todo.coffee
View file @
2a30629f
class
window
.
Todo
extends
Backbone
.
Model
completed
:
(
completed
)
->
return
!!
@
get
(
'completed'
)
if
arguments
.
length
==
0
@
save
({
completed
:
if
completed
then
new
Date
()
else
null
})
return
!!
@
get
(
'completed'
)
if
arguments
.
length
is
0
# getter
@
save
({
completed
:
if
completed
then
new
Date
()
else
null
})
# setter
\ No newline at end of file
architecture-examples/knockback/src/models/todo_collection.coffee
View file @
2a30629f
class
window
.
TodoCollection
extends
Backbone
.
Collection
localStorage
:
new
Store
(
'todos-knockback'
)
# Save all of the todos under the
`"todos-knockback"`
namespace.
localStorage
:
new
Store
(
'todos-knockback'
)
# Save all of the todos under the
"todos-knockback"
namespace.
model
:
Todo
completedCount
:
->
@
models
.
reduce
(((
prev
,
cur
)
->
return
prev
+
if
cur
.
completed
()
then
1
else
0
),
0
)
...
...
@@ -10,3 +10,4 @@ class window.TodoCollection extends Backbone.Collection
destroyCompleted
:
->
completed_tasks
=
@
filter
((
todo
)
->
return
todo
.
completed
())
model
.
destroy
()
for
model
in
completed_tasks
return
\ No newline at end of file
architecture-examples/knockback/src/routers/app.coffee
deleted
100644 → 0
View file @
1bb1340f
class
window
.
AppRouter
extends
Backbone
.
Router
routes
:
""
:
"all"
"active"
:
"active"
"completed"
:
"completed"
all
:
->
app
.
viewmodels
.
settings
.
list_filter_mode
(
''
)
active
:
->
app
.
viewmodels
.
settings
.
list_filter_mode
(
'active'
)
completed
:
->
app
.
viewmodels
.
settings
.
list_filter_mode
(
'completed'
)
architecture-examples/knockback/src/viewmodels/app.coffee
0 → 100644
View file @
2a30629f
ENTER_KEY
=
13
window
.
AppViewModel
=
->
#############################
# Shared
#############################
# collections
@
collections
=
todos
:
new
TodoCollection
()
@
collections
.
todos
.
fetch
()
# shared observables
@
list_filter_mode
=
ko
.
observable
(
''
)
filter_fn
=
ko
.
computed
(
=>
switch
@
list_filter_mode
()
when
'active'
then
return
(
model
)
->
return
model
.
completed
()
when
'completed'
then
return
(
model
)
->
return
not
model
.
completed
()
else
return
->
return
false
)
@
todos
=
kb
.
collectionObservable
(
@
collections
.
todos
,
{
view_model
:
TodoViewModel
,
filters
:
filter_fn
})
@
todos_changed
=
kb
.
triggeredObservable
(
@
collections
.
todos
,
'change add remove'
)
@
tasks_exist
=
ko
.
computed
(
=>
@
todos_changed
();
return
!!
@
collections
.
todos
.
length
)
#############################
# Header Section
#############################
@
title
=
ko
.
observable
(
''
)
@
onAddTodo
=
(
view_model
,
event
)
=>
return
true
if
not
$
.
trim
(
@
title
())
or
(
event
.
keyCode
!=
ENTER_KEY
)
# Create task and reset UI
@
collections
.
todos
.
create
({
title
:
$
.
trim
(
@
title
())})
@
title
(
''
)
#############################
# Main Section
#############################
@
remaining_count
=
ko
.
computed
(
=>
@
todos_changed
();
return
@
collections
.
todos
.
remainingCount
())
@
completed_count
=
ko
.
computed
(
=>
@
todos_changed
();
return
@
collections
.
todos
.
completedCount
())
@
all_completed
=
ko
.
computed
(
read
:
=>
return
not
@
remaining_count
()
write
:
(
completed
)
=>
@
collections
.
todos
.
completeAll
(
completed
)
)
#############################
# Footer Section
#############################
@
onDestroyCompleted
=
=>
@
collections
.
todos
.
destroyCompleted
()
#############################
# Localization
#############################
@
loc
=
remaining_message
:
ko
.
computed
(
=>
return
"<strong>
#{
@
remaining_count
()
}
</strong>
#{
if
@
remaining_count
()
==
1
then
'item'
else
'items'
}
left"
)
clear_message
:
ko
.
computed
(
=>
return
if
(
count
=
@
completed_count
())
then
"Clear completed (
#{
count
}
)"
else
''
)
#############################
# Routing
#############################
router
=
new
Backbone
.
Router
router
.
route
(
''
,
null
,
=>
@
list_filter_mode
(
''
))
router
.
route
(
'active'
,
null
,
=>
@
list_filter_mode
(
'active'
))
router
.
route
(
'completed'
,
null
,
=>
@
list_filter_mode
(
'completed'
))
Backbone
.
history
.
start
()
return
\ No newline at end of file
architecture-examples/knockback/src/viewmodels/footer.coffee
deleted
100644 → 0
View file @
1bb1340f
window
.
FooterViewModel
=
(
todos
)
->
@
todos
=
kb
.
collectionObservable
(
todos
)
@
todos
.
collection
().
bind
(
'change'
,
=>
@
todos
.
valueHasMutated
())
# get notified of changes to any models
@
remaining_text
=
ko
.
computed
(
=>
return
"<strong>
#{
@
todos
.
collection
().
remainingCount
()
}
</strong>
#{
if
@
todos
.
collection
().
remainingCount
()
==
1
then
'item'
else
'items'
}
left"
)
@
clear_text
=
ko
.
computed
(
=>
count
=
@
todos
.
collection
().
completedCount
()
return
if
count
then
"Clear completed (
#{
count
}
)"
else
''
)
@
onDestroyCompleted
=
=>
todos
.
destroyCompleted
()
@
architecture-examples/knockback/src/viewmodels/header.coffee
deleted
100644 → 0
View file @
1bb1340f
ENTER_KEY
=
13
window
.
HeaderViewModel
=
(
todos
)
->
@
title
=
ko
.
observable
(
''
)
@
onAddTodo
=
(
view_model
,
event
)
=>
return
true
if
not
$
.
trim
(
@
title
())
or
(
event
.
keyCode
!=
ENTER_KEY
)
# Create task and reset UI
todos
.
create
({
title
:
$
.
trim
(
@
title
())})
@
title
(
''
)
@
architecture-examples/knockback/src/viewmodels/settings.coffee
deleted
100644 → 0
View file @
1bb1340f
window
.
SettingsViewModel
=
->
@
list_filter_mode
=
ko
.
observable
(
''
)
@
architecture-examples/knockback/src/viewmodels/todo
s
.coffee
→
architecture-examples/knockback/src/viewmodels/todo.coffee
View file @
2a30629f
TodoViewModel
=
(
model
)
->
# Task UI state
window
.
TodoViewModel
=
(
model
)
->
@
editing
=
ko
.
observable
(
false
)
@
completed
=
kb
.
observable
(
model
,
{
key
:
'completed'
,
read
:
(
->
return
model
.
completed
()),
write
:
((
completed
)
->
model
.
completed
(
completed
))
},
@
)
@
visible
=
ko
.
computed
(
=>
switch
app
.
viewmodels
.
settings
.
list_filter_mode
()
when
'active'
then
return
not
@
completed
()
when
'completed'
then
return
@
completed
()
else
return
true
)
@
title
=
kb
.
observable
(
model
,
{
key
:
'title'
...
...
@@ -19,18 +12,14 @@ TodoViewModel = (model) ->
@
onDestroyTodo
=
=>
model
.
destroy
()
@
onCheckEditBegin
=
=>
@
editing
(
true
)
if
not
@
editing
()
and
not
@
completed
()
@
onCheckEditEnd
=
(
view_model
,
event
)
=>
(
$
(
'.todo-input'
).
blur
();
@
editing
(
false
))
if
(
event
.
keyCode
==
13
)
or
(
event
.
type
==
'blur'
)
@
window
.
TodosViewModel
=
(
todos
)
->
@
todos
=
kb
.
collectionObservable
(
todos
,
{
view_model
:
TodoViewModel
})
@
todos
.
collection
().
bind
(
'change'
,
=>
@
todos
.
valueHasMutated
())
# get notified of changes to any models
@
onCheckEditBegin
=
=>
if
not
@
editing
()
and
not
@
completed
()
@
editing
(
true
)
$
(
'.todo-input'
).
focus
()
@
tasks_exist
=
ko
.
computed
(
=>
@
todos
().
length
)
@
onCheckEditEnd
=
(
view_model
,
event
)
=>
if
(
event
.
keyCode
==
13
)
or
(
event
.
type
==
'blur'
)
$
(
'.todo-input'
).
blur
()
@
editing
(
false
)
@
all_completed
=
ko
.
computed
(
read
:
=>
return
not
@
todos
.
collection
().
remainingCount
()
write
:
(
completed
)
=>
@
todos
.
collection
().
completeAll
(
completed
)
)
@
return
\ 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