Commit e904feb4 authored by MStumpp's avatar MStumpp Committed by Sindre Sorhus

Update Meteor app to Meteor 0.3.8. Closes #225

Replace it with vanilla JS instead of CoffeScript
parent 45e277d8
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Meteor • TodoMVC</title>
</head>
<body>
<section id="todoapp">
{{> todoapp}}
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="https://github.com/MStumpp">Matthias Stumpp</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</body>
<template name="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
{{#if todos}}
{{> main}}
{{> footer}}
{{/if}}
</template>
<template name="main">
<section id="main">
<input id="toggle-all" type="checkbox" {{#unless todos_not_completed}}checked="checked"{{/unless}}>
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
{{#each todos}}
{{> todo}}
{{/each}}
</ul>
</section>
</template>
<template name="todo">
<li class="{{#if todo_completed}}completed{{/if}}{{#if todo_editing}}editing{{/if}}">
<div class="view">
<input class="toggle" type="checkbox" {{#if todo_completed}}checked="checked"{{/if}}>
<label>{{title}}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="{{title}}">
</li>
</template>
<template name="footer">
<footer id="footer">
<span id="todo-count"><strong>{{todos_not_completed}}</strong>
{{#if todos_one_not_completed}}item{{else}}items{{/if}} left</span>
<ul id="filters">
{{#each filters}}
<li>
<a class="{{#if filter_selected this}} selected {{/if}}" href="#/{{this}}">{{this}}</a>
</li>
{{/each}}
</ul>
{{#if todos_completed}}
<button id="clear-completed">Clear completed ({{todos_completed}})</button>
{{/if}}
</footer>
</template>
\ No newline at end of file
// Collection to keep the todos
Todos = new Meteor.Collection('todos');
// JS code for the client (browser)
if (Meteor.is_client) {
// Session var to keep current filter type ("all", "active", "completed")
Session.set('filter', 'all');
// Session var to keep todo which is currently in editing mode, if any
Session.set('editing_todo', null);
// Set up filter types and their mongo db selectors
var filter_selections = {
all: {},
active: {completed: false},
completed: {completed: true}
};
// Get selector types as array
var filters = _.keys(filter_selections);
// Bind route handlers to filter types
var routes = {};
_.each(filters, function(filter) {
routes['/'+filter] = function() {
Session.set('filter', filter);
};
});
// Initialize router with routes
var router = Router(routes);
router.init();
/////////////////////////////////////////////////////////////////////////
// The following two functions are taken from the official Meteor
// "Todos" example
// The original code can be viewed at: https://github.com/meteor/meteor
/////////////////////////////////////////////////////////////////////////
// Returns an event_map key for attaching "ok/cancel" events to
// a text input (given by selector)
var okcancel_events = function (selector) {
return 'keyup '+selector+', keydown '+selector+', focusout '+selector;
};
// Creates an event handler for interpreting "escape", "return", and "blur"
// on a text field and calling "ok" or "cancel" callbacks.
var make_okcancel_handler = function (options) {
var ok = options.ok || function () {};
var cancel = options.cancel || function () {};
return function (evt) {
if (evt.type === 'keydown' && evt.which === 27) {
// escape = cancel
cancel.call(this, evt);
} else if (evt.type === 'keyup' && evt.which === 13 ||
evt.type === 'focusout') {
// blur/return/enter = ok/submit if non-empty
var value = String(evt.target.value || '');
if (value) {
ok.call(this, value, evt);
} else {
cancel.call(this, evt);
}
}
};
};
// Some helpers
// Get the number of todos completed
var todos_completed_helper = function() {
return Todos.find({completed: true}).count();
};
// Get the number of todos not completed
var todos_not_completed_helper = function() {
return Todos.find({completed: false}).count();
};
////
// Logic for the 'todoapp' partial which represents the whole app
////
// Helper to get the number of todos
Template.todoapp.todos = function() {
return Todos.find().count();
};
Template.todoapp.events = {};
// Register key events for adding new todo
Template.todoapp.events[okcancel_events('#new-todo')] =
make_okcancel_handler({
ok: function (title, evt) {
Todos.insert({title: $.trim(title), completed: false,
created_at: new Date().getTime()});
evt.target.value = '';
}
});
////
// Logic for the 'main' partial which wraps the actual todo list
////
// Get the todos considering the current filter type
Template.main.todos = function() {
return Todos.find(filter_selections[Session.get('filter')], {sort: {created_at: 1}});
};
Template.main.todos_not_completed = todos_not_completed_helper;
// Register click event for toggling complete/not complete button
Template.main.events = {
'click input#toggle-all': function(evt) {
var completed = true;
if (!Todos.find({completed: false}).count()) {
completed = false;
}
Todos.find({}).forEach(function(todo) {
Todos.update({'_id': todo._id}, {$set: {completed: completed}});
});
}
};
////
// Logic for the 'todo' partial representing a todo
////
// True of current todo is completed, false otherwise
Template.todo.todo_completed = function() {
return this.completed;
};
// Get the current todo which is in editing mode, if any
Template.todo.todo_editing = function() {
return Session.equals('editing_todo', this._id);
};
// Register events for toggling todo's state, editing mode and destroying a todo
Template.todo.events = {
'click input.toggle': function() {
Todos.update(this._id, {$set: {completed: !this.completed}});
},
'dblclick label': function() {
Session.set('editing_todo', this._id);
},
'click button.destroy': function() {
Todos.remove(this._id);
}
};
// Register key events for updating title of an existing todo
Template.todo.events[okcancel_events('li.editing input.edit')] =
make_okcancel_handler({
ok: function (value) {
Session.set('editing_todo', null);
Todos.update(this._id, {$set: {title: $.trim(value)}});
},
cancel: function () {
Session.set('editing_todo', null);
Todos.remove(this._id);
}
});
////
// Logic for the 'footer' partial
////
Template.footer.todos_completed = todos_completed_helper;
Template.footer.todos_not_completed = todos_not_completed_helper;
// True if exactly one todo is not completed, false otherwise
// Used for handling pluralization of "item"/"items" word
Template.footer.todos_one_not_completed = function() {
return Todos.find({completed: false}).count() == 1;
};
// Prepare array with keys of filter_selections only
Template.footer.filters = filters;
// True if the requested filter type is currently selected,
// false otherwise
Template.footer.filter_selected = function(type) {
return Session.equals('filter', type);
};
// Register click events for clearing completed todos
Template.footer.events = {
'click button#clear-completed': function() {
Todos.remove({completed: true});
}
};
};
\ No newline at end of file
/* base.css overrides */
#filters li a {
text-transform:capitalize;
}
......@@ -23,7 +23,7 @@ button {
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eeeeee url('bg.png');
background: #eaeaea url('./client/images/bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
......@@ -57,6 +57,15 @@ body {
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;
......@@ -79,7 +88,7 @@ body {
border-radius: inherit;
}
#todoapp header:before {
#header:before {
content: '';
position: absolute;
top: 0;
......@@ -96,20 +105,13 @@ body {
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-radius: inherit;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
......@@ -137,7 +139,6 @@ body {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
position: relative;
z-index: 2;
box-shadow: none;
}
......@@ -154,9 +155,12 @@ label[for='toggle-all'] {
#toggle-all {
position: absolute;
top: -42px;
left: 12px;
top: -56px;
left: -15px;
width: 65px;
height: 41px;
text-align: center;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
......@@ -180,15 +184,6 @@ label[for='toggle-all'] {
color: #737373;
}
/* Need this ugly hack, since only
WebKit supports styling of inputs */
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all {
top: -52px;
left: -11px;
}
}
#todo-list {
margin: 0;
padding: 0;
......@@ -223,7 +218,13 @@ WebKit supports styling of inputs */
#todo-list li .toggle {
text-align: center;
width: 35px;
width: 40px;
height: 40px;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
......@@ -234,7 +235,7 @@ WebKit supports styling of inputs */
#todo-list li .toggle:after {
font-size: 18px;
content: '✔';
line-height: 40px;
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
......@@ -249,8 +250,10 @@ WebKit supports styling of inputs */
#todo-list li label {
word-break: break-word;
margin: 20px 15px;
display: inline-block;
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;
......@@ -266,10 +269,12 @@ WebKit supports styling of inputs */
#todo-list li .destroy {
display: none;
position: absolute;
top: 10px;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
......@@ -312,6 +317,7 @@ WebKit supports styling of inputs */
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
......@@ -322,13 +328,13 @@ WebKit supports styling of inputs */
right: 0;
bottom: 31px;
left: 0;
height: 100px;
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 42px 0 -6px rgba(255, 255, 255, 0.8),
0 43px 2px -6px rgba(0, 0, 0, 0.2);
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
......@@ -361,12 +367,12 @@ WebKit supports styling of inputs */
#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;
position: relative;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
......@@ -387,3 +393,14 @@ WebKit supports styling of inputs */
#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;
}
}
\ No newline at end of file
(function( window ) {
'use strict';
if ( location.hostname === 'todomvc.com' ) {
var _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'));
}
})( window );
\ No newline at end of file
//
// Generated on Thu Jul 26 2012 15:11:39 GMT-0400 (EDT) by Nodejitsu, Inc (Using Codesurgeon).
// Version 1.1.3
//
(function(a){function i(a,b){~a.indexOf("*")&&(a=a.replace(/\*/g,"([_.()!\\ %@&a-zA-Z0-9-]+)"));var c=a.match(/:([^\/]+)/ig),d;if(c){d=c.length;for(var e=0;e<d;e++)a=a.replace(c[e],h(c[e],b))}return a}function h(a,b,c){c=a;for(var d in b)if(b.hasOwnProperty(d)){c=b[d](a);if(c!==a)break}return c===a?"([._a-zA-Z0-9-]+)":c}function g(a,b,c){if(!a.length)return c();var d=0;(function e(){b(a[d],function(b){b||b===!1?(c(b),c=function(){}):(d+=1,d===a.length?c():e())})})()}function f(a){var b=[];for(var c=0,d=a.length;c<d;c++)b=b.concat(a[c]);return b}function e(a,b){for(var c=0;c<a.length;c+=1)if(b(a[c],c,a)===!1)return}Array.prototype.filter||(Array.prototype.filter=function(a,b){var c=[],d;for(var e=0,f=this.length;e<f;e++)e in this&&a.call(b,d=this[e],e,this)&&c.push(d);return c}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"});var b=document.location,c={mode:"modern",hash:b.hash,history:!1,check:function(){var a=b.hash;a!=this.hash&&(this.hash=a,this.onHashChanged())},fire:function(){this.mode==="modern"?this.history===!0?window.onpopstate():window.onhashchange():this.onHashChanged()},init:function(a,b){function d(a){for(var b=0,c=window.Router.listeners.length;b<c;b++)window.Router.listeners[b](a)}var c=this;this.history=b,window.Router.listeners||(window.Router.listeners=[]);if("onhashchange"in window&&(document.documentMode===undefined||document.documentMode>7))this.history===!0?setTimeout(function(){window.onpopstate=d},500):window.onhashchange=d,this.mode="modern";else{var e=document.createElement("iframe");e.id="state-frame",e.style.display="none",document.body.appendChild(e),this.writeFrame(""),"onpropertychange"in document&&"attachEvent"in document&&document.attachEvent("onpropertychange",function(){event.propertyName==="location"&&c.check()}),window.setInterval(function(){c.check()},50),this.onHashChanged=d,this.mode="legacy"}window.Router.listeners.push(a);return this.mode},destroy:function(a){if(!!window.Router&&!!window.Router.listeners){var b=window.Router.listeners;for(var c=b.length-1;c>=0;c--)b[c]===a&&b.splice(c,1)}},setHash:function(a){this.mode==="legacy"&&this.writeFrame(a),this.history===!0?(window.history.pushState({},document.title,a),this.fire()):b.hash=a[0]==="/"?a:"/"+a;return this},writeFrame:function(a){var b=document.getElementById("state-frame"),c=b.contentDocument||b.contentWindow.document;c.open(),c.write("<script>_hash = '"+a+"'; onload = parent.listener.syncHash;<script>"),c.close()},syncHash:function(){var a=this._hash;a!=b.hash&&(b.hash=a);return this},onHashChanged:function(){}},d=a.Router=function(a){if(this instanceof d)this.params={},this.routes={},this.methods=["on","once","after","before"],this._methods={},this._insert=this.insert,this.insert=this.insertEx,this.historySupport=(window.history!=null?window.history.pushState:null)!=null,this.configure(),this.mount(a||{});else return new d(a)};d.prototype.init=function(a){var d=this;this.handler=function(a){var b=d.history===!0?d.getPath():a.newURL.replace(/.*#/,"");d.dispatch("on",b)},c.init(this.handler,this.history),this.history===!1?b.hash===""&&a?b.hash=a:b.hash.length>0&&d.dispatch("on",b.hash.replace(/^#/,"")):(routeTo=b.hash===""&&a?a:b.hash.length>0?b.hash.replace(/^#/,""):null,routeTo&&window.history.replaceState({},document.title,routeTo),(routeTo||this.run_in_init===!0)&&this.handler());return this},d.prototype.explode=function(){var a=this.history===!0?this.getPath():b.hash;a[1]==="/"&&(a=a.slice(1));return a.slice(1,a.length).split("/")},d.prototype.setRoute=function(a,b,d){var e=this.explode();typeof a=="number"&&typeof b=="string"?e[a]=b:typeof d=="string"?e.splice(a,b,s):e=[a],c.setHash(e.join("/"));return e},d.prototype.insertEx=function(a,b,c,d){a==="once"&&(a="on",c=function(a){var b=!1;return function(){if(!b){b=!0;return a.apply(this,arguments)}}}(c));return this._insert(a,b,c,d)},d.prototype.getRoute=function(a){var b=a;if(typeof a=="number")b=this.explode()[a];else if(typeof a=="string"){var c=this.explode();b=c.indexOf(a)}else b=this.explode();return b},d.prototype.destroy=function(){c.destroy(this.handler);return this},d.prototype.getPath=function(){var a=window.location.pathname;a.substr(0,1)!=="/"&&(a="/"+a);return a},d.prototype.configure=function(a){a=a||{};for(var b=0;b<this.methods.length;b++)this._methods[this.methods[b]]=!0;this.recurse=a.recurse||this.recurse||!1,this.async=a.async||!1,this.delimiter=a.delimiter||"/",this.strict=typeof a.strict=="undefined"?!0:a.strict,this.notfound=a.notfound,this.resource=a.resource,this.history=a.html5history&&this.historySupport||!1,this.run_in_init=this.history===!0&&a.run_handler_in_init!==!1,this.every={after:a.after||null,before:a.before||null,on:a.on||null};return this},d.prototype.param=function(a,b){a[0]!==":"&&(a=":"+a);var c=new RegExp(a,"g");this.params[a]=function(a){return a.replace(c,b.source||b)}},d.prototype.on=d.prototype.route=function(a,b,c){var d=this;!c&&typeof b=="function"&&(c=b,b=a,a="on");if(Array.isArray(b))return b.forEach(function(b){d.on(a,b,c)});b.source&&(b=b.source.replace(/\\\//ig,"/"));if(Array.isArray(a))return a.forEach(function(a){d.on(a.toLowerCase(),b,c)});this.insert(a,this.scope.concat(b.split(new RegExp(this.delimiter))),c)},d.prototype.dispatch=function(a,b,c){function h(){d.last=e.after,d.invoke(d.runlist(e),d,c)}var d=this,e=this.traverse(a,b,this.routes,""),f=this._invoked,g;this._invoked=!0;if(!e||e.length===0){this.last=[],typeof this.notfound=="function"&&this.invoke([this.notfound],{method:a,path:b},c);return!1}this.recurse==="forward"&&(e=e.reverse()),g=this.every&&this.every.after?[this.every.after].concat(this.last):[this.last];if(g&&g.length>0&&f){this.async?this.invoke(g,this,h):(this.invoke(g,this),h());return!0}h();return!0},d.prototype.invoke=function(a,b,c){var d=this;this.async?g(a,function f(c,d){if(Array.isArray(c))return g(c,f,d);typeof c=="function"&&c.apply(b,a.captures.concat(d))},function(){c&&c.apply(b,arguments)}):e(a,function h(c){if(Array.isArray(c))return e(c,h);if(typeof c=="function")return c.apply(b,a.captures||null);typeof c=="string"&&d.resource&&d.resource[c].apply(b,a.captures||null)})},d.prototype.traverse=function(a,b,c,d,e){function l(a){function c(a){for(var b=a.length-1;b>=0;b--)Array.isArray(a[b])?(c(a[b]),a[b].length===0&&a.splice(b,1)):e(a[b])||a.splice(b,1)}function b(a){var c=[];for(var d=0;d<a.length;d++)c[d]=Array.isArray(a[d])?b(a[d]):a[d];return c}if(!e)return a;var d=b(a);d.matched=a.matched,d.captures=a.captures,d.after=a.after.filter(e),c(d);return d}var f=[],g,h,i,j,k;if(b===this.delimiter&&c[a]){j=[[c.before,c[a]].filter(Boolean)],j.after=[c.after].filter(Boolean),j.matched=!0,j.captures=[];return l(j)}for(var m in c)if(c.hasOwnProperty(m)&&(!this._methods[m]||this._methods[m]&&typeof c[m]=="object"&&!Array.isArray(c[m]))){g=h=d+this.delimiter+m,this.strict||(h+="["+this.delimiter+"]?"),i=b.match(new RegExp("^"+h));if(!i)continue;if(i[0]&&i[0]==b&&c[m][a]){j=[[c[m].before,c[m][a]].filter(Boolean)],j.after=[c[m].after].filter(Boolean),j.matched=!0,j.captures=i.slice(1),this.recurse&&c===this.routes&&(j.push([c.before,c.on].filter(Boolean)),j.after=j.after.concat([c.after].filter(Boolean)));return l(j)}j=this.traverse(a,b,c[m],g);if(j.matched){j.length>0&&(f=f.concat(j)),this.recurse&&(f.push([c[m].before,c[m].on].filter(Boolean)),j.after=j.after.concat([c[m].after].filter(Boolean)),c===this.routes&&(f.push([c.before,c.on].filter(Boolean)),j.after=j.after.concat([c.after].filter(Boolean)))),f.matched=!0,f.captures=j.captures,f.after=j.after;return l(f)}}return!1},d.prototype.insert=function(a,b,c,d){var e,f,g,h,j;b=b.filter(function(a){return a&&a.length>0}),d=d||this.routes,j=b.shift(),/\:|\*/.test(j)&&!/\\d|\\w/.test(j)&&(j=i(j,this.params));if(b.length>0){d[j]=d[j]||{};return this.insert(a,b,c,d[j])}{if(!!j||!!b.length||d!==this.routes){f=typeof d[j],g=Array.isArray(d[j]);if(d[j]&&!g&&f=="object"){e=typeof d[j][a];switch(e){case"function":d[j][a]=[d[j][a],c];return;case"object":d[j][a].push(c);return;case"undefined":d[j][a]=c;return}}else if(f=="undefined"){h={},h[a]=c,d[j]=h;return}throw new Error("Invalid route context: "+f)}e=typeof d[a];switch(e){case"function":d[a]=[d[a],c];return;case"object":d[a].push(c);return;case"undefined":d[a]=c;return}}},d.prototype.extend=function(a){function e(a){b._methods[a]=!0,b[a]=function(){var c=arguments.length===1?[a,""]:[a];b.on.apply(b,c.concat(Array.prototype.slice.call(arguments)))}}var b=this,c=a.length,d;for(d=0;d<c;d++)e(a[d])},d.prototype.runlist=function(a){var b=this.every&&this.every.before?[this.every.before].concat(f(a)):f(a);this.every&&this.every.on&&b.push(this.every.on),b.captures=a.captures,b.source=a.source;return b},d.prototype.mount=function(a,b){function d(b,d){var e=b,f=b.split(c.delimiter),g=typeof a[b],h=f[0]===""||!c._methods[f[0]],i=h?"on":e;h&&(e=e.slice((e.match(new RegExp(c.delimiter))||[""])[0].length),f.shift());h&&g==="object"&&!Array.isArray(a[b])?(d=d.concat(f),c.mount(a[b],d)):(h&&(d=d.concat(e.split(c.delimiter))),c.insert(i,d,a[b]))}if(!!a&&typeof a=="object"&&!Array.isArray(a)){var c=this;b=b||[],Array.isArray(b)||(b=b.split(c.delimiter));for(var e in a)a.hasOwnProperty(e)&&d(e,b.slice(0))}}})(typeof process!="undefined"&&process.title?module:window)
\ No newline at end of file
/*! HTML5 Shiv pre3.5 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
Uncompressed source: https://github.com/aFarkas/html5shiv */
(function(a,b){function h(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function i(){var a=l.elements;return typeof a=="string"?a.split(" "):a}function j(a){var b={},c=a.createElement,f=a.createDocumentFragment,g=f();a.createElement=function(a){l.shivMethods||c(a);var f;return b[a]?f=b[a].cloneNode():e.test(a)?f=(b[a]=c(a)).cloneNode():f=c(a),f.canHaveChildren&&!d.test(a)?g.appendChild(f):f},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+i().join().replace(/\w+/g,function(a){return b[a]=c(a),g.createElement(a),'c("'+a+'")'})+");return n}")(l,g)}function k(a){var b;return a.documentShived?a:(l.shivCSS&&!f&&(b=!!h(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),g||(b=!j(a)),b&&(a.documentShived=b),a)}function p(a){var b,c=a.getElementsByTagName("*"),d=c.length,e=RegExp("^(?:"+i().join("|")+")$","i"),f=[];while(d--)b=c[d],e.test(b.nodeName)&&f.push(b.applyElement(q(b)));return f}function q(a){var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(n+":"+a.nodeName);while(d--)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function r(a){var b,c=a.split("{"),d=c.length,e=RegExp("(^|[\\s,>+~])("+i().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),f="$1"+n+"\\:$2";while(d--)b=c[d]=c[d].split("}"),b[b.length-1]=b[b.length-1].replace(e,f),c[d]=b.join("}");return c.join("{")}function s(a){var b=a.length;while(b--)a[b].removeNode()}function t(a){var b,c,d=a.namespaces,e=a.parentWindow;return!o||a.printShived?a:(typeof d[n]=="undefined"&&d.add(n),e.attachEvent("onbeforeprint",function(){var d,e,f,g=a.styleSheets,i=[],j=g.length,k=Array(j);while(j--)k[j]=g[j];while(f=k.pop())if(!f.disabled&&m.test(f.media)){for(d=f.imports,j=0,e=d.length;j<e;j++)k.push(d[j]);try{i.push(f.cssText)}catch(l){}}i=r(i.reverse().join("")),c=p(a),b=h(a,i)}),e.attachEvent("onafterprint",function(){s(c),b.removeNode(!0)}),a.printShived=!0,a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea|object|iframe)$/i,e=/^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i,f,g;(function(){var c=b.createElement("a");c.innerHTML="<xyz></xyz>",f="hidden"in c,f&&typeof injectElementWithStyles=="function"&&injectElementWithStyles("#modernizr{}",function(b){b.hidden=!0,f=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).display=="none"}),g=c.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var l={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:k};a.html5=l,k(b);var m=/^$|\b(?:all|print)\b/,n="html5shiv",o=!g&&function(){var c=b.documentElement;return typeof b.namespaces!="undefined"&&typeof b.parentWindow!="undefined"&&typeof c.applyElement!="undefined"&&typeof c.removeNode!="undefined"&&typeof a.attachEvent!="undefined"}();l.type+=" print",l.shivPrint=t,t(b)})(this,document);
/*! Copyright (c) 2009, 280 North Inc. http://280north.com/ MIT License. */
(function(n){"function"==typeof define?define(n):n()})(function(){function n(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(d){}}if(!Function.prototype.bind)Function.prototype.bind=function(a){var d=this;if("function"!=typeof d)throw new TypeError;var b=p.call(arguments,1),c=function(){if(this instanceof c){var e=function(){};e.prototype=d.prototype;var e=new e,g=d.apply(e,b.concat(p.call(arguments)));return null!==g&&Object(g)===g?g:e}return d.apply(a,b.concat(p.call(arguments)))};
return c};var l=Function.prototype.call,f=Object.prototype,p=Array.prototype.slice,m=l.bind(f.toString),h=l.bind(f.hasOwnProperty),t,u,q,r,o;if(o=h(f,"__defineGetter__"))t=l.bind(f.__defineGetter__),u=l.bind(f.__defineSetter__),q=l.bind(f.__lookupGetter__),r=l.bind(f.__lookupSetter__);if(!Array.isArray)Array.isArray=function(a){return"[object Array]"==m(a)};if(!Array.prototype.forEach)Array.prototype.forEach=function(a,d){var b=i(this),c=0,e=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;
for(;c<e;)c in b&&a.call(d,b[c],c,b),c++};if(!Array.prototype.map)Array.prototype.map=function(a,d){var b=i(this),c=b.length>>>0,e=Array(c);if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g<c;g++)g in b&&(e[g]=a.call(d,b[g],g,b));return e};if(!Array.prototype.filter)Array.prototype.filter=function(a,d){var b=i(this),c=b.length>>>0,e=[];if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g<c;g++)g in b&&a.call(d,b[g],g,b)&&e.push(b[g]);return e};if(!Array.prototype.every)Array.prototype.every=
function(a,d){var b=i(this),c=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e<c;e++)if(e in b&&!a.call(d,b[e],e,b))return!1;return!0};if(!Array.prototype.some)Array.prototype.some=function(a,d){var b=i(this),c=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1};if(!Array.prototype.reduce)Array.prototype.reduce=function(a){var d=i(this),b=d.length>>>0;if("[object Function]"!=m(a))throw new TypeError;
if(!b&&1==arguments.length)throw new TypeError;var c=0,e;if(2<=arguments.length)e=arguments[1];else{do{if(c in d){e=d[c++];break}if(++c>=b)throw new TypeError;}while(1)}for(;c<b;c++)c in d&&(e=a.call(void 0,e,d[c],c,d));return e};if(!Array.prototype.reduceRight)Array.prototype.reduceRight=function(a){var d=i(this),b=d.length>>>0;if("[object Function]"!=m(a))throw new TypeError;if(!b&&1==arguments.length)throw new TypeError;var c,b=b-1;if(2<=arguments.length)c=arguments[1];else{do{if(b in d){c=d[b--];
break}if(0>--b)throw new TypeError;}while(1)}do b in this&&(c=a.call(void 0,c,d[b],b,d));while(b--);return c};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(a){var d=i(this),b=d.length>>>0;if(!b)return-1;var c=0;1<arguments.length&&(c=v(arguments[1]));for(c=0<=c?c:Math.max(0,b+c);c<b;c++)if(c in d&&d[c]===a)return c;return-1};if(!Array.prototype.lastIndexOf)Array.prototype.lastIndexOf=function(a){var d=i(this),b=d.length>>>0;if(!b)return-1;var c=b-1;1<arguments.length&&(c=Math.min(c,
v(arguments[1])));for(c=0<=c?c:b-Math.abs(c);0<=c;c--)if(c in d&&a===d[c])return c;return-1};if(!Object.getPrototypeOf)Object.getPrototypeOf=function(a){return a.__proto__||(a.constructor?a.constructor.prototype:f)};if(!Object.getOwnPropertyDescriptor)Object.getOwnPropertyDescriptor=function(a,d){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.getOwnPropertyDescriptor called on a non-object: "+a);if(h(a,d)){var b,c,e;b={enumerable:!0,configurable:!0};if(o){var g=
a.__proto__;a.__proto__=f;c=q(a,d);e=r(a,d);a.__proto__=g;if(c||e){if(c)b.get=c;if(e)b.set=e;return b}}b.value=a[d];return b}};if(!Object.getOwnPropertyNames)Object.getOwnPropertyNames=function(a){return Object.keys(a)};if(!Object.create)Object.create=function(a,d){var b;if(null===a)b={__proto__:null};else{if("object"!=typeof a)throw new TypeError("typeof prototype["+typeof a+"] != 'object'");b=function(){};b.prototype=a;b=new b;b.__proto__=a}void 0!==d&&Object.defineProperties(b,d);return b};if(Object.defineProperty){var l=
n({}),y="undefined"==typeof document||n(document.createElement("div"));if(!l||!y)var s=Object.defineProperty}if(!Object.defineProperty||s)Object.defineProperty=function(a,d,b){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.defineProperty called on non-object: "+a);if("object"!=typeof b&&"function"!=typeof b||null===b)throw new TypeError("Property description must be an object: "+b);if(s)try{return s.call(Object,a,d,b)}catch(c){}if(h(b,"value"))if(o&&(q(a,d)||r(a,
d))){var e=a.__proto__;a.__proto__=f;delete a[d];a[d]=b.value;a.__proto__=e}else a[d]=b.value;else{if(!o)throw new TypeError("getters & setters can not be defined on this javascript engine");h(b,"get")&&t(a,d,b.get);h(b,"set")&&u(a,d,b.set)}return a};if(!Object.defineProperties)Object.defineProperties=function(a,d){for(var b in d)h(d,b)&&Object.defineProperty(a,b,d[b]);return a};if(!Object.seal)Object.seal=function(a){return a};if(!Object.freeze)Object.freeze=function(a){return a};try{Object.freeze(function(){})}catch(D){Object.freeze=
function(a){return function(d){return"function"==typeof d?d:a(d)}}(Object.freeze)}if(!Object.preventExtensions)Object.preventExtensions=function(a){return a};if(!Object.isSealed)Object.isSealed=function(){return!1};if(!Object.isFrozen)Object.isFrozen=function(){return!1};if(!Object.isExtensible)Object.isExtensible=function(a){if(Object(a)!==a)throw new TypeError;for(var d="";h(a,d);)d+="?";a[d]=!0;var b=h(a,d);delete a[d];return b};if(!Object.keys){var w=!0,x="toString,toLocaleString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,constructor".split(","),
z=x.length,j;for(j in{toString:null})w=!1;Object.keys=function(a){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.keys called on a non-object");var d=[],b;for(b in a)h(a,b)&&d.push(b);if(w)for(b=0;b<z;b++){var c=x[b];h(a,c)&&d.push(c)}return d}}if(!Date.prototype.toISOString||-1===(new Date(-621987552E5)).toISOString().indexOf("-000001"))Date.prototype.toISOString=function(){var a,d,b,c;if(!isFinite(this))throw new RangeError;a=[this.getUTCMonth()+1,this.getUTCDate(),
this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];c=this.getUTCFullYear();c=(0>c?"-":9999<c?"+":"")+("00000"+Math.abs(c)).slice(0<=c&&9999>=c?-4:-6);for(d=a.length;d--;)b=a[d],10>b&&(a[d]="0"+b);return c+"-"+a.slice(0,2).join("-")+"T"+a.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};if(!Date.now)Date.now=function(){return(new Date).getTime()};if(!Date.prototype.toJSON)Date.prototype.toJSON=function(){if("function"!=typeof this.toISOString)throw new TypeError;return this.toISOString()};
if(!Date.parse||864E13!==Date.parse("+275760-09-13T00:00:00.000Z"))Date=function(a){var d=function g(b,d,c,f,h,i,j){var k=arguments.length;return this instanceof a?(k=1==k&&""+b===b?new a(g.parse(b)):7<=k?new a(b,d,c,f,h,i,j):6<=k?new a(b,d,c,f,h,i):5<=k?new a(b,d,c,f,h):4<=k?new a(b,d,c,f):3<=k?new a(b,d,c):2<=k?new a(b,d):1<=k?new a(b):new a,k.constructor=g,k):a.apply(this,arguments)},b=RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"),
c;for(c in a)d[c]=a[c];d.now=a.now;d.UTC=a.UTC;d.prototype=a.prototype;d.prototype.constructor=d;d.parse=function(d){var c=b.exec(d);if(c){c.shift();for(var f=1;7>f;f++)c[f]=+(c[f]||(3>f?1:0)),1==f&&c[f]--;var h=+c.pop(),i=+c.pop(),j=c.pop(),f=0;if(j){if(23<i||59<h)return NaN;f=6E4*(60*i+h)*("+"==j?-1:1)}h=+c[0];return 0<=h&&99>=h?(c[0]=h+400,a.UTC.apply(this,c)+f-126227808E5):a.UTC.apply(this,c)+f}return a.parse.apply(this,arguments)};return d}(Date);j="\t\n\u000b\u000c\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff";
if(!String.prototype.trim||j.trim()){j="["+j+"]";var A=RegExp("^"+j+j+"*"),B=RegExp(j+j+"*$");String.prototype.trim=function(){return(""+this).replace(A,"").replace(B,"")}}var v=function(a){a=+a;a!==a?a=0:0!==a&&a!==1/0&&a!==-(1/0)&&(a=(0<a||-1)*Math.floor(Math.abs(a)));return a},C="a"!="a"[0],i=function(a){if(null==a)throw new TypeError;return C&&"string"==typeof a&&a?a.split(""):Object(a)}});
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(j){var a="classList",f="prototype",m=(j.HTMLElement||j.Element)[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p<o;p++){if(p in this&&this[p]===q){return p}}return -1},n=function(o,p){this.name=o;this.code=DOMException[o];this.message=p},g=function(p,o){if(o===""){throw new n("SYNTAX_ERR","An invalid or illegal string was specified")}if(/\s/.test(o)){throw new n("INVALID_CHARACTER_ERR","String contains an invalid character")}return c.call(p,o)},d=function(s){var r=k.call(s.className),q=r?r.split(/\s+/):[],p=0,o=q.length;for(;p<o;p++){this.push(q[p])}this._updateClassName=function(){s.className=this.toString()}},e=d[f]=[],i=function(){return new d(this)};n[f]=Error[f];e.item=function(o){return this[o]||null};e.contains=function(o){o+="";return g(this,o)!==-1};e.add=function(o){o+="";if(g(this,o)===-1){this.push(o);this._updateClassName()}};e.remove=function(p){p+="";var o=g(this,p);if(o!==-1){this.splice(o,1);this._updateClassName()}};e.toggle=function(o){o+="";if(g(this,o)===-1){this.add(o)}else{this.remove(o)}};e.toString=function(){return this.join(" ")};if(b.defineProperty){var l={get:i,enumerable:true,configurable:true};try{b.defineProperty(m,a,l)}catch(h){if(h.number===-2146823252){l.enumerable=false;b.defineProperty(m,a,l)}}}else{if(b[f].__defineGetter__){m.__defineGetter__(a,i)}}}(self))};
/*! outerHTML - https://gist.github.com/1044128 */
"undefined"!==typeof document&&!("outerHTML"in document.createElementNS("http://www.w3.org/1999/xhtml","_"))&&function(a){var c=document.createElementNS("http://www.w3.org/1999/xhtml","_"),a=(a.HTMLElement||a.Element).prototype,e=new XMLSerializer,b=function(){var a;if(document.xmlVersion)return e.serializeToString(this);c.appendChild(this.cloneNode(!1));a=c.innerHTML.replace("><",">"+this.innerHTML+"<");c.innerHTML="";return a},d=function(a){var b=this.parentNode;if(null===b)throw DOMException.code=
DOMException.NOT_FOUND_ERR,DOMException;for(c.innerHTML=a;a=c.firstChild;)b.insertBefore(a,this);b.removeChild(this)};if(Object.defineProperty){b={get:b,set:d,enumerable:!0,configurable:!0};try{Object.defineProperty(a,"outerHTML",b)}catch(f){-2146823252===f.number&&(b.enumerable=!1,Object.defineProperty(a,"outerHTML",b))}}else Object.prototype.__defineGetter__&&Object.prototype.__defineSetter__&&(a.__defineGetter__("outerHTML",b),a.__defineSetter__("outerHTML",d))}(self);
\ No newline at end of file
......@@ -3,6 +3,8 @@ Meteor TodoMVC
A todo app built using [Meteor](http://meteor.com), inspired by [TodoMVC](https://github.com/addyosmani/todomvc).
Demo online: http://todomvcapp.meteor.com
Setup
=======
......@@ -21,9 +23,9 @@ Credits
- Stylesheet from [TodoMVC](https://github.com/addyosmani/todomvc)
- Meteor from [Meteor](http://meteor.com)
- This app by [siuying](https://github.com/siuying)
- This app by [MStumpp](https://github.com/MStumpp)
License
=======
Public Domain
Public Domain
\ No newline at end of file
Tasks = new Meteor.Collection('tasks')
ENTER_KEY = 13
if Meteor.is_client
refreshUI = ->
allCompleted = Tasks.find(completed: false).count() == 0
$('#toggle-all').prop 'checked', allCompleted
hasTask = Tasks.find().count() > 0
if hasTask
$('#main, #footer').removeClass('hidden')
else
$('#main, #footer').addClass('hidden')
# Listen to change on collection Tasks.
# When collection changed, refresh toggle all checkbox state
Tasks.find().observe
added: refreshUI
changed: refreshUI
removed: refreshUI
# Set the initial state of UI
Meteor.setTimeout ->
refreshUI()
, 200
Template.todo.tasks = ->
Tasks.find({}, sort: created_at: -1)
Template.todo.mainClass = ->
if Tasks.find().count() == 0 then 'hidden' else ''
Template.todo.events =
'click #toggle-all': (evt) ->
isChecked = $("#toggle-all").prop 'checked'
modifiers = $set: completed: isChecked
options = multi: true
Tasks.update {}, modifiers, options
'keyup #new-todo' : (evt) ->
if evt.type == 'keyup' && evt.which == ENTER_KEY
textbox = $('#new-todo')
text = textbox.val().trim()
if text
Tasks.insert
title: textbox.val()
completed: false
created_at: new Date()
textbox.val('')
Template.footer.incompleted = ->
Tasks.find(completed: false).count()
Template.footer.incompletedText = ->
count = Tasks.find(completed: false).count()
if count == 1 then ' item left' else ' items left'
Template.footer.completed = ->
Tasks.find(completed: true).count()
Template.footer.events =
'click #clear-completed': ->
Tasks.remove completed: true
Template.footer.footerClass = ->
if Tasks.find().count() == 0 then 'hidden' else ''
Template.item.events =
'click .toggle': (evt) ->
task = Tasks.findOne this._id
task.completed = $(evt.target).prop('checked')
Tasks.update _id: this._id, task
# force DOM redraw
Meteor.flush()
'click .destroy': (evt) ->
Template.item.updateTask this._id, null
'dblclick label': (evt) ->
# do not response to double click on checkbox
return if $(evt.target).hasClass('toggle')
Session.set 'editing_id', this._id
# force DOM redraw, so we can select the edit field
Meteor.flush()
$('.edit').focus()
'blur input.edit': (evt) ->
text = $(evt.target).val().trim()
Template.item.updateTask this._id, text
'keyup input.edit': (evt) ->
if evt.type == 'keyup' && evt.which == ENTER_KEY
text = $(evt.target).val().trim()
Template.item.updateTask this._id, text
return false
Template.item.updateTask = (id, value) ->
if value
task = Tasks.findOne id
task.title = value
Tasks.update _id: id, task, (err) ->
alert('Sorry, an error prevent the changes to be saved') if err
Session.set 'editing_id', null
else
Tasks.remove _id: id
Template.item.editingClass = ->
if Session.equals('editing_id', this._id) then 'editing' else ''
Template.item.completedClass = ->
if this.completed then 'completed' else ''
Template.item.completedCheck = ->
if this.completed then 'checked' else ''
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Meteor • TodoMVC</title>
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
<![endif]-->
</head>
<body>
<section id="todoapp">
{{> todo}}
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="https://github.com/siuying">siuying</a></p>
<p>Modifications by <a href="https://github.com/addyosmani">addyosmani</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</body>
<template name="todo">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
{{#each tasks}}
{{> item}}
{{/each}}
</ul>
</section>
{{> footer}}
</template>
<template name="item">
<li class="{{ editingClass }} {{ completedClass }}">
<div class="view">
<input class="toggle" type="checkbox" {{ completedCheck }}>
<label>{{ title }}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="{{ title }}">
</li>
</template>
<template name="footer">
<footer id="footer" class="{{ footerClass }}">
<span id="todo-count"><strong id="incompleted">{{ incompleted }}</strong>{{ incompletedText }}</span>
<button id="clear-completed">Clear completed (<span id="completed">{{ completed }}</span>)</button>
</footer>
</template>
\ No newline at end of file
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