Commit ba32f918 authored by Sindre Sorhus's avatar Sindre Sorhus

Merge pull request #552 from stephenplusplus/cujo_bower

cujo updated to use bower.
parents c08c83b8 c9d80c13
/*global define */
define(function () {
"use strict";
'use strict';
var updateRemainingCount, textProp;
var textProp;
updateRemainingCount = normalizeTextProp;
/**
* Self-optimizing function to set the text of a node
*/
var updateRemainingCount = function () {
// sniff for proper textContent property
textProp = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
// resume normally
updateRemainingCount = setTextProp;
updateRemainingCount(arguments);
};
var setTextProp = function (nodes, value) {
for (var i = 0; i < nodes.length; i++) {
nodes[i][textProp] = '' + value;
}
};
return {
/**
......@@ -12,27 +29,27 @@ define(function () {
* @param todo {Object} data used to create new todo
* @param todo.text {String} text of the todo
*/
createTodo: function(todo) {},
createTodo: function () {},
/**
* Remove an existing todo
* @injected
* @param todo {Object} existing todo, or object with same identifier, to remove
*/
removeTodo: function(todo) {},
removeTodo: function () {},
/**
* Update an existing todo
* @injected
* @param todo {Object} updated todo
*/
updateTodo: function(todo) {},
updateTodo: function () {},
/**
* Start inline editing a todo
* @param node {Node} Dom node of the todo
*/
beginEditTodo: function(node) {
beginEditTodo: function (node) {
this.querySelector('.edit', node).focus();
},
......@@ -40,7 +57,7 @@ define(function () {
* Finish editing a todo
* @param todo {Object} todo to finish editing and save changes
*/
endEditTodo: function(todo) {
endEditTodo: function (todo) {
// As per application spec, todos edited to have empty
// text should be removed.
if (/\S/.test(todo.text)) {
......@@ -53,24 +70,24 @@ define(function () {
/**
* Remove all completed todos
*/
removeCompleted: function() {
removeCompleted: function () {
var todos = this.todos;
todos.forEach(function(todo) {
if(todo.complete) todos.remove(todo);
todos.forEach(function (todo) {
if (todo.complete) {
todos.remove(todo);
}
});
},
/**
* Check/uncheck all todos
*/
toggleAll: function() {
var todos, complete;
todos = this.todos;
complete = this.masterCheckbox.checked;
toggleAll: function () {
var todos = this.todos;
var complete = this.masterCheckbox.checked;
todos.forEach(function(todo) {
todos.forEach(function (todo) {
todo.complete = complete;
todos.update(todo);
});
......@@ -81,14 +98,16 @@ define(function () {
* the check/uncheck all checkbox if all todos have become
* checked or unchecked.
*/
updateCount: function() {
var total, checked;
total = checked = 0;
updateCount: function () {
var total = 0;
var checked = 0;
this.todos.forEach(function(todo) {
this.todos.forEach(function (todo) {
total++;
if(todo.complete) checked++;
if (todo.complete) {
checked++;
}
});
this.masterCheckbox.checked = total > 0 && checked === total;
......@@ -99,32 +118,14 @@ define(function () {
this.updateRemainingCount(total - checked);
},
updateTotalCount: function(total) {},
updateTotalCount: function () {},
updateCompletedCount: function(completed) {
updateCompletedCount: function (completed) {
this.countNode.innerHTML = completed;
},
updateRemainingCount: function (remaining) {
updateRemainingCount(this.remainingNodes, remaining);
}
};
/**
* Self-optimizing function to set the text of a node
*/
function normalizeTextProp () {
// sniff for proper textContent property
textProp = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
// resume normally
(updateRemainingCount = setTextProp).apply(this, arguments);
}
function setTextProp (nodes, value) {
for (var i = 0; i < nodes.length; i++) {
nodes[i][textProp] = '' + value;
}
}
});
/*global define */
define({
// TODO: Deal with singular vs. plural
itemsLeft: {
zero: '<strong></strong> items left',
one: '<strong></strong> item left',
......
......@@ -19,20 +19,23 @@
#clear-completed {
opacity: 1;
}
.completed-zero #clear-completed {
opacity: 0;
}
#footer {
display: none;
}
.todos-one #main,
.todos-many #main,
.todos-one #footer,
.todos-many #footer {
display: block;
}
/* TODO: Reinstate once we add routing */
#filters {
#main,
#footer,
.todos-zero #main,
.todos-zero #footer {
display: none;
}
/* TODO: Reinstate once we add routing */
<footer id="footer">
<!-- This should be `0 items left` by default -->
<span id="todo-count">
<span class="remaining-count-zero">${itemsLeft.zero}</span>
<span class="remaining-count-one">${itemsLeft.one}</span>
<span class="remaining-count-many">${itemsLeft.many}</span>
</span>
<!-- Remove this if you don't implement routing -->
<ul id="filters">
<li>
<a class="selected" href="#/">${filter.all}</a>
</li>
<li>
<a href="#/active">${filter.active}</a>
</li>
<li>
<a href="#/completed">${filter.completed}</a>
</li>
</ul>
<button id="clear-completed">${clearCompleted} (<span class="count">1</span>)</button>
</footer>
define(function() {
/*global define */
define(function () {
'use strict';
return function(todo) {
return function (todo) {
todo.text = todo.text && todo.text.trim() || '';
todo.complete = !!todo.complete;
return todo;
}
};
});
define(function() {
/**
* Since we're using a datastore (localStorage) that doesn't generate ids and such
* for us, this transform generates a GUID id and a dateCreated. It can be
* injected into a pipeline for creating new todos.
*/
return function generateMetadata(item) {
item.id = guidLike();
item.dateCreated = new Date().getTime();
return item;
};
/*global define */
/*jshint bitwise:false */
define(function () {
'use strict';
// GUID-like generation, not actually a GUID, tho, from:
// http://stackoverflow.com/questions/7940616/what-makes-this-pseudo-guid-generator-better-than-math-random
function s4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
return (((1 + Math.random()) * 0x10000)|0).toString(16).substring(1);
}
function guidLike() {
return (s4()+s4()+"-"+s4()+"-"+s4()+"-"+s4()+"-"+s4()+s4()+s4());
return (s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4());
}
/**
* Since we're using a datastore (localStorage) that doesn't generate ids and
* such for us, this transform generates a GUID id and a dateCreated. It can
* be injected into a pipeline for creating new todos.
*/
return function generateMetadata(item) {
item.id = guidLike();
item.dateCreated = new Date().getTime();
return item;
};
});
/*global define */
define({
title: 'todos',
todo: {
......
define(function() {
/*global define */
define(function () {
'use strict';
/**
* Validate a todo
*/
return function validateTodo(todo) {
var valid, result;
// Must be a valid object, and have a text property that is non-empty
valid = todo && 'text' in todo && todo.text.trim();
result = { valid: !!valid };
if(!valid) result.errors = [{ property: 'text', message: 'missing' }];
var valid = todo && 'text' in todo && todo.text.trim();
var result = { valid: !!valid };
return result;
if (!valid) {
result.errors = [{ property: 'text', message: 'missing' }];
}
return result;
};
});
/*global define */
define({
edit: 'Double-click to edit a todo',
templateBy: 'Template by',
......
define(function() {
/*global define */
define(function () {
'use strict';
/**
* Custom data linking handler for setting the "completed" class.
......@@ -6,9 +8,8 @@ define(function() {
* handlers for data/dom linking to do anything that isn't provided
* by default.
*/
return function(node, data, info) {
return function (node, data, info) {
// Simple-minded implementation just to show custom data linking handler
node.className = data[info.prop] ? 'completed' : '';
};
});
/*global define */
define({
markAll: 'Mark all as complete'
});
#toggle-all {
display: none;
}
.todos-one #toggle-all, .todos-many #toggle-all {
.todos-one #toggle-all,
.todos-many #toggle-all {
display: block;
}
/*global define */
define({
// Cujo uses OOCSS principles and thus separates theme (skin)
// from structure CSS.
theme: { module: 'css!theme/base.css' },
......@@ -174,7 +174,7 @@ define({
},
plugins: [
// { module: 'wire/debug', trace: true },
// { module: 'wire/debug', trace: true },
{ module: 'wire/dom' },
{ module: 'wire/dom/render' },
{ module: 'wire/on' },
......
(function( curl ) {
/*global curl */
(function (curl) {
'use strict';
var config = {
baseUrl: 'app',
......@@ -17,5 +19,4 @@
};
curl(config, ['poly/string', 'poly/array']).next(['wire!main']);
})( curl );
})(curl);
{
"name": "todomvc-cujo",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.4",
"curl": "~0.7.3",
"cola": "latest",
"poly": "~0.5.1",
"when": "~2.0.1",
"wire": "~0.9.4",
"meld": "~1.3.0"
}
}
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
border: none; /* Mobile Safari */
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
word-break: break-word;
padding: 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
-moz-transition: color 0.4s;
-ms-transition: color 0.4s;
-o-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
-ms-transform: scale(1.3);
-o-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden{
display:none;
}
(function () {
'use strict';
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function getSourcePath() {
// If accessed via addyosmani.github.io/todomvc/, strip the project path.
if (location.hostname.indexOf('github.io') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/addyosmani/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'addyosmani.github.io') {
location.href = location.href.replace('addyosmani.github.io/todomvc', 'todomvc.com');
}
}
appendSourceLink();
redirect();
})();
......@@ -4,15 +4,12 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>cujo • TodoMVC</title>
<link rel="stylesheet" href="../../../assets/base.css">
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
<![endif]-->
<script src="lib/curl/src/curl.js"></script>
<script src="app/run.js"></script>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
</head>
<body>
<section id="todoapp"></section>
<script src="../../../assets/base.js"></script>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="lib/curl/src/curl.js"></script>
<script src="app/run.js"></script>
</body>
</html>
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