Commit c5ffea43 authored by Addy Osmani's avatar Addy Osmani

Merge pull request #547 from stephenplusplus/readmes

More helpful readmes for beginners - epic work by stephen.
parents 868271f6 3e6e853b
.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">
...@@ -14,15 +14,13 @@ ...@@ -14,15 +14,13 @@
<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/lib/can.mustache.min.js"></script>
<script src="js/models/todo.js"></script> <script src="js/models/todo.js"></script>
<script src="js/todos/todos.js"></script> <script src="js/todos/todos.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
</body> </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,7 +39,8 @@ Both Dart files and JS compilation result are provided in this sample, therefore ...@@ -12,7 +39,8 @@ 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
...@@ -23,7 +51,8 @@ The dart2js compilator can be found in the SDK. ...@@ -23,7 +51,8 @@ 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;
} }
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;
} }
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>
...@@ -33,17 +15,17 @@ ...@@ -33,17 +15,17 @@
<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`
...@@ -13,12 +42,12 @@ folder, so your directory structure looks like this: ...@@ -13,12 +42,12 @@ folder, so your directory structure looks like this:
├── 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">
...@@ -76,5 +76,5 @@ ...@@ -76,5 +76,5 @@
<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);
})();
<!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>
<body>
<script src="gwttodo/gwttodo.nocache.js"></script> <script src="gwttodo/gwttodo.nocache.js"></script>
</body> </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>
...@@ -48,5 +48,5 @@ ...@@ -48,5 +48,5 @@
<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="js/app.js"></script> <script src="js/app.js"></script>
</body> </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"
}
}
/**
* Backbone localStorage Adapter
* Version 1.1.3
*
* https://github.com/jeromegn/Backbone.localStorage
*/
(function (root, factory) {
if (typeof exports === 'object') {
module.exports = factory(require("underscore"), require("backbone"));
} else if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["underscore","backbone"], function(_, Backbone) {
// Use global variables if the locals are undefined.
return factory(_ || root._, Backbone || root.Backbone);
});
} else {
// RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags
factory(_, Backbone);
}
}(this, function(_, Backbone) {
// A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that.
// Hold reference to Underscore.js and Backbone.js in the closure in order
// to make things work even if they are removed from the global namespace
// Generate four random hex digits.
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
// Generate a pseudo-GUID by concatenating random hexadecimal.
function guid() {
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
};
// Our Store is represented by a single JS object in *localStorage*. Create it
// with a meaningful name, like the name you'd give a table.
// window.Store is deprectated, use Backbone.LocalStorage instead
Backbone.LocalStorage = window.Store = function(name) {
this.name = name;
var store = this.localStorage().getItem(this.name);
this.records = (store && store.split(",")) || [];
};
_.extend(Backbone.LocalStorage.prototype, {
// Save the current state of the **Store** to *localStorage*.
save: function() {
this.localStorage().setItem(this.name, this.records.join(","));
},
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create: function(model) {
if (!model.id) {
model.id = guid();
model.set(model.idAttribute, model.id);
}
this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
this.records.push(model.id.toString());
this.save();
return this.find(model);
},
// Update a model by replacing its copy in `this.data`.
update: function(model) {
this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
if (!_.include(this.records, model.id.toString()))
this.records.push(model.id.toString()); this.save();
return this.find(model);
},
// Retrieve a model from `this.data` by id.
find: function(model) {
return this.jsonData(this.localStorage().getItem(this.name+"-"+model.id));
},
// Return the array of all models currently in storage.
findAll: function() {
// Lodash removed _#chain in v1.0.0-rc.1
return (_.chain || _)(this.records)
.map(function(id){
return this.jsonData(this.localStorage().getItem(this.name+"-"+id));
}, this)
.compact()
.value();
},
// Delete a model from `this.data`, returning it.
destroy: function(model) {
if (model.isNew())
return false
this.localStorage().removeItem(this.name+"-"+model.id);
this.records = _.reject(this.records, function(id){
return id === model.id.toString();
});
this.save();
return model;
},
localStorage: function() {
return localStorage;
},
// fix for "illegal access" error on Android when JSON.parse is passed null
jsonData: function (data) {
return data && JSON.parse(data);
},
// Clear localStorage for specific collection.
_clear: function() {
var local = this.localStorage(),
itemRe = new RegExp("^" + this.name + "-");
// Remove id-tracking item (e.g., "foo").
local.removeItem(this.name);
// Lodash removed _#chain in v1.0.0-rc.1
// Match all data items (e.g., "foo-ID") and remove.
(_.chain || _)(local).keys()
.filter(function (k) { return itemRe.test(k); })
.each(function (k) { local.removeItem(k); });
},
// Size of localStorage.
_storageSize: function() {
return this.localStorage().length;
}
});
// localSync delegate to the model or collection's
// *localStorage* property, which should be an instance of `Store`.
// window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead
Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) {
var store = model.localStorage || model.collection.localStorage;
var resp, errorMessage, syncDfd = Backbone.$.Deferred && Backbone.$.Deferred(); //If $ is having Deferred - use it.
try {
switch (method) {
case "read":
resp = model.id != undefined ? store.find(model) : store.findAll();
break;
case "create":
resp = store.create(model);
break;
case "update":
resp = store.update(model);
break;
case "delete":
resp = store.destroy(model);
break;
}
} catch(error) {
if (error.code === DOMException.QUOTA_EXCEEDED_ERR && store._storageSize() === 0)
errorMessage = "Private browsing is unsupported";
else
errorMessage = error.message;
}
if (resp) {
if (options && options.success) {
if (Backbone.VERSION === "0.9.10") {
options.success(model, resp, options);
} else {
options.success(resp);
}
}
if (syncDfd) {
syncDfd.resolve(resp);
}
} else {
errorMessage = errorMessage ? errorMessage
: "Record Not Found";
if (options && options.error)
if (Backbone.VERSION === "0.9.10") {
options.error(model, errorMessage, options);
} else {
options.error(errorMessage);
}
if (syncDfd)
syncDfd.reject(errorMessage);
}
// add compatibility with $.ajax
// always execute callback for success and error
if (options && options.complete) options.complete(resp);
return syncDfd && syncDfd.promise();
};
Backbone.ajaxSync = Backbone.sync;
Backbone.getSyncMethod = function(model) {
if(model.localStorage || (model.collection && model.collection.localStorage)) {
return Backbone.localSync;
}
return Backbone.ajaxSync;
};
// Override 'Backbone.sync' to default to localSync,
// the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
Backbone.sync = function(method, model, options) {
return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
};
return Backbone.LocalStorage;
}));
(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);
})();
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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