Commit 3d71ff07 authored by Sindre Sorhus's avatar Sindre Sorhus

Fixed crlf issue

parent 9e536a3c
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;
}
#todoapp {
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;
-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;
}
#todoapp 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 .todo-clear a {
color: #777777;
font-size: 12px;
}
/* these two rules are overridden below. find ".todo-clear a" */
#todo-stats .todo-clear a:visited {
color: #777777;
}
#todo-stats .todo-clear a:hover, #todo-stats .todo-clear a:focus {
color: #336699;
}
#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 */
#todoapp #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 */
#todoapp #todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 118 */
#todoapp #todo-stats .todo-count {
float: left;
}
/* line 120 */
#todoapp #todo-stats .todo-count .number {
font-weight: bold;
color: #555555;
}
/* line 123 */
#todoapp #todo-stats .todo-clear {
float: right;
}
/* line 125 */
#todoapp #todo-stats .todo-clear a {
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 */
#todoapp #todo-stats .todo-clear a:hover, #todoapp #todo-stats .todo-clear a: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 .todo-clear a:active {
position: relative;
top: 1px;
}
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;
}
#todoapp {
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;
-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;
}
#todoapp 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 .todo-clear a {
color: #777777;
font-size: 12px;
}
/* these two rules are overridden below. find ".todo-clear a" */
#todo-stats .todo-clear a:visited {
color: #777777;
}
#todo-stats .todo-clear a:hover, #todo-stats .todo-clear a:focus {
color: #336699;
}
#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 */
#todoapp #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 */
#todoapp #todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 118 */
#todoapp #todo-stats .todo-count {
float: left;
}
/* line 120 */
#todoapp #todo-stats .todo-count .number {
font-weight: bold;
color: #555555;
}
/* line 123 */
#todoapp #todo-stats .todo-clear {
float: right;
}
/* line 125 */
#todoapp #todo-stats .todo-clear a {
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 */
#todoapp #todo-stats .todo-clear a:hover, #todoapp #todo-stats .todo-clear a: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 .todo-clear a:active {
position: relative;
top: 1px;
}
goog.require('goog.array');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
goog.require('goog.ui.Component');
goog.require('goog.ui.Control');
goog.require('todomvc.model.ToDoItem');
goog.require('todomvc.view');
goog.require('todomvc.view.ClearCompletedControlRenderer');
goog.require('todomvc.view.ItemCountControlRenderer');
goog.require('todomvc.view.ToDoItemControl');
goog.require('todomvc.view.ToDoListContainer');
/**
* @fileoverview The controller/business logic for the application.
*
* This file creates the interface and marshalls changes from the interface to the model and back.
*/
/**
* @type {Array.<todomvc.model.ToDoItem>}
*/
var items = [];
/**
* @type {Element}
*/
var todoStats = document.getElementById('todo-stats');
/**
* @type {goog.ui.Control}
*/
var itemCountControl = new goog.ui.Control(null, todomvc.view.ItemCountControlRenderer.getInstance());
itemCountControl.render(todoStats);
/**
* @type {goog.ui.Control}
*/
var clearCompletedControl = new goog.ui.Control(null, todomvc.view.ClearCompletedControlRenderer.getInstance());
clearCompletedControl.render(todoStats);
goog.events.listen(clearCompletedControl, goog.ui.Component.EventType.ACTION, function(e) {
// go backwards to avoid collection modification problems
goog.array.forEachRight(items, function(model) {
if (model.isDone()) {
goog.array.remove(items, model);
// do optimised model view sync
container.forEachChild(function(control) {
if (control.getModel() === model) {
container.removeChild(control, true);
}
});
}
});
updateStats();
});
function updateStats() {
var doneCount = goog.array.reduce(items, function(count, model) {
return model.isDone() ? count + 1 : count;
}, 0);
var remainingCount = items.length - (/**@type {number}*/ doneCount);
itemCountControl.setContent((/**@type {string}*/ remainingCount));
itemCountControl.setVisible(remainingCount > 0);
clearCompletedControl.setContent((/**@type {string}*/ doneCount));
clearCompletedControl.setVisible((/**@type {number}*/ doneCount) > 0);
}
updateStats();
/**
* @type {todomvc.view.ToDoListContainer}
*/
var container = new todomvc.view.ToDoListContainer();
container.decorate(document.getElementById('todo-list'));
goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.EDIT, function(e) {
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = e.target;
/**
* @type {todomvc.model.ToDoItem}
*/
var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
// do optimised model view sync
model.setNote((/**@type {!string} */ control.getContent()));
model.setDone((/**@type {!boolean} */ control.isChecked()));
updateStats();
});
goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.DESTROY, function(e) {
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = e.target;
/**
* @type {todomvc.model.ToDoItem}
*/
var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
// do optimised model view sync
goog.array.remove(items, model);
container.removeChild(control, true);
updateStats();
});
/**
* @type {Element}
*/
var newToDo = document.getElementById('new-todo');
goog.events.listen(newToDo, goog.events.EventType.KEYUP, function(e) {
if (e.keyCode === goog.events.KeyCodes.ENTER) {
/**
* @type {todomvc.model.ToDoItem}
*/
var model = new todomvc.model.ToDoItem(newToDo.value);
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = new todomvc.view.ToDoItemControl();
// do optimised model view sync
items.push(model);
control.setContent(model.getNote());
control.setChecked(model.isDone());
control.setModel(model);
container.addChild(control, true);
// clear the input box
newToDo.value = '';
updateStats();
}
goog.require('goog.array');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
goog.require('goog.ui.Component');
goog.require('goog.ui.Control');
goog.require('todomvc.model.ToDoItem');
goog.require('todomvc.view');
goog.require('todomvc.view.ClearCompletedControlRenderer');
goog.require('todomvc.view.ItemCountControlRenderer');
goog.require('todomvc.view.ToDoItemControl');
goog.require('todomvc.view.ToDoListContainer');
/**
* @fileoverview The controller/business logic for the application.
*
* This file creates the interface and marshalls changes from the interface to the model and back.
*/
/**
* @type {Array.<todomvc.model.ToDoItem>}
*/
var items = [];
/**
* @type {Element}
*/
var todoStats = document.getElementById('todo-stats');
/**
* @type {goog.ui.Control}
*/
var itemCountControl = new goog.ui.Control(null, todomvc.view.ItemCountControlRenderer.getInstance());
itemCountControl.render(todoStats);
/**
* @type {goog.ui.Control}
*/
var clearCompletedControl = new goog.ui.Control(null, todomvc.view.ClearCompletedControlRenderer.getInstance());
clearCompletedControl.render(todoStats);
goog.events.listen(clearCompletedControl, goog.ui.Component.EventType.ACTION, function(e) {
// go backwards to avoid collection modification problems
goog.array.forEachRight(items, function(model) {
if (model.isDone()) {
goog.array.remove(items, model);
// do optimised model view sync
container.forEachChild(function(control) {
if (control.getModel() === model) {
container.removeChild(control, true);
}
});
}
});
updateStats();
});
function updateStats() {
var doneCount = goog.array.reduce(items, function(count, model) {
return model.isDone() ? count + 1 : count;
}, 0);
var remainingCount = items.length - (/**@type {number}*/ doneCount);
itemCountControl.setContent((/**@type {string}*/ remainingCount));
itemCountControl.setVisible(remainingCount > 0);
clearCompletedControl.setContent((/**@type {string}*/ doneCount));
clearCompletedControl.setVisible((/**@type {number}*/ doneCount) > 0);
}
updateStats();
/**
* @type {todomvc.view.ToDoListContainer}
*/
var container = new todomvc.view.ToDoListContainer();
container.decorate(document.getElementById('todo-list'));
goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.EDIT, function(e) {
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = e.target;
/**
* @type {todomvc.model.ToDoItem}
*/
var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
// do optimised model view sync
model.setNote((/**@type {!string} */ control.getContent()));
model.setDone((/**@type {!boolean} */ control.isChecked()));
updateStats();
});
goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.DESTROY, function(e) {
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = e.target;
/**
* @type {todomvc.model.ToDoItem}
*/
var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
// do optimised model view sync
goog.array.remove(items, model);
container.removeChild(control, true);
updateStats();
});
/**
* @type {Element}
*/
var newToDo = document.getElementById('new-todo');
goog.events.listen(newToDo, goog.events.EventType.KEYUP, function(e) {
if (e.keyCode === goog.events.KeyCodes.ENTER) {
/**
* @type {todomvc.model.ToDoItem}
*/
var model = new todomvc.model.ToDoItem(newToDo.value);
/**
* @type {todomvc.view.ToDoItemControl}
*/
var control = new todomvc.view.ToDoItemControl();
// do optimised model view sync
items.push(model);
control.setContent(model.getNote());
control.setChecked(model.isDone());
control.setModel(model);
container.addChild(control, true);
// clear the input box
newToDo.value = '';
updateStats();
}
});
\ No newline at end of file
goog.provide('todomvc.model.ToDoItem');
/**
* The model object representing a todo item.
*
* @param {!string} note the text associated with this item
* @param {!boolean=} opt_done is this item complete? defaults to false
* @constructor
*/
todomvc.model.ToDoItem = function(note, opt_done) {
/**
* note the text associated with this item
* @private
* @type {!string}
*/
this.note_ = note;
/**
* is this item complete?
* @private
* @type {!boolean}
*/
this.done_ = opt_done || false;
};
/**
* @return {!string} the text associated with this item
*/
todomvc.model.ToDoItem.prototype.getNote = function() {
return this.note_;
};
/**
* @return {!boolean} is this item complete?
*/
todomvc.model.ToDoItem.prototype.isDone = function() {
return this.done_;
};
/**
* @param {!string} note the text associated with this item
*/
todomvc.model.ToDoItem.prototype.setNote = function(note) {
this.note_ = note;
};
/**
* @param {!boolean} done is this item complete?
*/
todomvc.model.ToDoItem.prototype.setDone = function(done) {
this.done_ = done;
goog.provide('todomvc.model.ToDoItem');
/**
* The model object representing a todo item.
*
* @param {!string} note the text associated with this item
* @param {!boolean=} opt_done is this item complete? defaults to false
* @constructor
*/
todomvc.model.ToDoItem = function(note, opt_done) {
/**
* note the text associated with this item
* @private
* @type {!string}
*/
this.note_ = note;
/**
* is this item complete?
* @private
* @type {!boolean}
*/
this.done_ = opt_done || false;
};
/**
* @return {!string} the text associated with this item
*/
todomvc.model.ToDoItem.prototype.getNote = function() {
return this.note_;
};
/**
* @return {!boolean} is this item complete?
*/
todomvc.model.ToDoItem.prototype.isDone = function() {
return this.done_;
};
/**
* @param {!string} note the text associated with this item
*/
todomvc.model.ToDoItem.prototype.setNote = function(note) {
this.note_ = note;
};
/**
* @param {!boolean} done is this item complete?
*/
todomvc.model.ToDoItem.prototype.setDone = function(done) {
this.done_ = done;
};
\ No newline at end of file
goog.provide('todomvc.view.ClearCompletedControlRenderer');
goog.require('goog.dom');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* A renderer for the clear completed control.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ClearCompletedControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ClearCompletedControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ClearCompletedControlRenderer
goog.addSingletonGetter(todomvc.view.ClearCompletedControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.clearCompleted({
number : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.canDecorate = function(element) {
return false;
};
/**
* @param {Element} element Element to populate.
* @param {goog.ui.ControlContent} content Text caption or DOM
*/
todomvc.view.ClearCompletedControlRenderer.prototype.setContent = function(element, content) {
element.innerHTML = todomvc.view.clearCompletedInner({
number : content
});
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
this.updateAriaState(element, state, enable);
}
};
goog.provide('todomvc.view.ClearCompletedControlRenderer');
goog.require('goog.dom');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* A renderer for the clear completed control.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ClearCompletedControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ClearCompletedControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ClearCompletedControlRenderer
goog.addSingletonGetter(todomvc.view.ClearCompletedControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.clearCompleted({
number : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.canDecorate = function(element) {
return false;
};
/**
* @param {Element} element Element to populate.
* @param {goog.ui.ControlContent} content Text caption or DOM
*/
todomvc.view.ClearCompletedControlRenderer.prototype.setContent = function(element, content) {
element.innerHTML = todomvc.view.clearCompletedInner({
number : content
});
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ClearCompletedControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
this.updateAriaState(element, state, enable);
}
};
goog.provide('todomvc.view.ItemCountControlRenderer');
goog.require('goog.dom');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* A renderer for the item count control.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ItemCountControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ItemCountControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ItemCountControlRenderer
goog.addSingletonGetter(todomvc.view.ItemCountControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ItemCountControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.itemCount({
number : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ItemCountControlRenderer.prototype.canDecorate = function(element) {
return false;
};
/**
* @param {Element} element Element to populate.
* @param {goog.ui.ControlContent} content Text caption or DOM
*/
todomvc.view.ItemCountControlRenderer.prototype.setContent = function(element, content) {
element.innerHTML = todomvc.view.itemCountInner({
number : content
});
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ItemCountControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
this.updateAriaState(element, state, enable);
}
};
goog.provide('todomvc.view.ItemCountControlRenderer');
goog.require('goog.dom');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* A renderer for the item count control.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ItemCountControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ItemCountControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ItemCountControlRenderer
goog.addSingletonGetter(todomvc.view.ItemCountControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ItemCountControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.itemCount({
number : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ItemCountControlRenderer.prototype.canDecorate = function(element) {
return false;
};
/**
* @param {Element} element Element to populate.
* @param {goog.ui.ControlContent} content Text caption or DOM
*/
todomvc.view.ItemCountControlRenderer.prototype.setContent = function(element, content) {
element.innerHTML = todomvc.view.itemCountInner({
number : content
});
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ItemCountControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
this.updateAriaState(element, state, enable);
}
};
goog.provide('todomvc.view.ToDoItemControl');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.Control');
goog.require('todomvc.view.ToDoItemControlRenderer');
/**
* A control representing each item in the todo list. It makes use of the CHECKED and SELECTED states to represent being
* done and being in edit mode.
*
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for document interaction.
* @constructor
* @extends {goog.ui.Control}
*/
todomvc.view.ToDoItemControl = function(opt_domHelper) {
goog.ui.Control.call(this, "", todomvc.view.ToDoItemControlRenderer
.getInstance(), opt_domHelper);
// enable CHECKED and SELECTED states
this.setSupportedState(goog.ui.Component.State.CHECKED, true);
this.setSupportedState(goog.ui.Component.State.SELECTED, true);
// disable auto handling of CHECKED and SELECTED states
this.setAutoStates(goog.ui.Component.State.CHECKED, false);
this.setAutoStates(goog.ui.Component.State.SELECTED, false);
// allow text selection within this control
this.setAllowTextSelection(true);
};
goog.inherits(todomvc.view.ToDoItemControl, goog.ui.Control);
todomvc.view.ToDoItemControl.EventType = {
EDIT: "edit",
DESTROY: "destroy"
};
/**
* Configures the component after its DOM has been rendered, and sets up event
* handling. Overrides {@link goog.ui.Component#enterDocument}.
*
* @override
*/
todomvc.view.ToDoItemControl.prototype.enterDocument = function() {
todomvc.view.ToDoItemControl.superClass_.enterDocument.call(this);
// prevent clicking the checkbox (or anything within the root element)
// from having any default behaviour. This stops the checkbox being set
// by the browser.
this.getHandler().listen(this.getElement(), goog.events.EventType.CLICK,
function(e) {
e.preventDefault();
});
};
/**
* Returns the renderer used by this component to render itself or to decorate
* an existing element.
*
* @return {todomvc.view.ToDoItemControlRenderer} Renderer used by the component
*/
todomvc.view.ToDoItemControl.prototype.getRenderer = function() {
return (/**@type {todomvc.view.ToDoItemControlRenderer}*/ this.renderer_);
};
/**
* Specialised handling of mouse events when clicking on the checkbox, label,
* textbox or remove link.
*
* @param {goog.events.Event} e Mouse event to handle.
*/
todomvc.view.ToDoItemControl.prototype.handleMouseUp = function(e) {
todomvc.view.ToDoItemControl.superClass_.handleMouseUp.call(this, e);
if (this.isEnabled()) {
if (e.target === this.getRenderer().getCheckboxElement(
this.getElement())) {
this.setChecked(!this.isChecked());
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.EDIT);
} else if (e.target === this.getRenderer().getDestroyElement(
this.getElement())) {
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.DESTROY);
} else if (!this.isSelected()) {
this.setSelected(true);
}
}
};
/**
* Override the behaviour when the control is unfocused.
* @param {boolean} focused
*/
todomvc.view.ToDoItemControl.prototype.setFocused = function(focused) {
todomvc.view.ToDoItemControl.superClass_.setFocused.call(this, focused);
if (!focused && this.isSelected()) {
/**
* @type {Element}
*/
var inputElement = this.getRenderer().getInputElement(
this.getElement());
this.setContent(inputElement.value);
this.setSelected(false);
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.EDIT);
}
};
/**
* Override the behaviour to switch to editing mode when the control is selected
* @param {boolean} selected
*/
todomvc.view.ToDoItemControl.prototype.setSelected = function(selected) {
todomvc.view.ToDoItemControl.superClass_.setSelected.call(this, selected);
if (selected) {
/**
* @type {Element}
*/
var inputElement = this.getRenderer().getInputElement(
this.getElement());
inputElement.value = this.getContent();
inputElement.focus();
}
goog.provide('todomvc.view.ToDoItemControl');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.Control');
goog.require('todomvc.view.ToDoItemControlRenderer');
/**
* A control representing each item in the todo list. It makes use of the CHECKED and SELECTED states to represent being
* done and being in edit mode.
*
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for document interaction.
* @constructor
* @extends {goog.ui.Control}
*/
todomvc.view.ToDoItemControl = function(opt_domHelper) {
goog.ui.Control.call(this, "", todomvc.view.ToDoItemControlRenderer
.getInstance(), opt_domHelper);
// enable CHECKED and SELECTED states
this.setSupportedState(goog.ui.Component.State.CHECKED, true);
this.setSupportedState(goog.ui.Component.State.SELECTED, true);
// disable auto handling of CHECKED and SELECTED states
this.setAutoStates(goog.ui.Component.State.CHECKED, false);
this.setAutoStates(goog.ui.Component.State.SELECTED, false);
// allow text selection within this control
this.setAllowTextSelection(true);
};
goog.inherits(todomvc.view.ToDoItemControl, goog.ui.Control);
todomvc.view.ToDoItemControl.EventType = {
EDIT: "edit",
DESTROY: "destroy"
};
/**
* Configures the component after its DOM has been rendered, and sets up event
* handling. Overrides {@link goog.ui.Component#enterDocument}.
*
* @override
*/
todomvc.view.ToDoItemControl.prototype.enterDocument = function() {
todomvc.view.ToDoItemControl.superClass_.enterDocument.call(this);
// prevent clicking the checkbox (or anything within the root element)
// from having any default behaviour. This stops the checkbox being set
// by the browser.
this.getHandler().listen(this.getElement(), goog.events.EventType.CLICK,
function(e) {
e.preventDefault();
});
};
/**
* Returns the renderer used by this component to render itself or to decorate
* an existing element.
*
* @return {todomvc.view.ToDoItemControlRenderer} Renderer used by the component
*/
todomvc.view.ToDoItemControl.prototype.getRenderer = function() {
return (/**@type {todomvc.view.ToDoItemControlRenderer}*/ this.renderer_);
};
/**
* Specialised handling of mouse events when clicking on the checkbox, label,
* textbox or remove link.
*
* @param {goog.events.Event} e Mouse event to handle.
*/
todomvc.view.ToDoItemControl.prototype.handleMouseUp = function(e) {
todomvc.view.ToDoItemControl.superClass_.handleMouseUp.call(this, e);
if (this.isEnabled()) {
if (e.target === this.getRenderer().getCheckboxElement(
this.getElement())) {
this.setChecked(!this.isChecked());
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.EDIT);
} else if (e.target === this.getRenderer().getDestroyElement(
this.getElement())) {
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.DESTROY);
} else if (!this.isSelected()) {
this.setSelected(true);
}
}
};
/**
* Override the behaviour when the control is unfocused.
* @param {boolean} focused
*/
todomvc.view.ToDoItemControl.prototype.setFocused = function(focused) {
todomvc.view.ToDoItemControl.superClass_.setFocused.call(this, focused);
if (!focused && this.isSelected()) {
/**
* @type {Element}
*/
var inputElement = this.getRenderer().getInputElement(
this.getElement());
this.setContent(inputElement.value);
this.setSelected(false);
this.dispatchEvent(todomvc.view.ToDoItemControl.EventType.EDIT);
}
};
/**
* Override the behaviour to switch to editing mode when the control is selected
* @param {boolean} selected
*/
todomvc.view.ToDoItemControl.prototype.setSelected = function(selected) {
todomvc.view.ToDoItemControl.superClass_.setSelected.call(this, selected);
if (selected) {
/**
* @type {Element}
*/
var inputElement = this.getRenderer().getInputElement(
this.getElement());
inputElement.value = this.getContent();
inputElement.focus();
}
};
\ No newline at end of file
goog.provide('todomvc.view.ToDoItemControlRenderer');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* The renderer for the ToDoItemControl which has knowledge of the DOM structure of the Control and the applicable CSS
* classes.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ToDoItemControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ToDoItemControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ToDoItemControlRenderer
goog.addSingletonGetter(todomvc.view.ToDoItemControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ToDoItemControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.toDoItem({
content : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ToDoItemControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
switch (state) {
case goog.ui.Component.State.CHECKED:
this.enableClassName(control, "done", enable);
this.getCheckboxElement(element).checked = enable;
break;
case goog.ui.Component.State.SELECTED:
this.enableClassName(control, "editing", enable);
break;
}
this.updateAriaState(element, state, enable);
}
};
/**
* Returns the element within the component's DOM that should receive keyboard
* focus (null if none). The default implementation returns the control's root
* element.
* @param {goog.ui.Control} control Control whose key event target is to be
* returned.
* @return {Element} The key event target.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getKeyEventTarget = function(control) {
return this.getInputElement(control.getElement());
};
/**
* Takes the control's root element and returns the display element
*
* @param {Element} element Root element of the control whose display element is
* to be returned.
* @return {Element} The control's display element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getDisplayElement = function(
element) {
return element ? element.childNodes[0].childNodes[0] : null;
};
/**
* Takes the control's root element and returns the parent element of the
* control's contents.
*
* @param {Element} element Root element of the control whose content element is
* to be returned.
* @return {Element} The control's content element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getContentElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[1] : null;
};
/**
* Takes the control's root element and returns the checkbox element
*
* @param {Element} element Root element of the control whose checkbox element
* is to be returned.
* @return {Element} The control's checkbox element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getCheckboxElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[0] : null;
};
/**
* Takes the control's root element and returns the destroy element
*
* @param {Element} element Root element of the control whose destroy element is
* to be returned.
* @return {Element} The control's destroy element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getDestroyElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[2] : null;
};
/**
* Takes the control's root element and returns the input element
*
* @param {Element} element Root element of the control whose input element is
* to be returned.
* @return {Element} The control's input element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getInputElement = function(
element) {
return element ? element.childNodes[0].childNodes[1].childNodes[0] : null;
};
goog.provide('todomvc.view.ToDoItemControlRenderer');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.ControlRenderer');
/**
* The renderer for the ToDoItemControl which has knowledge of the DOM structure of the Control and the applicable CSS
* classes.
*
* @constructor
* @extends {goog.ui.ControlRenderer}
*/
todomvc.view.ToDoItemControlRenderer = function() {
goog.ui.ControlRenderer.call(this);
};
goog.inherits(todomvc.view.ToDoItemControlRenderer, goog.ui.ControlRenderer);
// add getInstance method to todomvc.view.ToDoItemControlRenderer
goog.addSingletonGetter(todomvc.view.ToDoItemControlRenderer);
/**
* @param {goog.ui.Control} control Control to render.
* @return {Element} Root element for the control.
*/
todomvc.view.ToDoItemControlRenderer.prototype.createDom = function(control) {
var html = todomvc.view.toDoItem({
content : control.getContent()
});
var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
this.setAriaStates(control, element);
return element;
};
/**
* Updates the appearance of the control in response to a state change.
*
* @param {goog.ui.Control} control Control instance to update.
* @param {goog.ui.Component.State} state State to enable or disable.
* @param {boolean} enable Whether the control is entering or exiting the state.
*/
todomvc.view.ToDoItemControlRenderer.prototype.setState = function(control, state, enable) {
var element = control.getElement();
if (element) {
switch (state) {
case goog.ui.Component.State.CHECKED:
this.enableClassName(control, "done", enable);
this.getCheckboxElement(element).checked = enable;
break;
case goog.ui.Component.State.SELECTED:
this.enableClassName(control, "editing", enable);
break;
}
this.updateAriaState(element, state, enable);
}
};
/**
* Returns the element within the component's DOM that should receive keyboard
* focus (null if none). The default implementation returns the control's root
* element.
* @param {goog.ui.Control} control Control whose key event target is to be
* returned.
* @return {Element} The key event target.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getKeyEventTarget = function(control) {
return this.getInputElement(control.getElement());
};
/**
* Takes the control's root element and returns the display element
*
* @param {Element} element Root element of the control whose display element is
* to be returned.
* @return {Element} The control's display element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getDisplayElement = function(
element) {
return element ? element.childNodes[0].childNodes[0] : null;
};
/**
* Takes the control's root element and returns the parent element of the
* control's contents.
*
* @param {Element} element Root element of the control whose content element is
* to be returned.
* @return {Element} The control's content element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getContentElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[1] : null;
};
/**
* Takes the control's root element and returns the checkbox element
*
* @param {Element} element Root element of the control whose checkbox element
* is to be returned.
* @return {Element} The control's checkbox element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getCheckboxElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[0] : null;
};
/**
* Takes the control's root element and returns the destroy element
*
* @param {Element} element Root element of the control whose destroy element is
* to be returned.
* @return {Element} The control's destroy element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getDestroyElement = function(
element) {
return element ? this.getDisplayElement(element).childNodes[2] : null;
};
/**
* Takes the control's root element and returns the input element
*
* @param {Element} element Root element of the control whose input element is
* to be returned.
* @return {Element} The control's input element.
*/
todomvc.view.ToDoItemControlRenderer.prototype.getInputElement = function(
element) {
return element ? element.childNodes[0].childNodes[1].childNodes[0] : null;
};
goog.provide('todomvc.view.ToDoListContainer');
goog.require('goog.ui.Container');
goog.require('todomvc.view.ToDoListContainerRenderer');
/**
* A container for the ToDoItemControls, overridden to support keyboard focus on child controls.
*
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for document interaction.
* @constructor
* @extends {goog.ui.Container}
*/
todomvc.view.ToDoListContainer = function(opt_domHelper) {
goog.ui.Container
.call(this, goog.ui.Container.Orientation.VERTICAL,
todomvc.view.ToDoListContainerRenderer.getInstance(),
opt_domHelper);
// allow focus on children
this.setFocusable(false);
this.setFocusableChildrenAllowed(true);
};
goog.inherits(todomvc.view.ToDoListContainer, goog.ui.Container);
/**
* Override this method to allow text selection in children.
*
* @param {goog.events.BrowserEvent} e Mousedown event to handle.
*/
todomvc.view.ToDoListContainer.prototype.handleMouseDown = function(e) {
if (this.enabled_) {
this.setMouseButtonPressed(true);
}
goog.provide('todomvc.view.ToDoListContainer');
goog.require('goog.ui.Container');
goog.require('todomvc.view.ToDoListContainerRenderer');
/**
* A container for the ToDoItemControls, overridden to support keyboard focus on child controls.
*
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for document interaction.
* @constructor
* @extends {goog.ui.Container}
*/
todomvc.view.ToDoListContainer = function(opt_domHelper) {
goog.ui.Container
.call(this, goog.ui.Container.Orientation.VERTICAL,
todomvc.view.ToDoListContainerRenderer.getInstance(),
opt_domHelper);
// allow focus on children
this.setFocusable(false);
this.setFocusableChildrenAllowed(true);
};
goog.inherits(todomvc.view.ToDoListContainer, goog.ui.Container);
/**
* Override this method to allow text selection in children.
*
* @param {goog.events.BrowserEvent} e Mousedown event to handle.
*/
todomvc.view.ToDoListContainer.prototype.handleMouseDown = function(e) {
if (this.enabled_) {
this.setMouseButtonPressed(true);
}
};
\ No newline at end of file
goog.provide('todomvc.view.ToDoListContainerRenderer');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.Container');
goog.require('goog.ui.ContainerRenderer');
/**
* A renderer for the container, overridden to support keyboard focus on child controls.
* @constructor
* @extends {goog.ui.ContainerRenderer}
*/
todomvc.view.ToDoListContainerRenderer = function() {
goog.ui.ContainerRenderer.call(this);
};
goog.inherits(todomvc.view.ToDoListContainerRenderer,
goog.ui.ContainerRenderer);
goog.addSingletonGetter(todomvc.view.ToDoListContainerRenderer);
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ToDoListContainerRenderer.prototype.canDecorate = function(element) {
return element.tagName == 'UL';
};
/**
* Override this method to allow text selection in children
*
* @param {goog.ui.Container} container Container whose DOM is to be initialized
* as it enters the document.
*/
todomvc.view.ToDoListContainerRenderer.prototype.initializeDom = function(container) {
var elem = (/**@type {!Element}*/ container.getElement());
// Set the ARIA role.
var ariaRole = this.getAriaRole();
if (ariaRole) {
goog.dom.a11y.setRole(elem, ariaRole);
}
goog.provide('todomvc.view.ToDoListContainerRenderer');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.Container');
goog.require('goog.ui.ContainerRenderer');
/**
* A renderer for the container, overridden to support keyboard focus on child controls.
* @constructor
* @extends {goog.ui.ContainerRenderer}
*/
todomvc.view.ToDoListContainerRenderer = function() {
goog.ui.ContainerRenderer.call(this);
};
goog.inherits(todomvc.view.ToDoListContainerRenderer,
goog.ui.ContainerRenderer);
goog.addSingletonGetter(todomvc.view.ToDoListContainerRenderer);
/**
* @param {Element} element Element to decorate.
* @return {boolean} Whether the renderer can decorate the element.
*/
todomvc.view.ToDoListContainerRenderer.prototype.canDecorate = function(element) {
return element.tagName == 'UL';
};
/**
* Override this method to allow text selection in children
*
* @param {goog.ui.Container} container Container whose DOM is to be initialized
* as it enters the document.
*/
todomvc.view.ToDoListContainerRenderer.prototype.initializeDom = function(container) {
var elem = (/**@type {!Element}*/ container.getElement());
// Set the ARIA role.
var ariaRole = this.getAriaRole();
if (ariaRole) {
goog.dom.a11y.setRole(elem, ariaRole);
}
};
\ No newline at end of file
{namespace todomvc.view}
/**
* A todo list item template
* @param content the label for this item
*/
{template .toDoItem}
<li>
<div>
<div class="display">
<input class="check" type="checkbox" />
<div class="todo-content" style="cursor: pointer;">{$content}</div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text"/>
</div>
</div>
</li>
{/template}
/**
* A todo list item count template
* @param number the count of items
*/
{template .itemCount}
<span class="todo-count">
{call .itemCountInner data="all"/}
</span>
{/template}
/**
* A todo list item count template
* @param number the count of items
*/
{template .itemCountInner}
<span class="number">{$number}</span> <span class="word">{if $number > 1}items{else}item{/if}</span> left.
{/template}
/**
* A todo list clear completed template
* @param number the count of items
*/
{template .clearCompleted}
<span class="todo-clear">
{call .clearCompletedInner data="all"/}
</span>
{/template}
/**
* A todo list clear completed template
* @param number the count of items
*/
{template .clearCompletedInner}
<a href="#">
Clear <span class="number-done">{$number}</span> <span class="word-done">{if $number > 1}items{else}item{/if}</span>
</a>
{namespace todomvc.view}
/**
* A todo list item template
* @param content the label for this item
*/
{template .toDoItem}
<li>
<div>
<div class="display">
<input class="check" type="checkbox" />
<div class="todo-content" style="cursor: pointer;">{$content}</div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text"/>
</div>
</div>
</li>
{/template}
/**
* A todo list item count template
* @param number the count of items
*/
{template .itemCount}
<span class="todo-count">
{call .itemCountInner data="all"/}
</span>
{/template}
/**
* A todo list item count template
* @param number the count of items
*/
{template .itemCountInner}
<span class="number">{$number}</span> <span class="word">{if $number > 1}items{else}item{/if}</span> left.
{/template}
/**
* A todo list clear completed template
* @param number the count of items
*/
{template .clearCompleted}
<span class="todo-clear">
{call .clearCompletedInner data="all"/}
</span>
{/template}
/**
* A todo list clear completed template
* @param number the count of items
*/
{template .clearCompletedInner}
<a href="#">
Clear <span class="number-done">{$number}</span> <span class="word-done">{if $number > 1}items{else}item{/if}</span>
</a>
{/template}
\ No newline at end of file
{
"id" : "todomvc",
"inputs" : "js/main.js",
"paths" : "js/",
"output-wrapper" : "(function(){%output%})();",
"mode" : "ADVANCED",
"define" : {
"goog.LOCALE": "en_GB"
},
"checks": {
// Unfortunately, the Closure Library violates these in many places.
// "accessControls": "ERROR",
// "visibility": "ERROR"
"checkRegExp": "WARNING",
"checkTypes": "WARNING",
"checkVars": "WARNING",
"deprecated": "WARNING",
"fileoverviewTags": "WARNING",
"invalidCasts": "WARNING",
"missingProperties": "WARNING",
"nonStandardJsDocs": "WARNING",
"undefinedVars": "WARNING"
}
}
{
"id" : "todomvc",
"inputs" : "js/main.js",
"paths" : "js/",
"output-wrapper" : "(function(){%output%})();",
"mode" : "ADVANCED",
"define" : {
"goog.LOCALE": "en_GB"
},
"checks": {
// Unfortunately, the Closure Library violates these in many places.
// "accessControls": "ERROR",
// "visibility": "ERROR"
"checkRegExp": "WARNING",
"checkTypes": "WARNING",
"checkVars": "WARNING",
"deprecated": "WARNING",
"fileoverviewTags": "WARNING",
"invalidCasts": "WARNING",
"missingProperties": "WARNING",
"nonStandardJsDocs": "WARNING",
"undefinedVars": "WARNING"
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment