Commit 93d335a1 authored by Arthur Verschaeve's avatar Arthur Verschaeve

Drop `maria` example

Fix #1173
parent 82f0b016
......@@ -82,7 +82,6 @@ module.exports = [
'TodoMVC - flight, Routing, should respect the back button',
'TodoMVC - lavaca_require, Routing, should respect the back button',
'TodoMVC - somajs_require, Routing, should respect the back button',
'TodoMVC - maria, Routing, should respect the back button',
// the following are covered by this issue:
// https://github.com/tastejs/todomvc/issues/795
......
{
"name": "todomvc-maria",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.3.0",
"director": "~1.2.0",
"maria-bower": "~1.0.0",
"aristocrat-bower": "~1.0.1"
}
}
/*
Aristocrat version 1.0.1
Copyright (c) 2012, Peter Michaux
All rights reserved.
Licensed under the Simplified BSD License.
https://github.com/petermichaux/aristocrat/blob/master/LICENSE
*/
var aristocrat = {};
(function() {
var regExpCache = {};
function getRegExp(className) {
return Object.prototype.hasOwnProperty.call(regExpCache, className) ?
regExpCache[className] :
(regExpCache[className] = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'));
}
/**
@property aristocrat.hasClass
@parameter element {Element} The DOM element to test.
@parameter className {string} The class name to test for on element.
@returns {boolean}
@description
Tests if element has className in the element.className property.
aristocrat.hasClass(document.body, 'king');
*/
var hasClass = aristocrat.hasClass = function(el, className) {
return getRegExp(className).test(el.className);
};
/**
@property aristocrat.addClass
@parameter element {Element} The DOM element to test.
@parameter className {string} The class name to add to element.
@description
Add className to element.className if className is not already in element.className.
aristocrat.addClass(document.body, 'king');
*/
var addClass = aristocrat.addClass = function(el, className) {
if (!hasClass(el, className)) {
el.className = el.className + ' ' + className;
}
};
/**
@property aristocrat.removeClass
@parameter element {Element} The DOM element to test.
@parameter className {string} The class name to remove from element.
@description
Removes all occurrences of className in element.className.
aristocrat.removeClass(document.body, 'king');
*/
var removeClass = aristocrat.removeClass = function(el, className) {
var re = getRegExp(className);
while (re.test(el.className)) { // in case multiple occurrences
el.className = el.className.replace(re, ' ');
}
};
/**
@property aristocrat.toggleClass
@parameter element {Element} The DOM element to test.
@parameter className {string} The class name to toggle on element.
@description
If element.className has className then className is removed. Otherwise
className is added.
aristocrat.toggleClass(document.body, 'king');
*/
aristocrat.toggleClass = function(el, className) {
if (hasClass(el, className)) {
removeClass(el, className);
}
else {
addClass(el, className);
}
};
}());
This source diff could not be displayed because it is too large. You can view the blob instead.
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
button,
input[type="checkbox"] {
outline: none;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input::-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
/* Mobile Safari */
border: none;
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
/* Mobile Safari */
border: none;
-webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
/* 40 + a couple of pixels visual adjustment */
line-height: 43px;
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
white-space: pre;
word-break: break-word;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden {
display: none;
}
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);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
-webkit-transition-property: left;
transition-property: left;
-webkit-transition-duration: 500ms;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
.learn-bar > .learn {
left: 8px;
}
.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
// Underscore's Template Module
// Courtesy of underscorejs.org
var _ = (function (_) {
_.defaults = function (object) {
if (!object) {
return object;
}
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
var iterable = arguments[argsIndex];
if (iterable) {
for (var key in iterable) {
if (object[key] == null) {
object[key] = iterable[key];
}
}
}
}
return object;
}
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; });
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
}
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length;
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n";
try {
render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled function source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
return template;
};
return _;
})({});
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 redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base = location.href.indexOf('examples/');
return location.href.substr(0, base);
}
function getFile(file, callback) {
if (!location.host) {
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
}
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]').dataset.framework;
}
this.template = template;
if (learnJSON.backend) {
this.frameworkJSON = learnJSON.backend;
this.append({
backend: true
});
} else if (learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.append();
}
}
Learn.prototype.append = function (opts) {
var aside = document.createElement('aside');
aside.innerHTML = _.template(this.template, this.frameworkJSON);
aside.className = 'learn';
if (opts && opts.backend) {
// Remove demo link
var sourceLinks = aside.querySelector('.source-links');
var heading = sourceLinks.firstElementChild;
var sourceLink = sourceLinks.lastElementChild;
// Correct link path
var href = sourceLink.getAttribute('href');
sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
} else {
// Localize demo links
var demoLinks = aside.querySelectorAll('.demo-link');
Array.prototype.forEach.call(demoLinks, function (demoLink) {
if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
}
});
}
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
};
redirect();
getFile('learn.json', Learn);
})();
ul.completed li.incompleted,
ul.incompleted li.completed {
display: none;
}
<!doctype html>
<html data-framework="maria">
<head>
<meta charset="utf-8">
<title>Maria • TodoMVC</title>
<link href="bower_components/todomvc-common/base.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">
</head>
<body>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="http://github.com/petermichaux">Peter Michaux</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/director/build/director.js"></script>
<script src="bower_components/maria-bower/maria.js"></script>
<script src="bower_components/aristocrat-bower/aristocrat.js"></script>
<script src="js/namespace.js"></script>
<script src="js/util.js"></script>
<script src="js/models/TodoModel.js"></script>
<script src="js/models/TodosModel.js"></script>
<script src="js/templates/TodosTemplate.js"></script>
<script src="js/views/TodosView.js"></script>
<script src="js/controllers/TodosController.js"></script>
<script src="js/templates/TodoTemplate.js"></script>
<script src="js/views/TodoView.js"></script>
<script src="js/controllers/TodoController.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
/*jshint strict: false */
/*global maria, Router, checkit */
maria.on(window, 'load', function () {
var model;
if ((typeof localStorage === 'object') && (typeof JSON === 'object')) {
var store = localStorage.getItem('todos-maria');
if (store) {
model = checkit.TodosModel.fromJSON(JSON.parse(store));
} else {
model = new checkit.TodosModel();
}
maria.on(model, 'change', function () {
localStorage.setItem('todos-maria', JSON.stringify(model.toJSON()));
});
} else {
model = new checkit.TodosModel();
}
var routes = {
'/': function () {
model.setMode('all');
},
'/active': function () {
model.setMode('incompleted');
},
'/completed': function () {
model.setMode('completed');
}
};
var router = new Router(routes);
router.init();
var view = new checkit.TodosAppView(model);
document.body.insertBefore(view.build(), document.body.firstChild);
});
/*jshint strict: false */
/*global maria, checkit */
maria.Controller.subclass(checkit, 'TodoController', {
properties: {
onClickDestroy: function () {
this.getModel().destroy();
},
onClickToggle: function () {
this.getModel().toggleCompleted();
},
onDblclickLabel: function () {
this.getView().showEdit();
},
onKeyupEdit: function (evt) {
var keyCode = evt.keyCode;
if (checkit.isEnterKeyCode(keyCode)) {
this.onBlurEdit();
} else if (checkit.isEscapeKeyCode(keyCode)) {
var view = this.getView();
view.resetEdit();
view.showDisplay();
}
},
onBlurEdit: function () {
var model = this.getModel();
var view = this.getView();
var value = view.getInputValue();
view.showDisplay();
if (checkit.isBlank(value)) {
model.destroy();
} else {
model.setTitle(value);
}
}
}
});
/*jshint strict: false */
/*global maria, checkit */
maria.Controller.subclass(checkit, 'TodosAppController', {
properties: {
onKeyupNewTodo: function (evt) {
if (checkit.isEnterKeyCode(evt.keyCode)) {
var view = this.getView();
var value = view.getInputValue();
if (!checkit.isBlank(value)) {
var todo = new checkit.TodoModel();
todo.setTitle(value);
this.getModel().add(todo);
view.clearInput();
}
}
},
onClickToggleAll: function () {
var model = this.getModel();
if (model.isAllCompleted()) {
model.markAllIncompleted();
} else {
model.markAllCompleted();
}
},
onClickClearCompleted: function () {
this.getModel().deleteCompleted();
}
}
});
/*jshint strict: false */
/*global maria, checkit */
maria.Model.subclass(checkit, 'TodoModel', {
properties: {
_title: '',
_completed: false,
getTitle: function () {
return this._title;
},
setTitle: function (title) {
title = ('' + title).trim();
if (this._title !== title) {
this._title = title;
this.dispatchEvent({ type: 'change' });
}
},
isCompleted: function () {
return this._completed;
},
setCompleted: function (completed) {
completed = !!completed;
if (this._completed !== completed) {
this._completed = completed;
this.dispatchEvent({ type: 'change' });
}
},
toggleCompleted: function () {
this.setCompleted(!this.isCompleted());
},
toJSON: function () {
return {
title: this._title,
completed: this._completed
};
}
}
});
checkit.TodoModel.fromJSON = function (todoJSON) {
var model = new checkit.TodoModel();
model._title = todoJSON.title;
model._completed = todoJSON.completed;
return model;
};
/*jshint strict: false */
/*global maria, checkit */
maria.SetModel.subclass(checkit, 'TodosModel', {
properties: {
_mode: 'all',
getPossibleModes: function () {
return ['all', 'incompleted', 'completed'];
},
getMode: function () {
return this._mode;
},
setMode: function (mode) {
var modePossible = this.getPossibleModes().some(function (m) {
return m === mode;
});
if (modePossible) {
if (this._mode !== mode) {
this._mode = mode;
this.dispatchEvent({ type: 'change' });
}
} else {
throw new Error('checkit.TodosModel.prototype.setMode: unsupported mode "' + mode + '".');
}
},
getCompleted: function () {
var completeTodos = [];
this.forEach(function (todo) {
if (todo.isCompleted()) {
completeTodos.push(todo);
}
});
return completeTodos;
},
getIncompleted: function () {
var incompleteTodos = [];
this.forEach(function (todo) {
if (!todo.isCompleted()) {
incompleteTodos.push(todo);
}
});
return incompleteTodos;
},
isAllCompleted: function () {
return (this.size > 0) && (this.getCompleted().length === this.size);
},
isEmpty: function () {
return this.size === 0;
},
markAllCompleted: function () {
this.forEach(function (todo) {
todo.setCompleted(true);
});
},
markAllIncompleted: function () {
this.forEach(function (todo) {
todo.setCompleted(false);
});
},
deleteCompleted: function () {
this['delete'].apply(this, this.getCompleted());
},
toJSON: function () {
var todoJSON = [];
this.forEach(function (todo) {
todoJSON.push(todo.toJSON());
});
return todoJSON;
}
}
});
checkit.TodosModel.fromJSON = function (todosJSON) {
var model = new checkit.TodosModel();
var i;
var ilen;
for (i = 0, ilen = todosJSON.length; i < ilen; i++) {
model.add(checkit.TodoModel.fromJSON(todosJSON[i]));
}
return model;
};
/*jshint unused:false */
var checkit = {};
/*global checkit */
// In a full development environment this template would be expressed
// in a file containing only HTML and be compiled to the following as part
// of the server/build functionality.
//
// Due to the limitations of a simple example that does not require
// any special server environment to try, the manually compiled version is
// included here.
//
checkit.TodoTemplate =
'<li>' +
'<div class="view">' +
'<input class="toggle" type="checkbox">' +
'<label></label>' +
'<button class="destroy"></span>' +
'</div>' +
'<input class="edit">' +
'</li>';
/*global checkit */
// In a full development environment this template would be expressed
// in a file containing only HTML and be compiled to the following as part
// of the server/build functionality.
//
// Due to the limitations of a simple example that does not require
// any special server environment to try, the manually compiled version is
// included here.
//
checkit.TodosAppTemplate =
'<section id="todoapp">' +
'<header id="header">' +
'<h1>todos</h1>' +
'<input id="new-todo" placeholder="What needs to be done?" autofocus>' +
'</header>' +
'<section id="main">' +
'<input id="toggle-all" type="checkbox">' +
'<label for="toggle-all">Mark all as completed</label>' +
'<ul id="todo-list"></ul>' +
'</section>' +
'<footer id="footer">' +
'<span id="todo-count"></span>' +
'<ul id="filters">' +
'<li>' +
'<a class="all-filter" href="#/">All</a>' +
'</li>' +
'<li>' +
'<a class="incompleted-filter" href="#/active">Active</a>' +
'</li>' +
'<li>' +
'<a class="completed-filter" href="#/completed">Completed</a>' +
'</li>' +
'</ul>' +
'<button id="clear-completed"></button>' +
'</footer>' +
'</section>';
/*jshint strict: false */
/*global checkit */
checkit.isBlank = function (str) {
return (/^\s*$/).test(str);
};
checkit.escapeHTML = function (str) {
return String(str)
.replace(/&(?!\w+;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};
checkit.isEnterKeyCode = function (keyCode) {
return keyCode === 13;
};
checkit.isEscapeKeyCode = function (keyCode) {
return keyCode === 27;
};
/*jshint strict: false */
/*global maria, aristocrat, checkit */
maria.ElementView.subclass(checkit, 'TodoView', {
uiActions: {
'click .destroy': 'onClickDestroy',
'click .toggle': 'onClickToggle',
'dblclick label': 'onDblclickLabel',
'keyup .edit': 'onKeyupEdit',
'blur .edit': 'onBlurEdit'
},
properties: {
buildData: function () {
var model = this.getModel();
var item = this.find('li');
aristocrat.removeClass(item, '(in|)completed');
aristocrat.addClass(item, (model.isCompleted() ? 'completed' : 'incompleted'));
this.find('label').innerHTML = checkit.escapeHTML(model.getTitle());
this.find('.toggle').checked = model.isCompleted();
},
update: function () {
this.buildData();
},
resetEdit: function () {
var input = this.find('.edit');
input.value = this.getModel().getTitle();
},
showEdit: function () {
var input = this.find('.edit');
this.resetEdit();
aristocrat.addClass(this.find('li'), 'editing');
input.focus();
},
showDisplay: function () {
aristocrat.removeClass(this.find('li'), 'editing');
},
getInputValue: function () {
return this.find('.edit').value;
}
}
});
/*jshint strict: false */
/*global maria, aristocrat, checkit */
maria.SetView.subclass(checkit, 'TodosAppView', {
uiActions: {
'keyup #new-todo': 'onKeyupNewTodo',
'click #toggle-all': 'onClickToggleAll',
'click #clear-completed': 'onClickClearCompleted'
},
properties: {
buildData: function () {
var model = this.getModel();
var length = model.size;
this.find('#main').style.display = (length > 0) ? '' : 'none';
this.find('#footer').style.display = (length > 0) ? '' : 'none';
var checkbox = this.find('#toggle-all');
checkbox.checked = model.isAllCompleted();
checkbox.disabled = model.isEmpty();
var todoList = this.find('#todo-list');
model.getPossibleModes().forEach(function (mode) {
aristocrat.removeClass(todoList, mode);
});
aristocrat.addClass(todoList, model.getMode());
var incompletedLength = model.getIncompleted().length;
this.find('#todo-count').innerHTML =
'<strong>' + incompletedLength + '</strong> ' +
((incompletedLength === 1) ? 'item' : 'items') +
' left';
var selected = this.find('.selected');
if (selected) {
aristocrat.removeClass(selected, 'selected');
}
aristocrat.addClass(this.find('.' + model.getMode() + '-filter'), 'selected');
var completedLength = model.getCompleted().length;
var clearButton = this.find('#clear-completed');
clearButton.style.display = (completedLength > 0) ? '' : 'none';
clearButton.innerHTML = 'Clear completed (' + completedLength + ')';
},
update: function (evt) {
maria.SetView.prototype.update.call(this, evt);
this.buildData();
},
getContainerEl: function () {
// child views will be appended to this element
return this.find('#todo-list');
},
createChildView: function (todoModel) {
return new checkit.TodoView(todoModel);
},
getInputValue: function () {
return this.find('#new-todo').value;
},
clearInput: function () {
this.find('#new-todo').value = '';
}
}
});
# Maria TodoMVC Example
> The MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC.
> _[Maria - peter.michaux.ca/maria](http://peter.michaux.ca/maria)_
## Learning Maria
The [Maria website](http://peter.michaux.ca/maria) is a great resource for getting started.
Here are some links you may find helpful:
* [Quick Start Tutorial](http://peter.michaux.ca/maria/quick-start-tutorial-for-the-impatient.html)
* [API Reference](http://peter.michaux.ca/maria/api/maria.html)
* [GitHub](https://github.com/petermichaux/maria)
_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)._
......@@ -105,9 +105,6 @@
<li class="routing">
<a href="examples/canjs/" data-source="http://canjs.us" data-content="CanJS with jQuery. CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS</a>
</li>
<li class="routing">
<a href="examples/maria/" data-source="https://github.com/petermichaux/maria" data-content="An MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC. The three core design patterns of MVC (observer, composite, and strategy) are embedded in Maria's Model, View, and Controller objects. Other patterns traditionally included in MVC implementations (e.g. factory method and template) make appearances too.">Maria</a>
</li>
<li class="routing">
<a href="examples/polymer/index.html" data-source="http://polymer-project.org" data-content="Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. It is comprised of core platform features (e.g Shadow DOM, Custom Elements, MDV) enabled with polyfills and a next generation web application framework built on these technologies.">Polymer</a>
</li>
......
......@@ -1409,28 +1409,6 @@
}]
}]
},
"maria": {
"name": "Maria",
"description": "The MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC.",
"homepage": "peter.michaux.ca/maria",
"examples": [{
"name": "Example",
"url": "examples/maria"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "Quick Start Tutorial",
"url": "http://peter.michaux.ca/maria/quick-start-tutorial-for-the-impatient.html"
}, {
"name": "API Reference",
"url": "http://peter.michaux.ca/maria/api/maria.html"
}, {
"name": "GitHub",
"url": "https://github.com/petermichaux/maria"
}]
}]
},
"marionettejs": {
"name": "Backbone.Marionette",
"description": "Marionette simplifies your Backbone application code with robust views and architecture solutions.",
......
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