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 @@
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<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]>
<script src="../../assets/ie.js"></script>
<![endif]-->
</head>
<body>
<div
id=
"todo-app"
>
<div
class=
"title"
>
<h1>
Todos
</h1>
</div>
<label
class=
"todo-label"
for=
"new-todo"
></label>
<input
type=
"text"
id=
"new-todo"
class=
"todo-input"
placeholder=
"What needs to be done?"
>
<div
id=
"todos"
>
<section
id=
"todoapp"
>
<header
id=
"header"
>
<h1>
todos
</h1>
</header>
<input
id=
"new-todo"
placeholder=
"What needs to be done?"
autofocus
>
<section
id=
"main"
>
<input
id=
"toggle-all"
type=
"checkbox"
>
<label
for=
"toggle-all"
>
Mark all as complete
</label>
<ul
id=
"todo-list"
></ul>
</section>
<footer
id=
"footer"
></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
id=
"todo-stats"
></div>
</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
>
<
input
class
=
"
edit
"
value
=
"
{title}
"
>
</script>
<script
type=
"text/x-template"
id=
"todo-stats-template"
>
<
span
class
=
"
todo-count
"
>
<
span
class
=
"
todo-remaining
"
>
{
numRemaining
}
<
/span
>
<
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
type=
"text/x-template"
id=
"footer-template"
>
<
span
id
=
"
todo-count
"
><
strong
>
{
numRemaining
}
<
/strong> {remainingLabel} left</
span
>
<
button
id
=
"
clear-completed
"
>
Clear
completed
({
numCompleted
})
<
/button
>
</script>
<script
src=
"../../assets/base.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-yuilibrary
'
;
var
TodoAppView
,
TodoList
,
TodoModel
,
TodoView
,
localStorageName
=
'
todos-yui
'
,
ENTER_KEY
=
13
;
// -- Model --------------------------------------------------------------------
...
...
@@ -9,23 +10,27 @@ var TodoAppView, TodoList, TodoModel, TodoView, localStorageName = 'todos-yuilib
// sync provider (the source for that is further below) and to provide
// 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
// 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.
toggle
Done
:
function
()
{
this
.
set
(
'
done
'
,
!
this
.
get
(
'
done
'
)
).
save
();
toggle
:
function
()
{
this
.
set
(
'
completed
'
,
!
this
.
get
(
'
completed
'
)
).
save
();
}
},
{
ATTRS
:
{
// Indicates whether or not this todo item has been completed.
done
:
{
value
:
false
},
completed
:
{
value
:
false
},
// Contains the text of the todo item.
text
:
{
value
:
''
}
title
:
{
value
:
''
}
}
});
...
...
@@ -35,29 +40,43 @@ TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
// TodoModel instances, and to provide some convenience methods for getting
// 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.
model
:
TodoModel
,
// This tells the list to use a localStorage sync provider (which we'll
// 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`.
done
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
model
.
get
(
'
done
'
);
completed
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
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`.
remaining
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
!
model
.
get
(
'
done
'
);
remaining
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
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 ------------------------------------------------------------
...
...
@@ -72,9 +91,9 @@ TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
TodoAppView
=
Y
.
TodoAppView
=
Y
.
Base
.
create
(
'
todoAppView
'
,
Y
.
View
,
[],
{
// 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.
container
:
Y
.
one
(
'
#todo
-
app
'
),
container
:
Y
.
one
(
'
#todoapp
'
),
// This is a custom property that we'll use to hold a reference to the
// "new todo" input field.
...
...
@@ -82,43 +101,49 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// 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
// #
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.
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
// mapping of selectors to an object containing one or more events to attach
// to the node(s) matching each selector.
events
:
{
// 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
// clicked.
'
.todo-clear
'
:
{
click
:
'
clearDone
'
},
// Add and remove hover states on todo items.
'
.todo-item
'
:
{
mouseover
:
'
hoverOn
'
,
mouseout
:
'
hoverOff
'
'
#clear-completed
'
:
{
click
:
'
clearCompleted
'
}
},
// The initializer runs when a TodoAppView instance is created, and gives
// us an opportunity to set up the view.
initializer
:
function
()
{
initializer
:
function
()
{
// Create a new TodoList instance to hold the todo items.
var
list
=
this
.
todoList
=
new
TodoList
();
// Update the display when a new item is added to the list, or when the
// entire list is reset.
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
// Re-render the stats in the footer whenever an item is added, removed
// or changed, or when the entire list is reset.
list
.
after
([
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:doneChange
'
],
this
.
render
,
this
);
list
.
after
([
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:completedChange
'
],
this
.
render
,
this
);
// Load saved items from localStorage, if available.
list
.
load
();
...
...
@@ -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
// changed, thanks to the list event handler we attached in the initializer
// above.
render
:
function
()
{
var
todoList
=
this
.
todoList
,
stats
=
this
.
container
.
one
(
'
#todo-stats
'
),
numRemaining
,
numDone
;
render
:
function
()
{
var
numRemaining
,
numCompleted
,
todoList
=
this
.
todoList
,
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
(
todoList
.
isEmpty
())
{
stats
.
empty
();
// Ugly, but for some reason `main.hide()` doesn't work
if
(
todoList
.
isEmpty
()
)
{
main
.
_node
.
style
.
display
=
'
none
'
;
footer
.
_node
.
style
.
display
=
'
none
'
;
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.
num
Done
=
todoList
.
done
().
length
;
num
Completed
=
todoList
.
completed
().
length
;
numRemaining
=
todoList
.
remaining
().
length
;
// Update the statistics.
stats
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
numDone
:
numDone
,
numRemaining
:
numRemaining
,
doneLabel
:
numDone
===
1
?
'
task
'
:
'
tasks
'
,
remainingLabel
:
numRemaining
===
1
?
'
task
'
:
'
tasks
'
footer
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
numCompleted
:
numCompleted
,
numRemaining
:
numRemaining
,
remainingLabel
:
numRemaining
===
1
?
'
item
'
:
'
items
'
}));
// If there are no completed todo items, don't show the "Clear
// completed items" link.
if
(
!
numDone
)
{
stats
.
one
(
'
.todo-clear
'
).
remove
();
if
(
!
numCompleted
)
{
footer
.
one
(
'
#clear-completed
'
).
remove
();
}
return
this
;
...
...
@@ -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
// todo item is added to the list.
add
:
function
(
e
)
{
var
view
=
new
TodoView
({
model
:
e
.
model
});
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
add
:
function
(
e
)
{
var
view
=
new
TodoView
({
model
:
e
.
model
});
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
},
// Removes all finished todo items from the list.
clearDone
:
function
(
e
)
{
var
done
=
this
.
todoList
.
done
();
e
.
preventDefault
();
// Remove all finished items from the list, but do it silently so as not
// to re-render the app view after each item is removed.
this
.
todoList
.
remove
(
done
,
{
silent
:
true
});
// 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
});
// Creates and renders views for every todo item in the list when the entire
// list is reset.
reset
:
function
(
e
)
{
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
);
});
// Finally, re-render the app view.
this
.
render
();
this
.
container
.
one
(
'
#todo-list
'
).
setContent
(
fragment
);
},
// Creates a new todo item when the enter key is pressed in the new todo
// input field.
createTodo
:
function
(
e
)
{
createTodo
:
function
(
e
)
{
var
value
;
if
(
e
.
keyCode
===
13
)
{
// enter key
value
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
)
);
if
(
e
.
keyCode
===
ENTER_KEY
)
{
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
// specified text and automatically save it to localStorage in a
// 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.
hoverOff
:
function
(
e
)
{
e
.
currentTarget
.
removeClass
(
'
todo-hover
'
);
},
// Turns on the hover state on a todo item.
hoverOn
:
function
(
e
)
{
e
.
currentTarget
.
addClass
(
'
todo-hover
'
);
toggleAll
:
function
(
e
)
{
this
.
todoList
.
toggleAll
(
e
.
target
.
_node
.
checked
);
},
// Creates and renders views for every todo item in the list when the entire
// list is reset.
reset
:
function
(
e
)
{
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
);
// Removes all finished todo items from the list.
clearCompleted
:
function
(
e
)
{
this
.
todoList
.
clearCompleted
();
}
});
...
...
@@ -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
// 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
// HTML to be automatically converted into an unattached Y.Node instance.
// 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.
template
:
Y
.
one
(
'
#todo-
item-
template
'
).
getContent
(),
template
:
Y
.
one
(
'
#todo-template
'
).
getContent
(),
// Delegated DOM events to handle this view's interactions.
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.
'
.todo-checkbox
'
:
{
click
:
'
toggleDone
'
},
'
.toggle
'
:
{
click
:
'
toggle
'
},
// When the text of this todo item is clicked or focused, switch to edit
// mode to allow editing.
'
.todo-content
'
:
{
click
:
'
edit
'
,
focus
:
'
edit
'
'
.view
'
:
{
dblclick
:
'
edit
'
},
// On the edit field, when enter is pressed or the field loses focus,
// save the current value and switch out of edit mode.
'
.
todo-input
'
:
{
blur
:
'
save
'
,
'
.
edit
'
:
{
blur
:
'
save
'
,
keypress
:
'
enter
'
},
// 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
// it instantiates this TodoView.
var
model
=
this
.
model
;
// Re-render this view when the model changes, and destroy this view
// when the model is destroyed.
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
},
render
:
function
()
{
var
container
=
this
.
container
,
model
=
this
.
model
,
done
=
model
.
get
(
'
done
'
);
model
=
this
.
model
,
completed
=
model
.
get
(
'
completed
'
);
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
c
hecked
:
done
?
'
checked
'
:
''
,
t
ext
:
model
.
getAsHTML
(
'
text
'
)
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
c
ompleted
:
completed
?
'
checked
'
:
''
,
t
itle
:
model
.
get
(
'
title
'
)
}));
container
[
done
?
'
addClass
'
:
'
removeClass
'
](
'
todo-done
'
);
this
.
inputNode
=
container
.
one
(
'
.
todo-inpu
t
'
);
container
[
completed
?
'
addClass
'
:
'
removeClass
'
](
'
completed
'
);
this
.
inputNode
=
container
.
one
(
'
.
edi
t
'
);
return
this
;
},
...
...
@@ -302,37 +324,46 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
// -- Event Handlers -------------------------------------------------------
// Toggles this item into edit mode.
edit
:
function
()
{
edit
:
function
()
{
this
.
container
.
addClass
(
'
editing
'
);
this
.
inputNode
.
focus
();
this
.
inputNode
.
select
();
},
// 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()
// handler below.
enter
:
function
(
e
)
{
if
(
e
.
keyCode
===
13
)
{
// enter key
enter
:
function
(
e
)
{
if
(
e
.
keyCode
===
ENTER_KEY
)
{
Y
.
one
(
'
#new-todo
'
).
focus
();
}
},
// Removes this item from the list.
remove
:
function
(
e
)
{
e
.
preventDefault
(
);
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
this
.
model
.
destroy
({
'
delete
'
:
true
});
remove
:
function
(
e
)
{
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
this
.
model
.
destroy
({
'
delete
'
:
true
});
},
// 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
.
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.
toggle
Done
:
function
()
{
this
.
model
.
toggle
Done
();
// Toggles the `
completed
` state on this item's model.
toggle
:
function
()
{
this
.
model
.
toggle
();
}
});
...
...
@@ -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
// TodoModel and TodoList instances above use it to save and load items.
function
LocalStorageSync
(
key
)
{
function
localStorageSync
(
key
)
{
var
localStorage
;
if
(
!
key
)
{
if
(
!
key
)
{
Y
.
error
(
'
No storage key specified.
'
);
}
if
(
Y
.
config
.
win
.
localStorage
)
{
if
(
Y
.
config
.
win
.
localStorage
)
{
localStorage
=
Y
.
config
.
win
.
localStorage
;
}
// Try to retrieve existing data from localStorage, if there is any.
// 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.
function
destroy
(
id
)
{
function
destroy
(
id
)
{
var
modelHash
;
if
(
(
modelHash
=
data
[
id
])
)
{
delete
data
[
id
];
if
(
(
modelHash
=
data
[
id
]
)
)
{
delete
data
[
id
];
save
();
}
...
...
@@ -374,8 +405,8 @@ function LocalStorageSync(key) {
var
id
=
''
,
i
=
4
;
while
(
i
--
)
{
id
+=
(
((
1
+
Math
.
random
())
*
0x10000
)
|
0
)
while
(
i
--
)
{
id
+=
(
(
(
1
+
Math
.
random
())
*
0x10000
)
|
0
)
.
toString
(
16
).
substring
(
1
);
}
...
...
@@ -389,26 +420,26 @@ function LocalStorageSync(key) {
// 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
// layer to be used for both the TodoModel and TodoList classes.
function
get
(
id
)
{
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
function
get
(
id
)
{
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
}
// Saves the entire `data` object to localStorage.
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
// necessary), then saves it to localStorage.
function
set
(
model
)
{
var
hash
=
model
.
toJSON
(),
function
set
(
model
)
{
var
hash
=
model
.
toJSON
(),
idAttribute
=
model
.
idAttribute
;
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
])
)
{
hash
[
idAttribute
]
=
generateId
();
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
]
)
)
{
hash
[
idAttribute
]
=
generateId
();
}
data
[
hash
[
idAttribute
]
]
=
hash
;
data
[
hash
[
idAttribute
]
]
=
hash
;
save
();
return
hash
;
...
...
@@ -416,23 +447,23 @@ function LocalStorageSync(key) {
// Returns a `sync()` function that can be used with either a Model or a
// ModelList instance.
return
function
(
action
,
options
,
callback
)
{
return
function
(
action
,
options
,
callback
)
{
// `this` refers to the Model or ModelList instance to which this sync
// method is attached.
var
isModel
=
Y
.
Model
&&
this
instanceof
Y
.
Model
;
switch
(
action
)
{
switch
(
action
)
{
case
'
create
'
:
// intentional fallthru
case
'
update
'
:
callback
(
null
,
set
(
this
)
);
callback
(
null
,
set
(
this
)
);
return
;
case
'
read
'
:
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
))
);
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
)
)
);
return
;
case
'
delete
'
:
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
))
);
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
)
)
);
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