Commit 86c4c86f authored by Sindre Sorhus's avatar Sindre Sorhus

Merge labs branch into master/labs

parents e5748865 b2978df1
# TodoMVC Labs
TodoMVC Labs showcases sample Todo applications for frameworks that have just been released or are still awaiting consideration for inclusion in TodoMVC.
While our team are working on improving these applications for a future release of TodoMVC (e.g ensuring they meet our functional requirements), developers wishing to try out brand new frameworks or see what's coming next for this project can preview this today.
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Agility.js • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css">
</head>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" type="text" data-bind="newtitle" placeholder="What needs to be done?" autofocus>
</header>
<section id="main" data-bind="class = mainStyle">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<li>
<div class="view">
<input class="toggle" type="checkbox" data-bind="complete">
<label data-bind="title"></label>
<button class="destroy"></button>
</div>
<input class="edit" type="text" data-bind="title">
</li>
</ul>
</section>
<footer id="footer" data-bind="class = mainStyle">
<span id="todo-count"><strong data-bind='todoCount'></strong> item<span data-bind='pluralizer'></span> left</span>
<ul id="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed" data-bind="class = clearBtnStyle">Clear completed (<span data-bind="completeCount"></span>)</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
<p>Created by <a href="http://github.com/tshm/todomvc/">Tosh Shimayama</a></p>
<p>Part of <a href="http://github.com/addyosmani/todomvc/">TodoMVC</a></p>
</footer>
<script src="../../assets/jquery.min.js"></script>
<script src="js/lib/agility.min.js"></script>
<script src="js/localstorage.js"></script>
<script src="js/app.js"></script>
</body>
</html>
(function( $, $$ ) {
'use strict';
var ENTER_KEY = 13;
// Hack of taking out html elements from DOM so that agility's view can use it.
// We need 'outerhtml' also, as agilityjs will append DOM, so removing it.
var drawHtml = function( selector ) {
return $(selector).remove().wrap( '<div>' ).parent().html();
};
// Simple Two layer composition:
// individual 'todoitem' and 'app'lication which holds multiple todoitems.
$(function() {
// todo item
var todoitem = $$({
model: {
title: 'no name',
complete: false
},
view: {
format: drawHtml( '#todo-list li' ),
style: '.hidden { display: none }'
},
controller: {
'change:complete': function() {
this.view.$().toggleClass( 'complete', this.model.get( 'complete' ));
app.updateStatus();
},
'dblclick .view': function() {
this.view.$().addClass( 'editing' );
this.view.$('.edit').select();
},
'click .destroy': function() {
this.destroy();
},
'create': function() {
this.view.$().toggleClass( 'complete', this.model.get( 'complete' ));
},
'change': function() {
this.save();
},
'destroy': function() {
this.erase();
},
'change:title': function() {
this.view.$().removeClass( 'editing' );
var title = this.model.get( 'title' ).trim();
if ( title ) {
this.model.set({
title: title
});
} else {
this.destroy();
}
}
}
}).persist( $$.adapter.localStorage, {
collection: 'todos-agilityjs'
});
// The main application which holds todo items.
var app = $$({
model: {
todoCount: '0',
pluralizer: '',
completeCount: '0',
newtitle: '',
mainStyle: '',
clearBtnStyle: ''
},
view: {
format: drawHtml( '#todoapp' ),
style: '.hidden { display: none }'
},
controller: {
'remove': function() {
this.updateStatus();
},
'append': function() {
this.updateStatus();
},
'keyup #new-todo': function( event ) {
var title;
if ( event.which === ENTER_KEY && (title = $('#new-todo').val().trim()) ) {
var item = $$(todoitem, {
title: title
}).save();
this.append( item, '#todo-list' );
event.target.value = ''; // clear input field
}
},
'click #toggle-all': function() {
var ischecked = this.view.$('#toggle-all').prop('checked');
this.each(function( id, item ) {
item.model.set({
complete: ischecked
});
});
},
'click #clear-completed': function() {
this.each(function( id, item ) {
if ( item.model.get( 'complete' ) ) {
item.destroy();
}
});
}
},
// utility functions
updateStatus: function() {
// update counts
var count = this.size(),
completeCount = 0;
this.each(function( id, item ) {
if ( item.model.get( 'complete' ) ) {
completeCount++;
}
});
this.model.set({
todoCount: count - completeCount + '',
pluralizer: (count > 1 ? 's' : ''),
completeCount: completeCount + '',
mainStyle: (count === 0 ? 'hidden' : ''),
clearBtnStyle: (completeCount === 0 ? 'hidden' : '')
});
// update toggle-all checked status
$('#toggle-all').prop( 'checked', completeCount === count );
},
// filter handler
filters: {
'#/': function( item ) {
return true;
},
'#/active': function( item ) {
return !item.model.get( 'complete' );
},
'#/completed': function( item ) {
return item.model.get( 'complete' );
}
},
applyFilter: function( hash ) {
var isVisible = this.filters[hash];
this.each(function( id, item ) {
item.view.$().toggleClass( 'hidden', !isVisible( item ));
});
}
}).persist();
$$.document.prepend( app );
// load from localStorage
app.gather( todoitem, 'append', '#todo-list' ).updateStatus();
// manual routing (not supported by agilityjs)
$(window).on( 'hashchange', function() {
var hash = location.hash;
app.applyFilter( hash );
$('#filters a').each(function() {
if ( hash === $(this).attr( 'href' ) ) {
$(this).addClass( 'selected' );
} else {
$(this).removeClass( 'selected' );
}
});
});
if ( location.hash ) {
$(window).trigger( 'hashchange' );
}
});
})( window.jQuery, window.agility );
This diff is collapsed.
// custom agilityjs adapter for localstorage
(function( $$, undefined ) {
'use strict';
$$.adapter.localStorage = function( _params ) {
var storageKey = (this._data.persist.baseUrl || '') + this._data.persist.collection,
storageStr = localStorage[storageKey],
items = (storageStr ? JSON.parse( storageStr ) : {});
//
if ( _params.type === 'GET' ) {
if ( _params.id !== undefined ) { // normal get
if ( typeof items[_params.id] === 'object' ) {
_params.success( items[_params.id] );
} else {
_params.error();
}
} else { // gather call
_params.success( items );
}
} else if ( _params.type === 'DELETE' ) {
delete items[_params.id];
localStorage[storageKey] = JSON.stringify( items );
} else if ( _params.type === 'PUT' || _params.type === 'POST' ) {
if ( _params.id === undefined ) {
_params.id = (new Date()).getTime();
_params.data.id = _params.id;
}
items[_params.id] = _params.data;
localStorage[storageKey] = JSON.stringify( items );
} else {
_params.error();
}
_params.complete();
};
})( window.agility );
# batman.js • [TodoMVC](http://todomvc.com)
Batman.js is a framework for building rich web applications with CoffeeScript or JavaScript. App code is concise and declarative, thanks to a powerful system of view bindings and observable properties. The API is designed with developer and designer happiness as its first priority.
[Issue](https://github.com/addyosmani/todomvc/issues/14)
\ No newline at end of file
html, body {
margin: 0;
padding: 0;
}
body {
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
}
#views {
width: 520px;
margin: 0 auto 40px auto;
background: white;
-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;
}
#tasks {
padding: 20px;
}
#tasks h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 0 0 10px 0;
}
#tasks input[type="text"] {
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;
}
#tasks input::-webkit-input-placeholder {
font-style: italic;
}
#tasks .items {
margin: 10px 0;
list-style: none;
}
#tasks .item {
padding: 15px 20px 15px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
#tasks .item.done span {
color: #777777;
text-decoration: line-through;
}
#tasks .item .destroy {
position: absolute;
right: 5px;
top: 14px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
background: url(../images/destroy.png) no-repeat 0 0;
}
#tasks .item:hover .destroy {
display: block;
}
#tasks li:hover .todo-destroy {
display: block;
}
#tasks .destroy:hover {
background-position: 0 -20px;
}
/*
#tasks .item .edit { display: none; }
#tasks .item.editing .edit { display: block; }
#tasks .item.editing .view { display: none; }
*/
#tasks footer {
display: block;
margin: 20px -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 36px;
-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;
}
#tasks .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;
}
#tasks .clear:hover {
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;
}
#tasks .clear:active {
position: relative;
top: 1px;
}
#tasks .count span {
font-weight: bold;
}
#credits {
width: 520px;
margin: 30px auto;
color:
#999;
text-shadow:
rgba(255, 255, 255, .8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<title>Todos</title>
<link rel="stylesheet" href="css/todo.css" type="text/css">
<script src="lib/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="lib/batman.js" type="text/javascript"></script>
<script src="lib/batman.jquery.js" type="text/javascript"></script>
<script src="lib/es5-shim.js" type="text/javascript"></script>
<script src="lib/coffee-script.js" type="text/javascript"></script>
</head>
<body>
<div id="views">
<div id="tasks">
<h1>Todos</h1>
<form data-formfor-todo="controllers.todos.emptyTodo" data-event-submit="controllers.todos.create">
<input type="text" placeholder="What needs to be done?" data-bind="todo.body" />
</form>
<div class="items">
<div class="item" data-foreach-todo="Todo.all" data-addclass-done="todo.completed">
<div class="view" title="Double click to edit..." data-event-doubleclick="todo.on_edit" data-hideif="todo.editing">
<input type="checkbox" data-bind="todo.completed" data-event-change="todo.save" />
<span data-bind="todo.body"></span>
<a class="destroy" data-event-click="todo.destroy"></a>
</div>
<div data-showif="todo.editing">
<form data-event-submit="todo.on_blur">
<input type="text" data-bind="todo.body" data-event-blur="todo.on_blur"/>
</form>
</div>
</div>
</div>
<footer>
<a class="clear" data-event-click="Todo.clear">Clear completed</a>
<div class="count"><span class="countVal" data-bind="Todo.remaining"></span> left</div>
</footer>
<!--
This version by
Currently missing todo edit.
-->
</div>
</div>
<div id="credits">
<p>Created by <a href="https://github.com/johnknott/batman-todos-example">John Knott</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</div>
<script type="text/coffeescript">
class Example extends Batman.App
@root 'todos#index'
class Example.Todo extends Batman.Model
@global yes
@persist Batman.LocalStorage
@encode 'body', 'completed'
completed: false
editing: false
on_edit: (node, event) ->
@set 'todo.editing', true
$(node).parent().find("input[type=text]").focus()
on_blur: (node, event) ->
@set 'todo.editing', false
@todo.save()
@clear: (node, event) ->
Todo.all.forEach (todo) ->
if todo.get 'completed'
todo.destroy()
@classAccessor 'remaining',
get: -> Todo.get('all').get('length')
class Example.TodosController extends Batman.Controller
emptyTodo: null
index: ->
@set 'emptyTodo', new Todo
@render false
create: =>
@emptyTodo.save =>
@set 'emptyTodo', new Todo
Example.run()
</script>
</body>
</html>
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Batman.Request.prototype.send = function(data) {
var options, _ref;
options = {
url: this.get('url'),
type: this.get('method'),
dataType: this.get('type'),
data: data || this.get('data'),
username: this.get('username'),
password: this.get('password'),
beforeSend: __bind(function() {
return this.fire('loading');
}, this),
success: __bind(function(response, textStatus, xhr) {
this.set('status', xhr.status);
this.set('response', response);
return this.fire('success', response);
}, this),
error: __bind(function(xhr, status, error) {
this.set('status', xhr.status);
this.set('response', xhr.responseText);
xhr.request = this;
return this.fire('error', xhr);
}, this),
complete: __bind(function() {
return this.fire('loaded');
}, this)
};
if ((_ref = this.get('method')) === 'PUT' || _ref === 'POST') {
if (!this.get('formData')) {
options.contentType = this.get('contentType');
} else {
options.contentType = false;
options.processData = false;
options.data = this.constructor.objectToFormData(options.data);
}
}
return jQuery.ajax(options);
};
Batman.mixins.animation = {
show: function(addToParent) {
var jq, show, _ref, _ref2;
jq = $(this);
show = function() {
return jq.show(600);
};
if (addToParent) {
if ((_ref = addToParent.append) != null) {
_ref.appendChild(this);
}
if ((_ref2 = addToParent.before) != null) {
_ref2.parentNode.insertBefore(this, addToParent.before);
}
jq.hide();
setTimeout(show, 0);
} else {
show();
}
return this;
},
hide: function(removeFromParent) {
$(this).hide(600, __bind(function() {
var _ref;
if (removeFromParent) {
return (_ref = this.parentNode) != null ? _ref.removeChild(this) : void 0;
}
}, this));
return this;
}
};
}).call(this);
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
html, body {
margin: 0;
padding: 0;
}
body {
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
}
#views {
width: 520px;
margin: 0 auto 40px auto;
background: white;
-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;
}
#tasks {
padding: 20px;
}
#tasks h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 0 0 10px 0;
}
#tasks input[type="text"] {
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;
}
#tasks input::-webkit-input-placeholder {
font-style: italic;
}
#tasks .items {
margin: 10px 0;
list-style: none;
padding: 0;
}
#tasks .item {
padding: 15px 20px 15px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
#tasks .item.done span {
color: #777777;
text-decoration: line-through;
}
#tasks .item .destroy {
position: absolute;
right: 10px;
top: 16px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
background: url(../images/delete.png) no-repeat center center;
}
#tasks .item .edit {
position: absolute;
right: 36px;
top: 16px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
background: url(../images/pencil.png) no-repeat center center;
}
#tasks .item:hover .destroy,
#tasks .item:hover .edit {
display: block;
}
#tasks .item.editing .edit { display: block; }
#tasks .item.editing .view { display: none; }
#tasks footer {
display: block;
margin: 20px -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 36px;
-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;
}
#tasks .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;
margin-bottom: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;
}
#tasks .clear:hover, #tasks .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;
}
#tasks .clear:active {
position: relative;
top: 1px;
}
#tasks .count span {
font-weight: bold;
}
#credits {
width: 520px;
margin: 30px auto;
color:
#999;
text-shadow:
rgba(255, 255, 255, .8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
<!DOCTYPE html>
<html>
<head>
<title>Broke.js</title>
<link rel="stylesheet" href="css/application.css" type="text/css" charset="utf-8">
</head>
<body>
<div id="views">
<div id="tasks">
<h1>Todos</h1>
<form action="#/task/create/" method="post">
<input type="text" name="title" placeholder="What needs to be done?" />
</form>
<div id="content"></div>
<footer>
<a class="clear" href="#/task/clear_completed/">Clear completed</a>
<div class="count"><span class="countVal"></span></div>
</footer>
</div>
</div>
<div id="credits">
<p>Created by <a href="https://github.com/brokenseal">Davide Callegari</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</div>
<script src="libs/jquery-1.6.4.min.js"></script>
<script src="libs/gettext.min.js"></script>
<script src="libs/pyjammin.min.js"></script>
<script src="libs/broke-client-0.2b.min.js"></script>
<script src="project/my-blog.js"></script>
<script src="project/settings.js"></script>
<script src="project/models.js"></script>
<script src="project/views.js"></script>
<script src="project/urls.js"></script>
<script src="project/templates.js"></script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
(function(context, undefined){
var
models= broke.db.models
;
todo.models= {};
models.Model.create({
__name__: "todo.models.Task"
,title: models.CharField({ max_length: 200 })
,is_complete: models.BooleanField({ 'default': false })
});
})(this);
\ No newline at end of file
(function(context, undefined){
context.todo= {};
$(function(){
broke.init('todo.settings', function(){
// fill db
//todo.models.Task.objects.create({"pk": 1, "model": "todo.task", "fields": {"is_complete": false, "title": "Title A"}});
//todo.models.Task.objects.create({"pk": 2, "model": "todo.task", "fields": {"is_complete": false, "title": "Title B"}});
//todo.models.Task.objects.create({"pk": 3, "model": "todo.task", "fields": {"is_complete": false, "title": "Title C"}});
broke.events.request('/');
});
});
})(this);
\ No newline at end of file
;(function(context, undefined){
todo.settings= {
MIDDLEWARE_CLASSES: []
,DEBUG_PROPAGATE_EXCEPTIONS: true
,LANGUAGE_CODE: 'en'
,TEMPLATE_LOADERS: [
'broke.template.loaders.apps'
,'broke.template.loaders.remote'
]
,EVENT_TRIGGERING_METHOD: 'elements'
,HIDE_HASH: true
,USE_I18N: true
,DEBUG: false
,GET_LATEST_BY: 'title'
,INSTALLED_APPS: [
'todo'
]
,ROOT_URLCONF: 'todo.urls'
,URL_CHANGING_ELEMENTS: broke.extend(broke.conf.settings.URL_CHANGING_ELEMENTS, {
'input': {
events: ['click']
,urlAttribute: 'data-href'
}
})
};
})(this);
\ No newline at end of file
(function(context, undefined){
var
genericTaskTemplate= '<li class="item" data-app_label="{{ task.__class__._meta.appLabel }}" data-model="{{ task.__class__._meta.modelName }}" data-pk="{{ task.pk }}">'+
'<input type="checkbox" data-field="is_complete" data-href="#/task/complete/{{ task.pk }}/" {% if task.fields.is_complete %} checked="checked"{% endif %} />' +
'<span data-field="title">{{ task.title }}</span>' +
'<a class="edit" href="#/task/update/{{ task.pk }}/"></a>' +
'<a class="destroy" href="#/task/delete/{{ task.pk }}/"></a>' +
'</li>'
;
todo.templates= {
list: '<ul class="items">' +
'{% for task in taskList %}' +
genericTaskTemplate +
'{% endfor %}' +
'</ul>'
,view: genericTaskTemplate
,create: ''
,update: '<li class="item" data-app_label="{{ task.__class__._meta.appLabel }}" data-model="{{ task.__class__._meta.modelName }}" data-pk="{{ task.pk }}">'+
'<form action="#/task/update/{{ task.pk }}/">' +
'<input type="text" name="title" value="{{ task.title }}" />' +
'</form>' +
'</li>'
};
})(this);
\ No newline at end of file
(function(context, undefined){
var
patterns= broke.conf.urls.defaults.patterns
;
todo.urls= patterns('todo.views',
[ '^/$', 'list' ]
,[ '^/task/create/', 'create' ]
,[ '^/task/update/([a-zA-Z0-9_-]+)/', 'update' ]
,[ '^/task/delete/([a-zA-Z0-9_-]+)/', 'delete' ]
,[ '^/task/complete/([a-zA-Z0-9_-]+)/', 'complete' ]
,[ '^/task/clear_completed/', 'clear_completed' ]
);
})(this);
\ No newline at end of file
(function(context, undefined){
var
node= broke.shortcuts.node
,Task= todo.models.Task
;
todo.views= {
list: function(request, callback){
Task.objects.all(function(taskList){
callback(node.create({
htmlNode: '#content'
,template: 'list'
,object: taskList
,context: {
taskList: taskList
}
}));
});
}
,create: function(request, callback){
if(request.POST) {
Task.objects.create({
title: request.POST['title']
,pk: 'auto'
}, function(task){
callback(node.create({
htmlNode: '#content .items'
,template: 'view'
,object: task
,context: {
task: task
}
,callback: function(){
broke.DOM.val(request.event.target.title, '');
}
}));
});
}
}
,update: function(request, taskId, callback){
Task.objects.get({ pk: taskId }, function(task){
if(request.POST) {
task.update({ title: request.POST['title'] });
callback(node.replace({
template: 'view'
,context: {
task: task
}
,htmlNode: task.elements({ clearCache: true, filter: 'li' })
}));
} else {
callback(node.replace({
template: 'update'
,context: {
task: task
}
,htmlNode: task.elements({ clearCache: true, filter: 'li' })
,callback: function(){
broke.DOM.querySelector('input', this)[0].focus();
}
}));
}
});
}
,'delete': function(request, taskId, callback){
request.event.preventDefault();
Task.objects.get({ pk: taskId }, function(task){
task['delete']();
});
}
,complete: function(request, taskId, callback){
Task.objects.get({ pk: taskId }, function(task){
task.update({ is_complete: request.event.target.checked }, false);
});
}
,clear_completed: function(request, taskId, callback){
Task.objects.filter({ is_complete: true }).all(function(taskList){
builtins.forEach(taskList, function(task){
this['delete']();
});
});
}
};
})(this);
\ No newline at end of file
## CanJS TodoMVC Demos
This project contains a collection of [TodoMVC](https://github.com/addyosmani/todomvc/) demos using [CanJS](https://github.com/jupiterjs/canjs) with the different libraries that it supports.
### Demos
- [jquery](http://donejs.com/examples/todo/jquery/): CanJS with jQuery
- [jquery-widget](http://donejs.com/examples/todo/jquery-widget/): CanJS with jQuery (includes a jQuery UI widget binding example)
- [dojo](http://donejs.com/examples/todo/dojo/): CanJS with Dojo
- [dojo-widget](http://donejs.com/examples/todo/dojo-widget/): CanJS with Dojo (includes a Dojo widget binding example)
- [mootools](http://donejs.com/examples/todo/mootools/): CanJS with Mootools
- [yui](http://donejs.com/examples/todo/yui/): CanJS with YUI
- [yui-widget](http://donejs.com/examples/todo/yui-widget/): CanJS with YUI (includes a YUI widget binding example)
- [zepto](http://donejs.com/examples/todo/zepto/): CanJS with Zepto
### Getting Started
To get these demos:
1. Download the [latest release](#) or clone the project:
```git clone git@github.com:jupiterjs/cantodo.git```
2. Run these demos on a local server. Open the corresponding, self-named, demo page:
- `jquery`: `jquery/index.html`
- `jquery-widget`: `jquery-widget/index.html`
- `dojo`: `dojo/index.html`
- `dojo-widget`: `dojo-widget/index.html`
- `mootools`: `mootools/index.html`
- `yui`: `yui/index.html`
- `yui-widget`: `yui-widget/index.html`
- `zepto`: `zepto/index.html`
You can also use the [links above][demos] to view the demos live on donejs.com.
### Testing
FuncUnit tests for each demo are included in the `test` directory.
To run the unit tests:
1. First update the submodules:
```git submodule update --init --recursive```
2. Open the corresponding test page:
- `all frameworks`: `test/index.html`
- `jquery`: `test/jquery.html`
- `jquery-widget`: `test/jquery-widget.html`
- `dojo`: `test/dojo.html`
- `dojo-widget`: `test/dojo-widget.html`
- `mootools`: `test/mootools.html`
- `yui`: `test/yui.html`
- `yui-widget`: `test/yui-widget.html`
- `zepto`: `test/zepto.html`
---
Created and maintained by [Bitovi](http://bitovi.com)
\ No newline at end of file
html,
body {
margin: 0;
padding: 0;
}
body {
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
width: 520px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
}
#todoapp {
background: #fff;
padding: 20px;
margin-bottom: 40px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-ms-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;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#todoapp h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 0 0 10px 0;
}
#todoapp input[type="text"] {
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-ms-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;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#main {
display: none;
}
#todo-list {
margin: 10px 0;
padding: 0;
list-style: none;
}
#todo-list li {
padding: 18px 20px 18px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.done label {
color: #777777;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 20px;
right: 10px;
cursor: pointer;
width: 20px;
height: 20px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAABGdBTUEAALGPC/xhBQAAACdQTFRFzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAA////zMzMhnu0WAAAAAt0Uk5T5u3pqtV3jFQEKAC0bVelAAAAfUlEQVQI12NYtWpFsc8R865VqxhWrZpyBgg8QcylZ8AgCsjMgTCPrWJYfgYKqhjWwJgaDDVnzpw+c2bPmTPHGWzOnNm95/TuM2cOM/AARXfvBooeZAAp270bRCIz4QoOIGtDMqwJZoUEQzvCYrhzuhhWtUKYEahOX7UK6iEA3A6NUGwCTZIAAAAASUVORK5CYII=') no-repeat center center;
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li.editing {
border-bottom: none;
margin-top: -1px;
padding: 0;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#todo-list li.editing .edit {
display: block;
width: 444px;
padding: 13px 15px 14px 20px;
margin: 0;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .view label {
word-break: break-word;
}
#todo-list li .edit {
display: none;
}
#todoapp footer {
display: none;
margin: 0 -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 37px;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#clear-completed {
display: none;
float: right;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
margin-bottom: 8px;
padding: 0 10px 1px;
cursor: pointer;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
-ms-border-radius: 12px;
-o-border-radius: 12px;
border-radius: 12px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-ms-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;
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-ms-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;
}
#clear-completed:active {
position: relative;
top: 1px;
}
#todo-count span {
font-weight: bold;
}
#instructions {
margin: 10px auto;
color: #777777;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#instructions a {
color: #336699;
}
#credits {
margin: 30px auto;
color: #999;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Todo - CanJS with Dojo</title>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dijit/themes/nihilo/nihilo.css">
<link rel="stylesheet" href="font/font-awesome.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="todo.css">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body class="nihilo">
<div id="todoapp">
<header>
<h1>Todos</h1>
<input id="new-todo" type="text" placeholder="What needs to be done?">
</header>
</div>
<div id="instructions">
Double-click to edit a todo.
</div>
<div id="credits">
<p>Created by <a href="http://bitovi.com/">Bitovi</a>.</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a>.</p>
</div>
<div id="calendar"></div>
<script type='text/javascript' data-dojo-config="async: true" src='http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js.uncompressed.js'></script>
<script src="todo.js"></script>
</body>
</html>
\ No newline at end of file
#main.show,
#stats.show,
#stats.show #clear-completed {
display: block;
}
body {
position: relative;
}
#todo-list li .date {
color: #999;
font-size: 80%;
}
#todo-list li .date.late {
color: #900;
}
#todo-list li .destroy {
background: none;
}
#todo-list li .clear-date,
#todo-list li .due-date,
#todo-list li .destroy {
color: #ccc;
display: none;
position: absolute;
top: 20px;
right: 10px;
cursor: pointer;
font-size: 20px;
width: 20px;
height: 20px;
}
#todo-list li .clear-date {
right: 70px;
}
#todo-list li .due-date {
right: 40px;
}
#todo-list li:hover .clear-date.show,
#todo-list li:hover .due-date {
display: block;
}
#calendar {
position: absolute;
z-index: 999;
visibility: hidden;
top: -9999px;
}
#calendar,
.dijitCalendarMonthMenu {
font-size: 11px;
line-height: 1em;
}
.nihilo .dijitCalendarContainer {
font-family: "Lucida Grande","Lucida Sans",Calibri,Helvetica,Arial,sans-serif;
background: #f2f2f2; /* Old browsers */
background: -moz-linear-gradient(top, #f9f9f9 0%, #f2f2f2 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f9f9f9), color-stop(100%,#f2f2f2)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #f9f9f9 0%,#f2f2f2 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #f9f9f9 0%,#f2f2f2 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #f9f9f9 0%,#f2f2f2 100%); /* IE10+ */
background: linear-gradient(top, #f9f9f9 0%,#f2f2f2 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f9f9f9', endColorstr='#f2f2f2',GradientType=0 ); /* IE6-9 */
border-color: #808080;
-moz-border-radius: 5px;
border-radius: 5px;
padding: 10px;
}
.nihilo .dijitCalendarMonthContainer th,
.nihilo .dijitCalendarDayLabelTemplate {
background: transparent;
}
.nihilo .dijitCalendarDateTemplate {
padding: 5px;
}
.nihilo .dijitCalendarYearContainer {
display: none;
}
\ No newline at end of file
<section id="main" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<input id="toggle-all" type="checkbox" <%= todos.allComplete() ? "checked" : "" %>>
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<% list(todos, function( todo ) { %>
<li class="todo
<%= todo.attr("complete") ? "done" : "" %>
<%= todo.attr("editing") ? "editing" : "" %>"
<%= (el)-> can.data(el, 'todo', todo) %>>
<div class="view">
<input class="toggle" type="checkbox" <%= todo.attr("complete") ? "checked" : "" %>>
<label><%= todo.attr("text") %></label>
<span class="date <%= todo.isLate() ? "late" : "" %>"><%= todo.prettyDate() %></span>
<a class="destroy icon-remove-sign"></a>
<a class="due-date icon-time"></a>
<a class="clear-date icon-ban-circle <%= todo.attr("dueDate") != null ? "show" : "" %>"></a>
</div>
<input class="edit" type="text" value="<%= todo.attr("text") %>">
</li>
<% }) %>
</ul>
</section>
<footer id="stats" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<a id="clear-completed">Clear <%= todos.completed() %>
completed item<%= todos.completed() == 1 ? "" : "s" %></a>
<div id="todo-count"><span><%= todos.remaining() %></span>
item<%= todos.remaining() == 1 ? "" : "s" %> left</div>
</footer>
\ No newline at end of file
require({
packages: [{
name: "can/dojo",
location: "http://donejs.com/can/dist/edge/",
main: "can.dojo"
}]
}, ['can/dojo',
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-attr",
"dojo/dom-geometry",
"dojo/NodeList-manipulate",
"dijit/CalendarLite",
"dijit/place",
"dijit/focus",
"dojo/domReady!"],
function(can, dom, domConstruct, domAttr){
// Calculates the difference between two dates by number of days.
var difference = function(date1, date2) {
date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
return (date1 - date2) / (1000*60*60*24);
};
// Basic Todo entry model
// { text: 'todo', complete: false }
Todo = can.Model({
// Implement local storage handling
localStore: function(cb){
var name = 'todos-canjs-dojo-widget',
data = dojo.fromJson( window.localStorage[name] || (window.localStorage[name] = '[]') ),
res = cb.call(this, data);
if(res !== false){
can.each(data, function(i, todo) {
delete todo.editing;
});
window.localStorage[name] = dojo.toJson(data);
}
},
findAll: function(params){
var def = new dojo.Deferred();
this.localStore(function(todos){
var instances = [],
self = this;
can.each(todos, function(i, todo) {
instances.push(new self(todo));
});
def.resolve({data: instances});
})
return def;
},
destroy: function(id){
var def = new dojo.Deferred();
this.localStore(function(todos){
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todos.splice(i, 1);
break;
}
}
def.resolve({});
});
return def
},
create: function(attrs){
var def = new dojo.Deferred();
this.localStore(function(todos){
attrs.id = attrs.id || parseInt(100000 *Math.random());
todos.push(attrs);
});
def.resolve({id : attrs.id});
return def
},
update: function(id, attrs){
var def = new dojo.Deferred();
this.localStore(function(todos){
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
var todo = todos[i];
break;
}
}
can.extend(todo, attrs);
});
def.resolve({});
return def
}
},{
prettyDate: function(raw){
var raw = this.attr('dueDate');
if (!raw) {
return '';
}
var date = new Date(raw),
diff = difference(new Date(), date);
if(diff === -1) {
return 'Tomorrow';
} else if(diff === 0) {
return 'Today';
} else if(diff === 1) {
return 'Yesterday';
} else {
return (date.getMonth()+1) + '/' + (date.getDate()) + '/' + date.getFullYear();
}
},
isLate: function(raw) {
var raw = this.attr('dueDate');
return !raw ? false : difference(new Date(), new Date(raw)) > 0;
}
});
// List for Todos
Todo.List = can.Model.List({
completed: function() {
// Ensure this triggers on length change
this.attr('length');
var completed = 0;
this.each(function(i, todo) {
completed += todo.attr('complete') ? 1 : 0
});
return completed;
},
remaining: function() {
return this.attr('length') - this.completed();
},
allComplete: function() {
return this.attr('length') === this.completed();
}
});
Todos = can.Control({
// Initialize the Todos list
init : function(){
// Render the Todos
this.element.append(can.view('todo', {
todos: this.options.todos
}));
// Clear the new todo field
dijit.focus(dojo.byId('new-todo'));
// Hide the calendar on page click
var cal = this.options.calendar;
dojo.query(document).on('click', function(ev) {
if (!dojo.hasClass(ev.target, 'due-date') && !dojo.query(ev.target).closest('#calendar').length) {
dojo.query(cal.domNode).style('visibility', 'hidden');
}
})
},
// Listen for when a new Todo has been entered
'#new-todo keyup' : function(el, ev){
if(ev.keyCode == 13){
new Todo({
text : el.val(),
complete : false
}).save(function() {
el.val('');
});
}
},
// Handle a newly created Todo
'{Todo} created' : function(list, ev, item){
this.options.todos.push(item);
},
// Listen for editing a Todo
'.todo dblclick' : function(el) {
can.data(el, 'todo').attr('editing', true).save(function(){
dijit.focus(el.children('.edit')[0].select());
});
},
// Update a todo
updateTodo: function(el) {
can.data(el.closest('.todo'), 'todo')
.attr({
editing: false,
text: el.val()
}).save();
},
// Listen for an edited Todo
'.todo .edit keyup' : function(el, ev){
if(ev.keyCode == 13){
this.updateTodo(el);
}
},
'.todo .edit focusout' : function(el, ev) {
this.updateTodo(el);
},
// Listen for the toggled completion of a Todo
'.todo .toggle click' : function(el, ev) {
can.data(el.closest('.todo'), 'todo')
.attr('complete', el.attr('checked')[0])
.save();
},
// Listen for a removed Todo
'.todo .destroy click' : function(el){
can.data(el.closest('.todo'), 'todo').destroy();
},
// Listen for toggle all completed Todos
'#toggle-all click' : function(el, ev) {
var toggle = el.attr('checked')[0];
can.each(this.options.todos, function(i, todo) {
todo.attr('complete', toggle).save();
});
},
// Listen for removing all completed Todos
'#clear-completed click' : function() {
for (var i = this.options.todos.length - 1, todo; i > -1 && (todo = this.options.todos[i]); i--) {
todo.attr('complete') && todo.destroy();
}
},
// Listen for a change due date request
'.todo .due-date click' : function(el, ev){
ev.preventDefault();
// Cache the todo
var todo = can.data(el.closest('.todo'), 'todo');
// Display the calendar
var cal = this.options.calendar;
dijit.place.at(cal.domNode, {x: 510, y: dojo.position(el[0]).y}, ["TL"]);
cal.set('value', todo.dueDate || "");
this._todo = todo;
dojo.query(cal.domNode).style('visibility', 'visible');
},
// Listen for a clear due date
'.todo .clear-date click' : function(el, e){
can.data(el.closest('.todo'), 'todo').attr('dueDate', null).save();
},
// Date change for Todo
'{calendar} change': function(calendar, date){
// Update the todo if one exists
if (this._todo) {
dojo.query(this.options.calendar.domNode).style('visibility', 'hidden');
this._todo.attr('dueDate', date || null).save();
delete this._todo;
}
}
})
// Initialize the app
Todo.findAll({}, function(todos) {
new Todos('#todoapp', {
todos: todos,
calendar: new dijit.CalendarLite({}, "calendar")
});
});
});
\ No newline at end of file
html,
body {
margin: 0;
padding: 0;
}
body {
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
width: 520px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
}
#todoapp {
background: #fff;
padding: 20px;
margin-bottom: 40px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-ms-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;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#todoapp h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 0 0 10px 0;
}
#todoapp input[type="text"] {
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-ms-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;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#main {
display: none;
}
#todo-list {
margin: 10px 0;
padding: 0;
list-style: none;
}
#todo-list li {
padding: 18px 20px 18px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.done label {
color: #777777;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 20px;
right: 10px;
cursor: pointer;
width: 20px;
height: 20px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAABGdBTUEAALGPC/xhBQAAACdQTFRFzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAA////zMzMhnu0WAAAAAt0Uk5T5u3pqtV3jFQEKAC0bVelAAAAfUlEQVQI12NYtWpFsc8R865VqxhWrZpyBgg8QcylZ8AgCsjMgTCPrWJYfgYKqhjWwJgaDDVnzpw+c2bPmTPHGWzOnNm95/TuM2cOM/AARXfvBooeZAAp270bRCIz4QoOIGtDMqwJZoUEQzvCYrhzuhhWtUKYEahOX7UK6iEA3A6NUGwCTZIAAAAASUVORK5CYII=') no-repeat center center;
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li.editing {
border-bottom: none;
margin-top: -1px;
padding: 0;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#todo-list li.editing .edit {
display: block;
width: 444px;
padding: 13px 15px 14px 20px;
margin: 0;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .view label {
word-break: break-word;
}
#todo-list li .edit {
display: none;
}
#todoapp footer {
display: none;
margin: 0 -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 37px;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#clear-completed {
display: none;
float: right;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
margin-bottom: 8px;
padding: 0 10px 1px;
cursor: pointer;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
-ms-border-radius: 12px;
-o-border-radius: 12px;
border-radius: 12px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-ms-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;
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-ms-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;
}
#clear-completed:active {
position: relative;
top: 1px;
}
#todo-count span {
font-weight: bold;
}
#instructions {
margin: 10px auto;
color: #777777;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#instructions a {
color: #336699;
}
#credits {
margin: 30px auto;
color: #999;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Todo - CanJS with Dojo</title>
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="todo.css">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="todoapp">
<header>
<h1>Todos</h1>
<input id="new-todo" type="text" placeholder="What needs to be done?">
</header>
</div>
<div id="instructions">
Double-click to edit a todo.
</div>
<div id="credits">
<p>Created by <a href="http://bitovi.com/">Bitovi</a>.</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a>.</p>
</div>
<script type='text/javascript' data-dojo-config="async: true" src='http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js.uncompressed.js'></script>
<script src="todo.js"></script>
</body>
</html>
\ No newline at end of file
#main.show,
#stats.show,
#stats.show #clear-completed {
display: block;
}
\ No newline at end of file
<section id="main" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<input id="toggle-all" type="checkbox" <%= todos.allComplete() ? "checked" : "" %>>
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<% list(todos, function( todo ) { %>
<li class="todo
<%= todo.attr("complete") ? "done" : "" %>
<%= todo.attr("editing") ? "editing" : "" %>"
<%= (el)-> can.data(el, 'todo', todo) %>>
<div class="view">
<input class="toggle" type="checkbox" <%= todo.attr("complete") ? "checked" : "" %>>
<label><%= todo.attr("text") %></label>
<a class="destroy"></a>
</div>
<input class="edit" type="text" value="<%= todo.attr("text") %>">
</li>
<% }) %>
</ul>
</section>
<footer id="stats" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<a id="clear-completed">Clear <%= todos.completed() %>
completed item<%= todos.completed() == 1 ? "" : "s" %></a>
<div id="todo-count"><span><%= todos.remaining() %></span>
item<%= todos.remaining() == 1 ? "" : "s" %> left</div>
</footer>
\ No newline at end of file
require({
packages: [{
name: "can/dojo",
location: "http://donejs.com/can/dist/edge/",
main: "can.dojo"
}]
}, ['can/dojo',
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-attr",
"dojo/NodeList-manipulate",
"dijit/focus",
"dojo/domReady!"],
function(can, dom, domConstruct, domAttr){
// Basic Todo entry model
// { text: 'todo', complete: false }
Todo = can.Model({
// Implement local storage handling
localStore: function(cb){
var name = 'todos-canjs-dojo',
data = dojo.fromJson( window.localStorage[name] || (window.localStorage[name] = '[]') ),
res = cb.call(this, data);
if(res !== false){
can.each(data, function(i, todo) {
delete todo.editing;
});
window.localStorage[name] = dojo.toJson(data);
}
},
findAll: function(params){
var def = new dojo.Deferred();
this.localStore(function(todos){
var instances = [],
self = this;
can.each(todos, function(i, todo) {
instances.push(new self(todo));
});
def.resolve({data: instances});
})
return def;
},
destroy: function(id){
var def = new dojo.Deferred();
this.localStore(function(todos){
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todos.splice(i, 1);
break;
}
}
def.resolve({});
});
return def
},
create: function(attrs){
var def = new dojo.Deferred();
this.localStore(function(todos){
attrs.id = attrs.id || parseInt(100000 *Math.random());
todos.push(attrs);
});
def.resolve({id : attrs.id});
return def
},
update: function(id, attrs){
var def = new dojo.Deferred();
this.localStore(function(todos){
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
var todo = todos[i];
break;
}
}
can.extend(todo, attrs);
});
def.resolve({});
return def
}
},{});
// List for Todos
Todo.List = can.Model.List({
completed: function() {
// Ensure this triggers on length change
this.attr('length');
var completed = 0;
this.each(function(i, todo) {
completed += todo.attr('complete') ? 1 : 0
});
return completed;
},
remaining: function() {
return this.attr('length') - this.completed();
},
allComplete: function() {
return this.attr('length') === this.completed();
}
});
Todos = can.Control({
// Initialize the Todos list
init : function(){
// Render the Todos
this.element.append(can.view('todo', {
todos: this.options.todos
}));
// Clear the new todo field
dijit.focus(dojo.byId('new-todo'));
},
// Listen for when a new Todo has been entered
'#new-todo keyup' : function(el, ev){
if(ev.keyCode == 13){
new Todo({
text : el.val(),
complete : false
}).save(function() {
el.val('');
});
}
},
// Handle a newly created Todo
'{Todo} created' : function(list, ev, item){
this.options.todos.push(item);
},
// Listen for editing a Todo
'.todo dblclick' : function(el) {
can.data(el, 'todo').attr('editing', true).save(function(){
dijit.focus(el.children('.edit')[0].select());
});
},
// Update a todo
updateTodo: function(el) {
can.data(el.closest('.todo'), 'todo')
.attr({
editing: false,
text: el.val()
}).save();
},
// Listen for an edited Todo
'.todo .edit keyup' : function(el, ev){
if(ev.keyCode == 13){
this.updateTodo(el);
}
},
'.todo .edit focusout' : function(el, ev) {
this.updateTodo(el);
},
// Listen for the toggled completion of a Todo
'.todo .toggle click' : function(el, ev) {
can.data(el.closest('.todo'), 'todo')
.attr('complete', el.attr('checked')[0])
.save();
},
// Listen for a removed Todo
'.todo .destroy click' : function(el){
can.data(el.closest('.todo'), 'todo').destroy();
},
// Listen for toggle all completed Todos
'#toggle-all click' : function(el, ev) {
var toggle = el.attr('checked')[0];
can.each(this.options.todos, function(i, todo) {
todo.attr('complete', toggle).save();
});
},
// Listen for removing all completed Todos
'#clear-completed click' : function() {
for (var i = this.options.todos.length - 1, todo; i > -1 && (todo = this.options.todos[i]); i--) {
todo.attr('complete') && todo.destroy();
}
}
})
// Initialize the app
Todo.findAll({}, function(todos) {
new Todos('#todoapp', {
todos: todos
});
});
});
\ No newline at end of file
html,
body {
margin: 0;
padding: 0;
}
body {
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
width: 520px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
}
#todoapp {
background: #fff;
padding: 20px;
margin-bottom: 40px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-ms-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;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#todoapp h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 0 0 10px 0;
}
#todoapp input[type="text"] {
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-ms-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;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#main {
display: none;
}
#todo-list {
margin: 10px 0;
padding: 0;
list-style: none;
}
#todo-list li {
padding: 18px 20px 18px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.done label {
color: #777777;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 20px;
right: 10px;
cursor: pointer;
width: 20px;
height: 20px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAABGdBTUEAALGPC/xhBQAAACdQTFRFzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAA////zMzMhnu0WAAAAAt0Uk5T5u3pqtV3jFQEKAC0bVelAAAAfUlEQVQI12NYtWpFsc8R865VqxhWrZpyBgg8QcylZ8AgCsjMgTCPrWJYfgYKqhjWwJgaDDVnzpw+c2bPmTPHGWzOnNm95/TuM2cOM/AARXfvBooeZAAp270bRCIz4QoOIGtDMqwJZoUEQzvCYrhzuhhWtUKYEahOX7UK6iEA3A6NUGwCTZIAAAAASUVORK5CYII=') no-repeat center center;
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li.editing {
border-bottom: none;
margin-top: -1px;
padding: 0;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#todo-list li.editing .edit {
display: block;
width: 444px;
padding: 13px 15px 14px 20px;
margin: 0;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .view label {
word-break: break-word;
}
#todo-list li .edit {
display: none;
}
#todoapp footer {
display: none;
margin: 0 -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 37px;
-webkit-border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-ms-border-radius: 0 0 5px 5px;
-o-border-radius: 0 0 5px 5px;
border-radius: 0 0 5px 5px;
}
#clear-completed {
display: none;
float: right;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
margin-bottom: 8px;
padding: 0 10px 1px;
cursor: pointer;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
-ms-border-radius: 12px;
-o-border-radius: 12px;
border-radius: 12px;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-ms-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;
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-ms-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;
}
#clear-completed:active {
position: relative;
top: 1px;
}
#todo-count span {
font-weight: bold;
}
#instructions {
margin: 10px auto;
color: #777777;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#instructions a {
color: #336699;
}
#credits {
margin: 30px auto;
color: #999;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Todo - CanJS with jQuery/Widget</title>
<link rel="stylesheet" href="font/font-awesome.css">
<link rel="stylesheet" href="themes/base/jquery.ui.all.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="todo.css">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="todoapp">
<header>
<h1>Todos</h1>
<input id="new-todo" type="text" placeholder="What needs to be done?">
</header>
</div>
<div id="instructions">
Double-click to edit a todo.
</div>
<div id="credits">
<p>Created by <a href="http://bitovi.com/">Bitovi</a>.</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a>.</p>
</div>
<div id="calendar"></div>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script src="jquery.ui.core.js"></script>
<script src="jquery.ui.datepicker.js"></script>
<script src="http://donejs.com/can/dist/edge/can.jquery.js"></script>
<script src="todo.js"></script>
</body>
</html>
\ No newline at end of file
/*!
* jQuery UI 1.8.18
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI
*/
(function( $, undefined ) {
// prevent duplicate loading
// this is only a problem because we proxy existing functions
// and we don't want to double proxy them
$.ui = $.ui || {};
if ( $.ui.version ) {
return;
}
$.extend( $.ui, {
version: "1.8.18",
keyCode: {
ALT: 18,
BACKSPACE: 8,
CAPS_LOCK: 20,
COMMA: 188,
COMMAND: 91,
COMMAND_LEFT: 91, // COMMAND
COMMAND_RIGHT: 93,
CONTROL: 17,
DELETE: 46,
DOWN: 40,
END: 35,
ENTER: 13,
ESCAPE: 27,
HOME: 36,
INSERT: 45,
LEFT: 37,
MENU: 93, // COMMAND_RIGHT
NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34,
PAGE_UP: 33,
PERIOD: 190,
RIGHT: 39,
SHIFT: 16,
SPACE: 32,
TAB: 9,
UP: 38,
WINDOWS: 91 // COMMAND
}
});
// plugins
$.fn.extend({
propAttr: $.fn.prop || $.fn.attr,
_focus: $.fn.focus,
focus: function( delay, fn ) {
return typeof delay === "number" ?
this.each(function() {
var elem = this;
setTimeout(function() {
$( elem ).focus();
if ( fn ) {
fn.call( elem );
}
}, delay );
}) :
this._focus.apply( this, arguments );
},
scrollParent: function() {
var scrollParent;
if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
} else {
scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
}
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
},
zIndex: function( zIndex ) {
if ( zIndex !== undefined ) {
return this.css( "zIndex", zIndex );
}
if ( this.length ) {
var elem = $( this[ 0 ] ), position, value;
while ( elem.length && elem[ 0 ] !== document ) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned
position = elem.css( "position" );
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
// IE returns 0 when zIndex is not specified
// other browsers return a string
// we ignore the case of nested elements with an explicit value of 0
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
value = parseInt( elem.css( "zIndex" ), 10 );
if ( !isNaN( value ) && value !== 0 ) {
return value;
}
}
elem = elem.parent();
}
}
return 0;
},
disableSelection: function() {
return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
".ui-disableSelection", function( event ) {
event.preventDefault();
});
},
enableSelection: function() {
return this.unbind( ".ui-disableSelection" );
}
});
$.each( [ "Width", "Height" ], function( i, name ) {
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
type = name.toLowerCase(),
orig = {
innerWidth: $.fn.innerWidth,
innerHeight: $.fn.innerHeight,
outerWidth: $.fn.outerWidth,
outerHeight: $.fn.outerHeight
};
function reduce( elem, size, border, margin ) {
$.each( side, function() {
size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
if ( border ) {
size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
}
if ( margin ) {
size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
}
});
return size;
}
$.fn[ "inner" + name ] = function( size ) {
if ( size === undefined ) {
return orig[ "inner" + name ].call( this );
}
return this.each(function() {
$( this ).css( type, reduce( this, size ) + "px" );
});
};
$.fn[ "outer" + name] = function( size, margin ) {
if ( typeof size !== "number" ) {
return orig[ "outer" + name ].call( this, size );
}
return this.each(function() {
$( this).css( type, reduce( this, size, true, margin ) + "px" );
});
};
});
// selectors
function focusable( element, isTabIndexNotNaN ) {
var nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) {
var map = element.parentNode,
mapName = map.name,
img;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false;
}
img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img );
}
return ( /input|select|textarea|button|object/.test( nodeName )
? !element.disabled
: "a" == nodeName
? element.href || isTabIndexNotNaN
: isTabIndexNotNaN)
// the element and all of its ancestors must be visible
&& visible( element );
}
function visible( element ) {
return !$( element ).parents().andSelf().filter(function() {
return $.curCSS( this, "visibility" ) === "hidden" ||
$.expr.filters.hidden( this );
}).length;
}
$.extend( $.expr[ ":" ], {
data: function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] );
},
focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
},
tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
}
});
// support
$(function() {
var body = document.body,
div = body.appendChild( div = document.createElement( "div" ) );
// access offsetHeight before setting the style to prevent a layout bug
// in IE 9 which causes the elemnt to continue to take up space even
// after it is removed from the DOM (#8026)
div.offsetHeight;
$.extend( div.style, {
minHeight: "100px",
height: "auto",
padding: 0,
borderWidth: 0
});
$.support.minHeight = div.offsetHeight === 100;
$.support.selectstart = "onselectstart" in div;
// set display to none to avoid a layout bug in IE
// http://dev.jquery.com/ticket/4014
body.removeChild( div ).style.display = "none";
});
// deprecated
$.extend( $.ui, {
// $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: {
add: function( module, option, set ) {
var proto = $.ui[ module ].prototype;
for ( var i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || [];
proto.plugins[ i ].push( [ option, set[ i ] ] );
}
},
call: function( instance, name, args ) {
var set = instance.plugins[ name ];
if ( !set || !instance.element[ 0 ].parentNode ) {
return;
}
for ( var i = 0; i < set.length; i++ ) {
if ( instance.options[ set[ i ][ 0 ] ] ) {
set[ i ][ 1 ].apply( instance.element, args );
}
}
}
},
// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
contains: function( a, b ) {
return document.compareDocumentPosition ?
a.compareDocumentPosition( b ) & 16 :
a !== b && a.contains( b );
},
// only used by resizable
hasScroll: function( el, a ) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it
if ( $( el ).css( "overflow" ) === "hidden") {
return false;
}
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
has = false;
if ( el[ scroll ] > 0 ) {
return true;
}
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[ scroll ] = 1;
has = ( el[ scroll ] > 0 );
el[ scroll ] = 0;
return has;
},
// these are odd functions, fix the API or move into individual plugins
isOverAxis: function( x, reference, size ) {
//Determines when x coordinate is over "b" element axis
return ( x > reference ) && ( x < ( reference + size ) );
},
isOver: function( y, x, top, left, height, width ) {
//Determines when x, y coordinates is over "b" element
return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
}
});
})( jQuery );
/*
* jQuery UI CSS Framework 1.8.18
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming
*/
@import "jquery.ui.base.css";
@import "jquery.ui.theme.css";
@import url("jquery.ui.core.css");
@import url("jquery.ui.datepicker.css");
\ No newline at end of file
/*
* jQuery UI CSS Framework 1.8.18
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
This diff is collapsed.
<section id="main" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<input id="toggle-all" type="checkbox" <%= todos.allComplete() ? "checked" : "" %>>
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<% list(todos, function( todo ) { %>
<li class="todo
<%= todo.attr("complete") ? "done" : "" %>
<%= todo.attr("editing") ? "editing" : "" %>"
<%= (el)-> el.data('todo', todo) %>>
<div class="view">
<input class="toggle" type="checkbox" <%= todo.attr("complete") ? "checked" : "" %>>
<label><%= todo.attr("text") %></label>
<span class="date <%= todo.isLate() ? "late" : "" %>"><%= todo.prettyDate() %></span>
<a class="destroy icon-remove-sign"></a>
<a class="due-date icon-time"></a>
<a class="clear-date icon-ban-circle <%= todo.attr("dueDate") != null ? "show" : "" %>"></a>
</div>
<input class="edit" type="text" value="<%= todo.attr("text") %>">
</li>
<% }) %>
</ul>
</section>
<footer id="stats" class="<%= todos.attr("length") > 0 ? "show" : "" %>">
<a id="clear-completed">Clear <%= todos.completed() %>
completed item<%= todos.completed() == 1 ? "" : "s" %></a>
<div id="todo-count"><span><%= todos.remaining() %></span>
item<%= todos.remaining() == 1 ? "" : "s" %> left</div>
</footer>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#main.show,
#stats.show,
#stats.show #clear-completed {
display: block;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#main.show,
#stats.show,
#stats.show #clear-completed {
display: block;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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