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
0d07bb3c
Commit
0d07bb3c
authored
Jul 06, 2012
by
Sindre Sorhus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
YUI app update. Fixes #71
Updated it to the latest template and changed and fixed a lot of other stuff.
parent
1c04c6b5
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
216 additions
and
753 deletions
+216
-753
architecture-examples/yuilibrary/css/app.css
architecture-examples/yuilibrary/css/app.css
+4
-0
architecture-examples/yuilibrary/css/style.css
architecture-examples/yuilibrary/css/style.css
+0
-560
architecture-examples/yuilibrary/img/destroy.png
architecture-examples/yuilibrary/img/destroy.png
+0
-0
architecture-examples/yuilibrary/index.html
architecture-examples/yuilibrary/index.html
+27
-39
architecture-examples/yuilibrary/js/app.js
architecture-examples/yuilibrary/js/app.js
+185
-154
No files found.
architecture-examples/yuilibrary/css/app.css
0 → 100644
View file @
0d07bb3c
#main
,
#footer
{
display
:
none
;
}
\ No newline at end of file
architecture-examples/yuilibrary/css/style.css
deleted
100644 → 0
View file @
1c04c6b5
#todo-app
{
-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
;
}
#todo-list
,
#todo-stats
{
margin
:
1em
auto
;
text-align
:
left
;
width
:
450px
;
}
#todo-list
{
list-style
:
none
;
padding
:
0
;
}
#todo-stats
,
.todo-clear
{
color
:
#777
;
}
.todo-clear
{
float
:
right
;
}
.todo-done
.todo-content
{
color
:
#666
;
text-decoration
:
line-through
;
}
.todo-edit
,
.editing
.todo-view
{
display
:
none
;
}
.editing
.todo-edit
{
display
:
block
;
}
.todo-input
{
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
;
}
.todo-item
{
border-bottom
:
1px
dotted
#cfcfcf
;
font-size
:
20px
;
padding
:
6px
;
position
:
relative
;
}
.todo-label
{
color
:
#444
;
font-size
:
20px
;
font-weight
:
bold
;
text-align
:
center
;
}
.todo-remaining
{
color
:
#333
;
font-weight
:
bold
;
}
.todo-remove
{
position
:
absolute
;
right
:
0
;
top
:
12px
;
}
.todo-remove-icon
{
background
:
url(../img/destroy.png)
no-repeat
;
display
:
block
;
height
:
20px
;
opacity
:
0.6
;
visibility
:
hidden
;
width
:
20px
;
}
.todo-remove
:hover
.todo-remove-icon
{
opacity
:
1.0
;
}
.todo-hover
.todo-remove-icon
,
.todo-remove
:focus
.todo-remove-icon
{
visibility
:
visible
;
}
.editing
.todo-remove-icon
{
visibility
:
hidden
;
}
.todo-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
;
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
;
}
/************************************************/
body
{
margin
:
0
;
padding
:
0
;
font-family
:
Helvetica
;
color
:
#444
;
}
#surface
{
position
:
relative
;
margin
:
0
auto
;
width
:
600px
;
}
h1
{
position
:
relative
;
top
:
18px
;
z-index
:
2
;
margin
:
0
;
padding
:
0
;
width
:
100%
;
height
:
1.2em
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
font-size
:
25px
;
font-weight
:
normal
;
}
#lists
{
position
:
absolute
;
top
:
50px
;
left
:
400px
;
z-index
:
2
;
}
dl
{
margin
:
0
;
padding
:
0
;
color
:
#555
;
}
dt
{
margin
:
0
0
5px
0
;
padding
:
0
;
font-size
:
20px
;
font-weight
:
normal
;
}
dd
{
margin
:
0
0
5px
15px
;
padding
:
0
;
font-size
:
17px
;
cursor
:
pointer
;
}
#page
{
float
:
left
;
position
:
relative
;
z-index
:
1
;
width
:
400px
;
height
:
600px
;
}
#page
{
}
h2
{
position
:
absolute
;
top
:
56px
;
left
:
77px
;
margin
:
0
;
font-size
:
30px
;
width
:
275px
;
height
:
1.2em
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
font-weight
:
normal
;
}
/*ul { position: absolute; top: 116px; left: 80px; margin: 0; padding: 0; width: 275px; list-style: none; }*/
li
{
position
:
relative
;
margin
:
0
0
0
25px
;
padding
:
0
;
font-size
:
20px
;
line-height
:
27px
;
}
p
{
position
:
absolute
;
top
:
116px
;
left
:
80px
;
margin
:
0
;
padding
:
0
;
width
:
275px
;
font-size
:
20px
;
line-height
:
27px
;
}
[
contenteditable
]
:hover
{
outline
:
1px
dotted
#999
;
}
.new
{
opacity
:
.25
;
cursor
:
pointer
;
}
.new
:hover
{
opacity
:
.75
;
}
.trashcan
{
position
:
absolute
;
top
:
63px
;
left
:
57px
;
width
:
25px
;
height
:
25px
;
cursor
:
pointer
;
background
:
url(assets/destroy.png)
no-repeat
;
}
.trashcan
:hover
{
opacity
:
.75
;
}
li
.trashcan
{
float
:
right
;
left
:
95%
;
top
:
15px
;
}
#page
:hover
.trashcan
{
display
:
inline-block
;
}
/*todos*/
html
,
body
,
div
,
span
,
applet
,
object
,
iframe
,
h1
,
h2
,
h3
,
h4
,
h5
,
h6
,
p
,
blockquote
,
pre
,
a
,
abbr
,
acronym
,
address
,
big
,
cite
,
code
,
del
,
dfn
,
em
,
font
,
img
,
ins
,
kbd
,
q
,
s
,
samp
,
small
,
strike
,
strong
,
sub
,
sup
,
tt
,
var
,
dl
,
dt
,
dd
,
ol
,
ul
,
li
,
fieldset
,
form
,
label
,
legend
,
table
,
caption
,
tbody
,
tfoot
,
thead
,
tr
,
th
,
td
{
margin
:
0
;
padding
:
0
;
border
:
0
;
outline
:
0
;
font-weight
:
inherit
;
font-style
:
inherit
;
font-size
:
100%
;
font-family
:
inherit
;
vertical-align
:
baseline
;
}
body
{
line-height
:
1
;
color
:
black
;
background
:
white
;
}
ol
,
ul
{
list-style
:
none
;
}
a
img
{
border
:
none
;
}
html
{
background
:
#eeeeee
;
}
body
{
font-family
:
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
font-size
:
14px
;
line-height
:
1.4em
;
background
:
#eeeeee
;
color
:
#333333
;
}
#todo-app
{
width
:
480px
;
margin
:
0
auto
40px
;
background
:
white
;
padding
:
20px
;
-moz-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
5px
6px
0
;
-webkit-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
5px
6px
0
;
-o-box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
5px
6px
0
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.2
)
0
5px
6px
0
;
}
#todo-app
h1
{
font-size
:
36px
;
font-weight
:
bold
;
text-align
:
center
;
padding
:
20px
0
30px
0
;
line-height
:
1
;
}
#create-todo
{
position
:
relative
;
}
#create-todo
input
{
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
;
}
#create-todo
input
::-webkit-input-placeholder
{
font-style
:
italic
;
}
#create-todo
span
{
position
:
absolute
;
z-index
:
999
;
width
:
170px
;
left
:
50%
;
margin-left
:
-85px
;
}
#todo-list
{
margin-top
:
10px
;
}
#todo-list
li
{
padding
:
12px
20px
11px
0
;
position
:
relative
;
font-size
:
24px
;
line-height
:
1.1em
;
border-bottom
:
1px
solid
#cccccc
;
}
#todo-list
li
:after
{
content
:
"\0020"
;
display
:
block
;
height
:
0
;
clear
:
both
;
overflow
:
hidden
;
visibility
:
hidden
;
}
#todo-list
li
.editing
{
padding
:
0
;
border-bottom
:
0
;
}
#todo-list
.editing
.display
,
#todo-list
.edit
{
display
:
none
;
}
#todo-list
.editing
.edit
{
display
:
block
;
}
#todo-list
.editing
input
{
width
:
444px
;
font-size
:
24px
;
font-family
:
inherit
;
margin
:
0
;
line-height
:
1.6em
;
border
:
0
;
outline
:
none
;
padding
:
10px
7px
0px
27px
;
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
;
}
#todo-list
.check
{
position
:
relative
;
top
:
9px
;
margin
:
0
10px
0
7px
;
float
:
left
;
}
#todo-list
.done
.todo-content
{
text-decoration
:
line-through
;
color
:
#777777
;
}
#todo-list
.todo-destroy
{
position
:
absolute
;
right
:
5px
;
top
:
14px
;
display
:
none
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
background
:
url(destroy.png)
no-repeat
0
0
;
}
#todo-list
li
:hover
.todo-destroy
{
display
:
block
;
}
#todo-list
.todo-destroy
:hover
{
background-position
:
0
-20px
;
}
#todo-stats
{
*
zoom
:
1
;
margin-top
:
10px
;
color
:
#777777
;
}
#todo-stats
:after
{
content
:
"\0020"
;
display
:
block
;
height
:
0
;
clear
:
both
;
overflow
:
hidden
;
visibility
:
hidden
;
}
#todo-stats
.todo-count
{
float
:
left
;
}
#todo-stats
.todo-count
.number
{
font-weight
:
bold
;
color
:
#333333
;
}
#todo-stats
.todo-clear
{
float
:
right
;
}
#todo-stats
a
.todo-clear
{
color
:
#777777
;
font-size
:
12px
;
}
#todo-stats
a
.todo-clear
{
color
:
#777777
;
}
#todo-stats
a
.todo-clear
:hover
,
#todo-stats
a
.todo-clear
:focus
{
color
:
#336699
;
}
/* line 125 */
#todo-stats
a
.todo-clear
{
display
:
block
;
line-height
:
20px
;
text-decoration
:
none
;
-moz-border-radius
:
12px
;
-webkit-border-radius
:
12px
;
-o-border-radius
:
12px
;
-ms-border-radius
:
12px
;
-khtml-border-radius
:
12px
;
border-radius
:
12px
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
color
:
#555555
;
font-size
:
11px
;
margin-top
:
8px
;
padding
:
0
10px
1px
;
-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
;
}
/* line 136 */
#todo-stats
a
.todo-clear
:hover
,
#todo-stats
a
.todo-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
;
}
/* line 139 */
#todoapp
#todo-stats
a
.todo-clear
:active
{
position
:
relative
;
top
:
1px
;
}
#instructions
{
width
:
520px
;
margin
:
10px
auto
;
color
:
#777777
;
text-shadow
:
rgba
(
255
,
255
,
255
,
0.8
)
0
1px
0
;
text-align
:
center
;
}
#instructions
a
{
color
:
#336699
;
}
#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
;
}
/*
* François 'cahnory' Germain
*/
.ui-tooltip
,
.ui-tooltip-top
,
.ui-tooltip-right
,
.ui-tooltip-bottom
,
.ui-tooltip-left
{
color
:
#ffffff
;
cursor
:
normal
;
display
:
-moz-inline-stack
;
display
:
inline-block
;
font-size
:
12px
;
font-family
:
arial
;
padding
:
.5em
1em
;
position
:
relative
;
text-align
:
center
;
text-shadow
:
0
-1px
1px
#111111
;
-webkit-border-top-left-radius
:
4px
;
-webkit-border-top-right-radius
:
4px
;
-webkit-border-bottom-right-radius
:
4px
;
-webkit-border-bottom-left-radius
:
4px
;
-khtml-border-top-left-radius
:
4px
;
-khtml-border-top-right-radius
:
4px
;
-khtml-border-bottom-right-radius
:
4px
;
-khtml-border-bottom-left-radius
:
4px
;
-moz-border-radius-topleft
:
4px
;
-moz-border-radius-topright
:
4px
;
-moz-border-radius-bottomright
:
4px
;
-moz-border-radius-bottomleft
:
4px
;
border-top-left-radius
:
4px
;
border-top-right-radius
:
4px
;
border-bottom-right-radius
:
4px
;
border-bottom-left-radius
:
4px
;
-o-box-shadow
:
0
1px
2px
#000000
,
inset
0
0
0
1px
#222222
,
inset
0
2px
#666666
,
inset
0
-2px
2px
#444444
;
-moz-box-shadow
:
0
1px
2px
#000000
,
inset
0
0
0
1px
#222222
,
inset
0
2px
#666666
,
inset
0
-2px
2px
#444444
;
-khtml-box-shadow
:
0
1px
2px
#000000
,
inset
0
0
0
1px
#222222
,
inset
0
2px
#666666
,
inset
0
-2px
2px
#444444
;
-webkit-box-shadow
:
0
1px
2px
#000000
,
inset
0
0
0
1px
#222222
,
inset
0
2px
#666666
,
inset
0
-2px
2px
#444444
;
box-shadow
:
0
1px
2px
#000000
,
inset
0
0
0
1px
#222222
,
inset
0
2px
#666666
,
inset
0
-2px
2px
#444444
;
background-color
:
#3b3b3b
;
background-image
:
-moz-linear-gradient
(
top
,
#555555
,
#222222
);
background-image
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
color-stop
(
0
,
#555555
),
color-stop
(
1
,
#222222
));
filter
:
progid
:
DXImageTransform
.
Microsoft
.
gradient
(
startColorStr
=
#555555
,
EndColorStr
=
#222222
);
-ms-filter
:
progid
:
DXImageTransform
.
Microsoft
.
gradient
(
startColorStr
=
#555555
,
EndColorStr
=
#222222
);
}
.ui-tooltip
:after
,
.ui-tooltip-top
:after
,
.ui-tooltip-right
:after
,
.ui-tooltip-bottom
:after
,
.ui-tooltip-left
:after
{
content
:
"\25B8"
;
display
:
block
;
font-size
:
2em
;
height
:
0
;
line-height
:
0
;
position
:
absolute
;
}
.ui-tooltip
:after
,
.ui-tooltip-bottom
:after
{
color
:
#2a2a2a
;
bottom
:
0
;
left
:
1px
;
text-align
:
center
;
text-shadow
:
1px
0
2px
#000000
;
-o-transform
:
rotate
(
90deg
);
-moz-transform
:
rotate
(
90deg
);
-khtml-transform
:
rotate
(
90deg
);
-webkit-transform
:
rotate
(
90deg
);
width
:
100%
;
}
.ui-tooltip-top
:after
{
bottom
:
auto
;
color
:
#4f4f4f
;
left
:
-2px
;
top
:
0
;
text-align
:
center
;
text-shadow
:
none
;
-o-transform
:
rotate
(
-90deg
);
-moz-transform
:
rotate
(
-90deg
);
-khtml-transform
:
rotate
(
-90deg
);
-webkit-transform
:
rotate
(
-90deg
);
width
:
100%
;
}
.ui-tooltip-right
:after
{
color
:
#222222
;
right
:
-0.375em
;
top
:
50%
;
margin-top
:
-.05em
;
text-shadow
:
0
1px
2px
#000000
;
-o-transform
:
rotate
(
0
);
-moz-transform
:
rotate
(
0
);
-khtml-transform
:
rotate
(
0
);
-webkit-transform
:
rotate
(
0
);
}
.ui-tooltip-left
:after
{
color
:
#222222
;
left
:
-0.375em
;
top
:
50%
;
margin-top
:
.1em
;
text-shadow
:
0
-1px
2px
#000000
;
-o-transform
:
rotate
(
180deg
);
-moz-transform
:
rotate
(
180deg
);
-khtml-transform
:
rotate
(
180deg
);
-webkit-transform
:
rotate
(
180deg
);
}
/* new additions - cleanup required*/
/* line 109 */
#todo-app
#todo-stats
{
*
zoom
:
1
;
margin-top
:
10px
;
color
:
#555555
;
-moz-border-radius-bottomleft
:
5px
;
-webkit-border-bottom-left-radius
:
5px
;
-o-border-bottom-left-radius
:
5px
;
-ms-border-bottom-left-radius
:
5px
;
-khtml-border-bottom-left-radius
:
5px
;
border-bottom-left-radius
:
5px
;
-moz-border-radius-bottomright
:
5px
;
-webkit-border-bottom-right-radius
:
5px
;
-o-border-bottom-right-radius
:
5px
;
-ms-border-bottom-right-radius
:
5px
;
-khtml-border-bottom-right-radius
:
5px
;
border-bottom-right-radius
:
5px
;
background
:
#f4fce8
;
border-top
:
1px
solid
#ededed
;
padding
:
0
20px
;
line-height
:
36px
;
}
/* line 22, /opt/ree/lib/ruby/gems/1.8/gems/compass-0.10.5/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */
#todo-app
#todo-stats
:after
{
content
:
"\0020"
;
display
:
block
;
height
:
0
;
clear
:
both
;
overflow
:
hidden
;
visibility
:
hidden
;
}
/* line 118 */
#todo-app
#todo-stats
.todo-done
{
float
:
left
;
}
/* line 120 */
#todo-app
#todo-stats
.todo-done
.number
{
font-weight
:
bold
;
color
:
#555555
;
}
/* line 123 */
#todos
{
display
:
block
}
architecture-examples/yuilibrary/img/destroy.png
deleted
100644 → 0
View file @
1c04c6b5
1.19 KB
architecture-examples/yuilibrary/index.html
View file @
0d07bb3c
...
@@ -4,53 +4,41 @@
...
@@ -4,53 +4,41 @@
<meta
charset=
"utf-8"
>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<title>
YUI • TodoMVC
</title>
<title>
YUI • TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"css/style.css"
>
<link
rel=
"stylesheet"
href=
"../../assets/base.css"
>
<link
rel=
"stylesheet"
href=
"css/app.css"
>
<!--[if IE]>
<!--[if IE]>
<script src="../../assets/ie.js"></script>
<script src="../../assets/ie.js"></script>
<![endif]-->
<![endif]-->
</head>
</head>
<body>
<body>
<div
id=
"todo-app"
>
<section
id=
"todoapp"
>
<div
class=
"title"
>
<header
id=
"header"
>
<h1>
Todos
</h1>
<h1>
todos
</h1>
</div>
</header>
<label
class=
"todo-label"
for=
"new-todo"
></label>
<input
id=
"new-todo"
placeholder=
"What needs to be done?"
autofocus
>
<input
type=
"text"
id=
"new-todo"
class=
"todo-input"
placeholder=
"What needs to be done?"
>
<section
id=
"main"
>
<div
id=
"todos"
>
<input
id=
"toggle-all"
type=
"checkbox"
>
<label
for=
"toggle-all"
>
Mark all as complete
</label>
<ul
id=
"todo-list"
></ul>
<ul
id=
"todo-list"
></ul>
</section>
<footer
id=
"footer"
></footer>
</section>
<footer
id=
"info"
>
<p>
Based on code by the YUILibrary team
</p>
<p>
Created by
<a
href=
"https://github.com/addyosmani"
>
Addy Osmani
</a></p>
<p>
Rewrite by
<a
href=
"https://github.com/sindresorhus"
>
Sindre Sorhus
</a></p>
</footer>
<script
type=
"text/x-template"
id=
"todo-template"
>
<
div
class
=
"
view
"
>
<
input
class
=
"
toggle
"
type
=
"
checkbox
"
{
completed
}
>
<
label
>
{
title
}
<
/label
>
<
button
class
=
"
destroy
"
><
/button
>
<
/div
>
<
/div
>
<div
id=
"todo-stats"
></div>
<
input
class
=
"
edit
"
value
=
"
{title}
"
>
</div>
<div
id=
"credits"
>
This version by
<br
/>
<a
href=
"http://twitter.com/addyosmani"
>
Addy Osmani
</a>
<br
/>
based on code by the YUILibrary team.
</div>
<script
type=
"text/x-template"
id=
"todo-item-template"
>
<
div
class
=
"
todo-view
"
>
<
input
type
=
"
checkbox
"
class
=
"
todo-checkbox
"
{
checked
}
>
<
span
class
=
"
todo-content
"
tabindex
=
"
0
"
>
{
text
}
<
/span
>
<
/div
>
<
div
class
=
"
todo-edit
"
>
<
input
type
=
"
text
"
class
=
"
todo-input
"
value
=
"
{text}
"
>
<
/div
>
<
a
href
=
"
#
"
class
=
"
todo-remove
"
title
=
"
Remove this task
"
>
<
span
class
=
"
todo-remove-icon
"
><
/span
>
<
/a
>
</script>
</script>
<script
type=
"text/x-template"
id=
"todo-stats-template"
>
<script
type=
"text/x-template"
id=
"footer-template"
>
<
span
class
=
"
todo-count
"
>
<
span
id
=
"
todo-count
"
><
strong
>
{
numRemaining
}
<
/strong> {remainingLabel} left</
span
>
<
span
class
=
"
todo-remaining
"
>
{
numRemaining
}
<
/span
>
<
button
id
=
"
clear-completed
"
>
Clear
completed
({
numCompleted
})
<
/button
>
<
span
class
=
"
todo-remaining-label
"
>
{
remainingLabel
}
<
/span> left
.
<
/span
>
<
a
href
=
"
#
"
class
=
"
todo-clear
"
>
Clear
{
numDone
}
completed
<
span
class
=
"
todo-done-label
"
>
{
doneLabel
}
<
/span
>
<
/a
>
</script>
</script>
<script
src=
"../../assets/base.js"
></script>
<script
src=
"../../assets/base.js"
></script>
<script
src=
"js/yui-3.4.0.min.js"
></script>
<script
src=
"js/yui-3.4.0.min.js"
></script>
...
...
architecture-examples/yuilibrary/js/app.js
View file @
0d07bb3c
/*global YUI */
YUI
().
use
(
'
event-focus
'
,
'
json
'
,
'
model
'
,
'
model-list
'
,
'
view
'
,
function
(
Y
)
{
YUI
().
use
(
'
event-focus
'
,
'
json
'
,
'
model
'
,
'
model-list
'
,
'
view
'
,
function
(
Y
)
{
var
TodoAppView
,
TodoList
,
TodoModel
,
TodoView
,
localStorageName
=
'
todos-yui
'
,
ENTER_KEY
=
13
;
var
TodoAppView
,
TodoList
,
TodoModel
,
TodoView
,
localStorageName
=
'
todos-yuilibrary
'
;
// -- Model --------------------------------------------------------------------
// -- Model --------------------------------------------------------------------
...
@@ -9,23 +10,27 @@ var TodoAppView, TodoList, TodoModel, TodoView, localStorageName = 'todos-yuilib
...
@@ -9,23 +10,27 @@ var TodoAppView, TodoList, TodoModel, TodoView, localStorageName = 'todos-yuilib
// sync provider (the source for that is further below) and to provide
// sync provider (the source for that is further below) and to provide
// attributes and methods useful for todo items.
// attributes and methods useful for todo items.
TodoModel
=
Y
.
TodoModel
=
Y
.
Base
.
create
(
'
todoModel
'
,
Y
.
Model
,
[],
{
TodoModel
=
Y
.
TodoModel
=
Y
.
Base
.
create
(
'
todoModel
'
,
Y
.
Model
,
[],
{
// This tells the Model to use a localStorage sync provider (which we'll
// This tells the Model to use a localStorage sync provider (which we'll
// create below) to save and load information about a todo item.
// create below) to save and load information about a todo item.
sync
:
L
ocalStorageSync
(
localStorageName
),
sync
:
l
ocalStorageSync
(
localStorageName
),
// This method will toggle the `
done
` attribute from `true` to `false`, or
// This method will toggle the `
completed
` attribute from `true` to `false`, or
// vice versa.
// vice versa.
toggle
Done
:
function
()
{
toggle
:
function
()
{
this
.
set
(
'
done
'
,
!
this
.
get
(
'
done
'
)
).
save
();
this
.
set
(
'
completed
'
,
!
this
.
get
(
'
completed
'
)
).
save
();
}
}
},
{
},
{
ATTRS
:
{
ATTRS
:
{
// Indicates whether or not this todo item has been completed.
// Indicates whether or not this todo item has been completed.
done
:
{
value
:
false
},
completed
:
{
value
:
false
},
// Contains the text of the todo item.
// Contains the text of the todo item.
text
:
{
value
:
''
}
title
:
{
value
:
''
}
}
}
});
});
...
@@ -35,29 +40,43 @@ TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
...
@@ -35,29 +40,43 @@ TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
// TodoModel instances, and to provide some convenience methods for getting
// TodoModel instances, and to provide some convenience methods for getting
// information about the todo items in the list.
// information about the todo items in the list.
TodoList
=
Y
.
TodoList
=
Y
.
Base
.
create
(
'
todoList
'
,
Y
.
ModelList
,
[],
{
TodoList
=
Y
.
TodoList
=
Y
.
Base
.
create
(
'
todoList
'
,
Y
.
ModelList
,
[],
{
// This tells the list that it will hold instances of the TodoModel class.
// This tells the list that it will hold instances of the TodoModel class.
model
:
TodoModel
,
model
:
TodoModel
,
// This tells the list to use a localStorage sync provider (which we'll
// This tells the list to use a localStorage sync provider (which we'll
// create below) to load the list of todo items.
// create below) to load the list of todo items.
sync
:
LocalStorageSync
(
localStorageName
),
sync
:
localStorageSync
(
localStorageName
),
// Returns an array of all models in this list with the `
done
` attribute
// Returns an array of all models in this list with the `
completed
` attribute
// set to `true`.
// set to `true`.
done
:
function
()
{
completed
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
model
.
get
(
'
done
'
);
return
model
.
get
(
'
completed
'
);
});
});
},
},
// Returns an array of all models in this list with the `
done
` attribute
// Returns an array of all models in this list with the `
completed
` attribute
// set to `false`.
// set to `false`.
remaining
:
function
()
{
remaining
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
!
model
.
get
(
'
done
'
);
return
!
model
.
get
(
'
completed
'
);
});
});
}
},
toggleAll
:
function
(
toggle
)
{
Y
.
Array
.
each
(
this
.
toArray
(),
function
(
model
)
{
model
.
set
(
'
completed
'
,
toggle
);
});
},
clearCompleted
:
function
()
{
Y
.
Array
.
each
(
this
.
completed
(),
function
(
model
)
{
model
.
destroy
({
'
delete
'
:
true
});
});
},
});
});
// -- Todo App View ------------------------------------------------------------
// -- Todo App View ------------------------------------------------------------
...
@@ -72,9 +91,9 @@ TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
...
@@ -72,9 +91,9 @@ TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
TodoAppView
=
Y
.
TodoAppView
=
Y
.
Base
.
create
(
'
todoAppView
'
,
Y
.
View
,
[],
{
TodoAppView
=
Y
.
TodoAppView
=
Y
.
Base
.
create
(
'
todoAppView
'
,
Y
.
View
,
[],
{
// The container node is the wrapper for this view. All the view's events
// The container node is the wrapper for this view. All the view's events
// will be delegated from the container. In this case, the #todo
-
app
// will be delegated from the container. In this case, the #todoapp
// node already exists on the page, so we don't need to create it.
// node already exists on the page, so we don't need to create it.
container
:
Y
.
one
(
'
#todo
-
app
'
),
container
:
Y
.
one
(
'
#todoapp
'
),
// This is a custom property that we'll use to hold a reference to the
// This is a custom property that we'll use to hold a reference to the
// "new todo" input field.
// "new todo" input field.
...
@@ -82,43 +101,49 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
...
@@ -82,43 +101,49 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// The `template` property is a convenience property for holding a template
// The `template` property is a convenience property for holding a template
// for this view. In this case, we'll use it to store the contents of the
// for this view. In this case, we'll use it to store the contents of the
// #
todo-stats
-template element, which will serve as the template for the
// #
footer
-template element, which will serve as the template for the
// statistics displayed at the bottom of the list.
// statistics displayed at the bottom of the list.
template
:
Y
.
one
(
'
#
todo-stats
-template
'
).
getContent
(),
template
:
Y
.
one
(
'
#
footer
-template
'
).
getContent
(),
// This is where we attach DOM events for the view. The `events` object is a
// This is where we attach DOM events for the view. The `events` object is a
// mapping of selectors to an object containing one or more events to attach
// mapping of selectors to an object containing one or more events to attach
// to the node(s) matching each selector.
// to the node(s) matching each selector.
events
:
{
events
:
{
// Handle <enter> keypresses on the "new todo" input field.
// Handle <enter> keypresses on the "new todo" input field.
'
#new-todo
'
:
{
keypress
:
'
createTodo
'
},
'
#new-todo
'
:
{
keypress
:
'
createTodo
'
},
'
#toggle-all
'
:
{
change
:
'
toggleAll
'
},
// Clear all completed items from the list when the "Clear" link is
// Clear all completed items from the list when the "Clear" link is
// clicked.
// clicked.
'
.todo-clear
'
:
{
click
:
'
clearDone
'
},
'
#clear-completed
'
:
{
click
:
'
clearCompleted
'
// Add and remove hover states on todo items.
'
.todo-item
'
:
{
mouseover
:
'
hoverOn
'
,
mouseout
:
'
hoverOff
'
}
}
},
},
// The initializer runs when a TodoAppView instance is created, and gives
// The initializer runs when a TodoAppView instance is created, and gives
// us an opportunity to set up the view.
// us an opportunity to set up the view.
initializer
:
function
()
{
initializer
:
function
()
{
// Create a new TodoList instance to hold the todo items.
// Create a new TodoList instance to hold the todo items.
var
list
=
this
.
todoList
=
new
TodoList
();
var
list
=
this
.
todoList
=
new
TodoList
();
// Update the display when a new item is added to the list, or when the
// Update the display when a new item is added to the list, or when the
// entire list is reset.
// entire list is reset.
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
// Re-render the stats in the footer whenever an item is added, removed
// Re-render the stats in the footer whenever an item is added, removed
// or changed, or when the entire list is reset.
// or changed, or when the entire list is reset.
list
.
after
([
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:doneChange
'
],
list
.
after
([
this
.
render
,
this
);
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:completedChange
'
],
this
.
render
,
this
);
// Load saved items from localStorage, if available.
// Load saved items from localStorage, if available.
list
.
load
();
list
.
load
();
...
@@ -127,33 +152,41 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
...
@@ -127,33 +152,41 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// The render function is called whenever a todo item is added, removed, or
// The render function is called whenever a todo item is added, removed, or
// changed, thanks to the list event handler we attached in the initializer
// changed, thanks to the list event handler we attached in the initializer
// above.
// above.
render
:
function
()
{
render
:
function
()
{
var
todoList
=
this
.
todoList
,
var
numRemaining
,
numCompleted
,
stats
=
this
.
container
.
one
(
'
#todo-stats
'
),
todoList
=
this
.
todoList
,
numRemaining
,
numDone
;
main
=
this
.
container
.
one
(
'
#main
'
),
footer
=
this
.
container
.
one
(
'
#footer
'
);
// Check the toggleAll checkbox when all todos are checked
this
.
container
.
one
(
'
#toggle-all
'
).
set
(
'
checked
'
,
!
todoList
.
remaining
().
length
);
// If there are no todo items, then clear the stats.
// If there are no todo items, then clear the stats.
if
(
todoList
.
isEmpty
())
{
// Ugly, but for some reason `main.hide()` doesn't work
stats
.
empty
();
if
(
todoList
.
isEmpty
()
)
{
main
.
_node
.
style
.
display
=
'
none
'
;
footer
.
_node
.
style
.
display
=
'
none
'
;
return
this
;
return
this
;
}
else
{
main
.
_node
.
style
.
display
=
'
block
'
;
footer
.
_node
.
style
.
display
=
'
block
'
;
}
}
// Figure out how many todo items are completed and how many remain.
// Figure out how many todo items are completed and how many remain.
num
Done
=
todoList
.
done
().
length
;
num
Completed
=
todoList
.
completed
().
length
;
numRemaining
=
todoList
.
remaining
().
length
;
numRemaining
=
todoList
.
remaining
().
length
;
// Update the statistics.
// Update the statistics.
stats
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
footer
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
numDone
:
numDone
,
numCompleted
:
numCompleted
,
numRemaining
:
numRemaining
,
numRemaining
:
numRemaining
,
doneLabel
:
numDone
===
1
?
'
task
'
:
'
tasks
'
,
remainingLabel
:
numRemaining
===
1
?
'
item
'
:
'
items
'
remainingLabel
:
numRemaining
===
1
?
'
task
'
:
'
tasks
'
}));
}));
// If there are no completed todo items, don't show the "Clear
// If there are no completed todo items, don't show the "Clear
// completed items" link.
// completed items" link.
if
(
!
numDone
)
{
if
(
!
numCompleted
)
{
stats
.
one
(
'
.todo-clear
'
).
remove
();
footer
.
one
(
'
#clear-completed
'
).
remove
();
}
}
return
this
;
return
this
;
...
@@ -163,72 +196,58 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
...
@@ -163,72 +196,58 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// Creates a new TodoView instance and renders it into the list whenever a
// Creates a new TodoView instance and renders it into the list whenever a
// todo item is added to the list.
// todo item is added to the list.
add
:
function
(
e
)
{
add
:
function
(
e
)
{
var
view
=
new
TodoView
({
model
:
e
.
model
});
var
view
=
new
TodoView
({
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
model
:
e
.
model
});
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
},
},
// Removes all finished todo items from the list.
// Creates and renders views for every todo item in the list when the entire
clearDone
:
function
(
e
)
{
// list is reset.
var
done
=
this
.
todoList
.
done
();
reset
:
function
(
e
)
{
var
fragment
=
Y
.
one
(
Y
.
config
.
doc
.
createDocumentFragment
()
);
e
.
preventDefault
();
Y
.
Array
.
each
(
e
.
models
,
function
(
model
)
{
// Remove all finished items from the list, but do it silently so as not
var
view
=
new
TodoView
({
// to re-render the app view after each item is removed.
model
:
model
this
.
todoList
.
remove
(
done
,
{
silent
:
true
});
});
fragment
.
append
(
view
.
render
().
container
);
// Destroy each removed TodoModel instance.
Y
.
Array
.
each
(
done
,
function
(
todo
)
{
// Passing {'delete': true} to the todo model's `destroy()` method
// tells it to delete itself from localStorage as well.
todo
.
destroy
({
'
delete
'
:
true
});
});
});
// Finally, re-render the app view.
this
.
container
.
one
(
'
#todo-list
'
).
setContent
(
fragment
);
this
.
render
();
},
},
// Creates a new todo item when the enter key is pressed in the new todo
// Creates a new todo item when the enter key is pressed in the new todo
// input field.
// input field.
createTodo
:
function
(
e
)
{
createTodo
:
function
(
e
)
{
var
value
;
var
value
;
if
(
e
.
keyCode
===
13
)
{
// enter key
if
(
e
.
keyCode
===
ENTER_KEY
)
{
value
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
)
);
value
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
)
);
if
(
!
value
)
{
return
;
}
if
(
!
value
)
{
return
;
}
// This tells the list to create a new TodoModel instance with the
// This tells the list to create a new TodoModel instance with the
// specified text and automatically save it to localStorage in a
// specified text and automatically save it to localStorage in a
// single step.
// single step.
this
.
todoList
.
create
({
text
:
value
});
this
.
todoList
.
create
({
title
:
value
});
this
.
inputNode
.
set
(
'
value
'
,
''
);
this
.
inputNode
.
set
(
'
value
'
,
''
);
}
}
},
},
// Turns off the hover state on a todo item.
toggleAll
:
function
(
e
)
{
hoverOff
:
function
(
e
)
{
this
.
todoList
.
toggleAll
(
e
.
target
.
_node
.
checked
);
e
.
currentTarget
.
removeClass
(
'
todo-hover
'
);
},
// Turns on the hover state on a todo item.
hoverOn
:
function
(
e
)
{
e
.
currentTarget
.
addClass
(
'
todo-hover
'
);
},
},
// Creates and renders views for every todo item in the list when the entire
// Removes all finished todo items from the list.
// list is reset.
clearCompleted
:
function
(
e
)
{
reset
:
function
(
e
)
{
this
.
todoList
.
clearCompleted
();
var
fragment
=
Y
.
one
(
Y
.
config
.
doc
.
createDocumentFragment
());
Y
.
Array
.
each
(
e
.
models
,
function
(
model
)
{
var
view
=
new
TodoView
({
model
:
model
});
fragment
.
append
(
view
.
render
().
container
);
});
this
.
container
.
one
(
'
#todo-list
'
).
setContent
(
fragment
);
}
}
});
});
...
@@ -238,63 +257,66 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
...
@@ -238,63 +257,66 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// of a single todo item in the list. It also handles DOM events on the item to
// of a single todo item in the list. It also handles DOM events on the item to
// allow it to be edited and removed from the list.
// allow it to be edited and removed from the list.
TodoView
=
Y
.
TodoView
=
Y
.
Base
.
create
(
'
todoView
'
,
Y
.
View
,
[],
{
TodoView
=
Y
.
TodoView
=
Y
.
Base
.
create
(
'
todoView
'
,
Y
.
View
,
[],
{
// Specifying an HTML string as this view's container element causes that
// Specifying an HTML string as this view's container element causes that
// HTML to be automatically converted into an unattached Y.Node instance.
// HTML to be automatically converted into an unattached Y.Node instance.
// The TodoAppView (above) will take care of appending it to the list.
// The TodoAppView (above) will take care of appending it to the list.
container
:
'
<li
class="todo-item"/
>
'
,
container
:
'
<li>
'
,
// The template property holds the contents of the #todo-
item-
template
// The template property holds the contents of the #todo-template
// element, which will be used as the HTML template for each todo item.
// element, which will be used as the HTML template for each todo item.
template
:
Y
.
one
(
'
#todo-
item-
template
'
).
getContent
(),
template
:
Y
.
one
(
'
#todo-template
'
).
getContent
(),
// Delegated DOM events to handle this view's interactions.
// Delegated DOM events to handle this view's interactions.
events
:
{
events
:
{
// Toggle the "
done
" state of this todo item when the checkbox is
// Toggle the "
completed
" state of this todo item when the checkbox is
// clicked.
// clicked.
'
.todo-checkbox
'
:
{
click
:
'
toggleDone
'
},
'
.toggle
'
:
{
click
:
'
toggle
'
},
// When the text of this todo item is clicked or focused, switch to edit
// When the text of this todo item is clicked or focused, switch to edit
// mode to allow editing.
// mode to allow editing.
'
.todo-content
'
:
{
'
.view
'
:
{
click
:
'
edit
'
,
dblclick
:
'
edit
'
focus
:
'
edit
'
},
},
// On the edit field, when enter is pressed or the field loses focus,
// On the edit field, when enter is pressed or the field loses focus,
// save the current value and switch out of edit mode.
// save the current value and switch out of edit mode.
'
.
todo-input
'
:
{
'
.
edit
'
:
{
blur
:
'
save
'
,
blur
:
'
save
'
,
keypress
:
'
enter
'
keypress
:
'
enter
'
},
},
// When the remove icon is clicked, delete this todo item.
// When the remove icon is clicked, delete this todo item.
'
.todo-remove
'
:
{
click
:
'
remove
'
}
'
.destroy
'
:
{
click
:
'
remove
'
}
},
},
initializer
:
function
()
{
initializer
:
function
()
{
// The model property is set to a TodoModel instance by TodoAppView when
// The model property is set to a TodoModel instance by TodoAppView when
// it instantiates this TodoView.
// it instantiates this TodoView.
var
model
=
this
.
model
;
var
model
=
this
.
model
;
// Re-render this view when the model changes, and destroy this view
// Re-render this view when the model changes, and destroy this view
// when the model is destroyed.
// when the model is destroyed.
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
},
},
render
:
function
()
{
render
:
function
()
{
var
container
=
this
.
container
,
var
container
=
this
.
container
,
model
=
this
.
model
,
model
=
this
.
model
,
done
=
model
.
get
(
'
done
'
);
completed
=
model
.
get
(
'
completed
'
);
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
c
hecked
:
done
?
'
checked
'
:
''
,
c
ompleted
:
completed
?
'
checked
'
:
''
,
t
ext
:
model
.
getAsHTML
(
'
text
'
)
t
itle
:
model
.
get
(
'
title
'
)
}));
}));
container
[
done
?
'
addClass
'
:
'
removeClass
'
](
'
todo-done
'
);
container
[
completed
?
'
addClass
'
:
'
removeClass
'
](
'
completed
'
);
this
.
inputNode
=
container
.
one
(
'
.
todo-inpu
t
'
);
this
.
inputNode
=
container
.
one
(
'
.
edi
t
'
);
return
this
;
return
this
;
},
},
...
@@ -302,37 +324,46 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
...
@@ -302,37 +324,46 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
// -- Event Handlers -------------------------------------------------------
// -- Event Handlers -------------------------------------------------------
// Toggles this item into edit mode.
// Toggles this item into edit mode.
edit
:
function
()
{
edit
:
function
()
{
this
.
container
.
addClass
(
'
editing
'
);
this
.
container
.
addClass
(
'
editing
'
);
this
.
inputNode
.
focus
();
this
.
inputNode
.
select
();
},
},
// When the enter key is pressed, focus the new todo input field. This
// When the enter key is pressed, focus the new todo input field. This
// causes a blur event on the current edit field, which calls the save()
// causes a blur event on the current edit field, which calls the save()
// handler below.
// handler below.
enter
:
function
(
e
)
{
enter
:
function
(
e
)
{
if
(
e
.
keyCode
===
13
)
{
// enter key
if
(
e
.
keyCode
===
ENTER_KEY
)
{
Y
.
one
(
'
#new-todo
'
).
focus
();
Y
.
one
(
'
#new-todo
'
).
focus
();
}
}
},
},
// Removes this item from the list.
// Removes this item from the list.
remove
:
function
(
e
)
{
remove
:
function
(
e
)
{
e
.
preventDefault
(
);
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
this
.
model
.
destroy
({
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
'
delete
'
:
true
this
.
model
.
destroy
({
'
delete
'
:
true
});
});
},
},
// Toggles this item out of edit mode and saves it.
// Toggles this item out of edit mode and saves it.
save
:
function
()
{
save
:
function
()
{
var
val
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
)
);
this
.
container
.
removeClass
(
'
editing
'
);
this
.
container
.
removeClass
(
'
editing
'
);
this
.
model
.
set
(
'
text
'
,
this
.
inputNode
.
get
(
'
value
'
)).
save
();
if
(
val
)
{
this
.
model
.
set
(
'
title
'
,
val
).
save
();
}
else
{
this
.
model
.
destroy
({
'
delete
'
:
true
});
}
},
},
// Toggles the `
done
` state on this item's model.
// Toggles the `
completed
` state on this item's model.
toggle
Done
:
function
()
{
toggle
:
function
()
{
this
.
model
.
toggle
Done
();
this
.
model
.
toggle
();
}
}
});
});
...
@@ -342,27 +373,27 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
...
@@ -342,27 +373,27 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
// be used as a sync layer for either a Model or a ModelList instance. The
// be used as a sync layer for either a Model or a ModelList instance. The
// TodoModel and TodoList instances above use it to save and load items.
// TodoModel and TodoList instances above use it to save and load items.
function
LocalStorageSync
(
key
)
{
function
localStorageSync
(
key
)
{
var
localStorage
;
var
localStorage
;
if
(
!
key
)
{
if
(
!
key
)
{
Y
.
error
(
'
No storage key specified.
'
);
Y
.
error
(
'
No storage key specified.
'
);
}
}
if
(
Y
.
config
.
win
.
localStorage
)
{
if
(
Y
.
config
.
win
.
localStorage
)
{
localStorage
=
Y
.
config
.
win
.
localStorage
;
localStorage
=
Y
.
config
.
win
.
localStorage
;
}
}
// Try to retrieve existing data from localStorage, if there is any.
// Try to retrieve existing data from localStorage, if there is any.
// Otherwise, initialize `data` to an empty object.
// Otherwise, initialize `data` to an empty object.
var
data
=
Y
.
JSON
.
parse
(
(
localStorage
&&
localStorage
.
getItem
(
key
))
||
'
{}
'
);
var
data
=
Y
.
JSON
.
parse
(
(
localStorage
&&
localStorage
.
getItem
(
key
)
)
||
'
{}
'
);
// Delete a model with the specified id.
// Delete a model with the specified id.
function
destroy
(
id
)
{
function
destroy
(
id
)
{
var
modelHash
;
var
modelHash
;
if
(
(
modelHash
=
data
[
id
])
)
{
if
(
(
modelHash
=
data
[
id
]
)
)
{
delete
data
[
id
];
delete
data
[
id
];
save
();
save
();
}
}
...
@@ -374,8 +405,8 @@ function LocalStorageSync(key) {
...
@@ -374,8 +405,8 @@ function LocalStorageSync(key) {
var
id
=
''
,
var
id
=
''
,
i
=
4
;
i
=
4
;
while
(
i
--
)
{
while
(
i
--
)
{
id
+=
(
((
1
+
Math
.
random
())
*
0x10000
)
|
0
)
id
+=
(
(
(
1
+
Math
.
random
())
*
0x10000
)
|
0
)
.
toString
(
16
).
substring
(
1
);
.
toString
(
16
).
substring
(
1
);
}
}
...
@@ -389,26 +420,26 @@ function LocalStorageSync(key) {
...
@@ -389,26 +420,26 @@ function LocalStorageSync(key) {
// If an id is specified, then it loads a single model. If no id is
// If an id is specified, then it loads a single model. If no id is
// specified then it loads an array of all models. This allows the same sync
// specified then it loads an array of all models. This allows the same sync
// layer to be used for both the TodoModel and TodoList classes.
// layer to be used for both the TodoModel and TodoList classes.
function
get
(
id
)
{
function
get
(
id
)
{
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
}
}
// Saves the entire `data` object to localStorage.
// Saves the entire `data` object to localStorage.
function
save
()
{
function
save
()
{
localStorage
&&
localStorage
.
setItem
(
key
,
Y
.
JSON
.
stringify
(
data
)
);
localStorage
&&
localStorage
.
setItem
(
key
,
Y
.
JSON
.
stringify
(
data
)
);
}
}
// Sets the id attribute of the specified model (generating a new id if
// Sets the id attribute of the specified model (generating a new id if
// necessary), then saves it to localStorage.
// necessary), then saves it to localStorage.
function
set
(
model
)
{
function
set
(
model
)
{
var
hash
=
model
.
toJSON
(),
var
hash
=
model
.
toJSON
(),
idAttribute
=
model
.
idAttribute
;
idAttribute
=
model
.
idAttribute
;
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
])
)
{
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
]
)
)
{
hash
[
idAttribute
]
=
generateId
();
hash
[
idAttribute
]
=
generateId
();
}
}
data
[
hash
[
idAttribute
]
]
=
hash
;
data
[
hash
[
idAttribute
]
]
=
hash
;
save
();
save
();
return
hash
;
return
hash
;
...
@@ -416,23 +447,23 @@ function LocalStorageSync(key) {
...
@@ -416,23 +447,23 @@ function LocalStorageSync(key) {
// Returns a `sync()` function that can be used with either a Model or a
// Returns a `sync()` function that can be used with either a Model or a
// ModelList instance.
// ModelList instance.
return
function
(
action
,
options
,
callback
)
{
return
function
(
action
,
options
,
callback
)
{
// `this` refers to the Model or ModelList instance to which this sync
// `this` refers to the Model or ModelList instance to which this sync
// method is attached.
// method is attached.
var
isModel
=
Y
.
Model
&&
this
instanceof
Y
.
Model
;
var
isModel
=
Y
.
Model
&&
this
instanceof
Y
.
Model
;
switch
(
action
)
{
switch
(
action
)
{
case
'
create
'
:
// intentional fallthru
case
'
create
'
:
// intentional fallthru
case
'
update
'
:
case
'
update
'
:
callback
(
null
,
set
(
this
)
);
callback
(
null
,
set
(
this
)
);
return
;
return
;
case
'
read
'
:
case
'
read
'
:
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
))
);
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
)
)
);
return
;
return
;
case
'
delete
'
:
case
'
delete
'
:
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
))
);
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
)
)
);
return
;
return
;
}
}
};
};
...
...
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