mirror of https://github.com/vuejs/vue.git
complete todo example
This commit is contained in:
parent
dc04a1af69
commit
7d126127e6
|
|
@ -11,6 +11,8 @@ WIP, playing with data binding
|
|||
|
||||
### Data Binding
|
||||
|
||||
### Event Handling
|
||||
|
||||
### Filters
|
||||
|
||||
### Computed Properties
|
||||
|
|
|
|||
5
TODO.md
5
TODO.md
|
|
@ -1,3 +1,6 @@
|
|||
- parse textNodes
|
||||
- parse textNodes?
|
||||
- method invoke with arguments
|
||||
- more directives / filters
|
||||
- sd-if
|
||||
- sd-route
|
||||
- nested properties in scope (kinda hard, maybe later)
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
{
|
||||
"name": "seed",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"component/emitter": "*"
|
||||
},
|
||||
"main": "src/main.js",
|
||||
"scripts": [
|
||||
"src/main.js",
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Todo</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="../dist/seed.js"></script>
|
||||
<style type="text/css">
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
.done {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
#app.all .all {
|
||||
font-weight: bold;
|
||||
}
|
||||
#app.remaining .todo.done {
|
||||
display: none;
|
||||
}
|
||||
#app.remaining .remaining {
|
||||
font-weight: bold;
|
||||
}
|
||||
#app.completed .todo:not(.done) {
|
||||
display: none;
|
||||
}
|
||||
#app.completed .completed {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" sd-controller="Todos" sd-class="filter">
|
||||
<div>
|
||||
<input placeholder="What needs to be done?" sd-on="change:addTodo">
|
||||
</div>
|
||||
<ul sd-show="todos">
|
||||
<li class="todo" sd-each="todo:todos" sd-class="done:todo.done">
|
||||
<input type="checkbox" sd-checked="todo.done" sd-on="change:toggleTodo">
|
||||
<span sd-text="todo.text"></span>
|
||||
<a sd-on="click:removeTodo">X</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="footer">
|
||||
Total: <span sd-text="total < todos"></span> |
|
||||
Remaining: <span sd-text="remaining < completed"></span> |
|
||||
Completed: <span sd-text="completed"></span>
|
||||
<br>
|
||||
<a class="all" sd-on="click:setFilter">Show All</a> |
|
||||
<a class="remaining" sd-on="click:setFilter">Show Remaining</a> |
|
||||
<a class="completed" sd-on="click:setFilter">Show Completed</a>
|
||||
<br>
|
||||
<a sd-on="click:removeCompleted">Remove Completed</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
var Seed = require('seed')
|
||||
|
||||
var todos = [
|
||||
{ text: 'make nesting controllers work', done: true },
|
||||
{ text: 'complete ArrayWatcher', done: false },
|
||||
{ text: 'computed properties', done: false },
|
||||
{ text: 'parse textnodes', done: false }
|
||||
]
|
||||
|
||||
Seed.controller('Todos', function (scope) {
|
||||
|
||||
// regular properties
|
||||
scope.todos = todos
|
||||
scope.filter = 'all'
|
||||
scope.completed = todos.reduce(function (count, todo) {
|
||||
return count + (todo.done ? 1 : 0)
|
||||
}, 0)
|
||||
|
||||
// computed properties
|
||||
scope.total = function () {
|
||||
return scope.todos.length
|
||||
}
|
||||
|
||||
scope.remaining = function () {
|
||||
return scope.todos.length - scope.completed
|
||||
}
|
||||
|
||||
// event handlers
|
||||
scope.addTodo = function (e) {
|
||||
var val = e.el.value
|
||||
if (val) {
|
||||
e.el.value = ''
|
||||
scope.todos.unshift({ text: val, done: false })
|
||||
}
|
||||
}
|
||||
|
||||
scope.removeTodo = function (e) {
|
||||
scope.todos.remove(e.scope)
|
||||
scope.completed -= e.scope.done ? 1 : 0
|
||||
}
|
||||
|
||||
scope.toggleTodo = function (e) {
|
||||
scope.completed += e.scope.done ? 1 : -1
|
||||
}
|
||||
|
||||
scope.setFilter = function (e) {
|
||||
scope.filter = e.el.className
|
||||
}
|
||||
|
||||
scope.removeCompleted = function () {
|
||||
scope.todos = scope.todos.filter(function (todo) {
|
||||
return !todo.done
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
var app = Seed.bootstrap()
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
var Seed = require('seed')
|
||||
|
||||
var todos = [
|
||||
{ text: 'make nesting controllers work', done: true },
|
||||
{ text: 'complete ArrayWatcher', done: false },
|
||||
{ text: 'computed properties', done: false },
|
||||
{ text: 'parse textnodes', done: false }
|
||||
]
|
||||
|
||||
Seed.controller('Todos', function (scope) {
|
||||
|
||||
// regular properties -----------------------------------------------------
|
||||
scope.todos = todos
|
||||
scope.filter = 'all'
|
||||
scope.allDone = false
|
||||
scope.remaining = todos.reduce(function (count, todo) {
|
||||
return count + (todo.done ? 0 : 1)
|
||||
}, 0)
|
||||
|
||||
// computed properties ----------------------------------------------------
|
||||
scope.total = function () {
|
||||
return scope.todos.length
|
||||
}
|
||||
|
||||
scope.completed = function () {
|
||||
return scope.total() - scope.remaining
|
||||
}
|
||||
|
||||
scope.itemLabel = function () {
|
||||
return scope.remaining > 1 ? 'items' : 'item'
|
||||
}
|
||||
|
||||
// event handlers ---------------------------------------------------------
|
||||
scope.addTodo = function (e) {
|
||||
var val = e.el.value
|
||||
if (val) {
|
||||
e.el.value = ''
|
||||
scope.todos.unshift({ text: val, done: false })
|
||||
}
|
||||
scope.remaining++
|
||||
}
|
||||
|
||||
scope.removeTodo = function (e) {
|
||||
scope.todos.remove(e.scope)
|
||||
scope.remaining -= e.scope.done ? 0 : 1
|
||||
}
|
||||
|
||||
scope.updateCount = function (e) {
|
||||
scope.remaining += e.scope.done ? -1 : 1
|
||||
scope.allDone = scope.remaining === 0
|
||||
}
|
||||
|
||||
scope.edit = function (e) {
|
||||
e.scope.editing = true
|
||||
}
|
||||
|
||||
scope.stopEdit = function (e) {
|
||||
e.scope.editing = false
|
||||
}
|
||||
|
||||
scope.setFilter = function (e) {
|
||||
scope.filter = e.el.dataset.filter
|
||||
}
|
||||
|
||||
scope.toggleAll = function (e) {
|
||||
scope.todos.forEach(function (todo) {
|
||||
todo.done = e.el.checked
|
||||
})
|
||||
scope.remaining = e.el.checked ? 0 : scope.total()
|
||||
}
|
||||
|
||||
scope.removeCompleted = function () {
|
||||
scope.todos = scope.todos.filter(function (todo) {
|
||||
return !todo.done
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Seed.bootstrap()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1,13 @@
|
|||
#todoapp.all [data-filter="all"],
|
||||
#todoapp.active [data-filter="active"],
|
||||
#todoapp.completed [data-filter="completed"] {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#todoapp.active #todo-list li.completed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#todoapp.completed #todo-list li:not(.completed) {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Todo</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="todomvc.css">
|
||||
<link rel="stylesheet" type="text/css" href="custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<section id="todoapp" sd-controller="Todos" sd-class="filter">
|
||||
|
||||
<header id="header">
|
||||
<h1>todos</h1>
|
||||
<!-- main input box -->
|
||||
<input
|
||||
id="new-todo"
|
||||
autofocus
|
||||
sd-on="keyup:addTodo | key enter"
|
||||
placeholder="What needs to be done?"
|
||||
>
|
||||
</header>
|
||||
|
||||
<section id="main" sd-show="total < todos">
|
||||
<input id="toggle-all" type="checkbox" sd-checked="allDone" sd-on="change:toggleAll">
|
||||
<ul id="todo-list">
|
||||
<!-- a single todo item -->
|
||||
<li sd-each="todo:todos" sd-class="completed:todo.done, editing:todo.editing">
|
||||
<div class="view">
|
||||
<input
|
||||
class="toggle"
|
||||
type="checkbox"
|
||||
sd-checked="todo.done"
|
||||
sd-on="change:updateCount"
|
||||
>
|
||||
<label
|
||||
sd-text="todo.text"
|
||||
sd-on="dblclick:edit"
|
||||
></label>
|
||||
<button class="destroy" sd-on="click:removeTodo"></button>
|
||||
</div>
|
||||
<input
|
||||
class="edit"
|
||||
type="text"
|
||||
sd-focus="todo.editing"
|
||||
sd-on="blur:stopEdit, keyup:stopEdit | key enter"
|
||||
sd-value="todo.text"
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- footer controls -->
|
||||
<footer id="footer" sd-show="total < todos">
|
||||
<span id="todo-count">
|
||||
<strong sd-text="remaining"></strong>
|
||||
<span sd-text="itemLabel < remaining"></span>
|
||||
left
|
||||
</span>
|
||||
<ul id="filters">
|
||||
<li><a href="#/all" data-filter="all" sd-on="click:setFilter">All</a></li>
|
||||
<li><a href="#/active" data-filter="active" sd-on="click:setFilter">Active</a></li>
|
||||
<li><a href="#/completed" data-filter="completed" sd-on="click:setFilter">Completed</a></li>
|
||||
</ul>
|
||||
<button id="clear-completed" sd-on="click:removeCompleted">
|
||||
Remove Completed (<span sd-text="completed < total remaining"></span>)
|
||||
</button>
|
||||
</footer>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- info -->
|
||||
<footer id="info">
|
||||
<p>Double-click to edit a todo</p>
|
||||
<p>Powered by <a href="https://github.com/yyx990803/seed">Seed.js</a></p>
|
||||
<p>Created by <a href="http://evanyou.me">Evan You</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- js -->
|
||||
<script src="../../dist/seed.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
/*-moz-appearance: none;*/
|
||||
-ms-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
line-height: 1.4em;
|
||||
background: #eaeaea url('bg.png');
|
||||
color: #4d4d4d;
|
||||
width: 550px;
|
||||
margin: 0 auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#todoapp {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
margin: 130px 0 40px 0;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
|
||||
0 25px 50px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
#todoapp:before {
|
||||
content: '';
|
||||
border-left: 1px solid #f5d6d6;
|
||||
border-right: 1px solid #f5d6d6;
|
||||
width: 2px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 40px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#todoapp input::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#todoapp input::-moz-placeholder {
|
||||
font-style: italic;
|
||||
color: #a9a9a9;
|
||||
}
|
||||
|
||||
#todoapp h1 {
|
||||
position: absolute;
|
||||
top: -120px;
|
||||
width: 100%;
|
||||
font-size: 70px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #b3b3b3;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
|
||||
-webkit-text-rendering: optimizeLegibility;
|
||||
-moz-text-rendering: optimizeLegibility;
|
||||
-ms-text-rendering: optimizeLegibility;
|
||||
-o-text-rendering: optimizeLegibility;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
#header {
|
||||
padding-top: 15px;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
#header:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 15px;
|
||||
z-index: 2;
|
||||
border-bottom: 1px solid #6c615c;
|
||||
background: #8d7d77;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
|
||||
border-top-left-radius: 1px;
|
||||
border-top-right-radius: 1px;
|
||||
}
|
||||
|
||||
#new-todo,
|
||||
.edit {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #999;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#new-todo {
|
||||
padding: 16px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
z-index: 2;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#main {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-top: 1px dotted #adadad;
|
||||
}
|
||||
|
||||
label[for='toggle-all'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#toggle-all {
|
||||
position: absolute;
|
||||
top: -42px;
|
||||
left: -4px;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
border: none; /* Mobile Safari */
|
||||
}
|
||||
|
||||
#toggle-all:before {
|
||||
content: '»';
|
||||
font-size: 28px;
|
||||
color: #d9d9d9;
|
||||
padding: 0 25px 7px;
|
||||
}
|
||||
|
||||
#toggle-all:checked:before {
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
#todo-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#todo-list li {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
}
|
||||
|
||||
#todo-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#todo-list li.editing {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#todo-list li.editing .edit {
|
||||
display: block;
|
||||
width: 506px;
|
||||
padding: 13px 17px 12px 17px;
|
||||
margin: 0 0 0 43px;
|
||||
}
|
||||
|
||||
#todo-list li.editing .view {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none; /* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
/*-moz-appearance: none;*/
|
||||
-ms-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle:after {
|
||||
content: '✔';
|
||||
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
|
||||
font-size: 20px;
|
||||
color: #d9d9d9;
|
||||
text-shadow: 0 -1px 0 #bfbfbf;
|
||||
}
|
||||
|
||||
#todo-list li .toggle:checked:after {
|
||||
color: #85ada7;
|
||||
text-shadow: 0 1px 0 #669991;
|
||||
bottom: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#todo-list li label {
|
||||
word-break: break-word;
|
||||
padding: 15px;
|
||||
margin-left: 45px;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
-webkit-transition: color 0.4s;
|
||||
-moz-transition: color 0.4s;
|
||||
-ms-transition: color 0.4s;
|
||||
-o-transition: color 0.4s;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
|
||||
#todo-list li.completed label {
|
||||
color: #a9a9a9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
#todo-list li .destroy {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 22px;
|
||||
color: #a88a8a;
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
-ms-transition: all 0.2s;
|
||||
-o-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
#todo-list li .destroy:hover {
|
||||
text-shadow: 0 0 1px #000,
|
||||
0 0 10px rgba(199, 107, 107, 0.8);
|
||||
-webkit-transform: scale(1.3);
|
||||
-moz-transform: scale(1.3);
|
||||
-ms-transform: scale(1.3);
|
||||
-o-transform: scale(1.3);
|
||||
transform: scale(1.3);
|
||||
}
|
||||
|
||||
#todo-list li .destroy:after {
|
||||
content: '✖';
|
||||
}
|
||||
|
||||
#todo-list li:hover .destroy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#todo-list li .edit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#todo-list li.editing:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
#footer {
|
||||
color: #777;
|
||||
padding: 0 15px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -31px;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#footer:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 31px;
|
||||
left: 0;
|
||||
height: 50px;
|
||||
z-index: -1;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
|
||||
0 6px 0 -3px rgba(255, 255, 255, 0.8),
|
||||
0 7px 1px -3px rgba(0, 0, 0, 0.3),
|
||||
0 43px 0 -6px rgba(255, 255, 255, 0.8),
|
||||
0 44px 2px -6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
#todo-count {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#filters {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#filters li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#filters li a {
|
||||
color: #83756f;
|
||||
margin: 2px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#filters li a.selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#clear-completed {
|
||||
float: right;
|
||||
position: relative;
|
||||
line-height: 20px;
|
||||
text-decoration: none;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
font-size: 11px;
|
||||
padding: 0 10px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
#clear-completed:hover {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#info {
|
||||
margin: 65px auto 0;
|
||||
color: #a6a6a6;
|
||||
font-size: 12px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#info a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Hack to remove background from Mobile Safari.
|
||||
Can't use it globally since it destroys checkboxes in Firefox and Opera
|
||||
*/
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
#toggle-all,
|
||||
#todo-list li .toggle {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#toggle-all {
|
||||
top: -56px;
|
||||
left: -15px;
|
||||
width: 65px;
|
||||
height: 41px;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden{
|
||||
display:none;
|
||||
}
|
||||
|
|
@ -95,7 +95,12 @@ function Directive (directiveName, expression) {
|
|||
// called when a dependency has changed
|
||||
Directive.prototype.refresh = function () {
|
||||
if (this.value) {
|
||||
this._update(this.value.call(this.seed.scope))
|
||||
var value = this.value.call(this.seed.scope)
|
||||
this._update(
|
||||
this.filters
|
||||
? this.applyFilters(value)
|
||||
: value
|
||||
)
|
||||
}
|
||||
if (this.binding.refreshDependents) {
|
||||
this.binding.refreshDependents()
|
||||
|
|
@ -104,16 +109,17 @@ Directive.prototype.refresh = function () {
|
|||
|
||||
// called when a new value is set
|
||||
Directive.prototype.update = function (value) {
|
||||
if (value && (value === this.value)) return
|
||||
this.value = value
|
||||
// computed property
|
||||
if (typeof value === 'function' && !this.fn) {
|
||||
value = value()
|
||||
}
|
||||
// apply filters
|
||||
if (this.filters) {
|
||||
value = this.applyFilters(value)
|
||||
}
|
||||
this._update(value)
|
||||
this._update(
|
||||
this.filters
|
||||
? this.applyFilters(value)
|
||||
: value
|
||||
)
|
||||
if (this.deps) this.refresh()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,11 @@ var mutationHandlers = {
|
|||
unshift: function (m) {
|
||||
var self = this
|
||||
m.args.forEach(function (data, i) {
|
||||
var seed = self.buildItem(data, i)
|
||||
self.container.insertBefore(seed.el, self.collection[m.args.length].$seed.el)
|
||||
var seed = self.buildItem(data, i),
|
||||
ref = self.collection.length > m.args.length
|
||||
? self.collection[m.args.length].$seed.el
|
||||
: self.marker
|
||||
self.container.insertBefore(seed.el, ref)
|
||||
})
|
||||
self.reorder()
|
||||
},
|
||||
|
|
@ -132,7 +135,6 @@ module.exports = {
|
|||
},
|
||||
|
||||
reorder: function () {
|
||||
console.log('reorder')
|
||||
this.collection.forEach(function (scope, i) {
|
||||
scope.$index = i
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,14 +4,23 @@ module.exports = {
|
|||
each : require('./each'),
|
||||
|
||||
text: function (value) {
|
||||
this.el.textContent = value === null ?
|
||||
'' : value.toString()
|
||||
this.el.textContent =
|
||||
(value !== null && value !== undefined)
|
||||
? value.toString() : ''
|
||||
},
|
||||
|
||||
show: function (value) {
|
||||
this.el.style.display = value ? '' : 'none'
|
||||
},
|
||||
|
||||
hide: function (value) {
|
||||
this.el.style.display = value ? 'none' : ''
|
||||
},
|
||||
|
||||
focus: function (value) {
|
||||
this.el[value ? 'focus' : 'blur']()
|
||||
},
|
||||
|
||||
class: function (value) {
|
||||
if (this.arg) {
|
||||
this.el.classList[value ? 'add' : 'remove'](this.arg)
|
||||
|
|
@ -22,17 +31,32 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
|
||||
value: {
|
||||
bind: function () {
|
||||
var el = this.el, self = this
|
||||
this.change = function () {
|
||||
self.seed.scope[self.key] = el.value
|
||||
}
|
||||
el.addEventListener('change', this.change)
|
||||
},
|
||||
update: function (value) {
|
||||
this.el.value = value
|
||||
},
|
||||
unbind: function () {
|
||||
this.el.removeEventListener('change', this.change)
|
||||
}
|
||||
},
|
||||
|
||||
checked: {
|
||||
bind: function () {
|
||||
var el = this.el,
|
||||
self = this
|
||||
var el = this.el, self = this
|
||||
this.change = function () {
|
||||
self.seed.scope[self.key] = el.checked
|
||||
}
|
||||
el.addEventListener('change', this.change)
|
||||
},
|
||||
update: function (value) {
|
||||
this.el.checked = value
|
||||
this.el.checked = !!value
|
||||
},
|
||||
unbind: function () {
|
||||
this.el.removeEventListener('change', this.change)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
var keyCodes = {
|
||||
enter: 13,
|
||||
tab: 9,
|
||||
'delete': 46,
|
||||
up: 38,
|
||||
left: 37,
|
||||
right: 39,
|
||||
down: 40
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
capitalize: function (value) {
|
||||
|
|
@ -7,6 +17,27 @@ module.exports = {
|
|||
|
||||
uppercase: function (value) {
|
||||
return value.toString().toUpperCase()
|
||||
},
|
||||
|
||||
currency: function (value, args) {
|
||||
if (!value) return value
|
||||
var sign = (args && args[0]) || '$',
|
||||
i = value % 3,
|
||||
f = '.' + value.toFixed(2).slice(-2),
|
||||
s = Math.floor(value).toString()
|
||||
return sign + s.slice(0, i) + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
|
||||
},
|
||||
|
||||
key: function (handler, args) {
|
||||
var code = keyCodes[args[0]]
|
||||
if (!code) {
|
||||
code = parseInt(args[0], 10)
|
||||
}
|
||||
return function (e) {
|
||||
if (e.originalEvent.keyCode === code) {
|
||||
handler(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
47
src/seed.js
47
src/seed.js
|
|
@ -1,5 +1,4 @@
|
|||
var Emitter = require('emitter'),
|
||||
config = require('./config'),
|
||||
var config = require('./config'),
|
||||
DirectiveParser = require('./directive-parser'),
|
||||
TextNodeParser = require('./textnode-parser')
|
||||
|
||||
|
|
@ -7,20 +6,6 @@ var slice = Array.prototype.slice,
|
|||
ctrlAttr = config.prefix + '-controller',
|
||||
eachAttr = config.prefix + '-each'
|
||||
|
||||
function determinScope (key, scope) {
|
||||
if (key.nesting) {
|
||||
var levels = key.nesting
|
||||
while (scope.parentSeed && levels--) {
|
||||
scope = scope.parentSeed
|
||||
}
|
||||
} else if (key.root) {
|
||||
while (scope.parentSeed) {
|
||||
scope = scope.parentSeed
|
||||
}
|
||||
}
|
||||
return scope
|
||||
}
|
||||
|
||||
function Seed (el, options) {
|
||||
|
||||
if (typeof el === 'string') {
|
||||
|
|
@ -45,11 +30,15 @@ function Seed (el, options) {
|
|||
|| {}
|
||||
el.removeAttribute(dataPrefix)
|
||||
|
||||
// if the passed in data is already consumed by
|
||||
// a Seed instance, make a copy from it
|
||||
if (scope.$seed) {
|
||||
scope = this.scope = scope.$dump()
|
||||
}
|
||||
|
||||
scope.$seed = this
|
||||
scope.$destroy = this._destroy.bind(this)
|
||||
scope.$dump = this._dump.bind(this)
|
||||
scope.$on = this.on.bind(this)
|
||||
scope.$emit = this.emit.bind(this)
|
||||
scope.$index = options.index
|
||||
scope.$parent = options.parentSeed && options.parentSeed.scope
|
||||
|
||||
|
|
@ -76,7 +65,7 @@ Seed.prototype._compileNode = function (node, root) {
|
|||
|
||||
self._compileTextNode(node)
|
||||
|
||||
} else {
|
||||
} else if (node.nodeType !== 8) { // exclude comment nodes
|
||||
|
||||
var eachExp = node.getAttribute(eachAttr),
|
||||
ctrlExp = node.getAttribute(ctrlAttr)
|
||||
|
|
@ -164,9 +153,7 @@ Seed.prototype._bind = function (node, directive) {
|
|||
}
|
||||
|
||||
// set initial value
|
||||
if (binding.value) {
|
||||
directive.update(binding.value)
|
||||
}
|
||||
directive.update(binding.value)
|
||||
|
||||
// computed properties
|
||||
if (directive.deps) {
|
||||
|
|
@ -259,6 +246,20 @@ Seed.prototype._dump = function () {
|
|||
return dump
|
||||
}
|
||||
|
||||
Emitter(Seed.prototype)
|
||||
// Helpers --------------------------------------------------------------------
|
||||
|
||||
function determinScope (key, scope) {
|
||||
if (key.nesting) {
|
||||
var levels = key.nesting
|
||||
while (scope.parentSeed && levels--) {
|
||||
scope = scope.parentSeed
|
||||
}
|
||||
} else if (key.root) {
|
||||
while (scope.parentSeed) {
|
||||
scope = scope.parentSeed
|
||||
}
|
||||
}
|
||||
return scope
|
||||
}
|
||||
|
||||
module.exports = Seed
|
||||
Loading…
Reference in New Issue