Commit 3e6e853b authored by Stephen Sawchuk's avatar Stephen Sawchuk

add more helpful readmes and learn.json.

parent 868271f6
.DS_Store .DS_Store
tasks/node_modules
todomvc.com
\ No newline at end of file
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="agilityjs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
......
# Agility.js TodoMVC Example
> [Agility.js](http://agilityjs.com) is an MVC library for Javascript that lets you write maintainable and reusable browser code without the verbose or infrastructural overhead found in other MVC libraries. The goal is to enable developers to write web apps at least as quickly as with jQuery, while simplifying long-term maintainability through MVC objects.
> _[Agility.js - agilityjs.com](http://agilityjs.com)_
## Learning Agility.js
The [Agility.js website](http://agilityjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Official Documentation](http://agilityjs.com/docs/docs.html)
* [Try it out on JSBin](http://jsbin.com/agility/224/edit)
* [Applications built with Agility.js](http://agilityjs.com/docs/gallery.html)
Articles and guides from the community:
* [Step by step from jQuery to Agility.js](https://gist.github.com/pindia/3166678)
Get help from other Agility.js users:
* [Google Groups mailing list](http://groups.google.com/group/agilityjs)
* [agility.js on Stack Overflow](http://stackoverflow.com/questions/tagged/agility.js)
* [Agility.js on Twitter](https://twitter.com/agilityjs)
* [Agility.js on Google +](https://plus.google.com/116251025970928820842/posts)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Credit
This TodoMVC application was created by [tshm](https://github.com/tshm).
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en" ng-app="todomvc"> <html lang="en" ng-app="todomvc" data-framework="angularjs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>AngularJS • TodoMVC</title> <title>AngularJS • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<style>[ng-cloak] {display: none}</style> <style>[ng-cloak] { display: none; }</style>
</head> </head>
<body> <body>
<section id="todoapp" ng-controller="TodoCtrl"> <section id="todoapp" ng-controller="TodoCtrl">
......
# AngularJS (performance optimized) TodoMVC app # AngularJS (Performance Optimized) TodoMVC Example
> HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.
> _[AngularJS - angularjs.com](http://angularjs.com)_
## Learning AngularJS
The [AngularJS website](http://angularjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Tutorial](http://docs.angularjs.org/tutorial)
* [API Reference](http://docs.angularjs.org/api)
* [Developer Guide](http://docs.angularjs.org/guide)
* [Applications built with AngularJS](http://builtwith.angularjs.org)
* [Blog](http://blog.angularjs.org)
* [FAQ](http://docs.angularjs.org/misc/faq)
* [AngularJS Meetups](http://www.youtube.com/angularjs)
Articles and guides from the community:
* [Code School AngularJS course](http://www.codeschool.com/code_tv/angularjs-part-1)
* [5 Awesome AngularJS Features](http://net.tutsplus.com/tutorials/javascript-ajax/5-awesome-angularjs-features)
* [Using Yeoman with AngularJS](http://briantford.com/blog/angular-yeoman.html)
* [me&ngular - an introduction to MVW](http://stephenplusplus.github.io/meangular)
Get help from other AngularJS users:
* [Walkthroughs and Tutorials on YouTube](http://www.youtube.com/playlist?list=PL1w1q3fL4pmgqpzb-XhG7Clgi67d_OHXz)
* [Google Groups mailing list](https://groups.google.com/forum/?fromgroups#!forum/angular)
* [angularjs on Stack Overflow](http://stackoverflow.com/questions/tagged/angularjs)
* [AngularJS on Twitter](https://twitter.com/angularjs)
* [AngularjS on Google +](https://plus.google.com/+AngularJS/posts)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Implementation
The normal AngularJS TodoMVC implemetation performs deep watching of the todos array object. This means that it keeps an in-memory copy of the complete array that is used for dirty checking in order to detect model mutations. For smaller applications such as TodoMVC, this is completely fine as one trades off a little memory and performance for the sake of simplicity. The normal AngularJS TodoMVC implemetation performs deep watching of the todos array object. This means that it keeps an in-memory copy of the complete array that is used for dirty checking in order to detect model mutations. For smaller applications such as TodoMVC, this is completely fine as one trades off a little memory and performance for the sake of simplicity.
In larger more complex applications however, where one might be working with 100s or 1000s of large objects one definitely should avoid using this approach. This implementation of the AngularJS app demonstrates the correct way to approach this problem when working in larger apps. In larger more complex applications however, where one might be working with 100s or 1000s of large objects one definitely should avoid using this approach. This implementation of the AngularJS app demonstrates the correct way to approach this problem when working in larger apps.
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en" ng-app="todomvc"> <html lang="en" ng-app="todomvc" data-framework="angularjs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>AngularJS • TodoMVC</title> <title>AngularJS • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<style>[ng-cloak] {display: none}</style> <style>[ng-cloak] { display: none; }</style>
</head> </head>
<body> <body>
<section id="todoapp" ng-controller="TodoCtrl"> <section id="todoapp" ng-controller="TodoCtrl">
......
# AngularJS TodoMVC Example
> HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.
> _[AngularJS - angularjs.com](http://angularjs.com)_
## Learning AngularJS
The [AngularJS website](http://angularjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Tutorial](http://docs.angularjs.org/tutorial)
* [API Reference](http://docs.angularjs.org/api)
* [Developer Guide](http://docs.angularjs.org/guide)
* [Applications built with AngularJS](http://builtwith.angularjs.org)
* [Blog](http://blog.angularjs.org)
* [FAQ](http://docs.angularjs.org/misc/faq)
* [AngularJS Meetups](http://www.youtube.com/angularjs)
Articles and guides from the community:
* [Code School AngularJS course](http://www.codeschool.com/code_tv/angularjs-part-1)
* [5 Awesome AngularJS Features](http://net.tutsplus.com/tutorials/javascript-ajax/5-awesome-angularjs-features)
* [Using Yeoman with AngularJS](http://briantford.com/blog/angular-yeoman.html)
* [me&ngular - an introduction to MVW](http://stephenplusplus.github.io/meangular)
Get help from other AngularJS users:
* [Walkthroughs and Tutorials on YouTube](http://www.youtube.com/playlist?list=PL1w1q3fL4pmgqpzb-XhG7Clgi67d_OHXz)
* [Google Groups mailing list](https://groups.google.com/forum/?fromgroups#!forum/angular)
* [angularjs on Stack Overflow](http://stackoverflow.com/questions/tagged/angularjs)
* [AngularJS on Twitter](https://twitter.com/angularjs)
* [AngularjS on Google +](https://plus.google.com/+AngularJS/posts)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="backbonejs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
......
# Backbone.js TodoMVC Example
> Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
> _[Backbone.js - backbonejs.org](http://backbonejs.org)_
## Learning Backbone.js
The [Backbone.js website](http://backbonejs.org) is a great resource for getting started.
Here are some links you may find helpful:
* [Annotated source code](http://backbonejs.org/docs/backbone.html)
* [Applications built with Backbone.js](http://backbonejs.org/#examples)
* [FAQ](http://backbonejs.org/#faq)
Articles and guides from the community:
* [Developing Backbone.js Applications](http://addyosmani.github.io/backbone-fundamentals)
* [Collection of tutorials, blog posts, and example sites](https://github.com/documentcloud/backbone/wiki/Tutorials%2C-blog-posts-and-example-sites)
Get help from other Backbone.js users:
* [Backbone.js on StackOverflow](http://stackoverflow.com/questions/tagged/backbone.js)
* [Google Groups mailing list](https://groups.google.com/forum/#!forum/backbonejs)
* [Backbone.js on Twitter](http://twitter.com/documentcloud)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="canjs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>CanJS • TodoMVC</title> <title>CanJS • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
</section> </section>
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Written by <a href="http://bitovi.com">Bitovi</a></p> <p>Written by <a href="http://bitovi.com">Bitovi</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/jquery/jquery.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/todomvc-common/base.js"></script> <script src="bower_components/canjs/can.jquery.js"></script>
<script src="bower_components/canjs/can.jquery.js"></script> <script src="bower_components/canjs-localstorage/can.localstorage.js"></script>
<script src="bower_components/canjs-localstorage/can.localstorage.js"></script> <script src="js/lib/can.mustache.min.js"></script>
<script src="js/models/todo.js"></script>
<script src="js/lib/can.mustache.min.js"></script> <script src="js/todos/todos.js"></script>
<script src="js/models/todo.js"></script> <script src="js/app.js"></script>
<script src="js/todos/todos.js"></script> </body>
<script src="js/app.js"></script>
</body>
</html> </html>
# CanJS # CanJS TodoMVC Example
CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides: > CanJS is a MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
- *can.Model* - for connecting to RESTful JSON interfaces > _[CanJS - canjs.com](http://canjs.com)_
- *can.View* - for template loading and caching
- *can.Observe* - for key-value binding
- *can.EJS* - live binding templates
- *can.Control* - declarative event bindings
- *can.route* - routing support
And works with jQuery, Zepto, YUI, Dojo and Mootools.
## CanJS and JavaScriptMVC ## Learning CanJS
*CanJS* is the extracted, more modern and more library-like MVC parts of [JavaScriptMVC](http://javascriptmvc.com) The [CanJS website](http://canjs.com) is a great resource for getting started.
(formerly known as *jQueryMX*).
*JavaScriptMVC 3.3* uses CanJS for the MVC structure so this TodoMVC example **applies to JavaScriptMVC** as well. Here are some links you may find helpful:
Additionally JavaScriptMVC contains:
- [CanJS](http://canjs.us) - For the MVC parts * [Documentation](http://donejs.com/docs.html#!canjs)
* [Why CanJS](http://canjs.com/#why_canjs)
* [Applications built with CanJS](http://canjs.com/#examples)
* [Blog](http://bitovi.com/blog/tag/canjs)
* [Getting started video](http://www.youtube.com/watch?v=GdT4Oq6ZQ68)
Articles and guides from the community:
* [Diving into CanJS](http://net.tutsplus.com/tutorials/javascript-ajax/diving-into-canjs)
Get help from other CanJS users:
* [CanJS on StackOverflow](http://stackoverflow.com/questions/tagged/canjs)
* [CanJS Forums](http://forum.javascriptmvc.com/#Forum/canjs)
* [CanJS on Twitter](http://twitter.com/canjs)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Implementation
### CanJS and JavaScriptMVC
CanJS is the extracted, more modern and more library-like MVC parts of [JavaScriptMVC](http://javascriptmvc.com), formerly known as jQueryMX.
JavaScriptMVC 3.3 uses CanJS for the MVC structure so this TodoMVC example applies to JavaScriptMVC as well.
Additionally, JavaScriptMVC contains:
- [CanJS](http://canjs.com) - For the MVC parts
- [jQuery++](http://jquerypp.com) - jQuery's missing utils and special events - [jQuery++](http://jquerypp.com) - jQuery's missing utils and special events
- [StealJS](http://javascriptmvc.com/docs.html#!stealjs) - A JavaScript package manager - [StealJS](http://javascriptmvc.com/docs.html#!stealjs) - A JavaScript package manager
- [DocumentJS](http://javascriptmvc.com/docs.html#!DocumentJS) - A documentation engine - [DocumentJS](http://javascriptmvc.com/docs.html#!DocumentJS) - A documentation engine
- [FuncUnit](http://funcunit.com) - jQuery style functional unit testing - [FuncUnit](http://funcunit.com) - jQuery style functional unit testing
## View engines
### View engines
CanJS supports both live binding [EJS](http://canjs.us/#can_ejs) and [Mustache/Handlebars](http://canjs.us/#can_mustache) CanJS supports both live binding [EJS](http://canjs.us/#can_ejs) and [Mustache/Handlebars](http://canjs.us/#can_mustache)
templates. By default the Mustache view will be used but an EJS example is available as well. templates. By default the Mustache view will be used but an EJS example is available as well.
You can easily change it by modifying the `view` option in the `js/app.js` file: You can easily change it by modifying the `view` option in the `js/app.js` file:
```js ```js
Models.Todo.findAll({}, function(todos) { Models.Todo.findAll({}, function (todos) {
new Todos('#todoapp', { new Todos('#todoapp', {
todos: todos, todos: todos,
state : can.route, state: can.route,
view : 'views/todos.ejs' view: 'views/todos.ejs'
}); });
}); });
``` ```
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="closure">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
......
# TodoMVC Closure Architecture Example # Closure Tools TodoMVC Example
## Introduction > The Closure Tools project is an effort by Google engineers to open source the tools used in many of Google's sites and web applications for use by the wider Web development community.
> _[Closure Tools - developers.google.com/closure](https://developers.google.com/closure)_
## Learning Closure Tools
The [Closure Tools website](https://developers.google.com/closure) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](https://developers.google.com/closure/library/docs/overview)
* [API Reference](http://docs.closure-library.googlecode.com/git/index.html)
* [Blog](http://closuretools.blogspot.com)
* [FAQ](https://developers.google.com/closure/faq)
Articles and guides from the community:
* [Examples, walkthroughs, and articles](http://www.googleclosure.com)
* [First Adventure in Google Closure](http://www.codeproject.com/Articles/265364/First-Adventures-in-Google-Closure)
Get help from other Closure Tools users:
* [Google Groups mailing list](https://groups.google.com/group/closure-library-discuss)
* [Closure Tools on Twitter](http://twitter.com/closuretools)
* [Closure Tools on Google +](https://plus.google.com/communities/113969319608324762672)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Implementation
Note this project breaks with the convention of the others and uses spaces in place of tabs within JavaScript files. This is to comply with the Google style guidelines which the Closure Linter enforces (see [Linting](#linting) below).
An example making use of the [Closure toolkit](https://developers.google.com/closure/). Note this project breaks with the convention of the others and uses spaces in place of tabs within JavaScript files. This is to comply with the Google style guidelines which the Closure Linter enforces (see Linting below).
## Running ## Running
...@@ -29,6 +60,7 @@ The linter must be installed before use, the installation package is included in ...@@ -29,6 +60,7 @@ The linter must be installed before use, the installation package is included in
(or whatever floats your OSs boat) (or whatever floats your OSs boat)
## Compiling ## Compiling
To compile the code from the command line run Plovr like so - To compile the code from the command line run Plovr like so -
...@@ -37,14 +69,7 @@ To compile the code from the command line run Plovr like so - ...@@ -37,14 +69,7 @@ To compile the code from the command line run Plovr like so -
This will overwrite the js/compiled.js file with the new version, be sure to change the script tag reference in the HTML page. This will overwrite the js/compiled.js file with the new version, be sure to change the script tag reference in the HTML page.
## Credits
Template by [Sindre Sorhus](http://github.com/sindresorhus)
Created by [Chris Price](http://www.scottlogic.co.uk/blog/chris/)
Part of [TodoMVC](http://todomvc.com) ## Credits
## License
Public Domain This TodoMVC application was created by [Chris Price](http://www.scottlogic.co.uk/blog/chris/).
{
"directory": "web/bower_components"
}
{
"name": "dart",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.6"
}
}
\ No newline at end of file
# Dart • [TodoMVC](http://todomvc.com) # Dart TodoMVC Example
A TodoMVC sample built with Dart. It does not use a MVC framework - it's a Vanilla Dart sample. > Dart is a class-based, object-oriented language with lexical scoping, closures, and optional static typing. Dart helps you build structured modern web apps and is easy to learn for a wide range of developers.
Dart firstly targets the development of modern and large scale browser-side web apps. It's an object oriented language with a C-style syntax. > _[Dart - dartlang.org](http://dartlang.org)_
## Run
## Learning Dart
The [Dart website](http://www.dartlang.org) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](http://www.dartlang.org/docs/technical-overview)
* [API Reference](http://api.dartlang.org/docs/releases/latest)
* [A Tour of the Dart Language](http://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html)
* [Articles](http://www.dartlang.org/articles)
* [Tutorials](http://www.dartlang.org/docs/tutorials)
* [FAQ](http://www.dartlang.org/support/faq.html)
Articles and guides from the community:
* [Getting started with Google Dart](http://www.techrepublic.com/blog/webmaster/getting-started-with-google-dart/931)
Get help from other Dart users:
* [Dart on StackOverflow](http://stackoverflow.com/questions/tagged/dart)
* [Dart on Twitter](http://twitter.com/dart_lang)
* [Dart on Google +](https://plus.google.com/+dartlang/posts)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running
Dart compiles to JavaScript and thus runs across modern browsers. Dart also can run in its own virtual machine. Dart compiles to JavaScript and thus runs across modern browsers. Dart also can run in its own virtual machine.
...@@ -12,18 +39,20 @@ Both Dart files and JS compilation result are provided in this sample, therefore ...@@ -12,18 +39,20 @@ Both Dart files and JS compilation result are provided in this sample, therefore
To edit and debug the code, you can use Dart Editor. The editor ships with the [SDK](http://dartlang.org) and [Dartium](http://www.dartlang.org/dartium/), a dedicated version of Chromium with an embedded Dart VM. To edit and debug the code, you can use Dart Editor. The editor ships with the [SDK](http://dartlang.org) and [Dartium](http://www.dartlang.org/dartium/), a dedicated version of Chromium with an embedded Dart VM.
## How to compile to JS
## Compiling
``` ```
cd web/dart cd web/dart
dart2js app.dart -oapp.dart.js dart2js app.dart -oapp.dart.js
``` ```
The dart2js compilator can be found in the SDK. The dart2js compilator can be found in the SDK.
The currently provided JS is minified (dart2js [...] --minify). The currently provided JS is minified (dart2js [...] --minify).
## Dart syntax analysis
## Syntax Analysis
``` ```
cd web/dart cd web/dart
...@@ -36,6 +65,7 @@ Dart SDK is still under active development, and new releases include breaking ch ...@@ -36,6 +65,7 @@ Dart SDK is still under active development, and new releases include breaking ch
Build history can be seen [here](https://drone.io/mlorber/todomvc-dart) Build history can be seen [here](https://drone.io/mlorber/todomvc-dart)
## Credit ## Credit
Made by [Mathieu Lorber](http://mlorber.net) This TodoMVC application was created by [Mathieu Lorber](http://mlorber.net).
(function () {
'use strict';
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function getSourcePath() {
// If accessed via tastejs.github.io/todomvc/, strip the project path.
if (location.hostname.indexOf('github.io') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
appendSourceLink();
redirect();
})();
This diff is collapsed.
...@@ -155,22 +155,11 @@ label[for='toggle-all'] { ...@@ -155,22 +155,11 @@ label[for='toggle-all'] {
#toggle-all { #toggle-all {
position: absolute; position: absolute;
top: -56px; top: -42px;
left: -15px; left: -4px;
width: 65px; width: 40px;
height: 41px;
text-align: center; text-align: center;
border: none; /* Mobile Safari */ border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-webkit-transform: rotate(90deg);
/*-moz-transform: rotate(90deg);*/
-ms-transform: rotate(90deg);
/*-o-transform: rotate(90deg);*/
transform: rotate(90deg);
} }
#toggle-all:before { #toggle-all:before {
...@@ -219,7 +208,8 @@ label[for='toggle-all'] { ...@@ -219,7 +208,8 @@ label[for='toggle-all'] {
#todo-list li .toggle { #todo-list li .toggle {
text-align: center; text-align: center;
width: 40px; width: 40px;
height: 40px; /* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
...@@ -233,7 +223,6 @@ label[for='toggle-all'] { ...@@ -233,7 +223,6 @@ label[for='toggle-all'] {
} }
#todo-list li .toggle:after { #todo-list li .toggle:after {
font-size: 18px;
content: '✔'; content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */ line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px; font-size: 20px;
...@@ -403,8 +392,164 @@ label[for='toggle-all'] { ...@@ -403,8 +392,164 @@ label[for='toggle-all'] {
#todo-list li .toggle { #todo-list li .toggle {
background: none; background: none;
} }
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
} }
.hidden{ .hidden{
display:none; display:none;
} }
\ No newline at end of file
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function getSourcePath() {
// If accessed via tastejs.github.io/todomvc/, strip the project path.
if (location.hostname.indexOf('github.io') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink();
redirect();
getFile('learn.json', Learn);
})();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="dart">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dart • TodoMVC</title> <title>Dart • TodoMVC</title>
<link rel="stylesheet" href="assets/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<!--[if IE]>
<script src="assets/ie.js"></script>
<![endif]-->
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
...@@ -41,7 +38,7 @@ ...@@ -41,7 +38,7 @@
<p>Created by <a href="http://mlorber.net">Mathieu Lorber</a></p> <p>Created by <a href="http://mlorber.net">Mathieu Lorber</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="assets/base.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script type="application/dart" src="dart/app.dart"></script> <script type="application/dart" src="dart/app.dart"></script>
<script src="sdk/dart.js"></script> <script src="sdk/dart.js"></script>
</body> </body>
......
{
"name": "todmvc-dojo",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.6"
}
}
...@@ -23,7 +23,7 @@ button { ...@@ -23,7 +23,7 @@ button {
body { body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em; line-height: 1.4em;
background: #eaeaea url('./client/images/bg.png'); background: #eaeaea url('bg.png');
color: #4d4d4d; color: #4d4d4d;
width: 550px; width: 550px;
margin: 0 auto; margin: 0 auto;
...@@ -155,22 +155,11 @@ label[for='toggle-all'] { ...@@ -155,22 +155,11 @@ label[for='toggle-all'] {
#toggle-all { #toggle-all {
position: absolute; position: absolute;
top: -56px; top: -42px;
left: -15px; left: -4px;
width: 65px; width: 40px;
height: 41px;
text-align: center; text-align: center;
border: none; /* Mobile Safari */ border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-webkit-transform: rotate(90deg);
/*-moz-transform: rotate(90deg);*/
-ms-transform: rotate(90deg);
/*-o-transform: rotate(90deg);*/
transform: rotate(90deg);
} }
#toggle-all:before { #toggle-all:before {
...@@ -219,7 +208,8 @@ label[for='toggle-all'] { ...@@ -219,7 +208,8 @@ label[for='toggle-all'] {
#todo-list li .toggle { #todo-list li .toggle {
text-align: center; text-align: center;
width: 40px; width: 40px;
height: 40px; /* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
...@@ -233,7 +223,6 @@ label[for='toggle-all'] { ...@@ -233,7 +223,6 @@ label[for='toggle-all'] {
} }
#todo-list li .toggle:after { #todo-list li .toggle:after {
font-size: 18px;
content: '✔'; content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */ line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px; font-size: 20px;
...@@ -403,8 +392,164 @@ label[for='toggle-all'] { ...@@ -403,8 +392,164 @@ label[for='toggle-all'] {
#todo-list li .toggle { #todo-list li .toggle {
background: none; background: none;
} }
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
} }
.hidden{ .hidden{
display:none; display:none;
} }
\ No newline at end of file
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function getSourcePath() {
// If accessed via tastejs.github.io/todomvc/, strip the project path.
if (location.hostname.indexOf('github.io') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink();
redirect();
getFile('learn.json', Learn);
})();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="dojo">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dojo • TodoMVC</title> <title>Dojo • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<!-- CSS overrides - remove if you don't need it -->
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script src="../../assets/ie.js"></script>
<![endif]-->
</head> </head>
<body> <body>
<section id="todoapp" data-dojo-type="todo.app"></section> <section id="todoapp" data-dojo-type="todo.app">
</section>
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Created by <a href="http://jamesthom.as/">James Thomas</a> and <a href="https://github.com/edchat">Ed Chatelain</a></p> <p>Created by <a href="http://jamesthom.as/">James Thomas</a> and <a href="https://github.com/edchat">Ed Chatelain</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="../../assets/base.js"></script>
<script data-dojo-config="async:true, parseOnLoad:true, locale:'en', paths:{'todo':'../todo/'}, deps:['dojo/parser', 'todo/app']" src="js/lib/dojo/dojo.js"></script> <script data-dojo-config="async:true, parseOnLoad:true, locale:'en', paths:{'todo':'../todo/'}, deps:['dojo/parser', 'todo/app']" src="js/lib/dojo/dojo.js"></script>
</body> </body>
</html> </html>
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="dojo">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dojo • TodoMVC</title> <title>Dojo • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<!-- CSS overrides - remove if you don't need it -->
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script>
nativeDate = Date;
</script>
<script src="../../assets/ie.js"></script>
<script>
(function(nativeDate){
// It appears that the modification to Date constructor done by ie.js negatively affects new Date("X"), ending up a JS error.
// Using the native Date constructor for that case.
var origDate = Date;
Date = function(){
return (arguments.length == 1 && typeof arguments[0] == "string" ? nativeDate : origDate).apply(this, [].slice.call(arguments, 0));
};
Date.prototype = new origDate();
})(nativeDate);
</script>
<![endif]-->
</head> </head>
<body> <body>
<section id="todoapp" data-dojo-type="todo/app18"></section> <section id="todoapp" data-dojo-type="todo/app18"></section>
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Created by <a href="http://jamesthom.as/">James Thomas</a> and <a href="https://github.com/edchat">Ed Chatelain</a></p> <p>Created by <a href="http://jamesthom.as/">James Thomas</a> and <a href="https://github.com/edchat">Ed Chatelain</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="../../assets/base.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script> <script>
require = { require = {
async: true, async: true,
parseOnLoad: true, parseOnLoad: true,
locale: "en", locale: 'en',
paths: { paths: {
"dijit": "../dijit-1.8" dijit: '../dijit-1.8'
}, },
deps: ["dojo/parser", "dojo/domReady!"], deps: ['dojo/parser', 'dojo/domReady!'],
mvc: {debugBindings: true} mvc: { debugBindings: true }
}; };
</script> </script>
<script src="js/lib/dojo-1.8/dojo.js"></script> <script src="js/lib/dojo-1.8/dojo.js"></script>
......
# Dojo TodoMVC app # Dojo TodoMVC Example
## Building > Dojo saves you time and scales with your development process, using web standards as its platform. It’s the toolkit experienced developers turn to for building high quality desktop and mobile web applications.
> _[Dojo - dojotoolkit.org](http://dojotoolkit.org)_
## Learning Dojo
The [Dojo website](http://dojotoolkit.org) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](http://dojotoolkit.org/documentation)
* [Getting started guide](https://dojotoolkit.org/reference-guide/1.8/quickstart)
* [API Reference](http://dojotoolkit.org/api)
* [Blog](http://dojotoolkit.org/blog)
Articles and guides from the community:
* [Getting StartED with Dojo](http://startdojo.com)
Get help from other Dojo users:
* [Dojo on StackOverflow](http://stackoverflow.com/questions/tagged/dojo)
* [Mailing list](http://dojotoolkit.org/community)
* [Dojo on Twitter](http://twitter.com/dojo)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running
To build the Dojo app, you first need to download and extract the [Dojo SDK](https://dojotoolkit.org/download/#sdk). To build the Dojo app, you first need to download and extract the [Dojo SDK](https://dojotoolkit.org/download/#sdk).
At the root folder of the extracted SDK, copy or symlink the complete `todomvc` At the root folder of the extracted SDK, copy or symlink the complete `todomvc`
folder, so your directory structure looks like this: folder, so your directory structure looks like this:
dojo-release/ dojo-release/
├── dijit ├── dijit
├── dojo ├── dojo
├── dojox ├── dojox
├── todomvc ├── todomvc
└── util └── util
Enter the `dojo-release/util` folder and run these commands to build the Enter the `dojo-release/util` folder and run these commands to build the `dojo.js` file including all required resources and copy it back into the todomvc folder. You need either java or node on your system to run these:
`dojo.js` file including all required resources and copy it back into the
todomvc folder. You need either java or node on your system to run these:
buildscripts/build.sh --profile ../todomvc/architecture-examples/dojo/profiles/todomvc.profile.js -r ```
cp ../release/dojo/dojo/dojo.js ../todomvc/architecture-examples/dojo/js/lib/dojo-1.8/dojo.js buildscripts/build.sh --profile ../todomvc/architecture-examples/dojo/profiles/todomvc.profile.js -r
cp ../release/dojo/dojo/dojo.js ../todomvc/architecture-examples/dojo/js/lib/dojo-1.8/dojo.js
```
After a new release of Dojo, you may need to copy more files for this to work. After a new release of Dojo, you may need to copy more files for this to work.
Check out the `js/lib/` folder for other files that are required from the Check out the `js/lib/` folder for other files that are required from the
......
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="emberjs">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ember.js • TodoMVC</title> <title>ember.js • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
</head> </head>
<body> <body>
<script type="text/x-handlebars" data-template-name="todos"> <script type="text/x-handlebars" data-template-name="todos">
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
{{view Ember.TextField id="new-todo" placeholder="What needs to be done?" {{view Ember.TextField id="new-todo" placeholder="What needs to be done?"
valueBinding="newTitle" action="createTodo"}} valueBinding="newTitle" action="createTodo"}}
</header> </header>
{{#if length}} {{#if length}}
<section id="main"> <section id="main">
<ul id="todo-list"> <ul id="todo-list">
{{#each filteredTodos itemController="todo"}} {{#each filteredTodos itemController="todo"}}
<li {{bindAttr class="isCompleted:completed isEditing:editing"}}> <li {{bindAttr class="isCompleted:completed isEditing:editing"}}>
{{#if isEditing}} {{#if isEditing}}
{{view Todos.EditTodoView todoBinding="this"}} {{view Todos.EditTodoView todoBinding="this"}}
{{else}} {{else}}
{{view Ember.Checkbox checkedBinding="isCompleted" class="toggle"}} {{view Ember.Checkbox checkedBinding="isCompleted" class="toggle"}}
<label {{action "editTodo" on="doubleClick"}}>{{title}}</label> <label {{action "editTodo" on="doubleClick"}}>{{title}}</label>
<button {{action "removeTodo"}} class="destroy"></button> <button {{action "removeTodo"}} class="destroy"></button>
{{/if}} {{/if}}
</li> </li>
{{/each}} {{/each}}
</ul> </ul>
{{view Ember.Checkbox id="toggle-all" checkedBinding="allAreDone"}} {{view Ember.Checkbox id="toggle-all" checkedBinding="allAreDone"}}
</section> </section>
<footer id="footer"> <footer id="footer">
<span id="todo-count">{{{remainingFormatted}}}</span> <span id="todo-count">{{{remainingFormatted}}}</span>
<ul id="filters"> <ul id="filters">
<li> <li>
{{#linkTo todos.index activeClass="selected"}}All{{/linkTo}} {{#linkTo todos.index activeClass="selected"}}All{{/linkTo}}
</li> </li>
<li> <li>
{{#linkTo todos.active activeClass="selected"}}Active{{/linkTo}} {{#linkTo todos.active activeClass="selected"}}Active{{/linkTo}}
</li> </li>
<li> <li>
{{#linkTo todos.completed activeClass="selected"}}Completed{{/linkTo}} {{#linkTo todos.completed activeClass="selected"}}Completed{{/linkTo}}
</li> </li>
</ul> </ul>
{{#if hasCompleted}} {{#if hasCompleted}}
<button id="clear-completed" {{action "clearCompleted"}} {{bindAttr class="buttonClass:hidden"}}> <button id="clear-completed" {{action "clearCompleted"}} {{bindAttr class="buttonClass:hidden"}}>
Clear completed ({{completed}}) Clear completed ({{completed}})
</button> </button>
{{/if}} {{/if}}
</footer> </footer>
{{/if}} {{/if}}
</section> </section>
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p> <p>
Created by Created by
<a href="http://github.com/tomdale">Tom Dale</a>, <a href="http://github.com/tomdale">Tom Dale</a>,
<a href="http://github.com/addyosmani">Addy Osmani</a> <a href="http://github.com/addyosmani">Addy Osmani</a>
</p> </p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
</script> </script>
<script src="bower_components/todomvc-common/base.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script> <script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/handlebars/handlebars.js"></script> <script src="bower_components/handlebars/handlebars.js"></script>
<script src="bower_components/ember/ember.js"></script> <script src="bower_components/ember/ember.js"></script>
<!-- TODO: change out with a component when a built one is available on Bower --> <!-- TODO: change out with a component when a built one is available on Bower -->
<script src="js/libs/ember-data.js"></script> <script src="js/libs/ember-data.js"></script>
<script src="bower_components/ember-localstorage-adapter/localstorage_adapter.js"></script> <script src="bower_components/ember-localstorage-adapter/localstorage_adapter.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<script src="js/router.js"></script> <script src="js/router.js"></script>
<script src="js/models/todo.js"></script> <script src="js/models/todo.js"></script>
<script src="js/models/store.js"></script> <script src="js/models/store.js"></script>
<script src="js/controllers/todos_controller.js"></script> <script src="js/controllers/todos_controller.js"></script>
<script src="js/controllers/todo_controller.js"></script> <script src="js/controllers/todo_controller.js"></script>
<script src="js/views/edit_todo_view.js"></script> <script src="js/views/edit_todo_view.js"></script>
</body> </body>
</html> </html>
# Ember.js TodoMVC Example
> A framework for creating ambitious web applications.
> _[Ember.js - emberjs.com](http://emberjs.com)_
## Learning Ember.js
The [Ember.js website](http://emberjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Guides](http://emberjs.com/guides)
* [API Reference](http://emberjs.com/api)
* [Screencast - Building an App with Ember.js](https://www.youtube.com/watch?v=Ga99hMi7wfY)
* [Applications built with Ember.js](http://emberjs.com/ember-users)
* [Blog](http://emberjs.com/blog)
Articles and guides from the community:
* [Getting Into Ember.js](http://net.tutsplus.com/tutorials/javascript-ajax/getting-into-ember-js)
* [EmberWatch](http://emberwatch.com)
Get help from other Ember.js users:
* [Ember.js on StackOverflow](http://stackoverflow.com/questions/tagged/ember.js)
* [Ember.js on Twitter](http://twitter.com/emberjs)
* [Ember.js on Google +](https://plus.google.com/communities/106387049790387471205)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
{
"name": "gwt",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.6"
}
}
\ No newline at end of file
...@@ -23,7 +23,7 @@ button { ...@@ -23,7 +23,7 @@ button {
body { body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em; line-height: 1.4em;
background: #eeeeee url('bg.png'); background: #eaeaea url('bg.png');
color: #4d4d4d; color: #4d4d4d;
width: 550px; width: 550px;
margin: 0 auto; margin: 0 auto;
...@@ -57,6 +57,15 @@ body { ...@@ -57,6 +57,15 @@ body {
height: 100%; height: 100%;
} }
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 { #todoapp h1 {
position: absolute; position: absolute;
top: -120px; top: -120px;
...@@ -79,7 +88,7 @@ body { ...@@ -79,7 +88,7 @@ body {
border-radius: inherit; border-radius: inherit;
} }
#todoapp header:before { #header:before {
content: ''; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -96,20 +105,13 @@ body { ...@@ -96,20 +105,13 @@ body {
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); 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'); filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-radius: inherit; border-top-left-radius: 1px;
} border-top-right-radius: 1px;
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
} }
#new-todo, #new-todo,
.edit { .edit {
position: relative;
margin: 0; margin: 0;
width: 100%; width: 100%;
font-size: 24px; font-size: 24px;
...@@ -137,7 +139,6 @@ body { ...@@ -137,7 +139,6 @@ body {
padding: 16px 16px 16px 60px; padding: 16px 16px 16px 60px;
border: none; border: none;
background: rgba(0, 0, 0, 0.02); background: rgba(0, 0, 0, 0.02);
position: relative;
z-index: 2; z-index: 2;
box-shadow: none; box-shadow: none;
} }
...@@ -155,18 +156,10 @@ label[for='toggle-all'] { ...@@ -155,18 +156,10 @@ label[for='toggle-all'] {
#toggle-all { #toggle-all {
position: absolute; position: absolute;
top: -42px; top: -42px;
left: 12px; left: -4px;
width: 40px;
text-align: center; text-align: center;
-webkit-appearance: none; border: none; /* Mobile Safari */
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-webkit-transform: rotate(90deg);
/*-moz-transform: rotate(90deg);*/
-ms-transform: rotate(90deg);
/*-o-transform: rotate(90deg);*/
transform: rotate(90deg);
} }
#toggle-all:before { #toggle-all:before {
...@@ -180,15 +173,6 @@ label[for='toggle-all'] { ...@@ -180,15 +173,6 @@ label[for='toggle-all'] {
color: #737373; 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 { #todo-list {
margin: 0; margin: 0;
padding: 0; padding: 0;
...@@ -223,7 +207,14 @@ WebKit supports styling of inputs */ ...@@ -223,7 +207,14 @@ WebKit supports styling of inputs */
#todo-list li .toggle { #todo-list li .toggle {
text-align: center; text-align: center;
width: 35px; width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none; -webkit-appearance: none;
/*-moz-appearance: none;*/ /*-moz-appearance: none;*/
-ms-appearance: none; -ms-appearance: none;
...@@ -232,9 +223,8 @@ WebKit supports styling of inputs */ ...@@ -232,9 +223,8 @@ WebKit supports styling of inputs */
} }
#todo-list li .toggle:after { #todo-list li .toggle:after {
font-size: 18px;
content: '✔'; content: '✔';
line-height: 40px; line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px; font-size: 20px;
color: #d9d9d9; color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf; text-shadow: 0 -1px 0 #bfbfbf;
...@@ -249,8 +239,10 @@ WebKit supports styling of inputs */ ...@@ -249,8 +239,10 @@ WebKit supports styling of inputs */
#todo-list li label { #todo-list li label {
word-break: break-word; word-break: break-word;
margin: 20px 15px; padding: 15px;
display: inline-block; margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s; -webkit-transition: color 0.4s;
-moz-transition: color 0.4s; -moz-transition: color 0.4s;
-ms-transition: color 0.4s; -ms-transition: color 0.4s;
...@@ -258,7 +250,7 @@ WebKit supports styling of inputs */ ...@@ -258,7 +250,7 @@ WebKit supports styling of inputs */
transition: color 0.4s; transition: color 0.4s;
} }
#todo-list li.complete label { #todo-list li.completed label {
color: #a9a9a9; color: #a9a9a9;
text-decoration: line-through; text-decoration: line-through;
} }
...@@ -266,10 +258,12 @@ WebKit supports styling of inputs */ ...@@ -266,10 +258,12 @@ WebKit supports styling of inputs */
#todo-list li .destroy { #todo-list li .destroy {
display: none; display: none;
position: absolute; position: absolute;
top: 10px; top: 0;
right: 10px; right: 10px;
bottom: 0;
width: 40px; width: 40px;
height: 40px; height: 40px;
margin: auto 0;
font-size: 22px; font-size: 22px;
color: #a88a8a; color: #a88a8a;
-webkit-transition: all 0.2s; -webkit-transition: all 0.2s;
...@@ -312,6 +306,7 @@ WebKit supports styling of inputs */ ...@@ -312,6 +306,7 @@ WebKit supports styling of inputs */
right: 0; right: 0;
bottom: -31px; bottom: -31px;
left: 0; left: 0;
height: 20px;
z-index: 1; z-index: 1;
text-align: center; text-align: center;
} }
...@@ -322,13 +317,13 @@ WebKit supports styling of inputs */ ...@@ -322,13 +317,13 @@ WebKit supports styling of inputs */
right: 0; right: 0;
bottom: 31px; bottom: 31px;
left: 0; left: 0;
height: 100px; height: 50px;
z-index: -1; z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8), 0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3), 0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 42px 0 -6px rgba(255, 255, 255, 0.8), 0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 43px 2px -6px rgba(0, 0, 0, 0.2); 0 44px 2px -6px rgba(0, 0, 0, 0.2);
} }
#todo-count { #todo-count {
...@@ -361,12 +356,12 @@ WebKit supports styling of inputs */ ...@@ -361,12 +356,12 @@ WebKit supports styling of inputs */
#clear-completed { #clear-completed {
float: right; float: right;
position: relative;
line-height: 20px; line-height: 20px;
text-decoration: none; text-decoration: none;
background: rgba(0, 0, 0, 0.1); background: rgba(0, 0, 0, 0.1);
font-size: 11px; font-size: 11px;
padding: 0 10px; padding: 0 10px;
position: relative;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
} }
...@@ -387,3 +382,174 @@ WebKit supports styling of inputs */ ...@@ -387,3 +382,174 @@ WebKit supports styling of inputs */
#info a { #info a {
color: inherit; color: inherit;
} }
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden{
display:none;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function getSourcePath() {
// If accessed via tastejs.github.io/todomvc/, strip the project path.
if (location.hostname.indexOf('github.io') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/tastejs/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink();
redirect();
getFile('learn.json', Learn);
})();
/* The CSS that is common to all TodoMVC implementations, base.css, styles the selected routing filter using the /* The CSS that is common to all TodoMVC implementations, base.css, styles the selected routing filter using the
following selector: following selector:
#filters li a.selected #filters li a.selected
In the GWT implementation, a Hyperlink widget is used for the routing filters. This widget allows you to In the GWT implementation, a Hyperlink widget is used for the routing filters. This widget allows you to
specify a history - and will handle the clicks accordingly. The HTML for this widget is as follows: specify a history - and will handle the clicks accordingly. The HTML for this widget is as follows:
<div><a ...></a></div> <div><a ...></a></div>
Where the 'div' element represents the hyperlink GWT widget. This results in the following GWT Where the 'div' element represents the hyperlink GWT widget. This results in the following GWT
specific style. */ specific style. */
......
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="gwt">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>GWT • TodoMVC</title> <title>Google Web Toolkit • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
<!--[if IE]> </head>
<script src="../../assets/ie.js"></script> <body>
<![endif]--> <script src="bower_components/todomvc-common/base.js"></script>
</head> <script src="gwttodo/gwttodo.nocache.js"></script>
<body> </body>
<script src="gwttodo/gwttodo.nocache.js"></script>
</body>
</html> </html>
## TodoMVC - GWT Version # Google Web Toolkit TodoMVC Example
This is a Google Web Toolkit (GWT) implementation of the TodoMVC application. The GWT version > Google Web Toolkit (GWT) is a development toolkit for building and optimizing complex browser-based applications. GWT is used by many products at Google, including Google AdWords and Orkut. It's open source, completely free, and used by thousands of developers around the world.
is rather different to all the other TodoMVC versions (Backbone, Knockout etc ...) in that it is
written in Java which is compiled to JavaScript. The files within the `gwttodo` folder are the result
of running the GWT compilation process on the Java files found within the src folder. The UI
pattern used by this application is Model-View-Presenter.
Whilst this application is very different to the other TodoMVC implementations, it still makes for > _[Google Web Toolkit - developers.google.com/web-toolkit](https://developers.google.com/web-toolkit)_
an interesting comparison. Large-scale JavaScript applications are often written with GWT or Closure,
with the resulting JavaScript code delivered to the client being compiled.
You can read more about the implementation on my blog:
http://www.scottlogic.co.uk/blog/colin/2012/03/developing-a-gwt-todomvc-application/ ## Learning Google Web Toolkit
### Folder structure The [Google Web Toolkit website](https://developers.google.com/web-toolkit/) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](https://developers.google.com/web-toolkit/doc/latest/DevGuide)
* [Getting Started with the GWT SDK](https://developers.google.com/web-toolkit/gettingstarted)
* [Articles](https://developers.google.com/web-toolkit/articles)
* [Case Studies](https://developers.google.com/web-toolkit/casestudies)
* [Blog](http://googlewebtoolkit.blogspot.com)
* [FAQ](https://developers.google.com/web-toolkit/doc/latest/FAQ)
Get help from other Google Web Toolkit users:
* [Google Web Toolkit on StackOverflow](http://stackoverflow.com/questions/tagged/gwt)
* [Mailing list on Google Groups](http://groups.google.com/group/Google-Web-Toolkit)
* [Google Web Toolkit on Twitter](http://twitter.com/googledevtools)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Implementation
This application is rather different than most of the other TodoMVC versions in that it is written in Java which is compiled to JavaScript. The files within the `gwttodo` folder are the result of running the GWT compilation process on the Java files found within the src folder. The UI pattern used by this application is Model-View-Presenter.
Whilst this application is very different to the other implementations, it still makes for an interesting comparison. Large-scale JavaScript applications are often written with GWT or Closure, with the resulting JavaScript code delivered to the client being compiled.
You can read more about the implementation on [my blog](http://www.scottlogic.co.uk/blog/colin/2012/03/developing-a-gwt-todomvc-application).
## Folder Structure
- `css` - includes GWT specific `app.css`, most styling is taken from the base CSS file `../../assets/base.css` - `css` - includes GWT specific `app.css`, most styling is taken from the base CSS file `../../assets/base.css`
- `gwttodo` - the GWT compiled output, this includes various HTML files, which contain the JavaScript - `gwttodo` - the GWT compiled output, this includes various HTML files, which contain the JavaScript
...@@ -23,14 +45,8 @@ folder also includes some redundant files, see the issue <a href="https://github ...@@ -23,14 +45,8 @@ folder also includes some redundant files, see the issue <a href="https://github
Remove redundant compiler output</a>. Remove redundant compiler output</a>.
- `src` - the Java source for this application - `src` - the Java source for this application
### Building this application
The GWT TodoMVC application was built with Java 1.6 and GWT 2.4.0. The easiest way to build this application
is to download the GWT SDK:
http://code.google.com/webtoolkit/gettingstarted.html
Together with the Eclipse plugin: ## Building this application
http://code.google.com/webtoolkit/usingeclipse.html
The GWT TodoMVC application was built with Java 1.6 and GWT 2.4.0. The easiest way to build this application
is to [download the GWT SDK](http://code.google.com/webtoolkit/gettingstarted.html), or together with the [Eclipse plugin](http://code.google.com/webtoolkit/usingeclipse.html).
...@@ -412,3 +412,144 @@ label[for='toggle-all'] { ...@@ -412,3 +412,144 @@ label[for='toggle-all'] {
.hidden{ .hidden{
display:none; display:none;
} }
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
/**body*/.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
/**body*/.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
/**body*/.learn-bar > .learn {
left: 8px;
}
/**body*/.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
...@@ -33,6 +33,150 @@ ...@@ -33,6 +33,150 @@
} }
} }
function findRoot() {
var base;
[/labs/, /\w*-examples/].forEach(function (href) {
var match = location.href.match(href);
if (!base && match) {
base = location.href.indexOf(match);
}
});
return location.href.substr(0, base);
}
function getFile(file, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').getAttribute('data-framework');
}
if (template && learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.template = template;
this.append();
}
}
Learn.prototype._prepareTemplate = function () {
var aside = document.createElement('aside');
aside.innerHTML = this.template;
var header = aside.cloneNode(true);
header.removeChild(header.querySelector('ul'));
header.removeChild(header.querySelectorAll('footer')[1]);
return {
header: header,
links: aside.cloneNode(true).querySelector('ul a'),
footer: aside.cloneNode(true).querySelectorAll('footer')[1]
};
};
Learn.prototype._parseTemplate = function () {
if (!this.template) {
return;
}
var frameworkJSON = this.frameworkJSON;
var template = this._prepareTemplate();
var aside = document.createElement('aside');
var linksTemplate = template.links.outerHTML;
var parser = /\{\{([^}]*)\}\}/g;
var header, examples, links;
header = template.header.innerHTML.replace(parser, function (match, key) {
return frameworkJSON[key];
});
aside.innerHTML = header;
if (frameworkJSON.examples) {
examples = frameworkJSON.examples.map(function (example) {
return ''
+ '<h5>' + example.name + '</h5>'
+ '<p>'
+ (location.href.match(example.url + '/') ? '' : ' <a href="' + findRoot() + example.url + '">Demo</a>, ')
+ ' <a href="https://github.com/tastejs/todomvc/tree/gh-pages/' + (example.source_url || example.url) + '">Source</a>'
+ '</p>';
}).join('');
aside.querySelector('.source-links').innerHTML = examples;
}
if (frameworkJSON.link_groups) {
links = frameworkJSON.link_groups.map(function (linkGroup) {
return ''
+ '<h4>' + linkGroup.heading + '</h4>'
+ '<ul>'
+ linkGroup.links.map(function (link) {
return ''
+ '<li>'
+ linksTemplate.replace(parser, function (match, key) {
return link[key];
})
+ '</li>';
}).join('')
+ '</ul>';
}).join('');
aside.innerHTML += links;
aside.innerHTML += template.footer.outerHTML;
}
return aside;
};
Learn.prototype.append = function () {
var aside = this._parseTemplate();
aside.className = 'learn';
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentElement('afterBegin', aside);
};
appendSourceLink(); appendSourceLink();
redirect(); redirect();
getFile('learn.json', Learn);
})(); })();
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="jquery">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>jQuery • TodoMVC</title> <title>jQuery • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus> <input id="new-todo" placeholder="What needs to be done?" autofocus>
</header> </header>
<section id="main"> <section id="main">
<input id="toggle-all" type="checkbox"> <input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul> <ul id="todo-list"></ul>
</section>
<footer id="footer">
<span id="todo-count"><strong>0</strong> item left</span>
<button id="clear-completed">Clear completed</button>
</footer>
</section> </section>
<footer id="info"> <footer id="footer">
<p>Double-click to edit a todo</p> <span id="todo-count"><strong>0</strong> item left</span>
<p>Created by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p> <button id="clear-completed">Clear completed</button>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script id="todo-template" type="text/x-handlebars-template"> </section>
{{#this}} <footer id="info">
<li {{#if completed}}class="completed"{{/if}} data-id="{{id}}"> <p>Double-click to edit a todo</p>
<div class="view"> <p>Created by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
<label>{{title}}</label> </footer>
<button class="destroy"></button> <script id="todo-template" type="text/x-handlebars-template">
</div> {{#this}}
<input class="edit" value="{{title}}"> <li {{#if completed}}class="completed"{{/if}} data-id="{{id}}">
</li> <div class="view">
{{/this}} <input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}>
</script> <label>{{title}}</label>
<script id="footer-template" type="text/x-handlebars-template"> <button class="destroy"></button>
<span id="todo-count"><strong>{{activeTodoCount}}</strong> {{activeTodoWord}} left</span> </div>
{{#if completedTodos}}<button id="clear-completed">Clear completed ({{completedTodos}})</button>{{/if}} <input class="edit" value="{{title}}">
</script> </li>
<script src="bower_components/todomvc-common/base.js"></script> {{/this}}
<script src="bower_components/jquery/jquery.js"></script> </script>
<script src="bower_components/handlebars/handlebars.js"></script> <script id="footer-template" type="text/x-handlebars-template">
<script src="js/app.js"></script> <span id="todo-count"><strong>{{activeTodoCount}}</strong> {{activeTodoWord}} left</span>
</body> {{#if completedTodos}}<button id="clear-completed">Clear completed ({{completedTodos}})</button>{{/if}}
</script>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/handlebars/handlebars.js"></script>
<script src="js/app.js"></script>
</body>
</html> </html>
# jQuery TodoMVC Example
> jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.
> _[jQuery - jquery.com](http://jquery.com)_
## Learning jQuery
The [jQuery website](http://jquery.com) is a great resource for getting started.
Here are some links you may find helpful:
* [How jQuery Works](http://learn.jquery.com/about-jquery/how-jquery-works)
* [API Reference](http://api.jquery.com)
* [Plugins](http://plugins.jquery.com)
* [Brower Support](http://jquery.com/browser-support)
* [Blog](http://blog.jquery.com)
Articles and guides from the community:
* [Try jQuery](http://try.jquery.com)
* [10 Things I Learned From the jQuery Source](http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source)
Get help from other jQuery users:
* [jQuery on StackOverflow](http://stackoverflow.com/questions/tagged/jquery)
* [Forums](http://forum.jquery.com)
* [jQuery on Twitter](http://twitter.com/jquery)
* [jQuery on Google +](https://plus.google.com/102828491884671003608/posts)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
{
"name": "todomvc-knockback",
"version": "0.0.0",
"dependencies": {
"jquery": "~2.0.0",
"todomvc-common": "~0.1.6",
"Backbone.localStorage": "~1.1.3"
}
}
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="knockback">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Knockback.js • TodoMVC</title> <title>Knockback.js • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css"> <link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<!--[if IE]>
<script src="../../assets/ie.js"></script>
<![endif]-->
</head> </head>
<body> <body>
<section id="todoapp" kb-inject="AppViewModel"> <section id="todoapp" kb-inject="AppViewModel">
...@@ -55,10 +52,10 @@ ...@@ -55,10 +52,10 @@
</footer> </footer>
<!-- App Dependencies --> <!-- App Dependencies -->
<script src="../../assets/base.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script src="../../assets/jquery.min.js"></script> <script src="bower_components/jquery/jquery.js"></script>
<script src="js/lib/knockback-full-stack-0.16.9.min.js"></script> <script src="js/lib/knockback-full-stack-0.16.9.min.js"></script>
<script src="js/lib/backbone.localStorage-min.js"></script> <script src="bower_components/Backbone.localStorage/backbone.localStorage.js"></script>
<!-- App and Components --> <!-- App and Components -->
<script src="js/lib/knockout-extended-bindings.js"></script> <script src="js/lib/knockout-extended-bindings.js"></script>
...@@ -67,4 +64,4 @@ ...@@ -67,4 +64,4 @@
<script src="js/viewmodels/todo.js"></script> <script src="js/viewmodels/todo.js"></script>
<script src="js/viewmodels/app.js"></script> <script src="js/viewmodels/app.js"></script>
</body> </body>
</html> </html>
\ No newline at end of file
# Knockback.js • [TodoMVC](http://todomvc.com) # Knockback.js TodoMVC Example
## Getting started > Both Knockout.js and Backbone.js have their strengths and weaknesses, but together they are amazing! With Knockback.js, you can use the strong ORM provided by Backbone and create dynamic views using Knockout bindings.
You need [CoffeScript](http://coffeescript.org) to compile if you make changes to the files in the `src` folder. > _[Knockback.js - kmalakoff.github.io/knockback](http://kmalakoff.github.io/knockback)_
## Compile ## Learning Knockback.js
Open Terminal in this folder. The [Knockback.js website](http://kmalakoff.github.io/knockback) is a great resource for getting started.
- `cake build` to compile once Here are some links you may find helpful:
- `cake watch` to compile on save * [Getting Started with Knockback.js](http://kmalakoff.github.io/knockback/getting_started_introduction.html)
\ No newline at end of file * [Tutorials](http://kmalakoff.github.io/knockback/tutorials_introduction.html)
* [API Reference](http://kmalakoff.github.io/knockback/doc/index.html)
* [Knockback.js Reference App](http://kmalakoff.github.io/knockback/app_knockback_reference.html)
* [Knockback.js on Twitter](http://twitter.com/knockbackjs)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running
This app is written in [CoffeeScript](http://coffeescript.org/). If you wish to make changes, follow these steps to re-compile the code.
To install CoffeeScript globally:
npm install -g coffee-script
To compile once:
# from architecture-examples/knockback
cake build
To compile on save
# from architecture-examples/knockback
cake watch
This diff is collapsed.
# Knockout.js TodoMVC app # Knockout.js TodoMVC Example
[ashish101](https://github.com/ashish01/knockoutjs-todos) wrote the original version of this application, which was then refactored by Addy Osmani and later rewritten by TodoMVC contributors. > Knockout.js helps you simplify dynamic JavaScript UIs using the Model-View-ViewModel (MVVM) pattern.
> _[Knockout.js - knockoutjs.com](http://knockoutjs.com)_
## Learning Knockout.js
The [Knockout.js website](http://knockoutjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](http://knockoutjs.com/documentation/introduction.html)
* [Tutorials](http://learn.knockoutjs.com)
* [Live examples](http://knockoutjs.com/examples)
Articles and guides from the community:
* [Getting Started with Knockout.js](http://www.adobe.com/devnet/html5/articles/getting-started-with-knockoutjs.html)
* [Into the Ring with Knockout.js](http://net.tutsplus.com/tutorials/javascript-ajax/into-the-ring-with-knockout-js)
* [Beginners Guide to Knockout.js](http://www.sitepoint.com/beginners-guide-to-knockoutjs-part-1)
Get help from other Knockout.js users:
* [Knockout.js on StackOverflow](http://stackoverflow.com/questions/tagged/knockout)
* [Mailing list on Google Groups](http://groups.google.com/group/knockoutjs)
* [Knockout.js on Twitter](http://twitter.com/knockoutjs)
* [Knockout.js on Google +](https://plus.google.com/communities/106789046312204355684/stream/c5bfcfdf-3690-44a6-b015-35aad4f4e42e)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Credit
This TodoMVC application was originally created by [ashish101](https://github.com/ashish01/knockoutjs-todos), then refactored by Addy Osmani and later rewritten by TodoMVC contributors.
<!DOCTYPE html> <!DOCTYPE html>
<html> <html data-framework="maria">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Maria • TodoMVC</title> <title>Maria • TodoMVC</title>
......
This diff is collapsed.
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en" data-framework="spine">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
......
This diff is collapsed.
{
"name": "todomvc-yui",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.6"
}
}
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